An Exec command and other new features of Stringscope
I continued working on Stringscope, the string listing tool I'm developing with Medley Interlisp. I added the function
STRINGS to print the strings to the primary output stream rather than in a new window, as well as an Executive command that does the same.
To reflect this work I updated the Stringscope code and documentation hosted on a GitHub gist, describing also the function
EXTRACT.STRINGS as part of the interface. The code in the gist is intended for publication and can't be loaded as is into Interlisp.
In addition to the same arguments as
STRINGSCOPE, i.e. a file name
FILENAME and the minimum length
MIN.LEN strings must have,
STRINGS accepts a third optional boolean argument
NEWWIN. By default
NIL and makes
STRINGS print to the primary output, otherwise the function opens a new window and works exactly like
STRINGSCOPE. In fact,
STRINGSCOPE is now just a wrapper that calls
NEWWIN set to
STRINGS return a window if the functions open it otherwise the primary output stream. In case the input file can not be opened or contains no strings, the functions return
NIL and print a warning to the prompt window.
Interlisp functions that create or manipulate a window usually return the window itself as their value, so I adopted a similar convention.
An early version of
STRINGS duplicated a lot of the code of
STRINGSCOPE for opening the input stream, checking for errors, evaluating some forms with the stream bound to a variable, and closing the stream. I factored that boilerplate into the macro
(DEFMACRO WITH.INPUT.FILE ((STREAM FILE) &BODY BODY &AUX (RESULT (GENSYM)) (VALUE (GENSYM))) (* Opens an input stream to FILE and evaluates the forms in BODY with the stream bound to STREAM. Returns the value of the last form in BODY, or NIL if FILE can not be opened.) `(PROG NIL [SETQ ,RESULT (NLSETQ (OPENSTREAM ,FILE 'INPUT] (if ,RESULT then (SETQ ,STREAM (CAR ,RESULT)) (SETQ ,VALUE (PROGN ,@BODY)) (CLOSEF ,STREAM) (RETURN ,VALUE) else (RETURN NIL))))
The Executive command
The reason I implemented a function like
STRINGS that prints the output to the console is I wanted to try out creating an Executive command.
Also known as a listener in other Lisp environments, an Executive is an Interlisp window that provides a read-eval-print loop. In addition to Lisp expressions, an Executive accepts commands with a non-parenthesized syntax such as
DIR (the equivalent of
DIR on MS-DOS and
ls on Unix) or
CONN directory (
cd directory on MS-DOS and Unix).
So I defined the Stringscope Executive command
STRINGS that works exactly like the function
STRINGS but takes only the file name and the minimum length arguments:
STRINGS FILENAME MIN.LEN
DEFCOMMAND defines an Executive command and is really easy to use, here's the definition of
(DEFCOMMAND (STRINGS :EVAL) (FILE &OPTIONAL (MIN.LENGTH SSCOPE.MIN.LEN)) (STRINGS FILE MIN.LENGTH) (CL:VALUES))
STRINGS command is just a wrapper that calls the function
STRINGS with appropriate arguments.
I initially run Stringscope compiled but it was time to start using the File Manager commands for compiling the code,
(MAKEFILE 'STRINGSCOPE 'C) and
(CLEANUP 'STRINGSCOPE). However, these commands apparently compile only in memory and don't write a compiled file like
(TCOMPL 'STRINGSCOPE), which I have to call manually.
The File Manager is an Interlisp subsystem conceptually similar to the Unix tool Make. It's a collection of tools to notice, keep track of, and write to files the code changes to a Lisp system under development.
Another confusing aspect of compilation is when I load Stringscope with
(FILESLOAD STRINGSCOPE), I get a warning I don't understand concerning a comment in the macro
Warning: Possible comment not stripped. I actually see the compiler couldn't strip a comment from the compiled code to save space, but not why.
Some of these new features were on my initial roadmap, others emerged while coding and using Stringscope.
Since this is an exploration and learning project, going forward I'll go with the flow and implement what I need or find interesting, and consider the initial roadmap more like a source of ideas than an action plan. Which is the kind of exploratory development Lisp supports and makes enjoyable.