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