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

3 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!

  3. […] Documentation of the Standard Prelude is provided on the web page noted above. I defer to Chez Scheme for hash tables, structures and random numbers, rather than using the versions in my Standard Prelude, and also defer to Chez Scheme for the Standard Prelude functions that Chez Scheme provides natively. The only part of the Standard Prelude that is not loaded is avl trees, which are removed to their own library. Also loaded at each run of Chez Scheme are my literate programming environment described at https://programmingpraxis.com/2010/08/10/literate-programming and my interactive editing environment described at https://programmingpraxis.com/2017/04/07/edit-files-in-a-repl. […]

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 )

Connecting to %s

%d bloggers like this: