Paolo Amoroso's Journal

Lisp

I continued working on DandeGUI, a GUI library for Medley Interlisp I'm writing in Common Lisp. I added two new short public functions, GUI:CLEAR-WINDOW and GUI:PRINT-MESSAGE, and fixed a bug in some internal code.

GUI:CLEAR-WINDOW deletes the text of the window associated with the Interlisp TEXTSTREAM passed as the argument:

(DEFUN CLEAR-WINDOW (STREAM)
   "Delete all the text of the window associated with STREAM. Returns STREAM"
   (WITH-WRITE-ENABLED (STR STREAM)
          (IL:TEDIT.DELETE STR 1 (IL:TEDIT.NCHARS STR)))
   STREAM)

It's little more than a call to the TEdit API function IL:TEDIT.DELETE for deleting text in the editor buffer, wrapped in the internal macro GUI::WITH-WRITE-ENABLED that establishes a context for write access to a window.

I also wrote GUI:PRINT-MESSAGE. This function prints a message to the prompt area of the window associated with the TEXTSTREAM passed as an argument, optionally clearing the area prior to printing. The prompt area is a one-line Interlisp prompt window attached above the title bar of the TEdit window where the editor displays errors and status messages.

(DEFUN PRINT-MESSAGE (STREAM MESSAGE &OPTIONAL DONT-CLEAR-P)
   "Print MESSAGE to the prompt area of the window associated with STREAM. If DONT-CLEAR-P is non NIL the area will be cleared first. Returns STREAM."
   (IL:TEDIT.PROMPTPRINT STREAM MESSAGE (NOT DONT-CLEAR-P))
   STREAM)

GUI:PRINT-MESSAGE just passes the appropriate arguments to the TEdit API function IL:TEDIT.PROMPTPRINT which does the actual printing.

The documentation of both functions is in the API reference on the project repo.

Testing DandeGUI revealed that sometimes text wasn't appended to the end but inserted at the beginning of windows. To address the issue I changed GUI::WITH-WRITE-ENABLED to ensure the file pointer of the stream is set to the end of the file (i.e -1) prior to passing control to output functions. The fix was to add a call to the Interlisp function IL:SETFILEPTR:

(IL:SETFILEPTR ,STREAM -1)

#DandeGUI #CommonLisp #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

I'm working on DandeGUI, a Common Lisp GUI library for simple text and graphics output on Medley Interlisp. The name, pronounced “dandy guy”, is a nod to the Dandelion workstation, one of the Xerox D-machines Interlisp-D ran on in the 1980s.

DandeGUI allows the creation and management of windows for stream-based text and graphics output. It captures typical GUI patterns of the Medley environment such as printing text to a window instead of the standard output. The main window of this screenshot was created by the code shown above it.

A text output window created with DandeGUI on Medley Interlisp and the Lisp code that generated it.

The library is written in Common Lisp and exposes its functionality as an API callable from Common Lisp and Interlisp code.

Motivations

In most of my prior Lisp projects I wrote programs that print text to windows.

In general these windows are actually not bare Medley windows but running instances of the TEdit rich-text editor. Driving a full editor instead of directly creating windows may be overkill, but I get for free content scrolling as well as window resizing and repainting which TEdit handles automatically.

Moreover, TEdit windows have an associated TEXTSTREAM, an Interlisp data structure for text stream I/O. A TEXTSTREAM can be passed to any Common Lisp or Interlisp output function that takes a stream as an argument such as PRINC, FORMAT, and PRIN1. For example, if S is the TEXTSTREAM associated with a TEdit window, (FORMAT S "~&Hello, Medley!~%") inserts the text “Hello, Medley!” in the window at the position of the cursor. Simple and versatile.

As I wrote more GUI code, recurring patterns and boilerplate emerged. These programs usually create a new TEdit window; set up the title and other options; fetch the associated text stream; and return it for further use. The rest of the program prints application specific text to the stream and hence to the window.

These patterns were ripe for abstracting and packaging in a library that other programs can call. This work is also good experience with API design.

Usage

An example best illustrates what DandeGUI can do and how to use it. Suppose you want to display in a window some text such as a table of square roots. This code creates the table in the screenshot above:

(gui:with-output-to-window (stream :title "Table of square roots")
  (format stream "~&Number~40TSquare Root~2%")
  (loop
    for n from 1 to 30
    do (format stream "~&~4D~40T~8,4F~%" n (sqrt n))))

DandeGUI exports all the public symbols from the DANDEGUI package with nickname GUI. The macro GUI:WITH-OUTPUT-TO-WINDOW creates a new TEdit window with title specified by :TITLE, and establishes a context in which the variable STREAM is bound to the stream associated with the window. The rest of the code prints the table by repeatedly calling the Common Lisp function FORMAT with the stream.

GUI:WITH-OUTPUT-TO-WINDOW is best suited for one-off output as the stream is no longer accessible outside of its scope.

To retain the stream and send output in a series of steps, or from different parts of the program, you need a combination of GUI:OPEN-WINDOW-STREAM and GUI:WITH-WINDOW-STREAM. The former opens and returns a new window stream which may later be used by FORMAT and other stream output functions. These functions must be wrapped in calls to the macro GUI:WITH-WINDOW-STREAM to establish a context in which a variable is bound to the appropriate stream.

The DandeGUI documentation on the project repository provides more details, sample code, and the API reference.

Design

DandeGUI is a thin wrapper around the Interlisp system facilities that provide the underlying functionality.

The main reason for a thin wrapper is to have a simple API that covers the most common user interface patterns. Despite the simplicity, the library takes care of a lot of the complexity of managing Medley GUIs such as content scrolling and window repainting and resizing.

A thin wrapper doesn't hide much the data structures ubiquitous in Medley GUIs such as menus and font descriptors. This is a plus as the programmer leverages prior knowledge of these facilities.

So far I have no clear idea how DandeGUI may evolve. One more reason not to deepen the wrapper too much without a clear direction.

The user needs not know whether DandeGUI packs TEdit or ordinary windows under the hood. Therefore, another design goal is to hide this implementation detail. DandeGUI, for example, disables the main command menu of TEdit and sets the editor buffer to read-only so that typing in the window doesn't change the text accidentally.

Using Medley Common Lisp

DandeGUI relies on basic Common Lisp features. Although the Medley Common Lisp implementation is not ANSI compliant it provides all I need, with one exception.

The function DANDEGUI:WINDOW-TITLE returns the title of a window and allows to set it with a SETF function. However, the SEdit structure editor and the File Manager of Medley don't support or track function names that are lists such as (SETF WINDOW-TITLE). A good workaround is to define SETF functions with DEFSETF which Medley does support along with the CLtL macro DEFINE-SETF-METHOD.

Next steps

At present DandeGUI doesn't do much more than what described here.

To enhance this foundation I'll likely allow to clear existing text and give control over where to insert text in windows, such as at the beginning or end. DandeGUI will also have rich text facilities like printing in bold or changing fonts.

The windows of some of my programs have an attached menu of commands and a status area for displaying errors and other messages. I will eventually implement such menu-ed windows.

To support programs that do graphics output I plan to leverage the functionality of Sketch for graphics in a way similar to how I build upon TEdit for text.

Sketch is the line drawing editor of Medley. The Interlisp graphics primitives require as an argument a DISPLAYSTREAM, a data stracture that represents an output sink for graphics. It is possible to use the Sketch drawing area as an output destination by associating a DISPLAYSTREAM with the editor's window. Like TEdit, Sketch takes care of repainting content as well as window scrolling and resizing. In other words, DISPLAYSTREAM is to Sketch what TEXTSTREAM is to TEdit.

DandeGUI will create and manage Sketch windows with associated streams suitable for use as the DISPLAYSTREAM the graphics primitives require.

#DandeGUI #CommonLisp #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

My journey to Lisp began in the early 1990s. Over three decades later, a few days ago I rediscovered the first Lisp environment I ever used back then which contributed to my love for the language. Here it is, PC Scheme running under DOSBox-X on my Linux PC:

Screenshot of the PC Scheme Lisp development environment for MS-DOS by Texas Instruments running under DOSBox-X on Linux Mint Cinnamon.

Using PC Scheme again brought back lots of great memories and made me reflect on what the environment taught me about Lisp and Lisp tooling.

As a Computer Science student at the University of Milan, Italy, around 1990 I took an introductory computers and programming class taught by Prof. Stefano Cerri. The textbook was the first edition of Structure and Interpretation of Computer Programs (SICP) and Texas Instruments PC Scheme for MS-DOS the recommended PC implementation. I installed PC Scheme under DR-DOS on a 20 MHz 386 Olidata laptop with 2 MB RAM and a 40 MB hard disk drive.

Prior to the class I had read about Lisp here and there but never played with the language. SICP and its use of Scheme as an elegant executable formalism instantly fascinated me. It was Lisp love at first sight.

The class covered the first three chapters of the book but I later read the rest on my own. I did lots of exercises using PC Scheme to write and run them.

Soon I became one with PC Scheme.

The environment enabled a tight development loop thanks to its Emacs-like EDWIN editor that was well integrated with the system. The Lisp awareness of EDWIN blew my mind as it was the first such tool I encountered. The editor auto-indented and reformatted code, matched parentheses, and supported evaluating expressions and code blocks. Typing a closing parenthesis made EDWIN blink the corresponding opening one and briefly show a snippet of the beginning of the matched expression.

Paying attention to the matching and the snippets made me familiar with the shape and structure of Lisp code, giving a visual feel of whether code looks syntactically right or off. Within hours of starting to use EDWIN the parentheses ceased to be a concern and disappeared from my conscious attention. Handling parentheses came natural. I actually ended up loving parentheses and the aesthetics of classic Lisp.

Parenthesis matching suggested me a technique for writing syntactically correct Lisp code with pen and paper. When writing a closing parenthesis with the right hand I rested the left hand on the paper with the index finger pointed at the corresponding opening parenthesis, moving the hands in sync to match the current code. This way it was fast and easy to write moderately complex code.

PC Scheme spoiled me and set the baseline of what to expect in a Lisp environment.

After the class I moved to PCS/Geneva, a more advanced PC Scheme fork developed at the University of Geneva. Over the following decades I encountered and learned Common Lisp, Emacs, Lisp, and Interlisp. These experiences cemented my passion for Lisp.

In the mid-1990s Texas Instruments released the executable and sources of PC Scheme. I didn't know it at the time, or if I noticed I long forgot. Until a few days ago, when nostalgia came knocking and I rediscovered the PC Scheme release.

I installed PC Scheme under the DOSBox-X MS-DOS emulator on my Linux Mint Cinnamon PC. It runs well and I enjoy going through the system to rediscover what it can do.

Playing with PC Scheme after decades of Lisp experience and hindsight on computing evolution shines new light on the environment.

I didn't fully realize at the time but the product packed an amazing value for the price. It cost $99 in the US and I paid it about 150,000 Lira in Italy. Costing as much as two or three texbooks, the software was affordable even to students and hobbyists.

PC Scheme is a rich, fast, and surprisingly capable environment with features such as a Lisp-aware editor, a good compiler, a structure editor and other tools, many Scheme extensions such as engines and OOP, text windows, graphics, and a lot more. The product came with an extensive manual, a thick book in a massive 3-ring binder I read cover to cover more than once. A paper on the implementation of PC Scheme sheds light on how good the system is given the platform constraints.

Using PC Scheme now lets me put into focus what it taught me about Lisp and Lisp systems: the convenience and productivity of Lisp-aware editors; interactive development and exploratory programming; and a rich Lisp environment with a vast toolbox of libraries and facilities — this is your grandfather's batteries included language.

Three decades after PC Scheme a similar combination of features, facilities, and classic aesthetics drew me to Medley Interlisp, my current daily driver for Lisp development.

#Lisp #MSDOS #retrocomputing

Discuss... Email | Reply @amoroso@oldbytes.space

I wrote Bitsnap, a tool in Interlisp for capturing screenshots on the Medley environment. It can capture and optionally save to a file the full screen, a window with or without title bar and borders, or an arbitrary area.

This project helped me learn the internals of Medley, such as extending the background menu, and produced a tool I wanted. For example, with Bitsnap I can capture some areas like specific windows without manually framing them; or the full screen of Medley excluding the title bar and borders of the operating systems that hosts Medley, Linux in my case.

Medley can natively capture various portions of the screen. These facilities produce 1-bit images as instances of BITMAP, an image data structure Medley uses for everything from bit patterns, to icons, to actual images. Some Lisp functions manipulate bitmaps.

Bitsnap glues together these facilities and packages them in an interactive interface accessible as a submenu of the background menu as well as a programmatic interface, the Interlisp function SNAP.

To provide feedback after a capture Bitsnap displays in a window the area just captured, as shown here along with the Bitsnap menu.

A bitmap captured with the Bitsnap screenshot tool and its menu on Medley Interlisp.

The tool works by copying to a new bitmap the system bitmap that holds the designated area of the screen. Which is straighforward as there are Interlisp functions for accessing the source bitmaps. These functions return a BITMAP and capture:

  • SCREENBITMAP: the full screen
  • WINDOW.BITMAP: a window including the title bar and border
  • BITMAPCOPY: the interior of a window with no title bar and border
  • SNAPW: an arbitrary area

The slightly more involved part is bringing captured bitmaps out of Medley in a format today's systems and tools understand. Some Interlisp functions can save a BITMAP to disk in text and binary encodings, none of which are modern standards.

The only Medley tool to export to a modern — or less ancient — format less bound to Lisp is the xerox-to-xbm module which converts a BITMAP to the Unix XBM (X BitMap) format. However, xerox-to-xbm can't process large bitmaps.

To work around the issue I wrote the function BMTOPBM that saves a BITMAP to a file in a slightly more modern and popular format, PBM (Portable BitMap). I can't think of anything simpler and, indeed, it took me just half a dozen minutes to write the function. Linux and other modern operating systems can natively display PBM files and Netpbm converts PBM to PNG and other widely used standards. For example, this Netpbm pipeline converts to PNG:

$ pbmtopnm screenshot.pbm | pnmtopng > screenshot.png

BMTOPBM can handle bitmaps of any size but its simple algorithm is inefficient. However, on my PC the function takes about 5 seconds to save a 1920x1080 bitmap, which is the worst case as this is the maximum screen size Medley allows. Good enough for the time being.

Bitsnap does pretty much all I want and doesn't need major new features. Still, I may optimize BMTOPBM or save directly to PNG.

#Bitsnap #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

It's a joy to use the Cardputer uLisp Machine, a nice little microcontroller system that runs uLisp. But after a short experience I had to put aside my Cardputer due to a showstopper issue that made it impractical to program the device.

Since then a good workaround emerged and I learned how to improve the experience with the device.

The showstopper is a buffer overflow when sending Lisp code from Emacs to the Cardputer over a serial USB line. If the receive buffer fills up too fast the device will crash and disconnect. Sending more than a few hundred bytes triggers the issue and makes it impractical to evaluate medium or large code blocks. This acknowledged Arduino issue reported in February of 2022 has not been addressed yet.

Meanwhile, Dennis Draheim devised a workaround. He wrote some Emacs Lisp code to open a serial connection to the Cardputer and send an expressions or region for evaluation. The trick is to split the input into lines and send one line at a time, with a delay in between to keep the Cardputer's serial buffer from overflowing.

Dennis' code works well and makes uLisp usable on the Cardputer. The only downside is the echoed input clutters the Emacs serial buffer. Our attempts at turning off echo failed as we don't know where Emacs handles this.

The workaround enables running more substantial and interesting uLisp programs such as this nice surface of rotation graphics demo:

3D function plot on the display of a Cardputer uLisp Machine device.

The Cardputer has a tiny built-in keyboard that is handy for short interactions. But it's prone to overtyping when entering a character that requires pressing two keys, such as shifted characters or the parentheses.

I originally attempted to press at the same time the Aa shift key and the key with the desired symbol. But this often results in typing more than one character as hitting such tiny targets simultaneously is difficult. I later stumbled upon a way to consistently avoid overtyping: I press and hold Aa, then press the key with the desired character.

#Cardputer #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

I wrote Interpinkie, a basic Finger client in Interlisp that runs on the Medley environment. This is the main window of the program:

Main window of the Interpinkie Interlisp Finger client.

It was a fun challenge considering I couldn't use Medley's TCP/IP stack.

I always wanted to do some network programming with Medley. But the bitrot of its TCP/IP stack left it in a non working state since before the Medley Interlisp project, and the revival effort hasn't got around to the stack yet. The XNS stack still mostly works with the Dodo Services XNS implementation. But, as far as I know, XNS provides LAN services and I'm not sure whether or how it allows access to the outside Internet.

So I cheated and reached for Medley's escape hatch.

As part of the Medley modernization effort, the UNIXUTILS library module provides the ShellCommand function to run a Unix program on the host operating system and send the output to a stream. Since I can run arbitrary Unix commands from Medley, it's trivial to build a client that talks the Finger protocol via Netcat.

For example, to run the Finger query amoroso@happynetbox.com I can just execute this from the Linux shell:

$ echo "amoroso" | nc -C -w 3 happynetbox.com finger

where -C sends \r\n as line-ending, -w 3 sets a timeout of 3 seconds, and finger is the Finger port number as per /etc/services.

All Interpinkie does is to build and feed a query to ShellCommand, pipe the output through tr to remove extra \rs, and redirect the output to a suitable destination.

The Interlisp function QUERY.FINGER.SERVER wraps this functionality. By default the output goes to the primary output (Interlisp jargon for stdout), or optionally to a separate window with menu options for running another Finger query or quitting the program.

Interpinkie builds upon user interface techniques I used in previous projects such as attaching a menu to a TEdit window.

TEdit, the WYSIWYG the rich text editor of Medley, can be driven by other programs that send output to the editor buffer. This is handy as the programs get an automatically repainted scrollable window for free from TEdit. In addition, Interpinkie attaches a command menu to the TEdit window and uses TEdit's prompt window (Interlisp jargon for an edit field and status area) to request input and display errors.

Unlike my previous Interlisp projects, however, Interpinkie doesn't call the TEdit API to insert text in the buffer. Instead, the program redirects the ShellCommand output to the Lisp stream associated with the TEdit window, causing the text to appear in the buffer.

By default ordinary Lisp printing functions such as PRIN1 and PRINT send the output to the REPL or optionally to another Lisp I/O stream. Along with these output destinations, some Interlisp components and programs like TEdit have an associated stream. So it's easy to send output to TEdit by just printing to the stream returned by (TEXTSTREAM Window), where Window is a TEdit window, or redirecting to that stream the output of printing functions like PRIN1. In other words, ordinary stream I/O is the API.

Since ShellCommand accepts a stream as an optional argument, QUERY.FINGER.SERVER passes TEdit's stream to ShellCommand thus causing the output to go to the editor buffer. The benefit is Interpinkie uses the same QUERY.FINGER.SERVER function to output to both the primary output and a TEdit window.

If the destination is a window Interpinkie does some additional processing before and after sending the output. For example, before doing output the program updates the window title to reflect the Finger query, and sets the TEdit buffer to read-only once the output finishes.

These days there are not many Finger servers and I was lucky to stumble upon happynetbox.com. It is managed by Happy Net Box, a nice public Finger server anyone can sign up to for for free and publish a status file. Happy Nex Box was essential for developing and testing Interpinkie, as well as fun — and addictive — as you can see by running the query random@happynetbox.com to look up a random user.

#Interpinkie #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

For Chrismtas 2024 I bought myself a lovely little Cardputer uLisp Machine, an M5Stack Cardputer that can run uLisp.

The M5Stack Cardputer is a card-sized, microcontroller-based portable system for home automation, hobby, and industrial applications. Although not designed for Lisp the Cardputer can run uLisp, an implementation optimized for microcontrollers. This is my unit:

Cardputer uLisp Machine card-sized microcontroller-based computer.

The uLisp system provides a capable Lisp implementation, a rich anvironment, debugging and editing tools, and lots of libraries and examples. It's well maintained and has an active user community.

Motivation

Like many Lispers I always wanted to play with Lisp on the bare metal and the Cardputer uLisp Machine is a simple and inexpensive solution.

uLisp runs on a wide variety of microcontrollers and boards. I picked the ESP32-S3 based Cardputer because it's compact, can run off rechargeable batteries or USB without an external power source, and comes with a graphics display. And at $29.90 it was a no brainer.

Hardware

The Cardputer is a self-contained device with a keyboard, a 240x135 color TFT display, a USB-C port, and a microSD card slot.

Despite the minuscle keyboard, if I hold the Cardputer with both hands I can accurately press any key with my thumbs. However, the keys are very sensitive to pressure and if I hit one with slightly more force than needed I end up repeatedly typing the same character. Entering code and expressions with the built-in keyboard isn't practical for anything longer than a line or two.

The stamp sized display is tiny too but my new eyes help me read the microscopic text on it.

Software

The first thing I did was to install the uLisp firmware to replace the stock system software. The installation procedure is straightforward, took a few minutes, and required only the Arduino IDE which I run on Linux.

