This is my very fist Lisp program (yay!), so I’m interested in any kind of feedback on conventions, best practices, how I’ve mangled a beautiful programming language, etc…
I’ve made a little standalone uLisp computer using a Teensy 4.1 and a Propeller to generate an NTSC signal, so I thought a text editor would be a fine choice for a first program. ‘Back in the day’ DOS included a ‘line editor’ called edlin and this approach would mean I could use the existing uLisp/Terminal functionality for entering text and not have to worry about cursor placement, and such.
It’s not too lengthy, so I’m posting it here. It can be invoked with an optional parameter that’s expected to be a list of strings, and it will return the final list of strings after editing is completed. There’s nothing particular to my little uLisp machine about it; it works in the terminal…
(defun edlin (&optional textlines)
(cond ((not (listp textlines))
(setq textlines (list ""))))
(let ((currline "")
(currlineno (length textlines))
(lexresults (list #\a #\b 0))
(action #\a))
(loop
(format t "~a>" currlineno)
(setq currline (read-line))
(setq lexresults (read-from-string currline))
(cond
((listp lexresults)
(setq action (car lexresults))
(cond
((numberp (cadr lexresults))
(setq currlineno (cadr lexresults)))
(t
(setq currlineno (length textlines))))
(cond
((eq action 'e)
(format t "~a|~a~%" currlineno (nth currlineno textlines)))
((eq action 'd)
(setq textlines (removenth currlineno textlines))
(setq currlineno (length textlines)))
((eq action 'i)
(setq textlines (insertnth '"" currlineno textlines)))
((eq action 'k)
(cond
((numberp (cadr lexresults))
(setq currlineno (cadr lexresults)))
(t
(setq currlineno 0)))
(dotimes (i 5)
(format t "~a|~a~%" currlineno (nth currlineno textlines))
(incf currlineno)))
((eq action 'l)
(setq currlineno 0)
(dolist (aline textlines)
(format t "~a|~a~%" currlineno aline)
(incf currlineno)))
((eq action 'x)
(return textlines))))
(t
(cond
((< currlineno (length textlines))
(setf (nth currlineno textlines) currline)
(setq currlineno (length textlines)))
((>= currlineno (length textlines))
(setq textlines (reverse (cons currline (reverse textlines))))
(setq currlineno (length textlines)))))))))
I cheated a bit and found a couple of functions to insert and remove nth items from a list (Lee Mac Programs), so I’m including them here for reference.
(defun removenth (n l)
(if (and l (< 0 n))
(cons (car l) (removenth (1- n) (cdr l)))
(cdr l)))
(defun insertnth (x n l)
(cond
((null l) nil)
((< 0 n) (cons (car l) (insertnth x (1- n) (cdr l))))
((cons x l))))