Copyright (c) 2021, Charles Childers
As part of my personal goal of using my own tools as much as possible, I've written this little line editor. It's vaguely similar to ed or edlin, but I've not attempted to replicate these. Mine is much simpler.
On startup, it reads each line from a file into memory. The maximum line length and number of lines can be configured in the source, but must fit into Retro's memory space.
Commands are entered as a single character, which may be followed by optional or mandatory parameters.
An editing session (sans output) might look like:
,n a5 i5,enter some text on line 5 p0,10 x8 p15,30 x20,22 ,n w q
Look further in the source for a table of commands.
On startup, this loads a working file specified here. Use the commands later to load a specific file if needed.
The editor needs a max line length and max number of lines per file.
The file gets read into an array of lines. This is in the File structure. Lines holds the number of lines in the file.
A word, ed:to-line takes a line number and returns the address of the actual line contents.
Of note here: these account for adding in a NULL terminator for each line.
Line display is trivial in this. I optionally support line numbers, controlled by setting ShowLineNumbers to TRUE.
Commands are single characters. I reserve an array of pointers (Commands), with the ASCII value of the character being an index into this. If the final pointer is non-zero, this will call the command handler.
ed:register-command is used to add a handler to the table, and ed:deregister-command is used to remove one.
Input is read by ed:get-input. This returns the first character as a value and stores the rest, with the pointer being kept in Input.
The editor loop is thus simple. Get input, process the command, and repeat. I run this in a simple Heap preserving loop, so command handlers can allocate space at here without worrying about cleanup afterwards. I also reset the stack.
In general, each command is intended to do a single task.
re displays the file contents on command. I provide a few commands for this.
| , | | display all lines in the file | | , | n | display all lines in the file with line numbers | | p | line | display a single line | | p | first,last | display a range of lines | | / | | search for text; display matching lines | | # | | toggle display of line numbers |
The , command displays all lines in the file. It will optionally display line numbers if a n is included after the ,.
It's sometimes useful to have all outputs using line numbers. I define a # command to toggle the line number display. This will affect all outputs.
To display a single line, use p followed by the line number or to display a range of lines, use p, followed by a first,last line number pair.
The final display related command is /, which displays lines that contain the text following the /.
| a | line | add a line at line number, shifting lines down | | a | line,count | add lines at line number, shifting lines down |
Adding lines is done with a. Provide either a line number or a first,count pair and lines will be inserted starting at the specified line.
| x | line | remove line | | x | first,last | remove lines first through last, inclusive |
Use x to delete one or more lines. Pass either a single line number or a first,last pair.
| d | line | erase contents of a line |
To erase the contents of a line, use d followed by the line number.
| i | line,text | replace contents of line with text | | e | line | insert text beginning at line, shifting down | | y | line,text | append text to end of line |
I provide two words for editing the text of the file. i replaces the text on a line with the provided text, and e insterts text, shifting existing lines down. When entering text with e, use a period on an otherwise blank line to return to the command processing mode.
Copy/paste
| f | filename | set the filename for saves, loads |
| w | | save file |
Files are saved with w. The number of lines written will be displayed upon completion.
| q | | quit retro-edit |
Use q to quit the editor.
| n | line | indent line | | N | line | unindent line | | ; | | save, then run file via retro | | ; | text | save, then run text as a shell command |
The final startup process is:
• copy the file name to Filename
• create it if the file does not exist
• load the file into memory
• run the editor command loop
{ '|_|V|/|_|_/_CharlesChilders'PersonalComputingSystem '|/||||//_aUnixKernel,RetroForth,andanon-POSIX '|_||||_/_environmentwritteninForth }