There are two main ways of interacting with uLisp. The first is to access the REPL using the Cardputer keyboard and display, the other is to connect from a desktop computer over a USB serial line via the Arduino Serial Monitor or a terminal emulator such as GNU Screen or Minicom. There is also experimental user contributed code for accessing uLisp from Emacs via an inferior Lisp mode or Swank.

A limitation of interacting over USB is that sending code blocks longer than 256 characters overflows the serial buffer, which results in a string of error messages due to the dropped characters.

A workaround is to preceed the code with a comment line starting with a semicolon ; which temporarily turns off echo mode on the device and prevents it from being overwhelmed. Lisp mode on Emacs has no support for the workaround though. So the extra comment line needs to be manually copied from the source buffer and pasted into the inferior REPL along with the code, instead of executing commands such as eval-defun or C-M-x. This introduces friction in the rapid cycles of REPL and editor interactions Lispers are used to.

A showstopper

The limitations of interacting with the Cardputer over serial are just inconveniences that may be fixed by improving existing tools. But a showstopper forces me to set the Cardputer aside until a major Arduino core issue is resolved.

The Cardputer's ESP32-S3 native USB manages the serial port via software and currently has a nasty bug: if the receive buffer fills up too fast the ESP32-S3 will crash and disconnect. I can't do anything practical with the Cardputer without reliably sending medium or large Lisp code blocks to uLisp for evaluation.

The uLisp website does warn about the issue but I incorrectly assumed it affected the Cardputer only when connected to Macs, whereas I use Linux.

Only the Arduino team can fix this issue not caused by uLisp. But since it has been known for a couple of years I’m not holding my breath.

#Cardputer #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

The end of the work on WebCard marked the completion of my RetroChallenge 2024 project, in time as hoped.

I accomplished the initial goal of extending NoteCards to visit websites. This is my Linux desktop after traversing a NoteCards link to a Web card which opened the associated URL in Firefox:

A website opened in Firefox by traversing a Web card link with WebCard.

As the RetroChallenge encourages to do I learned a lot, shared my experience, and had lots of fun with retro stuff.

WebCard is not my first NoteCards project but helped me explore other features of the system, particularly the definition of new types of cards. Most of the work on WebCard involved researching the NoteCards API and writing code.

Once I understood the relevant API calls, implementing the planned features took relatively little code. NoteCards comes with an extensive, well designed and documented API that enables to add a lot of functionality by mostly plugging into the public hooks.

The NoteCards manual has nearly all the information I needed. However, to understand some features or subtle points of the API I had to study some of the NoteCards code, particularly the source that defines the File card type because of the similarities with what WebCard does. Some throwaway code and experimentation with the interactive Lisp environment plugged the last information gaps.

The project generated a flow of material for my blog and Mastodon profile. I posted frequent short updates on Mastodon and longer reports on the blog. This drained time and focus too.

The main takeaway of the project is that Medley Interlisp is a rich toolbox with which new programs can be developed by combining other programs as building blocks. NoteCards itself builds upon the TEdit text editor, the Sketch line drawaing program, the File Browser, and other tools.

As my first RetroChallenge I was lucky to complete the project. I set a goal reasonably achievable in one month but the actual work faced some unexpected detours that didn't impact the deadline.

What else to say? Mission accomplished.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

To complete WebCard for my RetroChallenge 2024 project I created a demo notefile, a file that stores the data of a NoteCards hypertext.

The notefile WCDEMO.NOTEFILE contains exmples of Web cards filed into various types of containers and cards such as fileboxes and Text cards. It provides some ready made Web cards for exploring WebCard.

This screenshot shows the main cards of the demo notefile:

The cards of a WebCard notefile open in NoteCards.

The link icons with the globe bitmap at the left of the outlined text are links to Web cards. Clicking such a link in NoteCards opens the associated URL in a web browser, which is the main feature of WebCard.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

With the last feature of WebCard behind me I proceeded with the next task to wrap up my RetroChallenge 2024 project: documenting the system.

Since WebCard enhances NoteCards with only a few simple but significant features a full manual would be overkill. So I added to the README file of the project repo some new sections on the requirements and dependencies, the installation, and the usage of WebCard.

The documentation assumes familiarity with NoteCards and Medley Interlisp, large systems in themselves, and describes only what WebCard adds to NoteCards. It explains how to create and manage Web cards and traverse links to them.

In addition the README file now has a screenshot that shows a website opened by WebCard in NoteCards.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space