Paolo Amoroso's Journal

Tech projects, hobby programming, and geeky thoughts of Paolo Amoroso

I fixed a URL validation bug of WebCard I have been stuck with for almost a week.

When creating a new card, the function WCD.AskURL brings up a dialog and loops prompting for a URL to go with the card until the input is valid. After the fix the input dialog looks like this, here shown above a new blank card. I entered https, the dialog warned it's not a valid URL, and then I typed a correct one.

URL input dialog of WebCard.when creating a new Web card.

WCD.AskURL initially checked only for a null input. I later wrote WCD.ValidURLP to check that the input resembles a URL.

In an attempt to call WCD.ValidURLP from the WCD.AskURL input loop I bumped into a syntax error in the bind clause of an Interlisp iterative statement. The issue eluded me when staring at the code for long. Then the problem suddenly jumped at me: a missing symbol.

The bug is now fixed for good and I can move on.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@fosstodon.org

The text of WebCard cards is intended to be read only but my previous attempt to achieve it by overriding card editing didn't work. I implemented a new, simpler approach that actually works.

The card type Web inherits from the Text type whose “substance” is a text stream associated with the TEdit editor embedded in Text cards. In NoteCards a substance is a data structure that contains the information in the card.

The trick of the new approach is to just make the text stream of the card read only.

An additional complication is that the read only state is a runtime property of open streams not preserved in saved notefiles. Therefore, if in a new session you load a notefile, any previously read only cards it stores will no longer be so. To catch this WebCard now intercepts the first access to an unopened Web card, which occurs when clicking a link icon to the card. I modified WCD.TraverseWebLink to set the text to read only.

If the user clicks the text area of a Web card and starts typing, a dialog informs that the text is read only. The Close option of the right-click menu dismisses the dialog.

A number of WebCard functions display the URL of a Web card in its text area. Since the code for inserting the text and handling the modification state was scattered and partially duplicated in various places, I factored it out into the new function WCD.UpdateCardText. It sets the card text to read-write, clears the existing text, inserts the new text, and makes the text read only again.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@fosstodon.org

A URL is associated with a WebCard card of type Web at creation time but it may later be necessary to change or take action on the URL. For example, to correct a typo or visit the URL again if its web browser tab was closed since an earlier visit.

For such situations I added the items Visit URL and Edit URL to the title bar menu of Web cards. This is the menu:

A WebCard card of type Web with its left-click title bar menu.

The card holds the URL shown in the text area. Left-clicking on the title bar brings up the menu with the new items Visit URL and Edit URL at the top.

The NoteCards API function NCP.AddTitleBarMenuItemsToType adds items to the menu of a specified card type. It's easy to use but it wasn't clear to me what arguments the item callback functions are supposed to take. Some experimentation with throwaway code revealed the system passes only one argument to callbacks, a window.

To prepare for the new functionality I factored out the initialization of the Web card type into the function WCD.InitWebCard that also calls NCP.AddTitleBarMenuItemsToType.

Functions WCD.VisitURLMenuCmd and WCD.EditURLMenuCmd carry out the actual menu actions and are straightfoward. In addition to updating the URL property of the card, WCD.EditURLMenuCmd substitutes the new URL for the old in the text area.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@fosstodon.org

The WebCard project is moving forward again. My latest work involved card initialization and URL visiting.

When a new Web card is created, the associated URL is now inserted as text in the content area of the card. This is useful documentation and prevents the potential confusion of a blank card.

Speaking of card initialization, the WCD.AskURL function that prompts for a URL initially prefilled the input buffer with https:// to spare some typing. But testing revealed an unexpected behavior of NCP.AskUser, the NoteCards API function URL prompting is built upon.

As soon as the user starts typing, NCP.AskUser deletes the prefix https://, whereas I assumed the new text would be appended to https://. To avoid the confusion WCD.AskURL no longer prefills the input buffer unless the function is called with an optional prefix. Even if deleted when the user types, the current URL will serve as an initial reminder when editing a card URL.

Finally, I factored out the code that visits a URL into its own function WCD.VisitURL since I'll eventually revise the feature and call it in other contexts.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@fosstodon.org

This is the year of my Linux desktop.

Three months ago today I moved back to Linux for good after almost a decade with ChromeOS. That day I installed Linux Mint Cinnamon on a freshly delivered System76 Merkaat.

