Library for defining custom ed editor commands through provided macros. For each command, a parser and an executor needs to be defined. The parser is defined using edward parser combinators. The executor receives an editor object as well as the return value of the parser combinator as procedure arguments and modifies the editor state accordingly. Additionally, this library defines several utility procedures that are useful for defining executor procedures and ed parser combinators.
Conceptually, edward distinguishes the following four command types:
p
command. These can be used as
suffixes to edit commands.d
).Commands of the different types are defined using the abstractions described in this section. Every command definition requires at least a unique command name (a symbol) and an executor procedure which is passed the editor object and values returned by the command parser.
Define a new file command. Apart from the unique name
and
executor procedure proc
, commands of this type require a default
edward address addr
. If no default address is
provided, it is assumed that this command doesn't expect an address.
Furthermore, a a parser combinator definition needs to be provided in
the body
. The combinators defined in the body
are expanded to a
parse-blanks-seq. The first combinator of the
body must be a parse-cmd-char. All
non-ignored parser combinator return values are
passed to proc
as procedure arguments.
(define-file-cmd (name proc addr) body ...)
Define a new edit command. These commands are conceptually similar to file commands. Therefore, please refer to the documentation of define-file-cmd for more information on the parameters.
Contrary to file commands, edit commands can additionally be suffixed with a print command. If a print command suffix is present, this print command will be executed after the editor changes have been performed by the edit command.
(define-edit-cmd (name proc addr) body ...)
Define a new input command. These commands are conceptually similar to edit commands. Similar to edit commands, input commands can also be suffixed with a print command. Therefore, please refer to the documentation of define-edit-cmd for more information on the parameters.
Contrary to other command types, input commands additionally
read data using ed input mode. The received data is passed as a
list of lines as the last parameter to proc
.
(define-input-cmd (name proc addr) body ...)
Define a new print command. Print commands are automatically parsed
using parse-cmd-char based on the provided
cmd-char
character. No custom parser combinator can be supplied
for these commands. Furthermore, print commands always use the
current line as the default address. Similar to other command types,
a unique command name
(a symbol) must be defined. The executor
procedure proc
is always passed an editor object and the address
range which was passed to the command.
(define-print-cmd name proc char)
Procedures to invoke parsers for defined editor commands.
Parse a single, arbitrary command that was previously defined using
one of the abstractions described above. If no
command parser matches the input, then parsing fails with the error
message "unknown command"
.
(parse-cmd)
Utility parser combinators that are useful for defining editor command parsers and, contrary to the combinators defined in edward parse, are somewhat specific to ed(1).
Parse a command character within a parse-seq / parse-blanks-seq. This character is ignored in the sequence and as such not returned.
(parse-cmd-char ch)
Parse RE pair for the substitute command (e.g. /RE/replacement/
).
The given procedure is responsible for parsing the replacement, it is
passed the utilized delimiter as a single character function
argument.
Returns triplet (RE, replacement, print?)
where print?
indicates
if the closing delimiter was emitted, i.e. if the resulting string
should be printed after the replacement was performed.
(parse-re-pair delim-proc)
Parses a regular expression enclosed by two matching delimiter characters.
parse-re
Parse a command list, as passed to the g
and v
command.
unwrap-command-list
Parses a filename, which is then read/written by ed. A file name is
either a path to a file or a shell command as passed to the ed
shell escape command. The latter is recognized by a !
character
prefix.
parse-filename
Parses a command character followed by an optional file parameter.
The parameters must be separated by one or more
(parse-file-cmd ch)
Utility procedures for common command executor operations.
If changes have been made to the current buffer since the last write of the buffer to a file, then ed should warn the user before the buffer is destroyed. Warnings must be confirmed by repeating the command, which closes the buffer.
This procedure expects an editor record, the symbol of the command to be repeated and a thunk executed if the command was confirmed or no confirmation is necessary (i.e. buffer was not modified).
(call-when-confirmed editor cmd-sym thunk)
Parameterizable executor for substitution cases where no addressed line matched the desired substitution. Can be overwritten using parameterize. By default, an error is raised if no substitution was performed.
subst-nomatch-handler
Execute a command list, parsed using
unwrap-command-list, for the g
and v
command.
(exec-command-list editor match-proc lines regex cmdstr)
Like exec-command-list but intended to be used
for interactive commands, i.e. G
and V
.
(exec-command-list-interactive editor match-proc lines regex)
Predicate which returns true if the given string fn
is a file name
and not a shell command.
(filename-cmd? fn)
Write a list of lines
(represented as a string without a terminating
newline) to a given filename
. If filename
starts with !
(i.e.
is a command according to filename-cmd?), write data
to standard input of given command string.
Returns amount of bytes written to the filename
on success and false
if an error occurred.
(write-lines filename lines)
Read data from given filename as a list of lines. If filename start
with !
(i.e. is a command), read data from the standard output of
the given command.
If an error occurs, returns false and prints an error message to the current-error-port. Otherwise, returns a pair of retrieved lines and amount of total bytes received.
(read-from filename)