edward

An extensible POSIX-compatible implementation of the ed(1) text editor

git clone https://git.8pit.net/edward.git

  1## About
  2
  3This is a POSIX-compatible implementation of the standard Unix text
  4editor [`ed(1)`][ed posix]. The implementation is written entirely in
  5[R7RS][r7rs] [CHICKEN Scheme][chicken] and provides a Scheme library
  6interface for extending the editor with custom commands.
  7
  8## Status
  9
 10I am presently not aware of any POSIX.1-2008 conformance issues. The
 11library interface, for extending `edward` with custom commands, is
 12usable but still very experimental and subject to change. Refer to
 13the `TODO.md` file for more information.
 14
 15## Design
 16
 17This implementation relies on [parser combinators][parser combinators]
 18as well as [hygienic Scheme macros][hygienic macros] to ease the
 19implementation of ed commands. Each ed command is defined using a macro
 20(i.e. similar to how one would normally define procedures in Scheme) and
 21parsed through provided parser combinators. In a sense, thus employing
 22[language-oriented programming][language-oriented programming] to
 23implement ed commands and thereby making this ed implementation very
 24hackable and easy to extend. The implementation is also split into a
 25CHICKEN program and various library components which allows defining
 26custom commands (refer to the library interface documentation below).
 27
 28## Installation
 29
 30The program can be installed either using [GNU make][gnu make] or
 31[chicken-install][chicken egg-install].
 32
 33### GNU make
 34
 35Installation via GNU make does not require any CHICKEN configuration
 36and should work out-of-the-box. As such, it is especially useful for
 37packaging purposes. In order to build edward using GNU make run the
 38following commands:
 39
 40	$ make
 41
 42To install edward to system-wide directories run the following command:
 43
 44	$ make install
 45
 46The GNU make installation method only installs the edward binary. It
 47does not install the library interface. If you want to interact with
 48the edward library you need to install edward via chicken-install.
 49
 50### chicken-install
 51
 52Contrary to installation via GNU make, this installation method requires
 53a properly configured CHICKEN toolchain. If CHICKEN has been configured
 54correctly, run the following command to install both the library and the
 55program component:
 56
 57	$ chicken-install
 58
 59The edward binary will be added to a directory in your `$PATH`,
 60furthermore the edward library will be available in your CHICKEN library
 61path. More usage information for the edward library is provided below.
 62
 63## Tests
 64
 65This repository contains both unit tests and integration tests. The
 66latter require a reference implementation of a POSIX.1-2008 compatible
 67ed implementation. Currently, [GNU ed >= 1.20.2][gnu ed] is used for this
 68purpose.
 69
 70Both unit and integration tests can be run using:
 71
 72	$ make check
 73
 74Optionally, [tmux][tmux web] can be installed to also execute tests for
 75edward's end-of-file handling in an interactive environment.
 76
 77## Usage
 78
 79For interactive usage I can highly recommend using this software in
 80conjunction with a [readline][GNU readline] frontend such as
 81[rlwrap][rlwrap github]. This enables readline-like keybindings (e.g.
 82Ctrl+A, Ctrl+W, …) as well as input history support.
 83
 84Detailed usage instructions for the `ed(1)` text editor can be found in
 85the [POSIX documentation][ed posix]. Additionally, a nice introduction
 86to the editor is provided in the book *The Unix Programming Environment*
 87by Brian W. Kernighan and Rob Pike (Appendix 1: Editor Summary). In
 88general, since ed is an old editor which hasn't changed much in the past
 89centuries, many historic documents explaining its usage are still
 90applicable today. Most notably, volume 2A of the seventh edition of the
 91[UNIX Programmer's Manual][unix v7vol2a] contains two documents which
 92provide a beginner-friendly introduction to the editor: *A Tutorial
 93Introduction to the UNIX Text Editor* and *Advanced Editing on UNIX*
 94both written by Brian W. Kernighan.
 95
 96## Library Interface
 97
 98Apart from an `ed(1)` implementation, `edward` also provides a library
 99interface for extending the editor with custom commands. While the
100implementation provided here focuses solely on POSIX compatibility,
101extension to the POSIX standard can be supplied separately using the
102library interface. The `edward` library can be used by creating a custom
103CHICKEN Scheme program which imports the edward libraries, defines
104custom commands through provided hygienic macros, and executes
105`(edward-main)` to start the editor. For example, an `edward` variant
106which provides a pipe command for passing a range of lines through
107a filter can be implemented as follows:
108
109	(import (scheme base)
110	        (chicken process)
111	        (srfi 14)
112	
113	        (edward cli)
114	        (edward util)
115	        (edward parse)
116	        (edward ed cmd)
117	        (edward ed addr)
118	        (edward ed posix)
119	        (edward ed editor))
120	
121	;; Executor for the pipe command
122	(define (exec-pipe editor range cmd)
123	  (let-values (((in out _) (process cmd))
124	               ((lines) (editor-get-lines editor range)))
125	    (call-with-port
126	      out
127	      (lambda (port) (lines->port lines port)))
128	    (let ((recv (port->lines in)))
129	      (close-input-port in)
130	      (exec-delete editor range)
131	      (exec-insert editor (car range) (car recv)))))
132	
133	;; Parser for the pipe command
134	(define-file-cmd (pipe exec-pipe (make-range))
135	  (parse-cmd-char #\|)
136	  (parse-token (char-set-complement (char-set #\newline))))
137	
138	;; Start the editor
139	(edward-main)
140
141Save this code in `edward++.scm` and compile it as follows:
142
143	$ csc -R r7rs edward++.scm
144
145Drop the resulting `edward++` binary somewhere in your `$PATH` and
146invoke it as usual. Naturally, it is possible to define multiple custom
147commands. Refer to `lib/ed/posix.scm` for the implementation of editor
148commands mandated by the POSIX standard. Additional commands are also
149available in a separate [edward-contrib][edward-contrib github]
150repository.
151
152## API Documentation
153
154The API of the library interface is documented using Scheme source code
155comments. An HTML documentation can be generated from these comments
156using the [scmdoc][scmdoc github] utility. More information on that
157is provided in `doc/README.md`.
158
159The API documentation is available via: https://files.8pit.net/edward/latest/doc/
160
161## History
162
163The existing GNU and BSD ed implementations are both derived from an
164implementation written by Andrew Moore in the early-to-mid 1990s. As
165such, they still share a lot of code and are potentially subject to the
166same bugs [\[1\]][ed history]. To the best of my knowledge, edward is
167the first ed implementation which strives to be fully POSIX compatible
168but is not derived from Andrew's original implementation.
169
170## License
171
172This program includes code from [chibi-scheme][chibi-scheme github]
173(`lib/parse/parse.scm`) written by Alex Shinn and licensed under a
174BSD-style license. Furthermore, it includes a stripped-down and slightly
175modified version of the [SRFI 214][srfi 214] reference implementation
176(`lib/buffer/srfi214-minimal.scm`) written by Adam Nelson under MIT.
177The program itself is licensed as follows:
178
179> This program is free software: you can redistribute it and/or modify it
180> under the terms of the GNU General Public License as published by the
181> Free Software Foundation, either version 3 of the License, or (at your
182> option) any later version.
183>
184> This program is distributed in the hope that it will be useful, but
185> WITHOUT ANY WARRANTY; without even the implied warranty of
186> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
187> Public License for more details.
188>
189> You should have received a copy of the GNU General Public License along
190> with this program. If not, see <https://www.gnu.org/licenses/>.
191
192[ed posix]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html
193[gnu make]: https://www.gnu.org/software/make/
194[chicken]: https://call-cc.org
195[chicken egg-install]: https://wiki.call-cc.org/man/5/Extensions#installing-eggs
196[chicken matchable]: https://wiki.call-cc.org/eggref/5/matchable
197[chicken posix-regex]: https://wiki.call-cc.org/eggref/5/posix-regex
198[chicken process signal]: https://api.call-cc.org/5/doc/chicken/process/signal
199[gnu ed]: https://www.gnu.org/software/ed/
200[srfi]: https://srfi.schemers.org/
201[srfi 204]: https://srfi.schemers.org/srfi-204/
202[srfi 214]: https://srfi.schemers.org/srfi-214/
203[r7rs]: https://small.r7rs.org/
204[parser combinators]: https://en.wikipedia.org/wiki/Parser_combinator
205[GNU readline]: https://tiswww.cwru.edu/php/chet/readline/rltop.html
206[rlwrap github]: https://github.com/hanslub42/rlwrap
207[unix v7vol2a]: https://s3.amazonaws.com/plan9-bell-labs/7thEdMan/v7vol2a.pdf
208[hygienic macros]: https://doi.org/10.1145/319838.319859
209[language-oriented programming]: https://doi.org/10.1145/3127323
210[ed history]: https://lists.gnu.org/archive/html/bug-ed/2021-12/msg00001.html
211[tmux web]: https://tmux.github.io
212[scmdoc github]: https://github.com/nmeum/scmdoc
213[edward-contrib github]: https://github.com/nmeum/edward-contrib
214[chibi-scheme github]: https://github.com/ashinn/chibi-scheme