I was growing increasingly dissatisfied with ChromeOS and bumping into the restricted confines of its Crostini Linux container more and more. The last straw was the rumor of Google considering a Recall-like feature for ChromeOS. I didn't like Chromebook Plus fragmenting the platform by delivering exclusive features only to premium users, either.

I put together my requirements for a Linux PC and distro and finally went with the System76 Merkaat and Mint.

Prior to the switch to ChromeOS I had been using Linux for almost two decades and coming back to Linux felt incredibly good. But I was still unsure and concerned about the hardware compatibility and stability of Linux.

Mint immedially dispelled my compatibility concerns as it fully supports every single hardware feature of the Merkaat and the connected peripherals. Nearly no software configuration is required, and the little that is is as simple as installing a couple of packages with the system's package manager.

As for stability, an incorrectly flashed USB boot stick caused some Linux installation glitches. A borked upgrade from Mint 21.3 to 22 forced a full instsllation of Mint 22. And I managed to lock myself out of my account, forcing another full reinstall.

The bottom line is I practiced enough emergency reinstalls I now have the experience to complete the full process in under three hours.

Despite the initial setbacks and annoyances, some of which due to my rustiness with Linux, it has been smooth sailing over the past three months. And the flawless software updates grew my confidence in Linux and my setup.

#Linux #ChromeOS

Discuss... Email | Reply @amoroso@fosstodon.org

I started working on URL validation in WebCard and soon bumped into a bug.

When creating a new Web card, WebCard prompts for a URL to store in the card. I wrote the predicate WCD.ValidURLP to do some minimal validation and make sure the input resembles a URL. For example, the function checks whether the input starts with https://, http://, or mailto:. Although I don't want to write a URL parser I ended up adding more logic than anticipated.

I could skip URL validation altogether and defer error cheking and reporting to the web browser. Or allow URLs with no URL scheme such as interlisp.org that a browser can handle. But it's probably better to have full URLs as a form of card documentation.

Next I tried calling WCD.ValidURLP from WCD.AskURL, the function that prompts for a URL in a loop until the input is valid. An Interlisp iterative statement with a bind clause controls the loop.

But I'm getting syntax errors for bind in the statement. I checked the documentation, read sample code, and tested a few variations.

I'm still struggling with this.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@fosstodon.org

I wrote some throwaway code to experiment with editing cards of type Web in WebCard, my RetroChallenge 2024 project. The goal is to make the card read only with the least amount of effort.

In a NoteCards hypertext a Web card is a stand-in for a website, a placeholder for a URL that gets visited when links leading to the card are clicked. The Web card type inherits from the Text type but, since the user isn't supposed to enter text into a Web card, the card should be read only.

An approach I tried is to override the card editing operation for the Web type. The overridden function was a no-op that did nothing and immediately returned, as I thought not calling the TEdit editor would prevent text from being entered or modified.

It turned out the function worked even too well and did nothing at all, really. Like, not even opening or displaying the card.

Back to the drawing board.

A more substantial function would involve additional complexity to interact with TEdit, which would do nothing anyway. An easier approach is to make the content of a Web card read only in the constructor as soon as it's created.

I'm actually also considering to drop the read only requirement and allow editing the content of Web cards. It could be handy to enter a description or note about the website.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@fosstodon.org

Success!

My WebCard prototype made NoteCards visit a site on the World-Wide Web for the first time. Think of it as a wormhole that connects the old world of hypertext with the new world of the modern web. WebCard, a NoteCards extension for visiting websites, is my RetroChallenge 2024 project.

This is my Linux desktop just after NoteCards visited a website for the very first time:

NoteCards and the Firefox window of the first website visited by NoteCards via WebCard.

The Table of Contents window near the bottom left of the screen is a filebox of a NoteCards hypertext. Under “NOTE CARDS” the filebox container card lists a link icon, a clickable area that leads to the indicated card “Medley Interlisp Project”. This card of type Web inherits from the type Text and holds a URL to visit.

When I clicked on “Medley Interlisp Project”, WebCard opened the corresponding card — blank in the screenshot — next to the Table of Contents. Then WebCard commanded Firefox to visit the URL https://interlisp.org stored in the card. The window of Firefox, already running, came to the foreground and displayed the website in a new tab.

This milestone comes after fixing a bug in the Web card constructor. To put my core idea to the test I deferred some non essential refinements and went straight for the website visiting functionality.

How does the functionality work? The NoteCards API provides a hook to override the operation of traversing links to specific types of card. To this effect WebCard sets an alternate function as the value of the LinkIconLeftButtonFn property of the symbol Web that names the type. NoteCards calls the alternate function when a clicked link has a Web card as the destination.

WebCard's alternate function is WCD.TraverseWebLink. It fetches the URL from a card, displays the card, and opens the URL in the system browser.

The screenshot shows both the Web card, next to the Table of Contents, and the code of WCD.TraverseWebLink in the Lisp editor at the top center. The comment, however, is out of date after fixing a series of issues.

What went wrong? A combination of misunderstandings and incomplete information made WebCard generate argument type errors, as I wasn't sure about the arguments of WCD.TraverseWebLink. On top of this, I called the internal function NC.TraverseLink that implements the default link traversal but I ended up not needing anyway.

Reading the sources of a few NoteCards functions cleared all doubts. To fix the issues I updated the code of WCD.TraverseWebLink but not the comment as I was eager for a test run.

The WebCard prototype is crude, but it works and validats my strategy of overriding the link traversal behavior.

An alternative I initially considered is to advise the NoteCards API functions for opening and displaying cards. However, unlike overriding link traversal which the API fully supports, advising is a fragile kludge that works around the API.

Now that the core feature of WebCard is in place I can continue the development.

WebCard is far from complete. There's still work to do to override editing Web cards, extend Web card construction, deal with input validation and error handling, check for visited URLs, and customize the bitmap of Web link icons. WebCard needs documentation and demo notefiles too.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@fosstodon.org

I fixed a bug in the initial code of WebCard, my RetroChallenge 2024 project.

An infinite loop in the constructor of the Web card type caused a stack overflow that aborted Medley. The Web constructor was supposed to call the constructor of the parent card type Text. But I misunderstood the NoteCards API and used NCP.CardTypeFn which ended up calling the Web constructor itself, hence the infinite loop.

The fix was easy: call the supertype's constructor with NCP.ApplySuperTypeFn. Troubleshooting the issue was a great learning experience.

With the bug out of the way I fleshed out a bit more of the Web card constructor. I wrote code to query the user for a URL and store it in the property list of the card. This gives persistence for free as NoteCards automatically stores properties to and retrieves them from notefiles.

There's still some card initialization to do in the case the constructor is passed the option to not display the card, but I'll leave it for later.

In my initial plan the constructor would query the user also for an optional card title but I dropped the idea. NoteCards already allows adding and editing card titles, so forcing this from the constructor seems redundant and possibly confusing. Like NoteCards, by default WebCard names new cards Untitled.

Reporting my progress and plans to the Medley Interlisp team sparked an interesting conversation on rapid prototyping in Interlisp and the Lisp development style. For example, I learned the Interlisp advising functionality was designed as a prototyping tool.

I'm not yet sure what to work next, whether to handle card editing or go straight for the website visiting functionality. The latter is the only missing piece of an early prototype.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@fosstodon.org

The initial Interlisp code of WebCard, my RetroChallenge 2024 project, defines the new type “Web” of NoteCards card. It's the first step for extending NoteCards to visit websites.

The main code is in the function WCD.CreateWebCardType, a thin wrapper around the NoteCards API function NCP.CreateCardType. The former passes to the latter the name of the new type Web, the name of the type Text it inherits from, an alist of functions that implement the overridden card operations, and an alist of customization parameters.

So far the only operation the Web type overrides is card creation via the constructor WCD.MakeWebCard. The function crashes Medley and ends the session but I left it there as I wanted to have something in place.

Although the initial code is little more than a stub, it's an important foundation the rest of WebCard will flesh out or build upon.

Next, I need to figure out why WCD.MakeWebCard crashes. Aside from removing a roadblock, the troubleshooting will provide insight into how card creation works.

The code is available at the project repo. WebCard function names and symbols start with the WCD. prefix as a form of limited namespace isolation as Interlisp has nod direct support for packages.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@fosstodon.org

Enter your email to subscribe to updates.