Edit Files In A REPL

April 7, 2017

Here is my REPL editor, which is stored in file edfile.ss and loaded when I start up my Scheme system:

(define-top-level-value '*editor* "ed")
(define-top-level-value '*edfile* #f)
(define (ed . args)
  (if (pair? args) (set-top-level-value! '*edfile* (car args)))
  (if (not (top-level-value '*edfile*)) (error 'ed "file not found"))
  (system (string-append (top-level-value '*editor*) " " (top-level-value '*edfile*)))
  (load (top-level-value '*edfile*)))

This is specific to Chez Scheme, and is ugly because of the change in Scheme top-level semantics that was brought in with R6RS. The asterisks around the variable names are a Lisp convention; they are known colloquially as “earmuffs” and mark global variables. Here is a sample editing session, where I write a Sieve of Eratosthenes:

phil@haydn ~ $ scheme edfile.ss
Chez Scheme Version 9.4.1
Copyright 1984-2016 Cisco Systems, Inc.

> (ed "primes.ss")
primes.ss: No such file or directory
(define (primes n)
  (let ((sieve (make-vector (+ n 1) #t)))
    (let loop ((p 2) (ps (list)))
      (cond ((< n p) (reverse ps))
            ((vector-ref sieve p)
              (do ((i (* p p) (+ i p))) ((< n i))                 (vector-set! siev i #f))               (loop (+ p 1) (cons p ps)))             (else (loop (+ p 1) ps)))))) . wq 338 > (primes 50)
Exception: variable siev is not bound
Type (debug) to enter the debugger.
> (ed)
  (let ((sieve (make-vector (+ n 1) #t)))
            ((vector-ref sieve p)
                (vector-set! siev i #f))
                (vector-set! sieve i #f))
> (primes 50)
(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47)
> (exit)

Yes, I really do use ed. As you see above, it flows very nicely in an interactive session.

You can see the program at http://ideone.com/dWZveh.


Pages: 1 2

2 Responses to “Edit Files In A REPL”

  1. John Cowan said

    Case-lambda would make this more readable, as well as providing better error checking. With its provision in R6RS and R7RS, I consider the manual style of handling multiple arguments obsolete. Let-optionals is even better if you have the original Shivers macro, but many implementations’ built-in versions are flaky, and the overhead can be high.

    You might want to consider changing from ed(1) to ex(1), trading a little standardosity for added convenience. Auto-indentation during text entry is very nice once set up, and I often find infinite undo saves my bacon. The z command to page through a file is also very useful. Above all, in Lisp work I find it indispensable to be able to enter vi-mode just before I’m done and bounce on the % key to make sure all non-obvious parens are matched. The only vi-mode commands I need for this are h, j, k, l (cursor movement), a, i (what you expect), %, and Q or gQ to return to ex-mode.

  2. programmingpraxis said

    @JohnCowan: I didn’t realize that case-lambda became part of the standard in R6RS. I’ll use it from now on.

    Although I didn’t show it in the exercise, for my own use I actually have two functions, (ed ...) and (vi ...), that share a common *edfile* but hardcode the name of the editor, and use whichever makes sense at the time. If I want to use ex I call it from vi. I normally use ed for simple editing, and vi for bigger edits. I generally prefer ed, except for very large edits, because I find the switch from line-mode in the REPL to screen-mode in the editor distracting. I do use vi when I get a mis-matched parenthesis error, as you do; maybe I will add an (ex ...) function to my toolbox for that purpose.

    I’ve always had a soft spot in my heart for ed, as it was the first editor I learned on Unix, more years ago than I care to admit. Long live ed!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: