commits
2024-09-04 | Bump version to 1.1.0 | Sören Tempel |
2024-09-04 | GNUmakefile: Make vendoring work with CHICKEN 5.4.0 again | Sören Tempel |
2024-08-18 | parse: use qualified imports for chicken libraries | Sören Tempel |
2024-08-18 | posix: Fix line numbers for replacements during multi-line substitutions | Sören Tempel |
2024-08-18 | Avoid unqualified imports of chicken libraries | Sören Tempel |
Clone the repository to access all 745 commits.
About
This is a POSIX-compatible implementation of the standard Unix text
editor ed(1)
. The implementation is written entirely in
R7RS CHICKEN Scheme and provides a Scheme library
interface for extending the editor with custom commands.
Status
I am presently not aware of any POSIX.1-2008 conformance issues. The
library interface, for extending edward
with custom commands, is
usable but still very experimental and subject to change. Refer to
the TODO.md
file for more information.
Design
This implementation relies on parser combinators as well as hygienic Scheme macros to ease the implementation of ed commands. Each ed command is defined using a macro (i.e. similar to how one would normally define procedures in Scheme) and parsed through provided parser combinators. In a sense, thus employing language-oriented programming to implement ed commands and thereby making this ed implementation very hackable and easy to extend. The implementation is also split into a CHICKEN program and various library components which allows defining custom commands (refer to the library interface documentation below).
Installation
The program can be installed either using GNU make or chicken-install.
GNU make
Installation via GNU make does not require any CHICKEN configuration and should work out-of-the-box. As such, it is especially useful for packaging purposes. In order to build edward using GNU make run the following commands:
$ make
To install edward to system-wide directories run the following command:
$ make install
The GNU make installation method only installs the edward binary. It does not install the library interface. If you want to interact with the edward library you need to install edward via chicken-install.
chicken-install
Contrary to installation via GNU make, this installation method requires a properly configured CHICKEN toolchain. If CHICKEN has been configured correctly, run the following command to install both the library and the program component:
$ chicken-install
The edward binary will be added to a directory in your $PATH
,
furthermore the edward library will be available in your CHICKEN library
path. More usage information for the edward library is provided below.
Tests
This repository contains both unit tests and integration tests. The latter require a reference implementation of a POSIX.1-2008 compatible ed implementation. Currently, GNU ed >= 1.20.2 is used for this purpose.
Both unit and integration tests can be run using:
$ make check
Optionally, tmux can be installed to also execute tests for edward’s end-of-file handling in an interactive environment.
Usage
For interactive usage I can highly recommend using this software in conjunction with a readline frontend such as rlwrap. This enables readline-like keybindings (e.g. Ctrl+A, Ctrl+W, …) as well as input history support.
Detailed usage instructions for the ed(1)
text editor can be found in
the POSIX documentation. Additionally, a nice introduction
to the editor is provided in the book The Unix Programming Environment
by Brian W. Kernighan and Rob Pike (Appendix 1: Editor Summary). In
general, since ed is an old editor which hasn’t changed much in the past
centuries, many historic documents explaining its usage are still
applicable today. Most notably, volume 2A of the seventh edition of the
UNIX Programmer’s Manual contains two documents which
provide a beginner-friendly introduction to the editor: A Tutorial
Introduction to the UNIX Text Editor and Advanced Editing on UNIX
both written by Brian W. Kernighan.
Library Interface
Apart from an ed(1)
implementation, edward
also provides a library
interface for extending the editor with custom commands. While the
implementation provided here focuses solely on POSIX compatibility,
extension to the POSIX standard can be supplied separately using the
library interface. The edward
library can be used by creating a custom
CHICKEN Scheme program which imports the edward libraries, defines
custom commands through provided hygienic macros, and executes
(edward-main)
to start the editor. For example, an edward
variant
which provides a pipe command for passing a range of lines through
a filter can be implemented as follows:
(import (scheme base)
(chicken process)
(srfi 14)
(edward cli)
(edward util)
(edward parse)
(edward ed cmd)
(edward ed addr)
(edward ed posix)
(edward ed editor))
;; Executor for the pipe command
(define (exec-pipe editor range cmd)
(let-values (((in out _) (process cmd))
((lines) (editor-get-lines editor range)))
(call-with-port
out
(lambda (port) (lines->port lines port)))
(let ((recv (port->lines in)))
(close-input-port in)
(exec-delete editor range)
(exec-insert editor (car range) (car recv)))))
;; Parser for the pipe command
(define-file-cmd (pipe exec-pipe (make-range))
(parse-cmd-char #\|)
(parse-token (char-set-complement (char-set #\newline))))
;; Start the editor
(edward-main)
Save this code in edward++.scm
and compile it as follows:
$ csc -R r7rs edward++.scm
Drop the resulting edward++
binary somewhere in your $PATH
and
invoke it as usual. Naturally, it is possible to define multiple custom
commands. Refer to lib/ed/posix.scm
for the implementation of editor
commands mandated by the POSIX standard. Additional commands are also
available in a separate edward-contrib
repository.
API Documentation
The API of the library interface is documented using Scheme source code
comments. An HTML documentation can be generated from these comments
using the scmdoc utility. More information on that
is provided in doc/README.md
.
The API documentation is available via: https://files.8pit.net/edward/latest/doc/
History
The existing GNU and BSD ed implementations are both derived from an implementation written by Andrew Moore in the early-to-mid 1990s. As such, they still share a lot of code and are potentially subject to the same bugs [1]. To the best of my knowledge, edward is the first ed implementation which strives to be fully POSIX compatible but is not derived from Andrew’s original implementation.
License
This program includes code from chibi-scheme
(lib/parse/parse.scm
) written by Alex Shinn and licensed under a
BSD-style license. Furthermore, it includes a stripped-down and slightly
modified version of the SRFI 214 reference implementation
(lib/buffer/srfi214-minimal.scm
) written by Adam Nelson under MIT.
The program itself is licensed as follows:
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.