begin

begin


[ Note: fare well. No one makes it out of life alive. ]

Estimated date of website non-existence:
2022 autumnal equinox

[ Roof and utilities remain available
 as autopay from prior owner
 after stage 4,
 and perhaps kindness or tolerance
 from realtors thereafter,
 as for two and a half years
 residentially
 I seem forgotten.

 In a deserted house with no name
 there is only nostalgia
 as distraction.
 As neither a pet nor of gossip,
 nor being a book or furniture
 for anyone,
 there need be no name
 for what remains,
 freed from all.

 Updates beyond
 2021 July 29
 are unlikely,
 as personal funds for food
 deplete definitively.

 One or two days beyond that
 I might wait before leaving
 to rid my body
 from this place,
 but sooner rather than later
 lest it rots and ruins
 unnecessarily.

 All the lines have been drawn,
 there is no place on Earth
 to lay down and starve
 without offense,
 so I will likely fail
 to rid myself
 properly. ]

Some considerations to have in mind.

Last words...
(or intended as such)




No one need be a book author to write a grocery list, nor be a computer programmer to write a computer instruction. Potentially, no one needs any computer programming skills for personalizing beyond computer programs. Though, notes help with gaining familiarity.

Generally, information is telegraphed amongst the components inside a computer, and to other computers. Pulses of significant amounts of electricity and insignificant amounts are the dashes and dots of machine code flowing circuitously.

Similar to a calculator, a computer accepts instructions for managing numbers and words. In essence, memory management akin to a notepad of paper. Without memory, it would be a basic tool, at most a machine.

There are simply two sets of instructions for a computer:

All interactions with a computer comprise those two purposes: now and later. The memory might be for the screen displaying drawings of text. It might be on another computer.

The promotion of literacy encourages sharing knowledge by writing and reading. Personal memory management and communication become possible with the ubiquitous skill of writing when the commodity software permits the buttonboard to function (Interactive curiosity: typing for actions and help).

Most commodity computers barricade their labeled buttonboards behind an unlabeled motionbox that must be repetitiously lifted, clunked, and slid with gymnastic precision. The computer instructions are what the software developers had time to offer, likely without documentation, and hidden within a cavernous maze of non-personalizable menus.

Jumping through hoops or over hurdles provides a false sense of accomplishment, a façade of freedom after the labyrinthine escape. Ideally, writing in the computer medium would be without an obstacle course entrance, as immediate as writing on paper.

A "personalizable computer" (...no need to change the world) is extensible beyond its default set of computer instructions and buttons. A person adapts the computer to fit within the current flow of events (Flow of the moment), such as re-assigning buttons or constructing a basic computer instruction (instead of computer programming).

The experience of pursuing personal interests is the core of personal disciplines, but is perceived externally or by self-reflection as freedom. That is, the perception of freedom is a side-effect from taking on the responsibility of following through with personal interests.

Opportunity is sometimes mistaken as freedom, as is the lack of molestation or lack of expectation from other people. Like the fantasies of security and privacy, freedom is never taken away because it is only a perception. At most, the daydream of freedom disperses when personal pursuits are disrupted.

Unique text editing software often produce unique file types, which make the documents eventually inaccessible when the software is inevitably abandoned by its company. Only plain text documents (Notetaking with the computer medium) are accessible with any computer, old or new, commodity or personalized.

Plain text documents are so versatile that all operating systems and programs are always made from them, although sometimes only their illegible conversion to machine code are ever shared.

Computer networking bridges the gap between discrete computers and their incompatible operating systems (Dual system approach...), a compatible means of transfering plain text files for reading and editing anywhere.

# notetaking with the computer medium

Paper is one of the best mediums for recording notes. Notes on a sheet of paper can be read by someone else without the need for that person to have a pad of paper.

Notes recorded in the computer medium are undeniably less accessible and less sharable. Computer documents require a computer for reading them, and the computer requires electricity.

A buttonboard with a button for each letter of the alphabet aids in writing legibly and quickly on a computer. However, the casual markings of underlining or thicker lines of text written on paper is typically beyond the limited set of symbols of a buttonboard.

Prose often has parentheses "( )" and square brackets "[ ]" distinguishing supplemental information, or quote marks specifying exact wording. Similarly, the uncommon angle brackets "< >" enclose a name for the kind of mark before its region of typed text.

# the motivation for markup

Whatever is typed is "plain text" when it is compatible with any operating system of any computer, from the past to the present and into the future. No need for converting a document that has plain text markup.

Spacing before and after paragraphs, thicker lines of text, and larger text for headings help demarcate and emphasize ideas. Some text editor programs merge that formatting with the prose in a way that is illegible and uneditable with any other text editor, thereby is no longer plain text.

Instead, consider two approaches: the primary view optimized for editing the text, and a temporary alternate view optimized for perusing. That is, when editing consider marking it when helpful for an alternate read-only view of the document.

Enclose the name of a mark within angle brackets "< >", whereby it is unmistakably distinguishable from the prose while ensuring compatibility as plain text. The alternate read-only view of a document is provided by a program hiding each mark while also modifying the appearance of the following text based on the name of the mark, without modifying the document itself.

Extra software for the alternate view is optional. Reading and editing personal or shared notes remains possible with any text editor on any computer, old or new, commodity or personalized.

# writing and marking plainly

The uncommon angle brackets < and > enclose a name for the kind of mark before its region of text. For example, thicker lines of text is known as "bold" text, therefore the mark is <b>. The region ends similarly with a forward slash "/" in the mark, f.e. </b>.

In other words, a region of text marked at its beginning with <b> would have </b> at its ending. Mnemonically, the "/" then "b" means "end b".

Normally drawn text with <b>this text to be drawn with thicker lines</b> and normally drawn text after it.

Sometimes the ending of a region is obvious by a mark beginning a new region after it, f.e. a paragraph after a paragraph, thereby the ending mark is conveniently optional.

<p>A paragraph of text that is followed by another paragraph.
<p>The previous paragraph obviously ends when this paragraph begins. This one has an ending mark, though it might be unnecessary.</p>

# using HTML for document sources

Hypertext markup language (HTML) is a system of named marks for typed regions of text. The marks evoke imagination of how the text would be drawn or spaced on paper, thereby promoting association and understanding of the content without an alternate view. The alternate view of an HTML document hides each mark and then applies its implied characteristics to its region of text.

For example, notes about some other document will often have the name of that other document for later reference. For computer documents, this more reliably also includes the filename of the document and its location.

The HTML mark for an address is <a> and is supplemented with the href attribute for the "hyperlink reference".

A hyperlink address region of text is underlined and becomes a trigger for viewing its specified document. That makes the alternate view more concise with document addresses, and enhances access to referenced documents.

# organizing and sharing files

A filesystem is a record of locations for documents (files) in a storage device. It tends to also be a source of the modification date and file size, but usually no special feature for comments or descriptions for files.

Commodity operating systems provide their own options for writing descriptions for a file, but those notes are inaccessible with other operating systems. The obvious compatible approach, regardless of operating system or type of filesystem, is consolidating personal descriptions of multiple files into a new document (file).

A document marked with HTML is plain text, therefore always accessible regardless of what computer. Type or copy/paste the document name and optionally mark it as a hyperlink address, perhaps followed by a description. Maybe mark each as a paragraph <p>, or grouped into distinct lists preceded by headings.

In this way, the reason for having each document or image is available, rather than opening each and every document with many different applications and trying to remember later. Documents without descriptions, reasons, or relations to other documents become prime candidates for removal in order to reduce clutter.

Include a framed view of either an HTML document or an image by referencing its source address in the src attribute of an internal frame <iframe>. The view of the document or image is scrollable when larger than the internal frame, which also can have width and height attributes (pixel values).

<iframe src="some-other-document.html"></iframe>
<iframe src="can-be-an-image.jpg" width="400" height="300">
This region is shown instead of the document only when a HTML viewer has no support for the iframe mark.
</iframe>

Or, add an image with the <img> mark and optionally scale it with width or height attributes (pixel values). There is no end mark for it.

<img src="an-image.jpg">
<img src="another.jpg" width="500" height="375">

Perhaps establish a tiled layout (split view) for previewing a set of documents with each at 50% width [need style attribute for non-pixel values], t.i. one pair at a time. Note that 50% + the width of one space character + 50% = more than 100%, so ensure there is no space between the end of one mark and beginning of the next.

<iframe
src="doc-1.html" style="width:50%;height:30em;border-width:0">
</iframe><iframe
src="doc-1_backup.html" style="width:50%;height:30em;border-width:0">
</iframe>
<iframe
src="doc-2.html" style="width:50%;height:30em;border-width:0">
</iframe><iframe
src="doc-3.html" style="width:50%;height:30em;border-width:0">
</iframe>

No matter what operating system, even from before the turn of the century, every computer comes with a simple text editor for editing plain text and an HTML viewer (a.k.a. web browser). Thereby, the document can be viewed in any web browser on any computer, and without need for a webserver or even an internet connection.

No special programs necessary, no extra cost, and HTML is as plain as the buttons on a buttonboard.

# essential HTML

The "language" in HyperText Markup Language (HTML) means it is a system or set of keywords. There is no communication by the means of HTML.

HTML marks are guidance for a temporary read-only view of a document. Sort of like proofreader marks, with a name consistently encapsulated within < and >. Sometimes after the name there is more describing the characteristics of the mark itself, before the >.

The angle brackets "< >" make the occasional HTML mark unmistakably distinguished from the prose, just like parentheses or square brackets. They are often readily available on the comma and period buttons of the buttonboard.

Any text can be placed in between < and >. Just type whatever. Programs providing a read-only view of a document with HTML marks generally ignore any unknown named marks and never show them.

The ".html" at the end of the filename for a document is typically the only (artificial) requirement made by the operating system and its applications. All HTML marks are optional, as such a document declared to be HTML can be just prose without any marks.

Links are "hyper" because the text is marked with an address for a location within the document or to another document. In other words, a link is an option to view some other part of the document or to view another document. A hyperlink is traditionally underlined by HTML viewers.

Mark a location in a document with an address mark and the id attribute. No need for anything within its region, merely type the marks before something interesting, like before a heading.

Mark text as hypertext with a reference href in an address mark <a href=""> before the text, then follow the text with the </a> ending mark.

In essence, making a note about another document typically involves typing the title of the document, and typing the address of where to find it. In other words, that is the act of referencing a source. A hypertext link is the same thing, with just a few more characters to type. The same information is recorded, and it will be a link in the read-only HTML view.

Include a framed view of either an HTML document or an image by referencing its address in an internal frame <iframe>. The view of the document or image is scrollable when larger than the internal frame, which also can have width and height attributes.

<iframe src="some-other-document.html"></iframe>

<iframe src="can-be-an-image.jpg" width="400" height="300"> This region is shown instead of the document only when a HTML viewer has no support for an iframe. </iframe>

Specifically add an image with the <img> mark and reference its source with the src attribute. There is no end mark for it. Optionally scale the image with its width or height attributes.

<img src="an-image.jpg">

<img src="another.jpg" width="500" height="375">

The same document or image can be referenced multiple times. That can be convenient for comparing side by side [perhaps each at 50% of the view width] one original version with many other versions, pairing a reference to the original version with each of the other versions.

Change the default characteristics of any mark with the style attribute for it. A colon associates a characteristic with its value, and a semicolon separates characteristics. Optionally use spaces around the colon or semicolon for clarity.

For example, set the width of a paragraph and center it horizontally.

<p
style="
background-color: black
;color: beige
;text-align: right
;width: 50%
;padding-top: 1em
;padding-right: .5em
;border-top-color: fuchsia
;border-top-style: dashed
;border-top-width: 10px
;border-right-style: solid
;border-right-width: .25in
;border-bottom-color: teal
;border-bottom-style: double
;border-bottom-width: 3mm
;/* Using automatic margins
centers the region. */
margin-top: 2em
;margin-left: auto
;margin-right: auto
">For example, set the width of a paragraph and center it horizontally.

# Dual-system approach for discrete computer experiences

Be wary about putting all of the eggs in the same basket. Discrete purposes with their own resources stay separate, thereby one is affected by its own needs or demise without draining other resources or damaging anything else.

In other words, rather than a large amount in one container, consider smaller amounts in multiple containers. Dedicating resources sparingly minimizes corruption or loss, while freeing remaining resources for additional or simultaneous endeavors.

Everybody wants to rule the world, for the sake of personal comfort. It is possible to let everything remain as it has come to be, and move forward without bearing the wait of it all following along.

# Discrete operating systems: no dual-boot, no multi-boot

Distinct from a dual-system, "dual-boot" or "multi-boot" are singular systems, each a setup for multiple losses. Those are approaches for having more than one operating system on the same storage device. The operating system is chosen by the person starting the computer.

An operating system needs its own memory storage separate from other operating systems, because "operating" means automated programs are doing whatever without being monitored. They can readily corrupt anything on the remainder of the storage device.

For example, there has been one operating system (for a "hardware inegrated with software" system) that replaces the partitions and filesystems of the whole storage device with its new and improved version of partitions and filesystems.

Unfortunately, any prior version of that same operating system on the same storage device is unable to properly recognize it anymore. That means the prior versions are prone to corrupting that storage device and the new operating system on it might become unusable, too. Reliability comes from discrete use, rather than shared.

# Discrete storage devices: no internal computer memory

Replaceable modular units provide the means for restoration and extensibility. Simply plug and unplug for instant modifications.

Ideally, the operating system is always kept on external storage, never permanently inside a personalizable computer. The computer can be started by attaching any operating system compatible with its hardware. Keep a backup on a second external storage device, then that can be used to start the computer when the primary fails.

                                    ..........
    __________     ......           |   OS   |
   |          |----| OS |           | backup |
   |          |    ``````           ``````````
   | computer |    .............    ..........
   |          |----| documents |    |  docs  |
   |__________|    `````````````    | backup |
         |                          ``````````
   ......|.....                     ............
   | programs |                     | programs |
   ````````````                     |  backup  |
                                    ````````````
                                    ..............
                                    | spare for  |
                                    | trying out |
                                    | new OS or  |
                                    | programs   |
                                    ``````````````

Personal documents are always kept separate from the operating system, ideally on a separate storage device. Documents can be plugged into any computer. No need to turn on the computer, and documents are never trapped inside a computer that fails to start.

Personal documents on separate storage are easily taken to a computer located beyond a local electrical power outage, f.e. to a nearby computer that uses a battery.

One computer with two memory storage devices for an operating (or operatable) system, primary and backup. Two more storage devices for personal documents, primary and backup. Perhaps another set of storage devices for additional software.

The amount of memory per storage device can be minimized for each purpose, no need for terabtyes in one device. Operating systems tend to use only a few gigabytes, but some operating systems are only a few megabytes, f.e. TinyCore and piCore.

# Discrete instability: never update, never upgrade

Never update nor upgrade an operating system, nor any software application. Instead, install the next version on a separate storage device, and try it out discretely without losing the currently working version.

Creating a new instance fits with one of the core principles of computing: make and work on a copy.

The memory devices need only as much memory as required for that particular purpose, no need for terabytes. Separate memory devices for trial of updates or upgrades can be re-used for that specific purpose, discretely from personal documents and discretely from stable software.

Reliably customizing a computer requires using some other stable computer. That is, a primary computer is used to setup a secondary computer. Once the secondary computer has its new modifications stabilized, then the secondary computer is eligible as a replacement for the primary computer.

    __________     ........      ___________     ........
   |          |----| OS 1 |     |           |----| OS 2 |
   | primary  |    ````````     | secondary |    ````````
   | computer |    ........     | computer  |
   |          |----| docs |     |___________|
   |__________|    ````````

Adding another computer requires only enough (external) memory storage for an operating system compatible with its hardware. Eventually, two such memory devices: primary and backup.

Once again, very small amounts of memory rather than large amounts. Gigabytes or megabytes (or even less), instead of terabytes, allows for sensible and affordable personalization of computers. Separate memory provides stabilty.

A physical computer tends to have small amounts of special memory (firmware) for itself on its circuitboard. The manufacturers usually never reveal how to customize that memory, but usually provide mysterious updates or upgrades for it, potentially removing features or causing corruption.

That is why it is important to have a second computer (hardware) for customizing, isolating the aforementioned possible corruption of its circuitboard memory (firmware) by operating systems or their updates.

By using a primary system to customize a secondary system, whatever happens to the secondary system (software or physical) can be assessed from the primary system. Furthermore, some tasks can be offloaded to the secondary computer (when it is stable enough) rather than stressing or slowing the priorities of the primary computer.

# A personalizable computer: no need to change the world

Almost any computer can be repurposed as a personalizable computer, just as long as the operating (or operatable) system needed for personalization can be installed on it.

Explicitly, a computer that has its operating system integrated with its hardware is less likely to be repurposable. Begging the manufacturer is unlikely to work, so be aware of that about integrated computer systems or unique hardware.

Personalize a computer by customizing the commands invoked with the buttonboard, f.e. rebinding keys (Customize the buttonboard). Or, enable the computer with special software to repeat any sequence of actions, a peculiarly uncommon ability of commodity computers.

Use a program for enabling the personalizable computer as a VNC "client" or RDP "client" in order to control any other non-customizable computer. Many operating systems already have VNC "host" or RDP "host" capabilities, so it is only a matter of having that feature activated on the other computer.

                           <-- video
               .:::::::::::::::::::.
    ________   ::  button         ::   ________
   |        |  ::  presses -->    ::  |        |
   |        |  ::                 ::  |        |
   |        |:::/                 \:::|        |
   |________|                         |________|
    | /__\                               /__\
    |
    |..............
    | buttonboard |
    ```````````````
    personalizable                 non-personalizable
    computer as                    computer as
    VNC or RDP "client"            VNC or RDP "host"

There is no need to replace the operating systems of all other computers on the planet. There is no need for a computer program to work on all operating systems. Simply connect with remote control software to the other computer, even on the same desk.

In other words, there is no need for a personalizable computer to have the fastest processor or lots of RAM (temporary memory) or recent hardware. It needs only just enough to personalize it, and to use the VNC "client" or RDP "client" computer program. Anything more is gravy.

# Lisp

[ ...describe some day...or contract the separation... ]

# Lisp lists are pairs

As a single item has no associates, a list of items conceptually begins when an item is paired with another (Dotted-pair notation). Written horizontally, one item is the left half and one item is the right half (Dexter and abdexter).

No need for first then last. Instead, access either half immediately (Reference a half).

Name memory for a list with setf, then re-set that memory with a pairing of another item with that list. Each item in a list is referenceable, therefore it is also a list of references (Re-listing rather than re-arranging).

Consistently pairing a new item right of a list forms a stream of half-pairs rightwardly, or when left of a list forms a stream of half-pairs leftwardly (Consistently half-paired lists).

A Lisp instruction is a list. Piece together an instruction, either forwards or backwards or inside-out (Contrary formation and Lisp instructions).

# Dotted-pair notation

For Lisp, a list is constructed parenthetically one pair at a time, and notated with a space-separated-dot, t.i. a period with spacing before and after. The spacing is important because numbers can have decimal points, and Common Lisp allows a period as a character in the name of a symbol (CLHS 22.1.3.5 examples).

   ("A message for later." . a-lisp-symbol)

   (one.symbol . 3.141592)

However, a parenthesis has no actual need for spacing on either side of it, neither "(" nor ")".

   ((((1 . 2). 3). 4). 5)

   (5 .(4 .(3 .(2 . 1))))

# Dexter and abdexter

The cons function constructs a new list by pairing the two Lisp forms it is given, perhaps quoted (An intro for Lisp).

   (cons (quote left) 'right)
     ->  (left . right)

In essence, a list is itself a single item. Therefore, lists are constructed further by pairing the next item with a prior list. As a left or right half, an item is readily referenced by its position within a sub-list, t.i. from inside to outside.

   (left . right)

   (L . R)

   ((LL . RL) . R)

   (L . (LR . RR))

   ((LL . RL) . (LR . RR))

For example, "the left half of the right half" references the left item of a sub-list, and that sub-list is the right half of another list. That describes the position (which side of the dot) from the inside list to the outside list, with this example succintly described as the "LR".

However, multiple "l" and "r" sounds smoothly slur together ambiguously when spoken. Another term for the right side is the dexter, or adjectively as "dextral" for the dextral half. Traditionally, left of dexter is "sinister", perhaps fitting with the Scheme dialect of Lisp.

The aspiration of the "s" contrasts distinctly with the explosive "d", even for a lengthy series spoken quickly or slurred. Their blending potentially invokes a lisp when spoken quickly enough, thus giving an onomatopoeia characteristic to Lisp discussions.

Alternatively, abdexter also applies as an alternate to dexter. The "ab" prefix means "away from", f.e. abduct contrasted with adduct.

The vowel "a" of abdexter (left) pronounced with a glottal stop of the throat contrasts with the dental consonant "d" of dexter (right) at the front of the mouth. A vowel other than "a" can be chosen for supporting the consistent pronunciation of the "d" itself, regardless of personal dialect or length of series.

Therefore, "abdexter" and "dexter" provide sequences of sub-lists succinctly written and clearly spoken with either one letter or one syllable per sub-list. The written letters contrast with each other, with numbers, and with symbols on the buttonboard, either when lowercase "ad" or when uppercase "AD" or when mixed "cADr".

   (abdexter . dexter)

   (a . d)

   ((aa . da) d)

   (a . (ad . dd))

   ((aa . da) . (ad . dd))

From inside to outside, "the left half of the right half" is the same as "the abdexter of the dexter", or the "ad" which is pronounced individually as "a-d". Visually, it is the item left of its dot within the sub-list right of its own dot.

Though a sequence of references is from inside to outside, it is readily understood from outside to inside by reading it reversely. Therefore, the prior example of "ad" also refers to the dexter (right half) of the outer list and then the abdexter (left half) of the sub-list. Dexter remains dexter, and abdexter remains abdexter, so it is the same follow-the-dot approach either way.

# Reference a half: cdr and car

For the pair of items in a list, call for its dexter reference with the cdr function, and call for its abdexter reference with the car function (An intro for Lisp).

   (cdr '(a . d))
     ->  D

   (car '(a . d))
     ->  A

Chaining multiple references accesses a list initially from its outside then gradually towards its inside.

       (car (car '((aa . da) . d)))
   ==  (car '(aa . da))
         ->  AA

       (cdr (car '((aa . da) . d)))
   ==  (cdr '(aa . da))
         ->  DA

Multiple car and cdr references can be consolidated by functions named with the concise sequences. Common Lisp provides functions for up to four places, f.e. cddddr. It is a bit like simply removing the "r(c" of consecutive functions, and their corresponding ")".

       (car(cdr '((aa . da) . (ad . dd))))
   ==  (cadr '((aa . da) . (ad . dd)))

The resulting inside-out sequence of references from the abdextrally half-paired Lisp instructions is least to greatest. This is in contrast to the greatest to least approach with digits in numbers (Pairs of pairs accessed sequentially).

# Re-listing rather than re-arranging


[ ...need to revise...
...trying to get across the notion of referencing memory
 and clarify how to ensure duplication when desired...

...referring to something in memory actually means
 referring to the memory itself...

...changing what is in the memory means
 whatever referred to the memory
 also refers to whatever happened to the memory...

...working on a copy
 requires duplicating what is in memory
 rather than referencing the memory...

...named memory is a reference to memory...
...car and cdr reference memory...

...inserting text into a prompt is new or duplicated...

...using format results in double-quoted text...
...using read-from-string results in a Lisp form...
...combining both results in a duplication of named memory...

... ]

Realize the difference between a list of items and the items themselves, for it is the same difference between a grocery list and the groceries themselves. Similarly, the cdr and car references are the positions in a list rather than the items.

The cons constructs a new list. The setf (An intro for Lisp) replaces a reference at a position in a list with another rather than modifying the content. List items are never moved, neither within a list nor from one list to another.

The Lisp interpreter uses the items, and also conveniently prints a copy of the actual items rather than the memory locations. However, that obscures whether a placeholder name has the original or only a reference.

Consider preventing ambiguity by naming a placeholder with intent when using setf.

   (setf list.1 '(one two three four))
     ->  (ONE TWO THREE FOUR)
   (setf part.1 (cdr list.1))
     ->  (TWO THREE FOUR)
   (setf part.1.ref (cdr list.1))
     ->  (TWO THREE FOUR)

   (cadr list.1)
     ->  TWO
   (setf (cadr list.1) 'five)
     ->  FIVE

   (cadr part.1)
     ->  THREE
   (setf (cadr part.1) 'six)
     ->  SIX

   (caddr part.1.ref)
     ->  FOUR
   (setf (caddr part.1.ref) 'seven)
     ->  SEVEN

   list.1
     ->  (ONE FIVE SIX SEVEN)
   part.1
     ->  (FIVE SIX SEVEN)
   part.1.ref
     ->  (FIVE SIX SEVEN)


 ;; Consing references.
   (setf list.2 (cons list.1 part.1.ref))
     ->  ((ONE FIVE SIX SEVEN) FIVE SIX SEVEN)

 ;; Setting placeholder.
   (setf part.1.ref 'eight)
     ->  EIGHT

 ;; Changing reference.
   (setf (cdr part.1) 'nine)
     ->  NINE

   list.1
     ->  (ONE FIVE . NINE)
   part.1
     ->  (FIVE . NINE)
   part.1.ref
     ->  EIGHT

 ;; No surprise, maybe.
   list.2
     ->  ((ONE FIVE . NINE) FIVE . NINE)

The format (CLHS) results in double-quoted text, and the read-from-string (CLHS) results in a Lisp form from reading double-quoted text. Combine both in order to duplicate any Lisp form, such as from named memory.

(setf thing.1 '(cons a d))
  ->  (CONS A D)

(setf thing.2
 (read-from-string
  (format nil "~s"
   thing.1)))
  ->  (CONS A D)

(setf thing.3
 (read-from-string
  (format nil "'(~s~s)"
   thing.1 thing.2)))
  ->  ((CONS A D) (CONS A D))

[ ...

Consider copy-list (CLHS) to copy the structure of a list without copying the content. Consider copy-tree (CLHS) for a list of pairs of pairs. Consider copy-seq (CLHS). Consider concatenate (CLHS) for an actual copy.


... ]

# Consistently half-paired lists

Besides the purposful construction of a list, there are a couple of obvious approaches for consistently constructing a list of arbitrary content.

   ((((1 . 2). 3). 4). 5)

   (5 .(4 .(3 .(2 . 1))))

Consistently pairing a new item right of a list forms a stream of half-pairs dextrally, ensuring the final item added is readily accessible with merely the cdr function.

      (1    . 2   )
      (a    . d   )

     ((1    . 2   ). 3  )
     ((aa   . da  ). d  )

    (((1    . 2   ). 3  ). 4 )
    (((aaa  . daa ). da ). d )

   ((((1    . 2   ). 3  ). 4 ). 5)
   ((((aaaa . daaa). daa). da). d)

Consistently pairing a new item left of a list forms a stream of half-pairs abdextrally, meaning the final item added is readily accessible with the car function instead.

                  (2    . 1)
                  (a    . d)

            (3   .(2    . 1 ))
            (a   .(ad   . dd))

       (4  .(3   .(2    . 1  )))
       (a  .(ad  .(add  . ddd)))

   (5 .(4  .(3   .(2    . 1   ))))
   (a .(ad .(add .(addd . dddd))))

A half-paired list of n items bypasses most its potential of 2^(n-1) items. For example, a 10 item half-paired list has 9 pairings wherewith it has 2^9 or 512 total possible positions. However, its other 502 locations are open for potential expansion.

Perhaps meaningfully pair each current item with an additional shorter half-paired stream or a chunk of pairs of pairs. Similarly for the 256 potential positions in the other half, perhaps as complementary information.

# Abbreviated notation for the dextral half

A space separated dot before a parenthetical list, t.i. the dextral half, can be abbreviated by removing both that prior dot and the parentheses for that next list. Notably, the Lisp interpreter favors this abbreviation for the dextral half, such as in abdextrally half-paired lists, when printing Lisp forms in messages.

       (a .(ad .(add .(addd . dddd))))
   ==  (a   ad .(add .(addd . dddd)))
   ==  (a   ad   add .(addd . dddd))
   ==  (a   ad   add   addd . dddd)

 Or:
       (a .(ad .(add .(addd . dddd))))
   ==  (a .(ad .(add   addd . dddd )))
   ==  (a .(ad   add   addd . dddd  ))
   ==  (a   ad   add   addd . dddd   )

One way of reversing that abbreviated notation is by pairing items from left to right, t.i. explicit dotted-pair notation of the car with the cdr.

       (a ad add addd . dddd)
   ==  (a .(ad add addd . dddd))
   ==  (a .(ad .(add addd . dddd)))
   ==  (a .(ad .(add .(addd . dddd))))

In other words, two items in a list without a dot between them means everything on the right half is actually another list. A Lisp list is truly a pair.

A list with nil as its dextral half, an empty list (Lisp and NIL), has only its abdextral half to show for itself.

       (a . nil)
   ==  (a .())
   ==  (a)

       (a ad . nil)
   ==  (a ad .())
   ==  (a ad)
   ==  (a .(ad))
   ==  (a .(ad .()))
   ==  (a .(ad . nil))

# Contrary formation and Lisp instructions

A Lisp function is used in an abdextrally half-paired list with the function name conveniently as the outermost abdexter. This also fits well with typing text from left-to-right, but that is contrary to the natural leftward formation of abdextrally half-paired lists.

   (setf abbi-list (cons 3 nil))
     ->  (3)

   (setf abbi-list (cons 2 abbi-list))
     ->  (2 3)

   (setf abbi-list (cons 1 abbi-list))
     ->  (1 2 3)

   (setf abbi-list (cons '+ abbi-list))
     ->  (+ 1 2 3)

   (eval abbi-list)
     ->  6

   abbi-list
     ->  (+ 1 2 3)

Contrary formation either dextrally or abdextrally is simple with setf (An intro for Lisp) by pairing the new content with the innermost item.

   (setf dex-list '((2 . 3). 4))
     ->  ((2 . 3). 4)

   (setf (caar dex-list)
    (cons 1 (caar dex-list)))
     ->  (1 . 2)

   dex-list
     ->  (((1 . 2). 3). 4)

A list as a Lisp instruction, such as for a Lisp function, is an abdextrally half-paired list that started with nil as its dextral half. That nil is the innermost item of the list. Simply substitute it with a pairing of the desired content and nil for maintaining that integrity.

   (setf do-it-later
    (quote (setf one 1 . nil)))
     ->  (SETF ONE 1)

   (setf (cdddr do-it-later)
    (cons 'two nil))
     -> (TWO)

   do-it-later
     ->  (SETF ONE 1 TWO)

   (setf (cddddr do-it-later)
    (cons 2 nil))
     -> (2)

   do-it-later
     ->  (SETF ONE 1 TWO 2)

   (setf (cdr (cddddr do-it-later))
     (cons 'three (cons 3 nil)))
      -> (three 3)

   do-it-later
     ->  (SETF ONE 1 TWO 2 THREE 3)
     ==  (SETF ONE 1 TWO 2 THREE 3 . nil)

Unwinding an abdextrally half-paired list (Exploring a half-paired list) exposes the middle items, and eventually the innermost item.

   (setf later.too (quote (setf one 1 . nil)))
     ->  (SETF ONE 1)

   (setf later.too
    (cons
     (cons (cADr later.too) (cAr later.too))
     (cDDr later.too)))
     ->  ((ONE . SETF) 1)

     Once more...
     ->  ((1 ONE . SETF))

   (setf (car later.too)
    (cons 'two (car later.too)))
     ->  (TWO 1 ONE . SETF)
   later.too
     -> ((TWO 1 ONE . SETF))

   (setf (cdr later.too)
    '(2 three 3 . nil))
     ->  (2 THREE 3)
   later.too
     ->  ((TWO 1 ONE . SETF) 2 THREE 3)

   (setf later.too
    (cons
     (cDAr later.too)
     (cons (cAAr later.too) (cDr later.too))))
     ->  ((1 ONE . SETF) TWO 2 THREE 3)

     Twice more...
     ->  (SETF ONE 1 TWO 2 THREE 3)

# List introspection in Lisp

A Lisp list is constructed as a pair with cons, and the car and cdr reference its left and right halves (Lisp lists are pairs). This provides an opportunity for pairs of pairs, as well as sequentially formed (t.i. half-paired) lists either abdextrally or dextrally.

Multiple pairs of pairs exponentially increase the potential storage of items: 2 from one pair, 2*2 from two, 2*2*2 from three, 2*2*2*2 from four, and so forth. Therein, an item is efficiently accessed by halving.

Positionally reference one half the list, either left or right, for each pairing: once for any item of 2, twice for any item of 2*2, thrice for any item of 2*2*2, and so forth.

Abbreviated functions consolidate two, three, or four car and cdr references, f.e. cadddr or cddddr. Access any of 2^4 or 16 halves with a single function, or any of 2^(4+4) or 256 items with two functions, or any of 2^(4+4+4) or 4096 with three functions, and so forth.

# Pairs of pairs accessed sequentially

A pair is 2 items, a pair of pairs is 4 items, a pair of pairs of pairs is 8 items, and so forth exponentially. An item in an exponentially paired list is referenced by gradually halving the list towards its position and noting each half leading to it.

The sequence of bisecting directions from outside to inside is also a binary description, thereby a binary number for each item. Assigning "left" as 0 and "right" as 1 reveals the sequence of binary digits for each item.

However, the abdextrally half-pairing of Lisp instructions leads to an inside-out consolidated reference. The binary digits are reversed as least to greatest for each number. This has no effect for percieving the sequence, only for interpreting the number.

  Paired once:   2^1 = 2 items
     car cdr
     (a . d)
      0   1

  Paired twice:  2^2 = 4 items
     caar cdar   cadr cddr
    ((aa . da) . (ad . dd))
      00   10     01   11
      0    1      2    3

  Paired thrice: 2^3 = 8 items
     caaar cdaar   cadar cddar     caadr cdadr   caddr cdddr
   (((aaa . daa) . (ada . dda)) . ((aad . dad) . (add . ddd)))
      000   100     010   110       001   101     011   111
      0     1       2     3         4     5       6     7

The numbers sequentially increase from left to right starting from zero, the equivalent of the rightward displacement of each item from the left end. The first item from the left has 0 items before it so skip zero items, the second item from the left has 1 item before it so skip one item, and so forth.

Therefore, the consecutive references with car and cdr describing the traversal from inside to outside for an item is equivalently the reversed binary digits for the rightward displacement of an item.

Access an item by noting its perceived sequential displacement as a reversed binary number. It has the same number of digits as the number of times an item is paired within the list, or the number of parentheses at the beginning or ending of the list.

For example, each item in a list of 16 items is paired four times (2 * 2 * 2 * 2 = 16), so consider the binary number for a position as four digits. The sixth item is displaced by 5 others, 5 is #b0101, reversed is 1010: use cDADAr.

Recall, only one function is needed for referencing any of 16 halves, two functions for any of 2^(4+4) or 256, three for any of 2^(4+4+4) or 4096, and so forth. For example, the cDAAr of the cDADAr is the 42nd item of 128 (t.i. 2^7), but so is the cDAADr of cADAr, because it is the "daadada". (But, within 64 items the 42nd is only "daadad".)

Consider using the Lisp interpreter for revealing binary numbers. The format (CLHS) prints a number as binary with ~b (CLHS 22.3.2.3). Or, also give the number of desired digits and a zero (preceded by an apostrophe ') (CLHS 22.3.2.1) for padding empty places. Then use the reverse (CLHS).

   (format nil "~b" 41)
     ->  "101001"
   (format nil "~7b" 41)
     ->  " 101001"
   (format nil "~7,'0b" 41)
     ->  "0101001"

   (reverse (format nil "~7,'0b" 41))
     ->  "1001010"
  Therefore:
          daadada

# Exploring a half-paired list

A half-paired list is a singular item paired with another list, perhaps by first pairing with an empty list, t.i. nil. Access the singular item of an abdextrally half-paired list with car, or of a dextrally half-paired list with cdr.

A consistently half-paired list is continuously deconstructable by referencing its inner list, with cdr for an abdextrally half-paired list or car for an dextrally half-paired list. Setting aside the singular items by constructing a new half-paired list opportunes reconstruction of the original list.

   (setf
    dexi nil
    abbi '(1 .(2 .(3 .(4 . nil)))))

   Dextrally cons             De-cons the
   a half-paired list.        abdextrally half-paired list.

   (cons dexi (car abbi))     (cdr abbi)

                (nil . 1)     (2 .(3 .(4 . nil)))
                       |       |
                      cdr     car

The foremost item of the inspected half-paired list is set aside as the former middle item. The inspected half-paired list is then deconstructed to its inner list, thereby exposing the next middle item.

Gradual unwinding exposes the middle items of the inspected list consistently with cdr or car from either replacement list. Pairing both lists into a new list would maintain that point of introspection. The order of the pairing is only a matter of preference because both halves are equally accessible.


# Dexi-abbi introspection.

Consider constructing dextrally half-paired lists from items of an abdextrally half-paired list while deconstructing it. Forming the dextrally half-paired list in the abdextral half maintains the visual appearance of the sequence order when printed.

   (setf coil '(1 .(2 .(3 . 4))))

     ->  (1 2 3 . 4)

   Introspection:
     (setf coil
      (cons
       (cons (cAr coil) (cADr coil))
       (cDDr coil)))

                         cADr
                          |
                 (1     .(2 .(3 . 4)))
                          |
     ->         ((1 . 2).(3 . 4))
                      |
     ->    (((1 . 2). 3).     4)
                      |
                     cDAr

     Reversal:
       (setf coil
        (cons
         (cAAr coil)
         (cons (cDAr coil) (cDr coil))))

                                    Default Lisp printer:

           (((1 . 2). 3). 4)    ==  (((1 . 2) . 3) . 4)
       ->   ((1 . 2).(3 . 4))   ==  ((1 . 2) 3 . 4)
       ->    (1 .(2 .(3 . 4)))  ==  (1 2 3 . 4)

# Abbi-abbi introspection.

A Lisp instruction is an abdextrally half-paired list that began with nil (Contrary formation and Lisp instructions). The Lisp printer favors the abbreviation for when a list is the dextral half of a pair (Abbreviated notation for a dextral half).

Consider constructing abdextrally half-paired lists from items of another abdextrally half-paired list, f.e. a Lisp instruction, while deconstructing it. A pair of abdextrally half-paired lists is printed more compactly than with a dextrally half-paired list (Dexi-abbi introspection).

   (setf abbi-abbi
    (cons nil '(1 2 3 4 . nil)))

   ->  (nil 1 2 3 4)

   Introspection:
     (setf abbi-abbi
      (cons
       (cons (cADr abbi-abbi) (cAr abbi-abbi))
       (cDDr abbi-abbi)))

        cAAr              cADr              Default Lisp printer:
         |                 |
          (nil          . (1 2 3 4 . nil))  ==  (nil 1 2 3 4)
   ->  ((1 . nil)       . (2 3 4 . nil))    ==  ((1) 2 3 4)
   ->  ((2 1 . nil)     . (3 4 . nil))      ==  ((2 1) 3 4)
   ->  ((3 2 1 . nil)   . (4 . nil))        ==  ((3 2 1) 4)
   ->  ((4 3 2 1 . nil) .    nil)           ==  ((4 3 2 1))

   Reversal:
     (setf abbi-abbi
      (cons
       (cDAr abbi-abbi)
       (cons (cAAr abbi-abbi) (cDr abbi-abbi))))

Of course, there was no need for prepending nil other than for slightly more compact printing. Without it, the reversal of the introspection results in the original abdextrally half-paired list without further ado.

Alternatively, reversal of an abbi-abbi introspection is as convenient as re-pairing the cdr with the car, then using the exact same introspection. Afterwards, the original first item is the cdr, so re-pair them once again.

   (setf abbi-abbi
    (cons (cdr abbi-abbi) (car abbi-abbi)))


[ ...describe using introspection for gradually constructing a Lisp form (which is an abdextrally half-paired list that began with nil). Also consider revising the examples in StumpWM section, promoting defining buttons for introspecting forwards and backwards, which now makes it easier to append to the innermost contrary position of a half-paired list (Contrary formation and Lisp instructions) with just cdr after unwinding the list all the way to nil... ]


[ ...

Consider associating each instruction to a button on the buttonboard (Introspect a referenced half-paired list), one for the next list item and one for the prior list item. Associate the placeholder name to another list for modifying it (Re-listing) with introspection. Afterwards, rewind it completely and then set the placeholder name to nil to detach the association.

Consider copy-list or copy-tree.


... ]

[ ...describe including the nifty (+ 1(length(car coil.my))) for position of introspected item for each evaluation by means of each defined key. For example, consider the cons for pairing the introspected item (as dexter) with its position for evaluation with stumpwm:eval-line, like when introspecting keysyms for keycodes listing (but that would be without the plus one because the keycodes were matched with the default zero indexing of arrays)... ]

# Lisp and NIL: No Items in List

Embracing items with parentheses
 acknowledges those items
 are associated with each other.

Nil is an empty list,
 as in "nothing in list".
 But that also asserts "Nil Is a List"
 rather than nothingness itself.
 It has become the mnemonic name
 for an empty set of parentheses.

   nil  ==  ()
        ==  '()  ; quoted Lisp form


A list of one item
 is never notated as a list,
 t.i. it has no parentheses.
 It is written simply as the item itself,
 for there are no other items associated.

A list of more than one item
 is notated as a dotted list,
 with a spaced separated period
 before its final item.

   '(one two . three)


A list with nil as its final item
 is commonly abbreviated
 without dotting with nil.

   '(one . nil)  ==  '(one)


A list of items without
 a dotted final item
 has visually consistent
 delimitation, thereby
 is a "proper list".
But as a list without
 a dotted final item,
 a proper list is merely
 the abbreviated form
 for its items dotted with nil
 as the final item.

   '(one)  ==  '(one . nil)


As such, a proper list with only nil
 is a list with an empty list:

   '(nil)  ==  '(())

 but is also the abbreviated form
 for a list of items dotted with nil
 as its final item:

   '(nil)  ==  '(nil . nil)

 which is a dotted list of two lists,
 or the egregious enlightenment emoticon
 for "I am become nil":

   '(nil)  ==  '(() . ())


--------


Consing constructs a dotted list.

   (cons 'one 'two)
     ->  '(one . two)


Multiple consing results in
 the last item added
 becoming the first.

   (cons 'three       ; second cons
    (cons 'one 'two)) ; first cons
      ->  '(three one . two)


Consing an item with nil
 results in a proper list,
 because a proper list
 is the abbreviated form
 for its items dotted with nil
 as its final item.

   (cons 'three            ; third cons
    (cons 'two             ; second cons
     (cons 'one nil)))     ; first cons
       ->  '(three two one . nil)
       ==  '(three two one . ())
       ==  '(three two one)


A proper list beginning with nil
 begins and ends with a list.

   (cons nil '(one))
     ->  '(nil one)
     ==  '(nil one . nil)
     ==  '(()  one .  ())

# Approaches and alternatives for Common Lisp

It seems like introspection of computer processing has always been ignored by computer programmers and hardware manufacturers. Nothing made explorable, or exploration of instructions written personally is buried within what was supplied by default.

The SBCL interpreter seems about as unfriendly with its feedback as any other Lisp or shell interpreter or computer program compiler. The "restarts" and whatnot of Common Lisp seem almost completely unusable and unreliable when compared to the pause/continue/step half-baked approaches of other systems.

Despite such disheartening contrary interests, Lisp interpreters tend to be personalizable. Changes can be made, for the moment or for longer.

# An introspective approach for defun

According to the description for defun (CLHS), there seems to be no access to the definition of a Lisp function from its results.

In particular, defun does not make the function definition available at compile time. An implementation may choose to store information about the function for the purposes of compile-time error-checking (such as checking the number of arguments on calls), or to enable the function to be expanded inline.

Consider constructing the replacement for a function with setf and the same name as that function (Assigning to named memory from collections). The instruction can be modified later and re-evaluated to replace again.

Describe Function: stumpwm::print-key
function: print-key
(print-key key)
Eval: stumpwm::print-key
The variable STUMPWM::PRINT-KEY is unbound.Backtrace...
Eval: (setf stumpwm::print-key '(defun stumpwm::print-key ...yadda yadda yadda...))
Eval: (eval stumpwm::print-key)
STUMPWM::PRINT-KEY

Consider pairing the original definition of the function with the replacement, for restoring either one as neeeded.

Eval: (setf stumpwm::print-key (cons stumpwm::print-key nil))
Eval: (setf stumpwm::print-key (cons '(defun stumpwm::print-key ...yoda yoda yoda...) stumpwm::print-key))

Consider pairing a description with each version to identify which is the replacement.

Eval: (setf (car stumpwm::print-key) (cons "original" (car stumpwm::print-key)))
Eval: (setf (cdr stumpwm::print-key) (cons "replacement" (cdr stumpwm::print-key)))


[ ...describe
(or revise and reference section Reading and writing to external memory)
about writing to external storage for later re-use... ]

# A friendler cons

The cons (CLHS) constructs a list of two items (Dexter and abdexter) regardless of whether either item is nil (Lisp and NIL), yet it requires both items are specified. Consider making both items optional, wherewith each item defaults to nil.

The COMMON-LISP package might be locked by default in SBCL (SBCL 12.1.1 Package Locks). Consider temporarily unlocking it with sb-ext:unlock-package (SBCL 12.2) in order to redefine the cons name with defun (CLHS), or pick a different name than "cons".

Eval: (defun cons (&optional Fabdexter Fdexter) (cl:cons Fabdexter Fdexter))
Lock on package COMMON-LISP violated when setting fdefinition of CONS
     while in package STUMPWM-USER.
See also:
  The SBCL Manual, Node "Package Locks"
  The ANSI Standard, Section 11.1.2.1.2Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {0123456789}>
0: (STUMPWM::BACKTRACE-STRING)
...
Eval: (sb-ext:unlock-package 'cl)
T
Eval: (defun cons (&optional Fabdexter Fdexter) (cl:cons Fabdexter Fdexter))
CONS
Eval: (sb-ext:lock-package 'cl)
T

Beginning the construction of an abdextrally half-paired list with nil for a Lisp instruction matches with the abbreviated results themselves. No more typing for nothing.

   (setf abbi-list (cons 3))
     ->  (3)
     ==  (3 . NIL)

   (cons)
     ->  (NIL)
     ==  (NIL .())
     ==  (NIL . NIL)

# StumpWM: an interactive extensible computer interface







The split-view manager StumpWM is a Lisp image exported from SBCL (Steel Bank Common Lisp), and is intended for managing the Xwindows of an Xserver (Essential split-view commands).

Split-views are adjacent non-intersecting areas, like tiles, thereby efficiently encompassing the whole screen. Initially, StumpWM was known as "ratpoison" because it focused on eliminating any requirement for an electronic device emulating the toggling of the buttocks on a rodent.

As an SBCL Lisp image, StumpWM is actually a copy of the SBCL Lisp interpreter with the code for StumpWM built-in. That means starting StumpWM is the same as starting a Lisp interpreter, and any new Lisp can be typed and evaluated instantly. While it is typical to modify a Lisp interpreter while using it, in this case that means being able to modify StumpWM while using StumpWM, too. No need to start over, just keep going.

Additionally, StumpWM is written entirely in Common Lisp, and SBCL is written mostly with Common Lisp. Technically, that means either the Xwindow manager or the Lisp environment can be personalized with the familiarity of Common Lisp, at first without recompiling and then compiled later for a copy with those additions.

Personalize StumpWM with its initialization file "~/.stumpwm.d/init.lisp", such as assigning names to Lisp instructions or assigning buttons to evaluated them. Or, include Lisp from other files when starting by using load (CLHS).

(load "~/common-lisp/something-new.lisp")

After starting the Xserver with StumpWM as the Xwindows manager, access the Lisp interpreter anytime with "Control-t :" (The Lisp instruction prompt). That is, hold the Control button then type the letter t, then let go of the Control button, then type a colon. The prompt "Eval: " will appear for typing a line of Common Lisp.

Instantly assign a button to any command, or create a new Xserver window and draw in it, or add a set of new commands from any file with load. In a nutshell: an interactive extensible computer interface.

# Example setup of StumpWM

StumpWM 1.0.1:
stumpwm.github.io ; StumpWM manual ; StumpWM wiki (tips and tricks)
Steel Bank Common Lisp (SBCL) 2.1.0
sbcl.org
Common Lisp X Interface (CLX) 0.7.5
github.com/sharplispers/clx
alexandria 1.0.1
common-lisp.net/project/alexandria
cl-ppcre 2.1.1
edicl.github.io/cl-ppcre
an Xserver, f.e. x.org (The X.Org Foundation R12008000)
any Xserver compatible system, f.e. TinyCore ( tinycorelinux.net/ports.html )
For example, piCore 12.0 (includes 64-bit version).

# Interactive curiosity: typing for actions and help

StumpWM provides various prompts for typing computer instructions, or the name of a StumpWM command, or for help.

Call forth a specific prompt by typing the abbreviated button sequence for it (f.e. "Control-t :"), or by invoking the command for it (Invoke a StumpWM command by its name). Use the Control button in the same manner as the Shift button, t.i. hold the Control button before typing a letter (skip the hyphen), then afterwards let go of it.

Move the text cursor anywhere within the single line of text as needed (Typing within a line of text).

Type the Return button or Enter button to complete the invocation, regardless of where the text cursor is located. Or, type the Esc button to escape from the prompt without invoking.

Consider bypassing the "Control-t" prefix by assigning a single button for any commonly invoked prompt (Assign a button to a command).

# Compose a Lisp instruction

Numbers and double-quoted text are the most basic forms of Lisp. Parentheses embrace items for a Lisp list (Lisp lists are pairs). There are about a half-dozen Lisp instructions for naming memory, referencing an item in a list, and constructing or re-listing a list (An intro for Lisp).


A couple of related prompts help with learning about or verifying named memory and names for Lisp instructions. Consider a more convenient prefix for the set of Help commands (New prefix for Help).


# Invoke a StumpWM command by its name

While typing, a list of command names beginning with those letters are shown below the prompt.

Type the Tab button to choose the name at the top of the list and the list is hidden. Type the Tab button to cycle through the other hidden choices, or hold the Shift button and type the Tab button to cycle in reverse.


Note the command command-mode makes the stumpwm::*root-map* temporarily like an interactive keymap (Interactive keymaps), meaning no need for its prefix (Re-assign the StumpWM prefix). Note "Control-g" ends the mode, as it states when it starts.

A couple of related prompts help with learning about commands, or discovering a button name and its assigned command. Consider a more convenient prefix for the set of Help commands (New prefix for Help).


# Use a program

While typing, a list of program names beginning with those letters are shown below the prompt. Type the Tab button to choose the name at the top of the list and the list is hidden. Type the Tab button to cycle through the other hidden choices, or hold the Shift button and type the Tab button to cycle in reverse.


Starting a program displaces the current document or program from the current frame (or full screen). The prior program or document is only hidden. Consider commands for switching to a hidden program, or splitting the screen (Essential split-view commands).

Note this is an alias for run-shell-command which actually accepts a "shell command", a computer instruction for the operating system rather than StumpWM. Thereby, the results for a shell command (instead of a program name) will appear in the console whence StumpWM was started, rather than with the StumpWM messages.

# Typing within a line of text

After typing text within a prompt, the left/right arrow buttons move the text cursor within the line of text.

The up/down arrow buttons bring forth prior/later typed text for editing and re-using, thereby less re-typing.

Other button sequences for moving the text cursor are described with "C-" for the Control button and "M-" for the Meta button (StumpWM 4.2 Using the Input Bar), and are similar to the text editing commands in the prompts of Emacs (GNU). The Alt button is usually the substitute for the Meta button.

The stumpwm:*input-map* keymap has no button for listing the command abbreviations for editing text in a prompt. Either consult the manual for StumpWM 4.2 Using the Input Bar for the full listing, or consider enabling the listing (Reveal button list for text editing).

Either the Home button or "Control-a" moves the text cursor to the beginning of the line. Either the End button or "Control-e" moves the text cursor to the end of the line.

Either "Meta-f" or "Alt-f" moves the text cursor forward one word, and "Meta-b" or "Alt-b" moves the text cursor backward one word.

Type the Return or Enter button to complete the invocation, regardless of where the text cursor is located within the line of text. Or, type the Esc button to escape from the prompt without invoking.

# Reveal button list for text editing

The only buttons assigned to commands while typing at a prompt are listed in stumpwm:*input-map* (StumpWM 4.2 Using the Input Bar). The full listing reveals many duplicates.

Prefix: F12
DEL   INPUT-DELETE-BACKWARD-CHAR
M-DEL INPUT-BACKWARD-KILL-WORD
C-d   INPUT-DELETE-FORWARD-CHAR
M-d   INPUT-FORWARD-KILL-WORD
Delete INPUT-DELETE-FORWARD-CHAR
C-f   INPUT-FORWARD-CHAR
Right INPUT-FORWARD-CHAR
M-f   INPUT-FORWARD-WORD
C-b   INPUT-BACKWARD-CHAR
Left  INPUT-BACKWARD-CHAR
M-b   INPUT-BACKWARD-WORD
C-a   INPUT-MOVE-BEGINNING-OF-LINE
Home  INPUT-MOVE-BEGINNING-OF-LINE
C-e   INPUT-MOVE-END-OF-LINE
End   INPUT-MOVE-END-OF-LINE
C-k   INPUT-KILL-LINE
C-u   INPUT-KILL-TO-BEGINNING
C-p   INPUT-HISTORY-BACK
Up    INPUT-HISTORY-BACK
C-n   INPUT-HISTORY-FORWARD
Down  INPUT-HISTORY-FORWARD
RET   INPUT-SUBMIT
C-g   INPUT-ABORT
ESC   INPUT-ABORT
C-y   INPUT-YANK-SELECTION
C-Y   INPUT-YANK-CLIPBOARD
TAB   INPUT-COMPLETE-FORWARD
ISO_LEFT_TAB INPUT-COMPLETE-BACKWARD
All else INPUT-SELF-INSERT

In effect, it is like an interactive keymap in the way its list of commands are isolated from all other assigned buttons without need for a prefix for each one (Interactive keymaps).

However, it is actually a regular StumpWM keymap that can have more assignments added to it (Make a list of command buttons). That also means, any of its assigned buttons can be unassigned by re-defining them to nil instead of to a command.

According to the StumpWM source files, all commands added to stumpwm:*input-map* must be defined to accept two Lisp forms: a reference to the current prompt, and the button that invoked the command. Most commands never use the button itself, but they must still be defined to receive it.

As a regular keymap, the stumpwm:*input-map* itself can be assigned to a button (New prefix for Help).

Eval: (describe-key)
F12 is not bound.
Eval: (define-key *top-map* (kbd "F12") '*input-map*)

While the commands are obviously useless outside of a prompt, typing its newly assigned prefix followed by a question mark "?" could reveal the button list with no need for the manual (Make a list of command buttons). Instead, a boring error excitingly appears (Named, memory, Lisp instructions, and errors).

StumpWM Crashed With An Unhandled Error!
Copy the error to the clipboard with the 'copy-unhandled-error' command.
The value
    T
  is not of type
    STUMPWM::KEY
Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {0123456789}>
0: (STUMPWM::PRINT-MODS T)
1: (STUMPWM::PRINT-KEY T)
2: (STUMPWM::DISPLAY-BINDINGS-FOR-KEYMAPS ...)
...

Consider replacing stumpwm::print-key with a minor modification (Replacement for stumpwm:print-key).

The button listing reveals a sort of mysterious command stumpwm:input-yank-clipboard (Insert text at a prompt) invoked with "Control-Y" (a capital y, t.i. Shift-y), as it seems to be undocumented in the manual.

# Insert text at a prompt

The abbreviations "Control-y" and "Control-Y" can be used for two different text insertions at a prompt. As double-quoted text, partial Lisp forms can be made available.

Both stumpwm:input-yank-selection and stumpwm:input-yank-clipboard (Reveal button list for text editing) access the stumpwm:*x-selection*, which is an abdextrally half-paired list beginning with nil (Consistently half-paired lists).

Initially, the stumpwm:*x-selection* starts as only nil.

Eval: *x-selection*
NIL

Invoking either stumpwm:input-kill-line or stumpwm:input-kill-to-beginning will add what is removed from the prompt into stumpwm:*x-selection* immediately after :primary within it as double-quoted text.

Eval: *x-selection*
(:PRIMARY "(cons 'something 'from-prompt)")

Yank is complementary to kill, a paradigm familiarized in Emacs (Emacs 12. Killing and moving text). The stumpwm:input-yank-selection inserts into the prompt whatever is listed immediately after :primary within it.

Consider using setf (An intro for Lisp) to replace the double-quoted text in stumpwm:*x-selection*.

Eval: (setf (cadr *x-selection*) "'(the-first-part of-something")
Eval: *x-selection*
(:PRIMARY "'(the-first-part of-something")

Similarly, the stumpwm:input-yank-clipboard accesses the info after :clipboard within the stumpwm:*x-selection*. When :clipboard is missing, just add it along with the new double-quoted text.

Eval: (setf (cddr *x-selection*) '(:clipboard " the-last-part)"))
Eval: *x-selection*
(:PRIMARY "'(the-first-part of-something" :CLIPBOARD " the-last-part)")

[ ...describe approach for inserting text from any named memory at a prompt, thus the requirements when adding new commands to stumpwm:*input-map*...
...reference the means for inserting any list (or a half of it) as text anywhere (t.i. into any program), which is distinct from and potentially obviating the singular copy/paste buffer, as noted in Flow of the moment (yet to be described), by means of introspection as in Abbi-abbi introspection...
... ]

# The Lisp instruction prompt: an outlet for ingenuity

Eval:            

StumpWM provides the Lisp instruction prompt "Eval: " by means of "Control-t :" for evaluating a single line of Lisp instruction after the Return button or Enter button is typed (Compose a line of instruction).

Numbers and double-quoted text essentially remain the same. Named memory is referenced for its content. A Lisp list is evaluated as an instruction.

Using quote for named memory prevents referencing the memory at that moment. Using quote for a Lisp list prevents evaluation of it as an instruction at that moment. There are about a half dozen essential Lisp instructions (An intro for Lisp).

# Named memory, Lisp instructions, and errors

The setf (An intro for Lisp) associates a name with a memory location in the computer, and anything can be stored in that memory. A Lisp instruction is a pair of parentheses with the instruction name as the leftmost list item.

Type a name to find out whether there is information associated with it yet, or type a Lisp instruction for the computer. A message with successful results appears on the screen for a few seconds, and then conveniently disappears.

Eval: stumpwm:*input-window-gravity*
:TOP-LEFT
Eval: (setf stumpwm:*input-window-gravity* :center)
:CENTER

The delay is the number of seconds set in stumpwm:*timeout-wait* (StumpWM 4.1). However, it can also be paused by typing the prefix for a button sequence, such as "Control-t", because StumpWM is waiting for the remainder of the sequence (Make a list of command buttons). Finish typing the sequence and the message will likely be cleared as the next command is invoked.

Otherwise, when the name has yet to be set or the Lisp instruction is mistyped, a boring description of an error will excitingly appear and stay visible.

Forever.

Almost. The error message will disappear when the next StumpWM command is invoked (Clear the message from the screen), f.e. when invoking the prompt again.

Eval: something
The variable SOMETHING is unbound.Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING> {1234567890}>
0: (STUMPWM::BACKTRACE-STRING)
1: (ERR "~A" #<UNBOUND-VARIABLE SOMETHING {2345678901}>)
2: (EVAL-LINE "something")
3: (STUMPWM::CALL-INTERACTIVELY "eval" #S(STUMPWM::ARGUMENT-LINE :STRING "eval" :START 5))
4: (STUMPWM::EVAL-COMMAND "eval" T)
5: ((LAMBDA (&REST #:GO &KEY :CODE :STATE &ALLOW-OTHER-KEYS) :IN "/tmp/stumpwm-20.11/events.lisp") :CODE 66 :STATE 0)
6: (STUMPWM::HANDLE-EVENT :DISPLAY #<XLIB:DISPLAY :0 (The X.Org Foundation R12008000)> ...)

 [ ...Pretty much the same hereafter
   for every error message,
   except maybe different line counting.
   Usually only terribly important,
   hence perfectly ignorable... ]

17: (STUMPWM ":0")
18: ((LAMBDA NIL :IN "/tmp/stumpwm-20.11/make-image.lisp"))
19: ((FLET SB-UNIX::BODY :IN SB-IMPL::START-LISP))
20: ((FLET "WITHOUT-INTERRUPTS-BODY-1" :IN SB-IMPL::START-LISP))
21: (SB-IMPL::START-LISP)

The very top line above line count zero is probably the most revealing, and probably enough to realize why the error happened.

The "Backtrace" is abruptly tacked onto the end of the first line, but can be made to start on a newline if desired (Replacement for stumpwm:err).

That "Backtrace" bores into the processing depths of the Lisp interpreter. Likely only about the first half-dozen lines of the error, line count zero through maybe five or so, will be relevant.

Afterwards is essentially the same for every error message. The middle reveals the constant looping that waits for typed buttons, the core of StumpWM. The very end is actually how the StumpWM program itself began, as a "Lisp image".

Consider trying again with the Lisp instruction prompt "Control-t :", then using the up arrow button to show the previous typed line, and then editing it to get a different result (Typing within a line of text).

# Assigning to named memory from collections

With Common Lisp, both a function from defun (CLHS) and any other Lisp form from setf (CLHS) can be associated with the same symbol, t.i. named memory, at the same time. Consider this as a convenience when replacing functions (An introspective approach for defun).

The pecularity of packages in Common Lisp means extra care is needed when querying named memory for ascertaining prior use of a name, especially with the misleading feedback from symbol-package and the package locks of SBCL.

Eval: (symbol-package 'print-key)
#<PACKAGE "STUMPWM-USER">
Eval: print-key
The variable PRINT-KEY is unbound.Backtrace...
Eval: (setf print-key '(something))
(SOMETHING)
Eval: print-key
(SOMETHING)

Query the named memory with its known package name and two colons "::" just to be sure. Consider "Control-t h f" for stumpwm:describe-function (New prefix for Help).

Eval: stumpwm:print-key
The symbol "PRINT-KEY" is not external in the STUMPWM package.
       Stream: #<dynamic-extent STRING-INPUT-STREAM (unavailable) from "stumpwm:...">Backtrace...
Eval: stumpwm::print-key
The variable STUMPWM::PRINT-KEY is unbound.Backtrace...
Describe Function: print-key
The symbol STUMPWM-USER::PRINT-KEY is not bound to any function.
Describe Function: stumpwm::print-key
function: print-key
(print-key key)

# Optional or required collection names

An error message claiming a (known) name is undefined is a clue that the collection name is needed.

Eval: (global-pointer-position stumpwm:*display*)
The function STUMPWM-USER::GLOBAL-POINTER-POSITION is undefined.Backtrace...

Friendlier feedback is given by "Control-t h f" for stumpwm:describe-function for querying about a instruction name, or "Control-t h v" for stumpwm:describe-variable for querying about a placeholder name (New prefix for Help). Though their responses never reveal the package name, they do confirm or deny the existence of a name in a package.

Describe Function: stumpwm:global-pointer-position
No such symbol: STUMPWM::GLOBAL-POINTER-POSITION.
Describe Function: xlib:global-pointer-position
function: global-pointer-position
(global-pointer-position DISPLAY)
Eval: (xlib:global-pointer-position stumpwm:*display*)
1050
787
#<XLIB:WINDOW :0 389>
Describe Variable: stumpwm:*display*
variable: *DISPLAY*
The display for the X server
Its value is:
#<DISPLAY :0 (The X.Org Foundation R12008000)>.
Eval: (xlib:global-pointer-position *display*)
1050
787
#<XLIB:WINDOW :0 389>

The feedback from the function or variable queries is a little misleading. It might print two colons when declaring the name as undefined, even when only one colon was used during a query.

Otherwise, consider trying another query with two colons whenever it says it did try only one colon and failed to find anything. Also, a successful message leaves off the collection name even when it is required.

Many StumpWM names for placeholders or Lisp instructions have no need for the "stumpwm:" collection name, f.e. *top-map* or define-key. Try it and find out. However, the collection name does make obvious where to personally seek documentation.

When the collection name is required, sometimes an extra colon is also needed, f.e. stumpwm::read-key. That is usually because the placeholder or Lisp instruction is probably unintended for common use. The documentation for it is likely in the source file, if at all.

The StumpWM names for placeholders usually include an asterisk "*" before and after the name, f.e. stumpwm:*top-map*. That is only a convention when creating a placeholder with the defvar (CLHS). (The intended effect of defvar is essentially useless from the Lisp instruction prompt, its intended use is for within files.) Consider a different approach for new names, distinctive for certainty.

# There can be only one

Only one Lisp form is evaluated by stumpwm:eval-line, either at its prompt or given to it as a command for a button. Later forms on the line are simply ignored by it.

The cons pairs the results of two Lisp forms. The format (CLHS) constructs double-quoted text, typically from the evaluation results of any number of Lisp forms.


# Two instructions at once.

Consider using cons for pairing two instructions for evaluation by eval-line.

For example, define a button on the buttonboard to press and release the primary button for the pointer (Alternative for pointer activation and drag'n drop).

Eval: (setf press.1 '(xlib/xtest:fake-button-event *display* 1 t))
Eval: (setf release.1 '(xlib/xtest:fake-button-event *display* 1 nil))
Eval: (describe-key)
F10 is not bound.
Eval: (define-key *top-map* (kbd "F10") "eval-line (cons (eval press.1) (eval release.1))")

# Multiple instructions at once.

The format (CLHS) is a way of having the computer write the results of any number of Lisp instructions, and formatted with additional text described within double-quotes. No additional text is required, and in fact an empty set of double-quotes is fine.

Consider using format for combining multiple instructions for evaluation by eval-line. Consider storing the format instruction to avoid the conflict of its double-quotes within the double-quotes for define-key.

For example, place the pointer at a specific location on the screen with xlib:warp-pointer (Alternative for pointer placement), then press and release the primary button for it.

Eval: do-point.a
The variable DO-POINT.A is unbound.Backtrace...
Eval: (setf do-point.a '(format nil "" (eval point.a) (eval press.1) (eval release.1)))
Eval: (describe-key)
F11 is not bound.
Eval: (define-key *top-map* (kbd "F11") "eval-line (eval do-point.a)")
Eval: point.a
The variable POINT.A is unbound.Backtrace...
Eval: (setf point.a '(xlib:warp-pointer (screen-root(current-screen)) 600 450))

Essentially, the format begins with three parts:

format nil ""

Consider using cons to add each part to the left end of any list of instructions.

Eval: press-release.1
The variable PRESS-RELEASE.1 is unbound.Backtrace...
Eval: (setf press-release.1 '((eval press.1) (eval release.1)))
Eval: do-point.b
The variable DO-POINT.B is unbound.Backtrace...
Eval: (setf do-point.b (cons '(eval point.b) press-release.1))
Eval: do-point.b
((EVAL POINT.B) (EVAL PRESS.1) (EVAL RELEASE.1))
Eval: (setf do-point.b (cons "" do-point.b))
Eval: (setf do-point.b (cons nil do-point.b))
Eval: (setf do-point.b (cons 'format do-point.b))
Eval: do-point.b
(FORMAT NIL "" (EVAL POINT.B) (EVAL PRESS.1) (EVAL RELEASE.1))
Eval: (eval do-point.b)

Optionally, use "~s" for the result of each instruction. The "~%" provides a blank line, but StumpWM consolidates a series of blank lines into only one for its messages.

Eval: (setf d.1 '(format nil "~s~%~s~%~s" (eval a.1) (eval b.1) (eval c.1)))

# An intro for Lisp with StumpWM

At the core of Lisp is a paragon of lists, either empty or efficiently multi-dimensional, because Lisp is "LISt Processing".

Lists are notated parenthetically: ( ). There are also computer actions for constructing a list from a pair of items, for referencing an item in a list, and for associating a name to a list.

There are about a half-dozen important Lisp functions, t.i. named instructions.

An instruction for the computer is written as a parenthetical list beginning with a name for a computer action. That name is followed by any additional info needed for functioning in that manner.

Technically, a "Lisp form" is text formatted in a way that is readable by the Lisp interpreter. It can be as plain as a number, or double-quoted text (with " ") such as for messages, or merely a name for a Lisp symbol associated with another Lisp form. It can also be a quoted symbol or list (with quote).

Decimal system numbers can begin with a - or +. A hexadecimal number begins with #x, then can have a - or +, then is followed by a group of 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f; capitalized is okay. A binary number begins with #b, then can have - or +, then is followed by a group of 0 or 1.

The Lisp interpreter prints a number as a decimal number, and without a +. For example, either 12 or #xC or #b+1100 is shown as 12.

A calculation with a number as a fraction, f.e. 4/3 or #b100/11 or #x4/3, produces a fraction when appropriate. For example, 4/3 subtracted from 2 results in 2/3, and #b100/11 subtracted from 2 also results in 2/3.

Basic calculations are with the +, -, *, and / Lisp functions (CLHS 12.2 The Numbers Dictionary). For example, (- 2 #b100/11) is 2/3. Notably (/ 4 3) is 4/3, but (/ 4.0 3) is 1.3333334 instead. The expt is for exponentials, f.e. 2^3 is (expt 2 3) is 8, though 2.0 results from the reverse (expt 8 1/3).

The "Eval: " prompt for Lisp instructions is from the stumpwm:eval-line command with "Control-t :" (The Lisp instruction prompt). Type the name of a Lisp symbol to reveal whether it is associated with anything, or type a Lisp instruction for the computer.

Eval: something
The variable SOMETHING is unbound.Backtrace...
Eval: (quote something)
SOMETHING

quote (CLHS): Suppress immediate evaluation of a legitimate Lisp form. Commonly abbreviated to one single quote mark ' instead, especially in messages with results or feedback from the Lisp interpreter.

Though evaluation is suppresed, the quoted item is expected to be a legit Lisp form, otherwise the Lisp interpreter (SBCL) complains. A quoted legit placeholder name is acceptable even when yet to be used.

However, a colon in the middle of a placeholder name (Optional or required collection names) indicates it is from a collection and it must already exist, otherwise an error is shown.

Eval: something
The variable SOMETHING is unbound.Backtrace...
Eval: (quote something)
SOMETHING
Eval: 'something
SOMETHING
Eval: (quote (quote something))
'SOMETHING
Eval: (quote cl:something)
Symbol "SOMETHING" not found in the COMMON-LISP package.
       Stream: #<dynamic-extent STRING-INPUT-STREAM (unavailable) from "'cl:some...">Backtrace...

cons (CLHS): Construct a new list by pairing two Lisp forms (Lisp lists are pairs).

Keep in mind the Lisp interpreter messages abbreviate the dextral half of a list (Abbreviated notation for the dextral half), and nil when it is the dexter because nil is a list (Lisp and NIL: No Items in List).

Eval: (cons "Two words." (quote a-name))
("Two words." . A-NAME)
Eval: (cons 3 '("Two words." . a-name))
(3 "Two words." . A-NAME)
Eval: (cons 'something nil)
(SOMETHING)
Eval: (cons ( ) 'something)
(NIL . SOMETHING)
Eval: (quote (cons 'something 'more))
(CONS 'SOMETHING 'MORE)
Eval: (quote (something . more))
(SOMETHING . MORE)

car (CLHS): Call up the abdexter reference of a list, t.i. its left half.

Eval: (car (quote ((1 . 2) . 3)))
(1 . 2)

cdr (CLHS): [just say "c-d-r", or "dexter"] Call up the dexter reference of a list, t.i. its right half.

Eval: (cdr '((1 . 2) . 3))
3

eval (CLHS): Evaluate a Lisp form, especially a Lisp form quoted with quote, or a placeholder name referencing a Lisp form.

Eval: '(cons 1 2)
(CONS 1 2)
Eval: (eval '(cons 1 2))
(1 . 2)
Eval: (setf later.test '(cons 1 2))
(CONS 1 2)
Eval: later.test
(CONS 1 2)
Eval: (eval later.test)
(1 . 2)

setf (CLHS): Assign the temporary memory of the Lisp interpreter.

Associate a name with double-quoted text, a number, the evaluation of a Lisp instruction, or a quoted Lisp instruction for later evaluation. Or, associate the reference within a list with anything, such as setting the car of the list.

Eval: prose
The variable PROSE is unbound.Backtrace...
Eval: (setf prose "A list of characters." a-list '(10 . 9))
(10 . 9)
Eval: prose
"A list of characters."
Eval: a-list
(10 . 9)
Eval: (setf (cdr a-list) 4)
4
Eval: a-list
(10 . 4)
Eval: (setf do-it (quote (setf (car a-list) 15)))
(SETF (CAR A-LIST) 15)
Eval: do-it
(SETF (CAR A-LIST) 15)
Eval: a-list
(10 . 4)
Eval: (eval do-it)
15
Eval: a-list
(15 . 4)
Eval: do-it
(SETF (CAR A-LIST) 15)

# Flow of the moment


[ ...at the very least,
 connect the dots by outlining this;
 then fill it in with whatever time remains... ]

An extensible computing environment, like the Lisp image with StumpWM, can be adjusted as needed for the moment. Modify with basic instructions for the moment rather than making permanent changes.

Consider making notes on what and how to modify, perhaps on paper. Note successes, possibilities, interests, and contradictions. Group a collection of changes that have been typed in for a session, and consider saving it to an external storage device for less re-typing later.

Only the changes that have been added for the moment need consideration. Rebooting is a fresh restart, a new beginning. Instructions are restorable from external storage as needed, and retain adaptability.

As a list, any part of such a collection can be modified, or re-stored into named memory, or simply referenced in place. Any part can be evaluated, or the parts can be coordinated for applying all at once.


[ ...outline briefly various basic approaches, and link to relevant sections... ]

Construct an instruction for evaluation

  1. Type text in the prompt.
  2. Insert as text any abdexter or dexter from any introspected list.
    [ ...see "insert text from introspected list into prompt" in notepad
    (also the page in notepad named "Beyond the Lisp evaluation prompt",
    section beginning with stumpwm:read-one-line,
    specifically "For example, (defun insert.cadr (input key)..."),
    as it is the final dot to connect
    (as it obviates copy/paste, and maybe text editors),
    so must prioritize and complete this before reaching final meal... ]
    
    [ ...partial description for introspection already (Abbi-abbi introspection),
    but reference the description for buttons when its description is added
    (but new from notes, for assigning to stumpwm:*input-map*)... ]
    
  3. Evaluate the instruction.

Re-use an instruction

Consider naming an instruction and then assigning a button to evaluate the name. In that way, the instruction can be modified later by means of its name. There also is no need to re-assign the button.

  1. Assign a button to evaluate an instruction. (Any instruction at the press of a button)

Modify an instruction

Any part of named instruction is readily modified with setf by referencing an abdexter or a dexter within it. No need to re-assign a button to a modified instruction.

  1. Introspect the instruction (as a list).
    [ ...part of #2 in "Construct an instruction" above... ]
  2. In the Lisp instruction prompt, type the replacement for any abdexter or dexter, likely with setf.
    Optionally insert as text the abdexter or dexter from introspecting the instruction and edit it as the replacement.
    [ ...same as #2 in "Construct an instruction" above... ]
  3. Complete the evaluation for the replacement.

Store an instruction for later use

  1. Pair a description (double-quoted text) with an instruction.
  2. Write to an external storage device.
    [ ...remember that section is from long ago,
    needs to be revised... ]

Re-store prior instructions

  1. Read a list from a storage device.
    [ ...remember that section is from long ago,
    needs to be revised... ]
  2. Introspection of the list.
  3. Assign a button to evaluate any abdexter or dexter that is a Lisp instruction, or to the whole list. (Any instruction at the press of a button)
    [ ...add another example over there that evaluates a list half... ]

# Customize prompts and messages

The messages and prompts from StumpWM appear when needed, each at pre-specified locations on the screen. The characteristics of text color, background color, and the border are generally shared by both messages and prompts (StumpWM 4.1).

As expected, those characteristics are adjustable with the Lisp instruction prompt.

Location of prompts and messages
Border and padding
Color for prompts:
Three message types, and their color

# Location of prompts and messages

Use setf (An intro for Lisp) to set the location of prompts and the location of messages.

Eval: (setf stumpwm:*input-window-gravity* :center)
Eval: (setf stumpwm:*message-window-gravity* :bottom)

Possible gravity names for the messages or prompts begin with a colon ":".

    _______________________________________________
   | :top-left |      |  :top   |     | :top-right |
   |___________|      |_________|     |____________|
   |                                               |
   |                                               |
   |--------          -----------         ---------|
   | :left |          | :center |         | :right |
   |--------          -----------         ---------|
   |                                               |
   |______________     _________    _______________|
   | :bottom-left |   | :bottom |  | :bottom-right |
   |______________|___|_________|__|_______________|

# Border and padding

The border width from stumpwm:set-msg-border-width and its color (X Window System color) from stumpwm:set-border-color are absolutely consistent for prompts and all types of messages. Use setf for the padding around messages and prompts.

Eval: (stumpwm:set-msg-border-width 3)
Eval: (stumpwm:set-border-color "CornflowerBlue")
Eval: (setf stumpwm:*message-window-padding* 7)
Eval: (setf stumpwm:*message-window-y-padding* 5)

# Color for prompts

The prompts use the background color from stumpwm:set-bg-color and the text color (foreground) from stumpwm:set-fg-color. Any standard X Window System color.

Eval: (stumpwm:set-bg-color "DarkOrchid4")
Eval: (stumpwm:set-fg-color "Thistle1")

# Three message types, and their color

The colors get messy in StumpWM when it comes to its messages. There are at least three types: documentation messages, error messages, and messages with Lisp results. They use some of the eight colors listed in stumpwm:*colors*.

Documentation messages come from the help commands describe-command, describe-key, where-is, describe-variable, and describe-function. The default buttons that invoke them are listed by "Control-t h ?" (New prefix for Help).

Documentation messages use the same background and text colors as the prompt, t.i. stumpwm:set-bg-color and stumpwm:set-fg-color. They also emphasize some text with the sixth color (darker and brighter) from stumpwm:*colors*. Technically, that means four colors must be coordinated legibly.

Eval: (setf (cADr (cDDDDr stumpwm:*colors*)) "LightSkyBlue1")
Eval: (stumpwm:update-color-map (stumpwm:current-screen))

Error messages use the background color from stumpwm:set-bg-color, but for the text they use the second color (its lighter version) in stumpwm:*colors*, t.i. its cadr.

Eval: (setf (cADr stumpwm:*colors*) "DeepSkyBlue3")
Eval: (stumpwm:update-color-map (stumpwm:current-screen))

Messages from Lisp results are temporarily displayed after using the Lisp instruction prompt. Those messages use the background color from stumpwm:set-bg-color only for the padding around the message. The background and text colors are the darker versions of the car and caddr colors from stumpwm:*colors*.

Eval: (setf (cAr stumpwm:*colors*) "DarkOrchid4")
Eval: (setf (cADDr stumpwm:*colors*) "Thistle1")
Eval: (stumpwm:update-color-map (stumpwm:current-screen))

Consider using a substitute for update-color-map (github.com) that respects the colors of stumpwm:*colors*. Just copy into a new file and modify it, then load the file with load and use the new instruction. Note some names within it will need "stumpwm::" (two colons).

For example, simply changing the -0.25 to 0 ensures the first fabricated list is the exact colors specified rather than darker. Maybe drop the brightener to 0.2 for the second fabricated list, or perhaps accept more colors in an &optional additional list.

# Customize the buttonboard

A computer does what a person desires at the mere press of a button, but for most people that is only science fiction.

Neural-scan interfaces, such as buttonboards and motionboxes, transcend operating systems by means of virtual network computing (VNC). Personalization of their operation on one computer overcomes the inadequate personalization options on all other computers.

A personalizable computer (...no need to change the world) shares its neural-scan interfaces by connecting to the VNC host on another computer on the same desk, then the latter has no need of its own. The common desire of "rebinding keys" for any software becomes consistent and resilient, regardless of software upgrades on other computers.

Marking relevant starting points for the pointer (Make a point...) and consistently maneuvering it (Efficient pointer jumping) effectively supplants the arbitrary approach of the motionbox with a never-miss selection-based interface. This helps open the door to repeatability of a sequence of actions.

# [ ...Deactivate the
super-hyper-uber-meta-elite-hacker
menus... ]


[ ...back to the beginnin'... ]

The dozens of pre-defined abbreviations revealed by "Control-t ?" are overwhelmingly unfamiliar, and many are duplicates for the same commands.

Invoking an interactive keymap (StumpWM 3.2 Interactive Keymaps) temporarily disables all abbreviations for commands in the *root-map*. That means no access to any prompts, and no access to Help documentation. There is also no access to the button listing for an interactive keymap itself.

Consider starting fresh with an ordinary button map of personally chosen commands, preventing it from becoming disabled, and having button lists always accessible for viewing. Add more commands later as they become familiar and commonly used personally.

Make the button for the stumpwm::*escape-key* (by default "Control-t") the means to a familiar listing of commands associated with personally chosen buttons.


[ ...for now, a wee bit too much information
 because it includes notes for why it works...
...will gradually revise...

...the Lisp instructions are already precise,
 with "stumpwm::" as needed, and so forth...

...would like to mention using the setf
 for assigning new button maps to the *top-map*
 as a quick way to replace the buttonboard layout,
 or to store the buttons defined in *top-map*
 to a name for later re-storing...
... ]


[ ...Requirement:
a separate top button map (t.i. a "top map") with the stumpwm::*escape-key* assigned to the button map (t.i. a "root map") that is desired to be always accessible... ]

Eval: (setf escape.top-map (stumpwm::make-kmap))
Eval: (setf escape.map (stumpwm::make-kmap))
Eval: (define-key escape.top-map stumpwm::*escape-key* 'escape.map)

[ ...replace or override the list of top button maps listed within stumpwm:*group-top-maps* with a list of top maps assigned to only the desired maps...
...always include stumpwm:*top-map* because it is the buttonboard itself...
...hmm, the stumpwm::top-maps [events.lisp: 218–230 (StumpWM 1.0.1 source)] is the focal point as it is always used for determing the "active keymaps" from stumpwm:*group-top-maps*...
...disengage stumpwm::top-maps from stumpwm:*group-top-maps* (An introspective approach for defun) by simply providing a predetermined list, making sure stumpwm:*top-map* is the first...
... ]

Eval: (setf stumpwm::top-maps '(defun stumpwm::top-maps (&optional group) '(stumpwm:*top-map* escape.top-map)))

[ ...evaluating the replacement stumpwm::top-maps will eliminate two of the three parts of the default "Control-t" menu of command abbreviations...
...only the *root-map* remains, but that is fine because that is what has the command abbreviations for the instruction prompt and other prompts (Interactive curiosity) as well as to the Help map "Control-t h" abbreviations...
...as such, evaluate the replacement stumpwm::top-maps whenever comfortable going without the other two-thirds of the "Control-t" menu (mostly just super-hyper-uber-meta-elite-hacker split-view management)... ]

Eval: (eval stumpwm::top-maps)

Assign desired command buttons to the replacement button map before disengaging the *root-map* itself.

[ ...typing the button declared as the stumwpm::*escape-key* causes StumpWM to invoke whatever command has been associated with the very next button typed...
...the send-escape command provides the means for typing the stumwpm::*escape-key* itself...
...for example, after defining the stumwpm::*escape-key* as the "a" button, typing the "a" button would activate the special buttonboard layout that has default StumpWM commands (or the new personal button map that replaces it) associated with the buttons. In order to type an actual "a", the button assigned to the send-escape command would need to be typed after typing the stumwpm::*escape-key*...
...it makes most sense to assign the send-escape command to the same button, because then simply typing the button twice gives what it would have given...
... ]

Eval: (define-key escape.map stumpwm::*escape-key*"send-escape")

Include a button for the stumpwm:*top-map*. Though seemingly redundant, typing the assigned button and then a question mark "?" reveals its elusive button list, similar to "Control-t ?".

Eval: (define-key escape.map (kbd "/") '*top-map*)

Consider a button for resetting the stumpwm:*top-map*, t.i. completely blank. Make sure to assign buttons to the prompts and their Help documentation (Interactive curiosity) in the new replacement map, too, then they will always be available regardless of blanking the stumpwm:*top-map*.

Eval: (define-key escape.map (kbd "Eject") "eval-line (setf *top-map* (stumpwm::make-kmap))")

[ ...buttons for the various prompts and the Help commands for them (Interactive curiosity)...
...Consider buttons near whatever button the stumpwm::*escape-key* will be...
... ]

Eval:(define-key escape.map (kbd "F1") "eval-line")
Eval:(define-key escape.map (kbd "1") "describe-function")
Eval:(define-key escape.map (kbd "q") "describe-variable")
Eval:(define-key escape.map (kbd "F2") "colon")
Eval:(define-key escape.map (kbd "2") "describe-command")
Eval:(define-key escape.map (kbd "w") "describe-key")
Eval:(define-key escape.map (kbd "s") "where-is")
Eval:(define-key escape.map (kbd "F3") "run-shell-command")

[ ...deciding to go with the Esc button for the stumwpm::*escape-key* for the overall StumpWM prefix key, replacing the default "Control-t"... ]

Eval: (stumpwm::print-key stumpwm::*escape-key*)
"C-t"
Eval: (set-prefix-key (kbd "ESC"))
Eval: (stumpwm::print-key stumpwm::*escape-key*)
"ESC"

[ ...finally, disassociate the stumpwm:*root-map* from the main top map, the last of the three default StumpWM menus of pre-defined abbreviations. By default, the stumpwm:*root-map* is assigned to the stumpwm::*escape-key*... ]

Eval: (define-key *top-map* stumpwm::*escape-key* nil)

All that remains is the main top map, likely with no assignments. Also, the new button map is always available by typing the stumpwm::*escape-key*. Very probable ensured recoverability, and without the pre-defined clutter.

Consider reviewing other commands in the manual (StumpWM 2. Key Bindings), or the full listing with the commands prompt and the Help descriptions for them (Interactive curiosity).

# Assign a button to a command or command list


[ ...need to re-summarize various other sections
 and revise for clarity,
 perhaps consolidating here...

...define-key is used for
 either a button
 or a list of buttons...

...making a list of command buttons
 is simply assigning several buttons...

...a "prefix button" is nothing special,
 it is just access to a list of command buttons...
... ]

A command can be invoked by many different assigned buttons. Any button can be re-assigned to a different command. Any button can be freed by assigning it to nil instead of a double-quoted command name.

Assign a StumpWM command to a button with stumpwm:define-key (StumpWM 2.2). There are three parts for define-key.

1. Name of a keymap.
2. Double-quoted name of the button.
Use stumwpwm:kbd with the double-quoted name.
3. Either the double-quoted name of the command, or the quote with th name of another keymap.

For example, dedicate a single button for the Lisp instruction prompt. The original button sequence for eval-line of "Control-t :" will still be available, too. A successful result from stumpwm:define-key is NIL rather than an error.

Eval: (describe-key)
F5 is not bound.
Eval: (stumpwm:define-key stumpwm:*top-map* (stumpwm:kbd "F5") "eval-line")
NIL

Or more conveniently, consider shortening the names by leaving off the "stumpwm:" (Optional or required collection names).

Eval: (define-key *top-map* (kbd "F5") "eval-line")

Assigning with the stumpwm:*top-map* bypasses the need for the StumpWM prefix "Control-t". Instead, type only the declared button to activate the command.

The stumpwm:kbd instruction converts the double-quoted name of a button. Most buttons are used for typing, so consider using the F1 through F12 buttons when assigning with the stumpwm:*top-map*. However, a custom keymap with a prefix button means any button is available (Make a list of command buttons).

Use the describe-key command (New prefix for Help) to check whether the desired button is already assigned to a command, and decide whether to re-assign it. That also provides the actual name for the button despite what might be written on the button itself.

Note the double-quoted command can be any StumpWM command, but it must also be typed without the "stumpwm:" collection name (Optional or required collection names).

Coincidentally, the eval-line StumpWM command makes custom instructions possible, too (Any instruction at the press of a button).

Consider reviewing the full command listing with the command prompt (Invoke a StumpWM command by its name). Note on paper anything interesting.

Find out more about a command with describe-command (New prefix for Help), or from the StumpWM command and function index.

# Examples of custom commands

Assigning a button to Lisp instructions for StumpWM requires the instructions are a StumpWM command.

Conveniently, eval-line is a StumpWM command that evaluates a Lisp instruction given to it. It optionally accepts info immediately without need for the prompt.

The stumpwm:define-key allows for giving such info to a command within the double-quotes, but there must be a space after the command.

No need to create a new command for every set of Lisp instructions, let alone have to think of a new name for a command.

At most, just pick a button on the button board (Assign a button to a command), and optionally associate with a prefixed keymap (Make a list of command buttons).


# Introspect a duplicated half-paired list.

Consider defining buttons for introspection of a half-paired list, f.e. perhaps a Lisp instruction (Contrary formation and Lisp instructions). Specifically, consider abbi-abbi introspection (Abbi-abbi introspection), and ensure working on a copy.


Introspect the cADr rightwardly by associating the cADr with the cAr. Note the name is assigned to the memory that has the new result, thereby no longer referencing the original list.


(setf abbi-abbi.inspect
 (cons
  (cons
   (cADr abbi-abbi.inspect)
   (cAr abbi-abbi.inspect))
  (cDDr abbi-abbi.inspect)))
Eval: (describe-key)
F17 is not bound.
Eval: (define-key *top-map* (kbd "F17") "eval-line (setf abbi-abbi.inspect (cons (cons (cADr abbi-abbi.inspect) (cAr abbi-abbi.inspect)) (cDDr abbi-abbi.inspect)))")

Introspect the cADr leftwardly by associating the cAAr with the cDr. Note the name is assigned to the memory that has the new result, thereby no longer referencing the original list.


(setf abbi-abbi.inspect
 (cons
  (cDAr abbi-abbi.inspect)
  (cons
   (cAAr abbi-abbi.inspect)
   (cDr abbi-abbi.inspect))))
Eval: (describe-key)
F16 is not bound.
Eval: (define-key *top-map* (kbd "F16") "eval-line (setf abbi-abbi.inspect (cons (cDAr abbi-abbi.inspect) (cons (cAAr abbi-abbi.inspect) (cDr abbi-abbi.inspect))))")

Use the setf to associate a list with the introspection name, t.i. the name used with setf in the instructions assigned to the buttons. Initially, that will be a reference to the memory (Re-listing rather than re-arranging).

Use the buttons until the StumpWM message reveals the desired sublist as the cADr. The instructions assigned to the buttons associate the name to the memory that has the new results, thereby no longer referencing the memory of the original list.


Easily assign a new cADr with the setf in the Lisp instruction prompt.

Eval: (setf (cadr abbi-abbi.inspect) 'something.new)

Prepend a new item to the cDr by pairing it with cDr. Nothing is eliminated.

Eval: (setf (cdr abbi-abbi.inspect) (cons 'something.new (cdr abbi-abbi.inspect)))

Displace the cADr is by setting it to a reference of the cDDr, thereby eliminating the cADr.

Eval: (setf (cadr abbi-abbi.inspect) (cddr abbi-abbi.inspect))

Use the buttons to rewind to the beginning to restore the new list. Use setf to associate the new list with a new name, or with the name of the original list to replace it.


# Introspect a referenced half-paired list.

Consider defining buttons for introspection of a half-paired list by reference, f.e. perhaps a Lisp instruction (Contrary formation and Lisp instructions). Specifically, consider abbi-abbi introspection (Abbi-abbi introspection), and maintain the reference to the orginal list.


Introspect the cADr rightwardly by associating the cADr with the cAr. Note references to the car and cdr of the named memory are assigned individually rather than assigning the name itself to new memory.

(setf (cAr abbi-abbi.inspect)
 (cons
  (cADr abbi-abbi.inspect)
  (cAr abbi-abbi.inspect)))

(setf (cDr abbi-abbi.inspect)
 (cDDr abbi-abbi.inspect))

Consider using cons with the eval-line command in order to evaluate a pair of instructions (Two instructions at once).

Eval: (describe-key)
F17 is not bound.
Eval: (define-key *top-map* (kbd "F17") "eval-line (cons (setf(cAr abbi-abbi.inspect) (cons(cADr abbi-abbi.inspect)(cAr abbi-abbi.inspect))) (setf(cDr abbi-abbi.inspect) (cDDr abbi-abbi.inspect)))")

Introspect the cADr leftwardly by associating the cAAr with the cDr. Note references to the car and cdr of the named memory are assigned individually rather than assigning the name itself to new memory.


(setf (cDr abbi-abbi.inspect)
 (cons
  (cAAr abbi-abbi.inspect)
  (cDr abbi-abbi.inspect)))

(setf (cAr abbi-abbi.inspect)
 (cDAr abbi-abbi.inspect))
Eval: (describe-key)
F16 is not bound.
Eval: (define-key *top-map* (kbd "F16") "eval-line (cons (setf(cDr abbi-abbi.inspect) (cons(cAAr abbi-abbi.inspect)(cDr abbi-abbi.inspect))) (setf(cAr abbi-abbi.inspect)(cDAr abbi-abbi.inspect)))")

Use the setf to associate a list from named memory with the introspection name, t.i. the name used with setf in the instructions assigned to the buttons. Initially, that will be a reference to the memory (Re-listing rather than re-arranging).

Use the buttons until the StumpWM message reveals the desired sublist as the cADr. Remember, these instructions assigned to the buttons associate results with individual references to the car and cdr of the list, t.i within the named memory, rather than reassigning the name itself to new memory.


Easily substitute the cADr using the setf, t.i. eliminate the current cADr and provide a new one.

Eval: (setf (cadr abbi-abbi.inspect) 'something.new)

Prepend a new item to the cDr by pairing it with cDr. Nothing is eliminated.

Eval: (setf (cdr abbi-abbi.inspect) (cons 'something.new (cdr abbi-abbi.inspect)))

Displace the cADr is by setting it to a reference of the cDDr, thereby eliminating the cADr.

Eval: (setf (cadr abbi-abbi.inspect) (cddr abbi-abbi.inspect))

Use the buttons to rewind to the beginning to restore the list, thereby also for the named memory it referenced.

Optionally use setf to assign nil to the introspection name in order to disassociate it from the list of the named memory it referenced, or to another list for another introspection.


# Any instruction at the press of a button.

Consider storing an instruction in named memory, then use the eval Lisp instruction to evaluate the named memory. Coincidentally, the double-quoted text prevents the need for named memory to already exist.

Eval: (describe-key)
F14 is not bound.
Eval: (define-key *top-map* (kbd "F14") "eval-line (eval do.it)")

Change the instruction in the named memory whenever desired. No need to redefine the button, it will evaluate whatever is currently in the named memory.

# Make a list of command buttons

Use the stumpwm:make-sparse-keymap (StumpWM 2.2) to reference a personalized set of StumpWM commands and custom commands.

Choose buttons that personally make sense for each command. Like the "Control-t" prefix (Essential split-view commands), typing a prefix button and then a question mark "?" reveals only what is associated with that prefix button.

Pick an unused name for the "sparse keymap", then assign it with setf.

Eval: buttons.my
The variable BUTTONS.MY is unbound.Backtrace...
Eval: (setf buttons.my (stumpwm:make-sparse-keymap))

Quote that new name instead of using a command name for stumpwm:define-key, and then the button will be a prefix for any commands assigned to that "sparse keymap".

Eval: (describe-key)
F20 is not bound.
Eval: (stumpwm:define-key stumpwm:*top-map* (stumpwm:kbd "F20") (quote buttons.my))

Or more conveniently, consider shortening the names by leaving off the "stumpwm:" (Optional or required collection names).

Eval: (define-key *top-map* (kbd "F20") 'buttons.my)

Choose buttons that fit comfortably with the workflow of the day or hour. Consider using the up/down arrows for bringing forth the prior/next lines for less re-typing (Typing within a line of text).

Eval: (stumpwm:define-key buttons.my (stumpwm:kbd "m") "run-shell-command")
Eval: (define-key buttons.my (kbd "j") "pull-hidden-next")
Eval: (define-key buttons.my (kbd "f") "pull-hidden-previous")
Eval: (define-key buttons.my (kbd"c") "pull-hidden-other")
Eval: (define-key buttons.my (kbd",") "gnew")
Eval: (define-key buttons.my (kbd"k")"gnext")
Eval: (define-key buttons.my (kbd"d")"gprev")
Eval: (define-key buttons.my(kbd"x")"gother")

Note the double-quoted command, f.e. "pull-hidden-other", must be a StumpWM command rather than just any instruction, but it must also be written without the "stumpwm:" collection name (Optional or required collection names).

Prefix: F20
m     run-shell-command
j     pull-hidden-next
f     pull-hidden-previous
c     pull-hidden-other
,     gnew
k     gnext
d     gprev
x     gother

Type the new personal prefix and then a question mark "?" to get a listing of the abbreviations that have been assigned with that prefix. They are listed in the order they were added.

# Interactive keymaps: custom buttonboard layouts


[ ...an interactive keymap is less flexible
 than a "sparse keymap"
 because it is impossible to change the buttons afterwards
 for an interactive keymap (kinda contradictory),
 and the *root-map* is unavailable unless specifically assigned
 which means no buttons for Help or for prompts like eval-line
 unless specifically assigned...

...consider using stumpwm:push-top-map with a new keymap,
 then stumpwm:pop-top-map to restore prior keymap...

...But...those simply assign another keymap to *top-map*
 then they use the stumpwm:sync-keys function.
 Though those push/pop functions also save and restore
 the prior buttons assigned in *top-map*,
 that is nothing special because
 the assigned buttons could simply be already in another keymap.
 Just switch between various keymaps for *top-map* instead...

 In other words, consider from the Lisp instruction prompt:
  (cons (setf *top-map* another-keymap) (stumpwm:sync-keys))

... ]

[ ...
 ...the stumpwm:*root-map* is separate.

 so consider assigning the StumpWM prefix
 or any other preferred button
 to the *root-map* for its command buttons
 (such as for the various prompts like eval-line)...
... ]

[ ...

The StumpWM prefix button is always available, by default as "C-t". The StumpWM prefix is reliably referenced as stumpwm:*escape-key*. It is reliably re-assignable with set-prefix-key. Use the stumpwm:*escape-key* reference when wanting to assign the StumpWM prefix button to a button, such as for a command or to a keymap.


... ]


[ ...all info about "interactive keymaps" will likely be removed soon... ]

Evoking an interactive keymap temporarily enables its assigned buttons without need of a prefix button for each. That is very similar to using Shift Lock or Caps Lock in order to get capital letters, but in this case each assigned button instantly invokes a command instead.

The stumpwm:define-interactive-keymap (StumpWM 3.2) accepts a list of options after the chosen name for the interactive keymap, but an empty list or nil means apply the defaults. Next, each button and its desired command is grouped within parentheses, distinct from the others.

   ;;Consider rebinding the pointer-halving commands.
   (stumpwm:define-interactive-keymap
    halving.map
    ()
    ((stumpwm:kbd "i") "pointer-halving-up.nu")
    ((kbd"j")"pointer-halving-left.nu")
    ((kbd"k")"pointer-halving-down.nu")
    ((kbd"l")"pointer-halving-right.nu")
    ((kbd";")"pointer-halving-toggle.nu")
    ((kbd"m")"pointer-halving-back.nu")
    ((kbd",")"pointer-halving-begin.nu")
    ((kbd".")"pointer-halving-recenter.nu")
    ((kbd"h")"pointer-button-activate.nu 1")
    ((kbd"u")"pointer-button-toggle.nu 1")
    ((kbd"n")"pointer-button-activate.nu 3"))

Use define-key to assign the button for activating the interactive keymap. Double-quote the chosen name because an interactive keymap is actually a command, unlike a sparse keymap (Make a list of command buttons).

   (stumpwm:define-key stumpwm:*top-map*
    (stumpwm:kbd "F7") "halving.map"))

By default, the Esc button, or the Return button, or "Control-g" disables the interactive keymap. As a command, the interactive keymap can be invoked by its chosen name with the commands prompt (Invoke a StumpWM command by its name) of "Control-t ;" (a semicolon), too.


[ ...describe at least the :exit-on option for changing the default buttons for exiting the interactive keymap. For example, set it to be the same as the button defined to start, so then it feels like an on/off toggle button for the interactive keymap. Probably something like:
(:exit-on ((kbd "F7")))
Or, also include "Control-g":
(:exit-on ((kbd "F7") (kbd "C-g")))
for the same familiarity of other StumpWM commands
... ]

[ ...describe defining an interactive keymap with the evaluation prompt (The Lisp instruction prompt) using list introspection (Exploring a half-paired list)...
Though, already described that for pointer jumping (Efficient pointer jumping for any grid of options)... ]

# New prefix for Help

Prefix: F12
v     describe-variable
f     describe-function
k     describe-key
c     describe-command
w     where-is

Discover the command assigned to a button by using "Control-t h k" for describe-key. Fail to completely type the "h" and kill a program with delete-window instead. Disaster.

Consider making the Help commands more convenient, and averting a none too happy slip, by choosing a single prefix button. Check it by typing the new prefix button then the "?".

Eval: (describe-key)
F12 is not bound.
Eval: (stumpwm:define-key stumpwm:*top-map* (stumpwm:kbd "F12") (quote stumpwm:*help-map*))

Or, use the abbreviated names (Optional or required collection names).

Eval: (define-key *top-map* (kbd "F12") '*help-map*)

# Re-assign the StumpWM prefix

StumpWM uses "Control-t" as the prefix for abbreviations of its commands (Essential split-view commands). Consider keeping them, as they are relevant when reading the manual and other documentation.

Emacs (GNU) has the abbreviation "Control-x Control-t" for "transpose-lines", swapping the previous line of text (paragraph) with the current line (paragraph). Either rebind that command within Emacs, or simply use m+ in the ed text editor (GNU) (perhaps ed within Emacs "M-x shell"), or change the StumpWM prefix "Control-t" to something else, like an F button.

Eval: (stumpwm:set-prefix-key (stumpwm:kbd "F19"))

Confirm the new prefix by typing it followed by a question mark "?" to reveal the listing of buttons assigned to StumpWM commands. Note the prior prefix will be freed, thereby ignored by StumpWM and usable in other programs.

Note that the stumpwm:pull-hidden-other command is by default "Control-t Control-t", but will be automatically re-assigned similarly to twice the new prefix button instead.

# Essential split-view commands

There are about a half-dozen essential StumpWM commands for splitting the screen area for viewing different documents and programs.

StumpWM favors abbreviations for its commands (StumpWM 2. Key Bindings), short sequences of buttons for its predefined sets of instructions. One of those commands also provides a prompt for visibly typing any command name (Invoke a StumpWM command by its name).

StumpWM uses "Control-t" as the prefix for segregating its own commands from other programs. Use the Control button in the same manner as the Shift button, t.i. hold the Control button before typing a letter (skip the hyphen), then afterwards let go of it.

Though a button sequence is invisible, typing a prefix like "Control-t" in Stumpwm changes the pointer cursor from an X or arrow into a square as an indicator until the button sequence is completed or canceled.


All StumpWM commands are in the "stumpwm:" collection. That collection name can be included for the commands, f.e. stumpwm:fnext, but is unnecessary for them.

There are some details that might be worth noting for each of those essential StumpWM commands.


Control-t ?

Show the abbreviations for StumpWM commands prefixed with "Control-t".
Invoking any command will clear that message from the screen.

Also shows at its top "Prefix: " with the name of the StumpWM prefix button. That means the prefix must be typed first before typing any of the listed buttons for their commands.

Note "C-" means hold the Control button before typing the next letter or character.

Note "M-" means hold the Meta button before typing the next letter or character. The "Meta" button is probably the same as either the Alt button or the Option button, depending on the buttonboard.

Note the "*HELP-MAP*" entry for "h" means "Control-t h" is another prefix. Therefore, type "Control-t h ?" to show the commands that have that prefix (New prefix for Help).

Note typing any prefix followed by the "?" will list all the abbreviations assigned to its keymap (Make a list of command buttons).

pull-hidden-previous
or Control-t Control-p

Show the most recently hidden document or program, while hiding the current one.

hsplit
or Control-t S

Split in half the width of the current frame, which makes room for another document or program, especially the most recently hidden.

Note that is a capital S, the same as Shift-s.

Note typing a lowercase s instead invokes vsplit for splitting in half the height of the current frame.

remove-split
or Control-t R

Remove the current frame and hide the document or program that was in it.

Note that is a capital R, the same as Shift-R.

Note typing a lowercase r instead begins interactive resize (iresize) of current frame (when more than one frame) by means of the arrow buttons. Up and left decrease the frame size; down and right increase the frame size. The Esc button finishes resizing.

Many default button bindings for StumpWM commands are temporarily removed until resizing is completed. Consider that possibility when messages appear unexpectedly saying a button sequence is "not bound". Try typing the Esc button for finishing an interactive command. When effective, a confirmation message appears as either "finished." or "Abort.".

balance-frames
or Control-t +

Equally divide width and height of screen amongst frames.

Consider splitting the screen into three frames and then equalize them. Each frame is then one-third the screen. Then remove one of the frames. Two frames remain: one frame is two-thirds, and the other is one-third.

fnext
or Control-t o

Switch to the next frame in sequence. Generally cycles left to right and top to bottom, when there are that many, and then starts over from the left top.

# Reading and writing within the Lisp interpreter


[ ...need to revise, essentially as "Naming memory"... ]

The means for associating a nickname with information on a computer has generally been obscure with the software pre-installed on it. However, a Lisp interpreter such as SBCL used by StumpWM makes it straightforward with the Common Lisp setf macro (CLHS). Any information can be noted within the Lisp interpreter by associating a label with it.

(setf
remember "Something to remember."
a-name   "And one more thing.")

Nonetheless, that, too, is obscured as Common Lisp has 978 symbols of its own, including variables, functions, and macros. For whatever reasons, many implementations of Common Lisp (such as SBCL) have implemented everything as if the Common Lisp specification was an assignment.

As aforementioned (The Lisp instruction prompt), the evaluation prompt provided by "Control-t :" in StumpWM waits for only a single line, suitable for a quick short note.

Eval: (setf a-symbol "A name is a Lisp symbol.")
"A name is a Lisp symbol."

To see the information again, simply type the name in the evaluation prompt again and type the Return or Enter button. The name, a Lisp symbol, will be evaluated and once again a message with the result will be displayed for a few seconds, then disappear again.

Eval: a-symbol
"A name is a Lisp symbol."

As noted about Lisp and NIL, the final item in every parenthetical list is denoted by a space-separated dot, t.i. a period. The final list item is typically nil, so for brevity such lists are typed or printed without it, as mentioned in Lisp lists are pairs. Therefore, a list without a dotted final item actually does have one, and in that case it is nil.

Therefore, a straightforward way of converting a named symbol with a single item into a list for itself is pairing it with nil, and re-using its name. Notice from the message that the Lisp interpreter favors printing the abbreviated form, without the dotted nil.

Eval: remember
"Something to remember."
Eval: (setf remember (cons remember nil))
("Something to remember.")
Eval: remember
("Something to remember.")

Replace with a new list from the cons function by pairing the new information with the list itself.

Eval: (setf remember (cons "Curiosity more than expectations." remember))
("Curiosity more than expectations."
 "Something to remember.")
Eval: (setf remember (cons a-name remember))
("And one more thing."
 "Curiosity more than expectations."
 "Something to remember.")
Eval: (setf remember (cons a-symbol remember))
("A name is a Lisp symbol."
 "And one more thing."
 "Curiosity more than expectations."
 "Something to remember.")
Eval: (setf remember (cons "A quick note: write questions on paper." remember))
("A quick note: write questions on paper."
 "A name is a Lisp symbol."
 "And one more thing."
 "Curiosity more than expectations."
 "Something to remember.")
Eval: remember
("A quick note: write questions on paper."
 "A name is a Lisp symbol."
 "And one more thing."
 "Curiosity more than expectations."
 "Something to remember.")

Multiple car and cdr references can be abbreviated up to four places, as mentioned in Lisp lists are pairs. For example, a reference to the car of the cdr of a list can be from the abbreviated cadr function, t.i. the "a-d" of the list. As noted about Lisp and NIL, a list without a dotted final item actually does have one, and in that case it is nil.

Eval: (car remember)
"A quick note: write questions on paper."
Eval: (cdr remember)
("A name is a Lisp symbol."
 "And one more thing."
 "Curiosity more than expectations."
 "Something to remember.")
Eval: (car (cdr remember))
"A name is a Lisp symbol."
Eval: (cadr remember)
"A name is a Lisp symbol."
Eval: remember
("A quick note: write questions on paper."
 "A name is a Lisp symbol."
 "And one more thing."
 "Curiosity more than expectations."
 "Something to remember.")
Eval: (cddddr remember)
("Something to remember.")
Eval: (car (cddddr remember))
"Something to remember."
Eval: (cdr (cddddr remember))
NIL

The information is accessible only while the Lisp interpreter exists, so it will be gone after quitting StumpWM or turning off the computer. On the other hand, there are ways of removing parts of a list, and without turning off the computer.

Recall the setf instruction can set the value for a position in a list (An intro for Lisp), t.i. either the car or the cdr of the list. That makes leaving out an item simple, which is the same as removing it.

Eval: remember
("A quick note: write questions on paper."
 "A name is a Lisp symbol."
 "And one more thing."
 "Curiosity more than expectations."
 "Something to remember.")
Eval: (car (cdr (cdr remember)))
"And one more thing."
Eval: (cdr (cdr (cdr remember)))
("Curiosity more than expectations."
 "Something to remember.")
Eval: (setf (caddr remember) (cdddr remember))
("Curiosity more than expectations."
 "Something to remember.")
Eval: remember
("A quick note: write questions on paper."
 "A name is a Lisp symbol."
 "Curiosity more than expectations."
 "Something to remember.")

# Reading and writing with the computer medium


[ ...need to revise, probably "...external storage"... ]

Write information to a document in computer memory so it will be available the next time the computer is turned on (if it successfully restarts) by using with-open-file (CLHS) along with pprint (CLHS) for "pretty printing".

The with-open-file instruction has a plethora of options because it uses open (CLHS), so focus on what is desired. For example: write to a document; create the document when non-existent; append to the document when it does exist.

(with-open-file
(to-the-doc-from-WOF "/actual/name/for/document"
:direction :output
:if-does-not-exist :create
:if-exists :append)
(pprint "What you can do, while weeping."
to-the-doc-from-WOF))

It turns out this makes the eyes water, as it is a bit much to be typing into the Lisp interpreter every single time, and the StumpWM evaluation prompt handles only one line at a time. However, a Lisp instruction is an abdextrally half-paired list (Lisp lists are pairs).

Consider writing on paper a list of instructions for writing to a document, then noting the parts.

(with-open-file
(WOFdoc "/actual/name/of/doc"
:direction :output
:if-does-not-exist :create
:if-exists :append)
(pprint "Less weeping." WOFdoc) )

That list of Lisp instructions is essentially a list of three items.

  1. The name of the function for the instruction list: with-open-file.

  2. A list of options for with-open-file. First, a placeholder for when the document is opened successfully, followed by the location and document name, which is required. After those two, an option name is associated with an option, as many as needed. (Therefore, there will be an even number of list items.)

  3. The pprint instruction list. It prints any quoted Lisp form, such as double-quoted text or the results of Lisp instructions. After that is the reference to the opened file provided by the aforementioned placeholder declared in the list of options for with-open-file.

One approach is by constructing each sublist separately using quote (An intro for Lisp), or its abbreviated form as one single quote mark ', to write as much as comfortably possible at the evaluation prompt. Associate a placeholder name for each with setf.

Eval: (setf wof-options '(WOFdoc "/actual/name/of/doc" :direction :output :if-does-not-exist :create :if-exists :append))
(WOFDOC "/actual/name/of/doc" :DIRECTION :OUTPUT :IF-DOES-NOT-EXIST :CREATE :IF-EXISTS :APPEND)
Eval: (setf the-printer '(pprint "Divide and concoct." WOFdoc))
(PPRINT "Divide and concoct." WOFDOC)

A confirmation message from the Lisp interpreter prints the names of Lisp symbols with all uppercase letters. That is partially because the Lisp interpreter acknowledges only one case for letters in symbol names, and the convention of the Lisp interpreter is to reveal that by printing Lisp symbols as having uppercase letters.

Of course, that means symbol names varying only by case all reference the same symbol assigned to the same information. For example, the Common Lisp instruction names can be typed with whatever case desired and the Lisp interpreter will be fine with that, such as Format or FORMAT or fOrMat, and so on.

A Lisp instruction is an abdextrally half-paired list (Contrary formation and Lisp instructions) that begins with nil as its dexter. As it is leftwardly constructed, each additional part is the left half of the pair and the gradually forming list is always the right half.

Remember, using the up/down arrow buttons within the evaluation prompt (The Lisp instruction prompt) brings forth prior/later typed text for editing and re-using, thereby less re-typing.

Eval: (setf write-to-doc-recipe (cons the-printer nil))
((PPRINT "Divide and concoct." WOFDOC))
Eval: (setf write-to-doc-recipe (cons wof-options write-to-doc-recipe))
((WOFDOC "/actual/name/of/doc" :DIRECTION :OUTPUT :IF-DOES-NOT-EXIST :CREATE :IF-EXISTS :APPEND)
(PPRINT "Divide and concoct." WOFDOC))
Eval: (setf write-to-doc-recipe (cons (quote with-open-file) write-to-doc-recipe))
(WITH-OPEN-FILE
(WOFDOC "/actual/name/of/doc" :DIRECTION :OUTPUT :IF-DOES-NOT-EXIST :CREATE :IF-EXISTS :APPEND)
(PPRINT "Divide and concoct." WOFDOC))

The name is just a placeholder for the list of Lisp instructions, so the name by itself just reveals what it references.

Eval: write-to-doc-recipe
(WITH-OPEN-FILE
(WOFDOC "/actual/name/of/doc" :DIRECTION :OUTPUT :IF-DOES-NOT-EXIST :CREATE :IF-EXISTS :APPEND)
(PPRINT "Divide and concoct." WOFDOC))

Evaluate what the placeholder references by placing it in an instruction list using eval (An intro for Lisp). The double-quoted text listed with the pprint instruction will be written to the document named with the overall with-open-file instruction.

Eval: (eval write-to-doc-recipe)

[ ...describe the Lisp instructions for reading from a document, perhaps with read (CLHS), though it is a little bit tricky to view a whole document... ]


[ ...describe the delete-file (CLHS) instruction for deleting the files... ]

   (delete-file "/name/of/file")

Whenever desired, either change what to write to the document or change the document name with setf (An intro for Lisp). Query the parts of the recipe for confirmation of the correct place to change before changing it.

Eval: write-to-doc-recipe
(WITH-OPEN-FILE
(WOFDOC "/actual/name/of/doc" :DIRECTION :OUTPUT :IF-DOES-NOT-EXIST :CREATE :IF-EXISTS :APPEND)
(PPRINT "Divide and concoct." WOFDOC))
Eval: (car (cdr write-to-doc-recipe))
(WOFDOC "/actual/name/of/doc" :DIRECTION :OUTPUT :IF-DOES-NOT-EXIST :CREATE :IF-EXISTS :APPEND)
Eval: (cadr (cadr write-to-doc-recipe))
"/actual/name/of/doc"
Eval: (setf (cadr (cadr write-to-doc-recipe)) "/another/doc")
"/another/doc"
Eval: (caddr write-to-doc-recipe)
(PPRINT "Divide and concoct." WOFDOC)
Eval: (cadr(caddr write-to-doc-recipe)))
"Divide and concoct."
Eval: (setf (cadr (caddr write-to-doc-recipe)) "This is something else.")
"This is something else."
Eval: write-to-doc-recipe
(WITH-OPEN-FILE
(WOFDOC "/another/doc" :DIRECTION :OUTPUT :IF-DOES-NOT-EXIST :CREATE :IF-EXISTS :APPEND)
(PPRINT "This is something else." WOFDOC))

Optionally, use setf to replace the text in the instructions with a placeholder. Thereon, use setf to change the placeholder instead of the Lisp instructions. Optionally, insert a placeholder in the instructions for the document name, too.

Eval: (setf (cadr (cadr write-to-doc-recipe)) (quote doc-for-writing))
DOC-FOR-WRITING
Eval: (setf (cadr (caddr write-to-doc-recipe)) (quote text-to-write))
TEXT-TO-WRITE
Eval: write-to-doc-recipe
(WITH-OPEN-FILE
(WOFDOC DOC-FOR-WRITING :DIRECTION :OUTPUT :IF-DOES-NOT-EXIST :CREATE :IF-EXISTS :APPEND)
(PPRINT TEXT-TO-WRITE WOFDOC))
Eval: (setf doc-for-writing "/and/another/doc")
"/and/another/doc"
Eval: (setf text-to-write "Something for another document.")
"Something for another document."
Eval: (eval write-to-doc-recipe)
Eval: (setf text-to-write "And some more.")
"And some more."
Eval: (eval write-to-doc-recipe)

[ ...describe a setf instruction that will set the contents of the recipe to a placeholder write-to-doc... ]

   (setf recipe-for-later (cons write-to-doc-recipe nil))
   (setf recipe-for-later (cons 'write-to-doc recipe-for-later))
   (setf recipe-for-later (cons 'setf recipe-for-later))

[ ...Therefore that instruction sets a placeholder named write-to-doc to the contents of the recipe. Write that setf instruction to a document, then it can be read by the Lisp interpreter later with the load instruction. No need to type the recipe again and it is readily used with eval. ... ]

[ ...Typing the name in the evaluation prompt reveals the recipe. That shows the document name and text to write both have placeholders in the recipe for easily changing without needing to modify the recipe. ... ]

Ultimately, choose a new document name for writing these Lisp instructions. [ ...refer to the previously described new symbol with new instructions... ] Evaluate the instructions again and this recipe is written to that chosen document.

Eval: (setf doc-for-writing "/doc/for/this/recipe")
"/doc/for/this/recipe"
Eval: (setf text-to-write recipe-for-later)
(SETF WRITE-TO-DOC
(WITH-OPEN-FILE
(WOFDOC DOC-FOR-WRITING :DIRECTION :OUTPUT :IF-DOES-NOT-EXIST :CREATE :IF-EXISTS :APPEND)
(PPRINT TEXT-TO-WRITE WOFDOC)))
Eval: (eval write-to-doc-recipe)

[ ...describe using load for reading it from the document. Or, maybe with read then eval... ]

# X Window System and its protocol

# A translation of a misnamed paradigm

A "window" is a misnomer for a designated area, typically rectangular. An area is simply the coordinates for its left-top corner associated with its width and height (rather than its kittycorner coordinates): (x, y) (w, h).

Various shapes within an area are displayed by declaring two different colors (background and foreground), the type of shape, and the method of merging the intersection with other prior drawn shapes within the same area. That is, each area constrains its own content, but shapes merge by a variety of methods (sixteen) within the area, f.e. merging of a red shape and a blue shape can make their intersection purple.

Abutting each designated area along their edges is akin to tiling the areas, such as when creating split-views. The X Window System protocol limitedly supports intersection of the designated areas themselves by means of a single priority list for the areas. Intersecting areas of higher priority are subtracted from areas of lesser priority, like what remains as each area is cut from a piece of paper.

Therefore, the designated area that has the highest priority maintains its rectangular shape because it has no intersecting areas subtracted from it. The other areas maintain their shape when intersecting only lesser priority shapes, if any intersection at all. This also implies there is no true transparency effect for an area, because designated areas are only subtracted and never merged.

In other words, the designated areas are meant to be rectangular and their intersections are subtracted, whereas a variety of additionally described shapes can merge with each other within a single designated area.

Furthermore, a designated area can have areas designated within its bounds prioritized amongst themselves, but those internal areas are forbidden from extending beyond the outer area. Obviously, those subregions are intersecting with whatever shapes have been described within the overall area, but only by means of subtraction because they are designated areas instead of shapes.

A pixmap, t.i. a picture map, is a simple list of dots (pixels) associated with a color for each dot. The content of a designated area can be exported as a pixmap. A pixmap can be applied fully or partially anywhere within any area, and can be assigned as the background of any area. The Xserver automatically applies the background of a designated area for the pixels that area has priority, but any other described content is managed separately by external software (t.i. a client) when it receives notifications from the Xserver.

An intersection is visibly changed by the higher priority area for that intersection. As such, a designated area with no content and no background seemingly acquires all pixels within its boundaries from either the overall backdrop of the Xserver or from lesser priority areas, with no further visible changes from modifications of intersections with lesser priority areas.

# Color names

Acceptable color names are the X11 rgb colors (freedesktop.org), which might be also located on the computer with the Xserver as "/usr/local/share/X11/rgb.txt".

Acceptable RGB hexadecimal numbers for the red, green, and blue hues of a color are similar to HTML colors, with an octothorpe # followed by either three or six digits.

   Hex #  0 1 2 3 4 5 6 7 8 9 A B C D E F
     Red  0 1 2 3 4 5 6 7 8 9 a b c d e #f00 or #ff0000
   Green  0 1 2 3 4 5 6 7 8 9 a b c d e #0f0 or #00ff00
    Blue  0 1 2 3 4 5 6 7 8 9 a b c d e #00f or #0000ff
   All 3                                #fff or #ffffff

For example, orange is either "orange" or "Orange". As a hexadecimal number, orange is more red than green, like "#f60", "#D40", or "#FA8038". Compare with "yellow" which is red and green somewhat equal, like "#ff0".

# Discover keycodes for buttons

Each button on a buttonboard has an id often known as a "keycode". A symbol or icon on a button is often known as a "key symbol" or "keysym". Associating a keysym with a keycode is often known as "keymapping". Changing the keysym associated with a keycode is often known as "remapping".

The Xserver keeps a list of keycodes for the buttons on a buttonboard, and each keycode is associated with seven keysyms (U.S. English). For example, the button labeled with "A" likely has the keysyms for at least "a" and "A".

Use the Lisp instruction prompt to discover the keycode for a button after it is typed by using the xlib:grab-key, the stumpwm::read-key (two colons!), and the xlib:ungrab-key functions.

Eval: (xlib:grab-key (stumpwm:screen-root (stumpwm:current-screen) :any))
42004
Eval: (stumpwm::read-key)
(66 . 0)
Eval: (xlib:ungrab-key (stumpwm:screen-root (stumpwm:current-screen) :any))
46422

The stumpwm::read-key instruction (StumpWM input.lisp, 262–267) reveals the keycode for the next button pressed, paired with a number representing which modifiers were active. No prompt. Only the keycode (the left half) is useful for the purpose of remapping. A button used as a modifier, like Shift, will reveal its own keycode when it is pressed by itself.

Eval: (stumpwm::read-key)
(28 . 4)
Eval: (car (stumpwm::read-key))
28

However, StumpWM normally grabs only the keys that were defined for commands, like the "Control-t" prefix. According to the documentation for xlib:grab-key, use :any (with the colon) as the keycode for accepting any button pressed.

The xlib:grab-key needs both an Xwindow and a keycode, and then returns a number that has nothing to do with keycodes, so ignore that number. StumpWM provides screen-root for extracting the root Xwindow from the results of the current-screen instruction. The root Xwindow for the current screen is often appropriate for generic introspection like this.

Predictably, specifying :any like this means StumpWM will notice any button pressed. Thereby, StumpWM will seek a command defined for each, and provide a message each time that fails. Obviously, this interferes with using other programs. Conveniently, StumpWM ceases looking for commands whenever it provides a prompt, like for Lisp evaluation.

In the mean time, use stumpwm::read-key from the Lisp instruction prompt. It will now reveal the keycode for the very next button pressed, even for a button like Caps Lock. Write on paper the label on the desired button, press the button, then write on the paper the keycode (the left half) that is revealed. Keycodes are often somewhat sequenced from left to right, top to bottom on a buttonboard.

Use stumpwm::read-key again for another button, or use the xlib:ungrab-key instruction with the exact same info that was given to xlib:grab-key to return typing to normal. Just like xlib:grab-key, the xlib:ungrab-key produces an arbitrary number, no need to record it.

The only difference between the grab/ungrab instructions is the "un" of xlib:ungrab-key. Recall, the up/down arrow buttons in the evaluation prompt reveal the prior/next lines that were typed, for less re-typing (the Lisp instruction prompt). The Home button or "Control-a" moves the text cursor to the beginning of the line in the prompt quicker than the left arrow button.

For a bit more convenience and less clutter in the prompt history, assign a button to a command using eval-line (Any instruction at the press of a button) with stumpwm::read-key (because it is was defined with defun rather than defcommand). Then, just press that button to invoke the command instead of using the Lisp instruction prompt each time.

Eval: (describe-key)
F16 is not bound.
Eval: (stumpwm:define-key stumpwm:*top-map* (stumpwm:kbd "F16") "eval-line (car(stumpwm::read-key))")

# Change button symbols for keycodes

[ ...rewriting... ...no need for "xmodmap", there are at least two simple approaches, either with aref or a foldy, while using CLX... ]
[ ...hmm, Xserver seems unaffected by the change...and sometimes StumpWM crashes...see xlib:change-keyboard-mapping pecularities... ]

Use the work-on-a-copy approach: obtain a copy of a current setting, modify the copy, replace the current setting with the modified copy.

The xlib:keyboard-mapping (CLX 15.4.2) provides a copy of each keycode (0–255) and its keysyms (probably seven each).

Eval: keymap.my
The variable KEYMAP.MY is unbound.Backtrace...
Eval: (setf keymap.my(xlib:keyboard-mapping stumpwm:*display*))
#2A((0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (65307 0 65307 0 0 0 0)
 (49 33 49 33 0 0 0)
 (50 64 50 64 0 0 0)
 ...)

The xlib:keyboard-mapping provides a two-dimensional array. An array looks like a list of lists preceded by an octothorpe "#" and its number of dimensions, but an array is accessed or modified with only array instructions (CLHS 15.2 The Arrays Dictionary).

Congruently, the xlib:change-keyboard-mapping (CLX 15.4.2) requires a two-dimensional array. It is also important to specify the :end as 255, or the final keycode.

Eval: (xlib:change-keyboard-mapping stumpwm:*display* keymap.my :end 255)

The aref (CLHS) gives the array reference for an item when given its position for each dimension. The position is the number of other items before the desired item, for each dimension from outside to inside. For example, there are zero items before the first item so it is at the zeroth position, there are forty-two items before the forty-third item so it is at the forty-second position, and so forth.

The two-dimensional keycode array is sized as [256 7], so the array indices are 0–255. That allows for the subrange of 8–255 to match exactly with the keycodes 8–255, so specifying the keycode number is conveniently the same as the array position. The extra few at the beginning are of no matter.

The seven keysyms are referenced by 0–6 for the second dimension by the conventional skip-index approach. So, skip 0 items for access to the first keysym, skip 1 item for access to the second, and so on.

Eval: (aref keymap.my 66 0)
65490
Eval: (setf (aref keymap.my 66 0) #xff0d)
65293
Eval: (aref keymap.my 66 0)
65293

It might be more convenient to replace a whole list of keysyms for a keycode rather than change each of its keysyms individually.

Convert the two-dimensional array of individual keysyms into a one-dimensional array of lists of keysyms with write-to-string (CLHS), then read-from-string (CLHS), and then make-array (CLHS).

The write-to-string converts any Lisp form into double-quoted text. The read-from-string converts double-quoted text into a Lisp form, but can also skip characters at the beginning and ending. Simply skip the description of the array, t.i. the text before the first parenthesis.

Eval: (setf keymap.my (write-to-string keymap.my))
"#2A((0 0 0 0 0 0 0)...)"
Eval: (setf keymap.my (read-from-string keymap.my nil nil :start 3))
((0 0 0 0 0 0 0)...)

The read-from-string has two other options prior the options to skip characters. Just provide nil for each before specifying :start for skipping the first three characters ("#2A") of the text. It then becomes an ordinary list of lists.

Give the make-array the number of items of only the outer list to make a one-dimensional array. Either presume 256 keycodes, or confirm with length (CLHS). The result will be a list prepended with an octothorpe, indicating it is actually an array.

Eval: (length keymap.my)
256
Eval: (setf keymap.my (make-array '(256) :initial-contents keymap.my))
#((0 0 0 0 0 0 0)...)

The solitary octothorpe is the abbreviation for "#1A", a one dimensional list. That means this is now an array of lists, so a whole list of keysyms is accessible and replaceable with aref. Individual keysyms are still accessible and replaceable within the lists, but by means of cdr and car.

Eval: (aref keymap.my 66)
(65293 0 65490 0 0 0 0)
Eval: (setf (aref keymap.my 66) '(#xff0d 0 #xff0d 0 0 0 0))
(65293 0 65293 0 0 0 0)
Eval: (cadr (aref keymap.my 66))
0
Eval: (setf (cadr (aref keymap.my 66)) #xff09)
65289
Eval: (aref keymap.my 66)
(65293 65289 65293 0 0 0 0)

Ultimately, the keycodes need to be a two-dimensional array for xlib:change-keyboard-mapping. Use the same technique: write as text, read the text without the array prefix, make a new array from the list of lists. Recall, count, or confirm with length there are 7 items for the second dimension.

Eval: (setf keymap.my (write-to-string keymap.my))
"#((0 0 0 0 0 0 0)...)"
Eval: (setf keymap.my (read-from-string keymap.my nil nil :start 1))
((0 0 0 0 0 0 0)...)
Eval: (setf keymap.my (make-array '(256 7) :initial-contents keymap.my))
#2A((0 0 0 0 0 0 0)...)
Eval: (xlib:change-keyboard-mapping stumpwm:*display* keymap.my :end 255)

[ ...See xlib:change-keyboard-mapping pecularities... ]




[ ...likely the modifier buttons section... ]


[ ...

The U.S. English buttonboards have 47 buttons for letters and symbols. Typically, holding down the Shift modifier button signals the computer to provide another 47 alternate symbols, such as capital letters and more punctuation.

The Control and Alt modifier buttons individually provide 47 additional alternate possibilities each. Holding two modifier buttons at the same time is another distinct signal for the computer for three more sets of 47 possibilities: Shift+Control, or Shift+Alt, or Control+Alt. Holding all three is yet another 47 possibilities.

Eight layouts overall, each providing 47 possibilites, totals a minimum of 376 possibilities. That is a minimum because there are other buttons, like F1–F12 or Home/End/Help or Tab/Return/Space or arrow buttons and more, and all can be combined with any combination of modifier buttons.

As such, there really is no need for so many (three!) modifier buttons. Also, a modifier button held with a thumb enables typing with the other fingers of the same hand, thereby making two of each modifier redundant.


... ]

[ ...some ideas or inspiration... ]


[ ...

Consider swapping "QWE" for the familiar sequence "ABC", or "123" to "012". Make the caps lock button the prefix for commands. Consider putting the braces "( )" (unshifted) and brackets "[ ]" (shifted) in the center at T Y (left and right), maybe the comma/double-quote at G and period/apostrophe at H, and rearrange the letters some.

Consider having the hands one row up, thereby the thumbs can easily type the buttons on the bottom row above the barbutton. Make each of those bottom buttons a space button and Return, and one each of Shift, Control, and Alt.

Consider rotating the buttonboard 180 degrees. The function buttons F1–F12 are then physically at the bottom for the thumbs. Assign a function button for the new space button, a new Return button, and single modifier buttons for Shift, Control, and Alt. Assign "Return" to a button somewhere left of the space button, since that is what each actually does anyway.

In essence, make it familiar and personally convenient, or continue using what was manufactured for no one in particular. Different is okay, likely no one else will ever notice, as it is a personalized computer. Either way, consider keeping notes on paper for each layout associated with each modifier button.


... ]

# Common Lisp X Interface (CLX)

For now, these are attempts at unraveling some obstinate functions of the Common Lisp X Interface, because every programming fad on the planet was used to implement any and every part, likely in the name of "modern programming" or "robustness". To be fair, many of the fads were in the Common Lisp HyperSpec, rather than as a separate set of approaches (like a cookbook).

On the other hand, some paradigms from other computer programming writing systems (misnomered as "computer languages") were prostheticized into CLX for the sake of whomever wrote it. That is fine, except there is no workflow or intent included, so there is no record of actual usage, no shared experience, and so no inspiration for extensibility.

Let it be made clear: There is no extensibility from "extended". The latter is merely the footprint of a dinosaur, what the computer manufacturers and operating system companies provide for free (extendedness) with the fantasies (marketing) they sell in the name (branding) of their own personal charities (online stores).

Source code is worthless when there is too much of it. Modular is only worthwhile when actually used, rather than made "just in case" or to fluff out all the possibilities.

Prefabricated is lifeless and unadaptable. Lack of intent and real world usage is uninformative and uninspiring. Perfectness itself never sits still and it is pointless as a goal, but is experienced in the flow of everyday life, beyond the dead written past of history or the freshly mummified bleeding edge computer programs.

Both CLX and Common Lisp were clearly too much for the people involved in writing them to handle, and they did the best they could with those two behemoths. They can only be torn apart, most of the pieces thrown aside, and maybe something familiar and inspiring will provide an outlet for ingenuity. They are clearly worthless for the everyday individual, for they are unspokenable by the vernacular of the layman and fail to fit with what emerges from the split second moment of life.

# xlib:change-keyboard-mapping pecularities

For whatever reason the Xserver seems to be unaffected by the changes from xlib:change-keyboard-mapping (CLX 15.4.2). CLX documentation says use NIL for NoSymbol, though X11 protocol says zero is fine. NIL sometimes produces an error. Zero is without error, but so far the changes to zero for the first keysym position for a keycode are unchangeable thereafter.

Most notable is an "unsigned byte 8" error occurring for values greater than 255 for :end, possibly from type checking done with the functions/macros named with the prefix "index..." that are from text.lisp of CLX source.

The xlib:keyboard-mapping returns an array sized as [256 7] by default, and is therefore unreturnable to xlib:change-keyboard-mapping because its :end is documented as (array-dimensions keysyms 0) by default, t.i. 256.

xlib:change-keyboard-mapping breaks (xlib::display-keysym-mapping stumpwm:*display*) sometimes by leading to 20 entries per keycode rather than just 7, and at other times inserts the wrong keysyms for a keycode.
The source code requires :end be one more than the final keycode because length equals ":end - :start", but it also rejects 256 as a value for including the final possible keycode 255, t.i. only 0–254 is possible even though 8–255 is what is specified in the X protocol.
A potential workaround is to provide a smaller array, such as [248 7] for 8–255 (seven keysyms each), and specify :first-keycode as greater than 0, such as 9 (typically the first on the buttonboard anyway, as Escape). Then :start is 0 and :end is number of keycodes plus one. However, additional testing suggests a smaller array fails.

The REWRITE would be to make :end be the actual final keycode position in the supplied array, then have the function calculate the count inclusively of the specified indices by ":end - :start + 1", and have the loop cease at ">" rather than ">=".
But xlib:change-keyboard-mapping fails to make correct changes, so there is no point normalizing its interface. It simply needs to be abandoned (or the funicular spaghetti code further untangled).
The xlib:process-event (CLX 13.2) documentation points out the CLX cache of keysyms needs to be invalidated, and that xlib:mapping-notify (translate.lisp: 494–506) is for helping with that. However, the latter takes four values and there is no example workflow. Prior experience and knowledge and intent is just supposed to be magically known for a custom CLX function with an indirect relation to the X protocol. Internally, there are just two significant lines, the most notable being (setf(xlib::display-keysym-mapping stumpwm:*display*)nil), which seems to have no effect when used from the Lisp evaulation prompt provided by eval-line from StumpWM. But that apparent ineffectiveness might be because of the failure or incorrect usage of xlib:change-keyboard-mapping (presuming there is a correct way of using it).

When no error or crashing, ineffectiveness is confirmed with xlib:keycode->keysym (CLX 15.4.3).

Eval: (xlib:keycode->keysym stumpwm:*display* 66 0)
0

But, confirmed it does work with prior xmodmap instructions:

(stumpwm:run-shell-command "xmodmap -e 'keycode 66 = Return Tab'")

However, consider changing keycode 66 to the keysyms for Return (#xff0d) and Tab (#xff09) with the xlib:change-keyboard-mapping. StumpWM crashes, but at the console. [StumpWM seems unrestartable after killing it, just repeats the same error at the console. Seem to need to kill both StumpWM and Xserver, then restart them, then everything seems fine again.]

Eval: (xlib:change-keyboard-mapping stumpwm:*display* (make-array '(1 7) :initial-contents '((65293 65289 65293 65289 0 0 0))) :first-keycode 66 :start 0 :end 1)

Or, consider swapping "@" (keysym 64) with "2" (keysym 50) for its typical keycode 11. Normally, the keysyms are (50 64 50 64 0 0 0). No error, and there is a change for keycode 11, but to all zeros, meaning there is now no way to type "2" or "@" (hence why it was chosen as a test rather than "1", so its keycode could be typed in the prompt afterwards).
[Hmm, does it really want an array with at least that many keycodes? If so, then the aforementioned workaround of using a smaller array simply avoids the error without ever being possible to set all keycodes.]

Eval: (xlib::disply-keysym-mapping stumpwm:*display*)
#2A((0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (65307 0 65307 0 0 0 0)
 (49 33 49 33 0 0 0)
 (50 64 50 64 0 0 0)
 ...)
Eval: (xlib:change-keyboard-mapping stumpwm:*display* (make-array '(1 7) :initial-contents '((64 50 64 50 0 0 0))) :first-keycode 11 :start 0 :end 1)
Eval: (xlib::disply-keysym-mapping stumpwm:*display*)
#2A((0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (0 0 0 0 0 0 0)
 (65307 0 65307 0 0 0 0)
 (49 33 49 33 0 0 0)
 (0 0 0 0 0 0 0)
 ...)
Eval: (xlib:keycode->keysym stumpwm:*display* 11 0)
0

Sometimes there is an error at the console with varying number for "the value". StumpWM crashes (maybe?) as it is no longer available, but ps shows its process still listed.
Rather repeatable, something to do with attempting to change keyboard mapping more than once, perhaps when trying something different. Try 12 keycodes in array with only two keysyms, t.i. size of [12 2], and include the first 12 keycodes, but specify only :first-keycode 11, :start 0, :end 1.
[ Ran out of room on paper...write the rest next time. ]

Caught 'The value
          1476395008
        is not of type
          (UNSIGNED BYTE 29)' at the top level. Please report this...
...
0:(XLIB::AREF-CARD29 #<unavailable argument> #<unavailable argument>)
1:(XLIB:KEYBOARD-MAPPING #<XLIB:DISPLAY :0 ...> :FIRST-KEYCODE NIL :START NIL :END NIL :DATA NIL)
...
6:(STUMPWM:UPDATE-MODIFIER-MAP)
...
8:(STUMPWM::HANDLE-EVENT :EVENT-KEY :MAPPING-NOTIFY :EVENT-CODE 34 ...)

Perhaps re-check stumpwm:handle-event (StumpWM events.lisp: 634–671) and the :mapping-notify handler (StumpWM events.lisp:380–385), as StumpWM might be causing interference. The latter is evoking stumpwm:update-modifier-map (StumpWM input.lisp: 836–838; but consider 796–838). (Note: personal keymap has no Meta, and StumpWM does something special when that is the case.) Probably just a distraction from the main concern of xlib:change-keyboard-mapping.

Restarts are advertised but impossible. Afterwards, there is a reference to the CLX source, though it claims the file has been modified since compilation (doubtful).

(XLIB::AREF-CARD29 #<unavailable argument> #<unavailable argument>)
; File has been modified since compilation:
;   /.../common-lisp/clx-0.7.5/dependent.lisp
; Using form offset instead of character position.
   source: (THE CARD29 (ASH (THE CARD8 (AREF A (INDEX+ I +LONG-2+))) 16))

# Pointer placement and activation

The most immediate change to StumpWM is applied with the eval-line command (the Lisp instruction prompt), available with Control-t then colon, usually notated as "C-t :".

That is also the means for loading a file with a more comprehensive change written with Common Lisp, by using load (CLHS). For example:

(load "~/.stumpwm.d/custom/points-later.lisp.html")

The ".lisp" suffix is common for files with Lisp, but is optional because Lisp is just plain text, just like HTML and CSS.

# Alternative for pointer activation and drag'n drop

The basic pointer activation in StumpWM (the Xwindow manager formerly known as "ratpoison") depends on a legacy function named ratclick. That might fail when the CLX library is without support for the XTEST extension for the Xserver, especially when the XTEST extension is undetected.

The StumpWM functions expect xlib:fake-button-event from a CLX library, but it has been known to be named xlib/xtest:fake-button-event (CLX extensions/xtest.lisp: 13 and 117–128). Therefore, confirm the name and requirements in the sources when needed.

The xlib/xtest:fake-button-event requires a display like stumpwm:*display*, the number of the motionbox button, and either t or nil for either pressing or releasing the button.

The primary button is usually 1 and the secondary button is traditionally 3, because the middle button is usually presumed even when nonexistent. Pressing a button on the motionbox is one event, and releasing the same button is another event.

Eval: (setf press.1 '(xlib/xtest:fake-button-event stumpwm:*display* 1 t))
Eval: (setf release.1 '(xlib/xtest:fake-button-event stumpwm:*display* 1 nil))

Consider defining a separate buttonboard button (Assign a button to a command) for each event, then drag'n'drop can be done without disaster.

Eval: (describe-key)
F7 is not bound.
Eval: (stumpwm:define-key stumpwm:*top-map* (stumpwm:kbd "F7") "eval-line (eval press.1)")
Eval: (describe-key)
F8 is not bound.
Eval: (stumpwm:define-key stumpwm:*top-map* (stumpwm:kbd "F8") "eval-line (eval release.1)")

Consider combining both events for a single buttonboard button, for when the pointer is already in the perfect location. The eval-line evaluates only one Lisp form (The Lisp instruction prompt), but cons is a single instruction that accepts two Lisp forms (There can be only one).

Eval: (cons (eval press.1) (eval release.1))

Drag'n'drop involves moving the pointer. A press of the button at the drop location is probably innocuous. Consider repurposing the buttonboard button assigned to releasing the motionbox button, as the press/release combo event likely suffices. Otherwise, choose another buttonboard button.

Eval: (define-key *top-map* (kbd "F8") "eval-line (cons (eval press.1) (eval release.1))")

Consider adding the actions to an interactive keymap (...custom buttonboard layouts), such as with pointer jumping (Efficient pointer jumping) or pointer halving (Mathemagical pointer and cursor placement).

# Toggle for drag'n drop

A dragon would probably drop what a bird typically drops, as they both have a cloaca, but likely a bit more biohazardous for anyone underneath it. Similarly, accidentally letting go of the button on a motionbox while trying to reposition the cursor might be disasterous, or at least lead to extra work to undo the accident.

The Xserver keeps track of whether a "pointer button" has been pressed, as well as any pressed modifer buttons on the buttonboard intended for that pointer button. As such, it is possible to toggle a button press and a button release individually with the same command bound to a single button on the buttonboard instead.

The Common Lisp X Interface function xlib:query-pointer (CLX 13.5 Pointer Position) reveals what pointer buttons are pressed, by means of the fifth element it returns.

(car
(cddddr
(multiple-value-call 'list
(xlib:query-pointer
(stumpwm:screen-root(stumpwm:current-screen))))))

For example, when button 1 is pressed, the result from it is 256, because it is actually the binary mask: 00000001 00000000. The first part (from right to left, just like decimal numbers) indicates the modifer buttons pressed on the buttonboard, with zero meaning nothing pressed. While 2^8 is 256 (t.i. 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2), the eight bits include zero, therefore the first byte is 0–255. A ninth bit is required to begin the next range for 256–511 (instead of 512 for 2^9), which is why the ninth bit is 1 and represents 256.

A decimal number can be used as a mask, which is why the results of xlib:query-pointer returns "256". The binary "1 00000000" is merely a different way of writing the number, rather than a different number. Specifically, in Common Lisp #b100000000 means that is a binary number, which is 1 with eight zeros, the aforementioned "256".

The Xserver seems to track only five pointer buttons, so only the first five bits are used of the second 8-bit byte. That means when there are five buttons on a motionbox and all are pressed (and held), and with no modifier buttons pressed, then the Xserver would return the number known in binary as: 00011111 00000000.

One way to programmatically determine from the bits of such a number which button is pressed is with Common Lisp logic functions (CLHS 12.2 The Numbers Dictionary). For example, logand can compare each bit from two numbers and return a new number. Only the bits for the positions that are 1 in both numbers will be 1 in the new number, otherwise a bit will be zero. Order of the numbers for logand is of no matter because it is only a comparison.

 (logand
 #b00011111
 #b00000100)
means:
   00011111  -  all five buttons are pressed
   00000100  -  mask representing button 3
   --------
   00000100  -  this figured out button 3 is pressed


 (logand
 #b00000001
 #b00000100)
means:
   00000001  -  only button 1 is pressed
   00000100  -  mask representing button 3
   --------
   00000000  -  this figured out button 3 is released

A number can be manipulated like a mask by using "arithmetic shift" to shift the bits to the left or right, by means of the function ash. That means "00000001" (binary for 2) shifted by 3 becomes "00001000" (binary for 8), because a positive shift is leftwards. In other words: 1 * 2^3.

 (ash 1 3)
   => 8

Since buttons 1–5 are positions 1–5 in the 8-bit byte, then the mask for a button can be made by shifting a "1" until it is in the same position. For exmaple, "00000001" to "00000100" for button 3 would be a shift of 2, which is one less than the button number.

 (setf button 3)
 (ash 1 (- button 1))
   => 4

Therefore, a command can be written to inform the Xserver a pointer button has been pressed, and the same command can be used for releasing the pointer button by confirming the button with the mask the Xserver returns when the pointer is queried.

Toggle primary button for "press" or "release", f.e. text selection, drag'n drop without accidental drop, or anything else distinguishing a button press from a button release event.

# Alternative for pointer placement

The Common Lisp X Interface function xlib:warp-pointer (CLX 13.5 Pointer Position) when given an Xwindow and coordinates will place the pointer at those coordinates within the area of that Xwindow.

The function xlib:pointer-position (CLX 13.5) when given a specified Xwindow returns the coordinates of the pointer (and some more data).

Alternatively, the function xlib:global-pointer-position (CLX 13.5) when given a display (like stumpwm:*display*) returns the individual coordinates of the pointer and the root Xwindow.

Eval: (xlib:global-pointer-position stumpwm:*display*)
600
450
#<XLIB:WINDOW :0 123>

These functions make use of the Common Lisp peculiarity (contrary to other Lisps) of "returning multiple values", t.i. returning a series instead of a list.

Eval: (cadr (xlib:global-pointer-position stumpwm:*display*))
The value
       600
     is not of type
       LIST
     when binding LISTBacktrace for: #<SB-THREAD:THREAD "main thread" RUNNING {0123456789}>
0: (STUMPWM::BACKTRACE-STRING)
1: (ERR "~A" #<TYPE-ERROR expected-type: LIST datum: 1050>)
...

Only the "primary value" gets noticed by other Lisp functions. All other values after the first are lost, by default.

Eval: point.test
The variable POINT.TEST is unbound.Backtrace...
Eval: (setf point.test (xlib:global-pointer-position stumpwm:*display*))
600
Eval: point.test
600

The Common Lisp special operator multiple-value-call (CLHS 5.3 The data and control flow dictionary) or a similar "multiple-value-" macro must be used for accessing all the values, f.e. as an actual list.

Eval: (multiple-value-call 'list (xlib:global-pointer-position stumpwm:*display*))
(600 450 #<XLIB:WINDOW :0 123>)
Eval: (multiple-value-list (xlib:global-pointer-position stumpwm:*display*))
(600 450 #<XLIB:WINDOW :0 123>)
Eval: (reverse (cdr (reverse (multiple-value-list (xlib:global-pointer-position stumpwm:*display*)))))
(600 450)
Eval: (multiple-value-call 'cons (xlib:global-pointer-position stumpwm:*display*))
invalid number of arguments: 3Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {0123456789}>
0: (STUMPWM::BACKTRACE-STRING)
1: (ERR "~A" #<SB-INT:SIMPLE-PROGRAM-ERROR "invalid number of arguments: ~S" {9012345678}>)
...
Eval: (multiple-value-bind (x y) (xlib:global-pointer-position stumpwm:*display*) (cons x y))
(600 . 450)

# Efficient pointer jumping for any grid of options

Experience with the pointer a selection-based interface from a consistent grid layout of commands or options, often presented as icons.

    ____  ____  ____  ____
   |    ||    ||    ||    |
   |    || *  ||    ||    |
   |____||____||____||____|
    ____  ____  ____  ____
   |    ||    ||    ||    |
   |    ||    ||    ||    |
   |____||____||____||____|

Start with the pointer placed within the region of one of the options. Displace the pointer either leftward or rightward approximately the same distance as the width of the columns, or either upward or downward approximately the same distance as the height of the rows.

The xlib:warp-pointer-relative (CLX 13.5) displaces the pointer from its current coordinates. It requires a display like stumpwm:*display*, then the offset for the x-axis (horizontal) and the offset for the y-axis (vertical).

The origin (0, 0) is left-top corner, so downward and rightward are positive offsets, and upward and leftward are negative offsets. The pointer is automatically kept within the bounds of the screen by xlib:warp-pointer-relative, despite any requests beyond.

Eval: (xlib:global-pointer-position stumpwm:*display*)
600
450
#<XLIB:WINDOW :0 123>
Eval: (xlib:warp-pointer-relative stumpwm:*display* -64 0)
Eval: (xlib:global-pointer-position stumpwm:*display*)
536
450
#<XLIB:WINDOW :0 123>
Eval: jump.offset
The variable JUMP.OFFSET is unbound.Backtrace...
Eval: (setf jump.offset 64)
64
Eval: (xlib:warp-pointer-relative *display* jump.offset 0)
Eval: (xlib:global-pointer-position *display*)
600
450
#<XLIB:WINDOW :0 123>

Consider stumpwm:define-interactive-keymap for defining an interactive keymap (...custom buttonboard layouts) with buttons for displacing the pointer each direction, perhaps r-d-s-f for up-down-left-right (for an ASDF buttonboard layout).

Gradually construct the Lisp instruction (Contrary formation and Lisp instructions) as a quoted Lisp form for later evaluation. One way is by beginning with a dextrally half-paired list for everything before all of the button/command pairs: function name, chosen name, and list of options (or nil when none).

Eval: jump.map
The variable JUMP.MAP is unbound.Backtrace...
Eval: make.jump.map
The variable MAKE.JUMP.MAP is unbound.Backtrace...
Eval: (setf make.jump.map '((define-interactive-keymap . jump.map) . (:exit-on ((kbd "F7")))))
((DEFINE-INTERACTIVE-KEYMAP . JUMP.MAP). (:EXIT-ON ((KBD "F7"))))

Then, cons each button/command list item abdextrally to a second half-paired list beginning with nil (required by a Lisp instruction). Recall, the up/down arrow buttons in the evaluation prompt reveal the prior/later typed instructions for editing and re-using (The Lisp instruction prompt).

Eval: (setf make.jump.map (cons make.jump.map nil))
(((DEFINE-INTERACTIVE-KEYMAP . JUMP.MAP) . (:EXIT-ON ((KBD "F7")))))
Eval: (setf (cdr make.jump.map) (cons '((kbd "r") "eval-line (xlib:warp-pointer-relative *display* 0 (- jump.offset))") (cdr make.jump.map)))
Eval: (setf (cdr make.jump.map) (cons '((kbd "d") "eval-line (xlib:warp-pointer-relative *display* 0 jump.offset)") (cdr make.jump.map)))
Eval: (setf (cdr make.jump.map) (cons '((kbd "s") "eval-line (xlib:warp-pointer-relative *display* (- jump.offset) 0)") (cdr make.jump.map)))
Eval: (setf (cdr make.jump.map) (cons '((kbd "f") "eval-line (xlib:warp-pointer-relative *display* jump.offset 0)") (cdr make.jump.map)))

Penultimately, unwind the dextrally half-paired list and cons each of its items with the abdextrally half-paired list (Exploring a half-paired list). There are three items in it, so only two need be addressed.

Eval: make.jump.map
(((DEFINE-INTERACTIVE-KEYMAP . JUMP.MAP) . (:EXIT-ON ((KBD "F7"))))
 ((KBD "f") "eval-line (xlib:warp-pointer-relative *display* jump.offset 0)")
 ((KBD "s") "eval-line (xlib:warp-pointer-relative *display* (- jump.offset) 0)")
 ((KBD "d") "eval-line (xlib:warp-pointer-relative *display* 0 jump.offset)")
 ((KBD "r") "eval-line (xlib:warp-pointer-relative *display* 0 (- jump.offset))"))
Eval: (setf make.jump.map (cons (caar make.jump.map) (cons (cdar make.jump.map) (cdr make.jump.map))))
((DEFINE-INTERACTIVE-KEYMAP . JUMP.MAP)
 (:EXIT-ON ((KBD "F7")))
 ((KBD "f") "eval-line (xlib:warp-pointer-relative *display* jump.offset 0)")
 ((KBD "s") "eval-line (xlib:warp-pointer-relative *display* (- jump.offset) 0)")
 ((KBD "d") "eval-line (xlib:warp-pointer-relative *display* 0 jump.offset)")
 ((KBD "r") "eval-line (xlib:warp-pointer-relative *display* 0 (- jump.offset))"))
Eval: (setf make.jump.map (cons (caar make.jump.map) (cons (cdar make.jump.map) (cdr make.jump.map))))
(DEFINE-INTERACTIVE-KEYMAP JUMP.MAP
 (:EXIT-ON ((KBD "F7")))
 ((KBD "f") "eval-line (xlib:warp-pointer-relative *display* jump.offset 0)")
 ((KBD "s") "eval-line (xlib:warp-pointer-relative *display* (- jump.offset) 0)")
 ((KBD "d") "eval-line (xlib:warp-pointer-relative *display* 0 jump.offset)")
 ((KBD "r") "eval-line (xlib:warp-pointer-relative *display* 0 (- jump.offset))"))

Finally, evaluate the instruction and a new command is made (t.i. the chosen name) for evoking the interactive keymap. Assign a button to that command name.

Eval: (eval make.jump.map)
#S(STUMPWM::COMMAND :NAME EXIT-JUMP.MAP :CLASS T :ARGS NIL)
Eval: (describe-key)
F7 is not bound.
Eval: (define-key *top-map* (kbd "F7") "jump.map")
NIL

By default, the Esc button, or the Return button, or "Control-g" disables the interactive keymap, unless :exit-on was assigned in its options.

Consider a couple of instructions for larger or smaller jumps with + and - (CLHS 12.1.1 Numeric Operations).

Eval: make.jump.bigger
The variable MAKE.JUMP.BIGGER is unbound.Backtrace...
Eval: make.jump.littler
The variable MAKE.JUMP.LITTLER is unbound.Backtrace...
Eval: (setf make.jump.bigger '(setf jump.offset (+ jump.offset 16)))
Eval: (setf make.jump.littler '(setf jump.offset (- jump.offset 16)))
Eval: jump.offset
64
Eval: (eval make.jump.bigger)
80
Eval: jump.offset
80
Eval: (eval make.jump.littler)
64
Eval: jump.offset
64

Consider assigning a couple more buttons for those instructions. Either unwind the Lisp instruction for that interactive keymap until the button/command pairs are exposed, or simply reference the cDDDr. Abdextrally cons the additional button/command pairs.

Eval: (cdddr make.jump.map)
(((KBD "f") "eval-line (xlib:warp-pointer-relative *display* jump.offset 0)")
 ((KBD "s") "eval-line (xlib:warp-pointer-relative *display* (- jump.offset) 0)")
 ((KBD "d") "eval-line (xlib:warp-pointer-relative *display* 0 jump.offset)")
 ((KBD "r") "eval-line (xlib:warp-pointer-relative *display* 0 (- jump.offset))"))
Eval: (setf (cdddr make.jump.map) (cons '((kbd "g") "eval-line (eval make.jump.bigger)") (cdddr make.jump.map)))
Eval: (setf (cdddr make.jump.map) (cons '((kbd "a") "eval-line (setf jump.offset (- jump.offset 16))") (cdddr make.jump.map)))
Eval: make.jump.map
(DEFINE-INTERACTIVE-KEYMAP JUMP.MAP
 (:EXIT-ON ((KBD "F7")))
 ((KBD "a") "eval-line (setf jump.offset (- jump.offset 16))")
 ((KBD "g") "eval-line (eval make.jump.bigger)")
 ((KBD "f") "eval-line (xlib:warp-pointer-relative *display* jump.offset 0)")
 ((KBD "s") "eval-line (xlib:warp-pointer-relative *display* (- jump.offset) 0)")
 ((KBD "d") "eval-line (xlib:warp-pointer-relative *display* 0 jump.offset)")
 ((KBD "r") "eval-line (xlib:warp-pointer-relative *display* 0 (- jump.offset))"))

Rewind if necessary, then use eval again. No need to re-assign the same button, because it is the same command name.

Eval: (eval make.jump.map)
#S(STUMPWM::COMMAND :NAME EXIT-JUMP.MAP :CLASS T :ARGS NIL)

Consider including buttons for pointer activation and drag'n drop (Alternative for pointer activation and drag'n drop). Perhaps "h" for the primary button, with "u" for press and "m" for release.

Eval: press.1
The variable PRESS.1 is unbound.Backtrace...
Eval: release.1
The variable RELEASE.1 is unbound.Backtrace...
Eval: (setf press.1 '(xlib/xtest:fake-button-event *display* 1 t))
Eval: (setf release.1 '(xlib/xtest:fake-button-event *display* 1 nil))
Eval: (cdddr make.jump.map)
(((KBD "a") "eval-line (setf jump.offset (- jump.offset 16))")
 ((KBD "g") "eval-line (eval make.jump.bigger)")
 ((KBD "f") "eval-line (xlib:warp-pointer-relative *display* jump.offset 0)")
 ((KBD "s") "eval-line (xlib:warp-pointer-relative *display* (- jump.offset) 0)")
 ((KBD "d") "eval-line (xlib:warp-pointer-relative *display* 0 jump.offset)")
 ((KBD "r") "eval-line (xlib:warp-pointer-relative *display* 0 (- jump.offset))"))
Eval: (setf (cdddr make.jump.map) (cons '((kbd "u") "eval-line (eval press.1)") (cdddr make.jump.map)))
Eval: (setf (cdddr make.jump.map) (cons '((kbd "m") "eval-line (eval release.1)") (cdddr make.jump.map)))
Eval: (setf (cdddr make.jump.map) (cons '((kbd "h") "eval-line (cons(eval press.1)(eval release.1))") (cdddr make.jump.map)))

Maybe ";" for the secondary button.

Eval: press.3
The variable PRESS.3 is unbound.Backtrace...
Eval: release.3
The variable RELEASE.3 is unbound.Backtrace...
Eval: (setf press.3 '(xlib/xtest:fake-button-event *display* 3 t))
Eval: (setf release.3 '(xlib/xtest:fake-button-event *display* 3 nil))
Eval: (setf (cdddr make.jump.map) (cons '((kbd ";") "eval-line (cons(eval press.3)(eval release.3))") (cdddr make.jump.map)))

Confirm and re-evalutate.

Eval: make.jump.map
(DEFINE-INTERACTIVE-KEYMAP JUMP.MAP
 (:EXIT-ON ((KBD "F7")))
 ((KBD ";") "eval-line (cons(eval press.3)(eval release.3))")
 ((KBD "h") "eval-line (cons(eval press.1)(eval release.1))")
 ((KBD "m") "eval-line (eval release.1)")
 ((KBD "u") "eval-line (eval press.1)")
 ((KBD "a") "eval-line (setf jump.offset (- jump.offset 16))")
 ((KBD "g") "eval-line (eval make.jump.bigger)")
 ((KBD "f") "eval-line (xlib:warp-pointer-relative *display* jump.offset 0)")
 ((KBD "s") "eval-line (xlib:warp-pointer-relative *display* (- jump.offset) 0)")
 ((KBD "d") "eval-line (xlib:warp-pointer-relative *display* 0 jump.offset)")
 ((KBD "r") "eval-line (xlib:warp-pointer-relative *display* 0 (- jump.offset))"))
Eval: (eval make.jump.map)
#S(STUMPWM::COMMAND :NAME EXIT-JUMP.MAP :CLASS T :ARGS NIL)

# Mathemagical Xserver cursor placement

Much like split-view management, the Xserver cursor can be placed anywhere within the bounds of a screen by halving it. Begin in the center of a screen, then split it (left, right, top, or bottom) and center the cursor within one of the halves.

Xserver cursor placement by mathemagically halving the screen, rather than arbitrary pointer motion. That is, no more need to use the force of dramatic physical gestures to move anything. Basic center, left, right, up, and down for positioning quickly, or go back to previous point or the screen center.

Includes pointer activation, and keybindings (for numeric pad), and inspiration...and a "Content outline" for the copious documentation. It is all quite simple, really; the fluff is in the doc rather than the code.

Or, recenter the Xserver cursor at any halving point and it becomes the beginning point. Going back stops at that halving point. Returning to the beginning returns to that recenter point, then returning once more makes the screen center as the beginning point once again.

# Mathemagical pointer and cursor placement

A single destination:

          y axis
          |
 x axis --+--------------------------------
          | origin       up
          |              |
          |              |    # destination
          |              |
          | left --------+-------- right
          |        point |
          |              |
          |              |
          |             down

Extending lines from the point isolates the destination within a quadrant and reveals the pointer trajectories for intersecting with the destination. Limiting the length of the lines to the width and height of the narrowed region reveals the current precision and the progress.

Many potential destinations:

          y axis
          |
 x axis --+---------------------------------------
          | origin           up
          |                  |
          |                  |
          |                  | destinations
          | left ------------+--#--#--#--#-- right
          |            point |
          |                  |
          |                  |
          |                 down

Multiple potential destinations might be axially aligned, f.e. a menu of options or a toolbar of outlined regions. Placing the pointer first along their axial alignment frees the other axis for selecting any of the items. Another option can be chosen by backtracking a little rather than starting over at the center of the screen.

The pointer has four parts that imply the crossing of a horizontal line with a vertical line. A gap for the implied intersection also provides the visual clearance needed for the Xserver cursor when activating the pointer buttons.

Other programs continue controlling the appearance of the Xserver cursor within their views without interference from the halving pointer.

Pointer placement by mathemagically halving the screen, rather than arbitrary pointer motion includes buttonboard bindings (for numeric pad) for multidirectional placement, and complementary commands for activation of the motionbox pointer.

Consider recentering the pointer and Xserver cursor at any halving point and it becomes the beginning point. Going back stops at that halving point. Returning to the beginning returns to that recenter point, then returning once more makes the screen center as the beginning point once again.

Either way, the pointer-halving-show command conveniently returns the cursor that has been moved (f.e. by a motionbox) back to the pointer position, and pointer-halving-hide hides the pointer without hiding the Xserver cursor. Or, consider combining the commands into pointer-halving-reveal-toggle for toggling revealing and hiding of the pointer.

# Make a point, collect them all, restore them later

Convert a pointer interface into a selection interface. First, move the Xserver cursor by whatever means available, then mark the location for returning the cursor to it later. Each point is then available as next or prior. Eliminate traversal of a vast void, and never miss a point.

With the convenience commands points-write and points-read, write a list of marked points to a document, then later read and apply that list of points to restore them for use again. Perhaps collect a group of preferred points for a specific program, then swap them for a group of points from another document for another program.

Convert "drag and drop" into "select and put" by adding pointer button activation commands for toggling the press or release of the primary pointer button from the buttonboard.

The hot spot for the Xserver cursor must have clearance when activating a pointer button. A point is drawn as a white perimeter of a square with a black mask, made from four Xwindows.

    ______        _   __   _
   |  __  |      | | |__| | |
   | |  | |  ==  | |      | |
   | |__| |      | |  __  | |
   |______|      |_| |__| |_|

The left and right sides each have a black background, and a subwindow with a black background and a white border as thick as the line for the square perimeter.

For example, the left side (though taller than this):

     left
    window              -->   cropped
    ______                    ______
   |  ____|__                |  ____|<-mask
   | |       |               | |    |
   |b| w _   |               |b| w _|<-perimeter
   |l| h| |  |               |l| h| |
   |a| i| |  |               |a| i| |<-black mask
   |c| t|_|  |               |c| t|_|
   |k| e     |               |k| e  |
   | |_______|subwindow      | |____|
   |______|                  |______|

The top and bottom sides each have a black background, and a subwindow with a white background as wide as the sides and as tall as the perimeter height.

    top or bottom
       window
    ____________
   |____________|<-black mask
   |subwindow   |<-white perimeter
   |____________|
   |____________|<-black mask

# Modifications for StumpWM

Some slight changes to consider.

# Clear the message from the screen

Some messages from StumpWM stay on the screen, such as Help documentation or error messages. Any message is cleared from the screen when the next StumpWM command is invoked, usually by typing the button assigned to it.

Some commands give a message that disappears after a few seconds. But, any message shown is also added to the message history.

Consider using a command to clear the message from the screen that also never gives a message, perhaps a command that does nothing. The "Foward Delete" button is named "Delete" according to describe-key (Invoke a StumpWM command by its name), and is probably seldom used.

Eval: (setf clear.message '(stumpwm:defcommand clear.message nil nil))
Eval: (describe-key)
Delete is not bound.
Eval: (define-key *top-map* (kbd "Delete") "clear.message")

# Alternative for stumpwm:eval-line

Sometimes evaluate a Lisp form without showing a message with results, such as for CLX "xlib:" instructions that return arbitrary numbers. Errors will still be shown, but without a backtrace. A short StumpWM command with stumpwm:defcommand (StumpWM 3.1).

Eval: (stumpwm:defcommand eval-quiet (Ftext) ((:rest "Lisp: ")) "Evaluate one Lisp form.  No result, usually." (eval (read-from-string Ftext)))
#S(STUMPWM::COMMAND :NAME EVAL-QUIET :CLASS T :ARGS ((:REST "Lisp: ")))

# Replacement for stumpwm:err

stumpwm:err in "message-window.lisp": 301–308 (StumpWM 1.0.1)

The stumpwm:err (Stumpwm 4. Message and Input Bar) concatenates the backtrace for an error without ensuring it begins on a newline.

Eval: something
The variable SOMETHING is unbound.Backtrace...
Eval: (cons)
invalid number of arguments: 0Backtrace...

Consider inserting a newline with format and "~%" (CLHS 23.3.1.2). (Additional blank lines would require digging deeper into StumpWM, f.e. starting with stumpwm:echo-string in "message-window.lisp" at lines 292–294.)


   (defun err (fmt &rest args)
    "Modified: [insert original description...]"
    (let ((stumpwm:*suppress-echo-timeout* t))
     (stumpwm:echo-string
      (stumpwm:current-screen)
      (stumpwm:concat
       (apply 'format nil fmt args)
       (format nil "~%")               ;;<-- the difference
       (stumpwm::backtrace-string)))))

When typing it into the evaluation prompt (The Lisp instruction prompt) all at once, perhaps start from the right end with stumpwm:concat (primitives.lisp: 1069–1070) and all the closing parenthesis marks, then type the earlier parts.

Otherwise, consider gradually forming an abdextrally half-paired list (Contrary formation and Lisp instructions) starting with nil for each sublist. The sublist for stumpwm:concat (see also concatenate (CLHS)) is a rather short beginning.

Eval: make.err
The variable MAKE.ERR is unbound.Backtrace...
Eval: (setf make.err '(concat (apply 'format nil fmt args) (format nil "~%") (stumpwm::backtrace-string)))
Eval: make.err
(CONCAT (APPLY 'FORMAT NIL FMT ARGS)
 (FORMAT NIL "~%") (STUMPWM::BACKTRACE-STRING))

The next outer list is for stumpwm:echo-string (StumpWM 4.3).

Eval: (setf make.err (cons make.err nil))
Eval: (setf make.err (cons '(current-screen) make.err))
Eval: (setf make.err (cons 'echo-string make.err))
Eval: make.err
(ECHO-STRING (CURRENT-SCREEN)
 (CONCAT (APPLY 'FORMAT NIL FMT ARGS)
  (FORMAT NIL "~%") (STUMPWM::BACKTRACE-STRING)))

Then the next outer list is for let (CLHS).

Eval: (setf make.err (cons make.err nil))
Eval: (setf make.err (cons '((*suppress-echo-timeout* t)) make.err))
Eval: (setf make.err (cons 'let make.err))
Eval: make.err
(LET ((*SUPPRESS-ECHO-TIMEOUT* T))
 (ECHO-STRING (CURRENT-SCREEN)
  (CONCAT (APPLY 'FORMAT NIL FMT ARGS)
   (FORMAT NIL "~%") (STUMPWM::BACKTRACE-STRING))))

The final outer list is for defun (CLHS).

Eval: (setf make.err (cons make.err nil))
Eval: (setf make.err (cons "Modified: [insert original description...]" make.err))
Eval: (setf make.err (cons '(fmt &rest args) make.err))
Eval: (setf make.err (cons 'err make.err))
Eval: (setf make.err (cons 'defun make.err))
Eval: make.err
(DEFUN ERR (FMT &REST ARGS)
 "Modified: [insert original description...]"
 (LET ((*SUPPRESS-ECHO-TIMEOUT* T))
  (ECHO-STRING (CURRENT-SCREEN)
   (CONCAT (APPLY 'FORMAT NIL FMT ARGS)
    (FORMAT NIL "~%") (STUMPWM::BACKTRACE-STRING)))))

Review and confirm, and then evaluate it. Try out some errors.

Eval: (eval make.err)
ERR
Eval: something
The variable SOMETHING is unbound.
Backtrace...
Eval: (cons)
invalid number of arguments: 0
Backtrace...

# Replacement for stumpwm::print-key

The StumpWM prompts (Interactive curiosity...) have a specialized approach to interpreting abbreviations for commands, and provide an experience similar to interactive keymaps (Interactive keymaps).

New commands for the stumwpm:*input-map* keymap require accepting two pieces of info: a reference to the current prompt, and the buttons that invoked the command. The latter is mostly for stumpwm:input-self-insert, and usually ignored by other commands.


# The error from stumpwm::print-key.

The stumpwm:input-self-insert command is assigned as t (meaning all unassigned buttons) instead of a specific button sequence. That leads to an error from stumpwm::print-mods.

For example, assign a button to stumwpm:*input-map* in order to use the button as a prefix for it, as with any keymap (New prefix for Help). Then, type the button and then a question mark "?" to reveal the button list.

StumpWM Crashed With An Unhandled Error!
Copy the error to the clipboard with the 'copy-unhandled-error' command.
The value
    T
  is not of type
    STUMPWM::KEY
Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {0123456789}>
0: (STUMPWM::PRINT-MODS T)
1: (STUMPWM::PRINT-KEY T)
2: (STUMPWM::DISPLAY-BINDINGS-FOR-KEYMAPS ...)
...

Tracing backwards through the source files leads to stumpwm::display-bindings-for-keymaps inappropriately passing T to stumpwm::print-key. But the latter is much smaller and simpler to rewrite in the Lisp instruction prompt for a quick resolution.


# The original and a replacement for stumpwm::print-key.

The stumpwm::print-key function is in "kmap.lisp": 174–177 (StumpWM 1.0.1).

174  (defun print-key (key)
175    (format nil "~a~a"
176            (print-mods key)
177            (keysym->stumpwm-name (key-keysym key))))

One approach is to include a conditional such as if (CLHS) with eq (CLHS) for matching T that returns double-quoted text, otherwise it does what it would have done. Notice stumpwm::print-key and all the StumpWM functions in it need "stumpwm::" prepended.

(defun
 stumpwm::print-key
 (Fkey)
 (if (eq t Fkey) "All else"       ;;<-- the difference
  (format nil "~a~a"
   (stumpwm::print-mods Fkey)
   (stumpwm::keysym->stumpwm-name
    (stumpwm::key-keysym Fkey)))))

When typing it in all at once (The Lisp instruction prompt), perhaps start with the final Lisp form at the right end and all the closing parenthesis marks, then type the earlier parts (Typing within a line of text).

Consider storing both versions in memory with the same name as the function (An introspective approach for defun).


# Typing and storing the original stumpwm::print-key.

Consider storing the original in memory with the same name as the function itself (An introspective approach for defun). Prepend "stumpwm::" to other function names as needed.

Consider gradually forming an abdextrally half-paired list (Contrary formation and Lisp instructions) starting with nil for each sublist. The sublist for stumpwm::keysym->stumpwm-name is a rather short beginning.

Eval: stumpwm::print-key
The variable STUMPWM::PRINT-KEY is unbound.Backtrace...
Eval: (setf stumpwm::print-key '(stumpwm::keysym->stumpwm-name (stumpwm::key-keysym Fkey)))

The next outer list is for the format Lisp instruction. Pair it with nil, then add the four additional parts individually, and use quote as needed. Remember to prepend "stumpwm::" as needed.

Eval: (setf stumpwm::print-key (cons stumpwm::print-key nil))
Eval: (setf stumpwm::print-key (cons '(stumpwm::print-mods Fkey) stumpwm::print-key))
Eval: (setf stumpwm::print-key (cons "~a~a" stumpwm::print-key))
Eval: (setf stumpwm::print-key (cons nil stumpwm::print-key))
Eval: (setf stumpwm::print-key (cons 'format stumpwm::print-key))
Eval: stumpwm::print-key
(FORMAT NIL "~a~a" (STUMPWM::PRINT-MODS FKEY)
        (STUMPWM::KEYSYM->STUMPWM-NAME (STUMPWM::KEY-KEYSYM FKEY)))

Finishing the original instruction, the next outer list is for the defun Lisp instruction. Pair it with nil, then add the three additional parts individually, and use quote as needed.

Eval: (setf stumpwm::print-key (cons stumpwm::print-key nil))
Eval: (setf stumpwm::print-key (cons '(Fkey) stumpwm::print-key))
Eval: (setf stumpwm::print-key (cons 'stumpwm::print-key stumpwm::print-key))
Eval: (setf stumpwm::print-key (cons 'defun stumpwm::print-key))
Eval: stumpwm::print-key
(DEFUN STUMPWM::PRINT-KEY (FKEY)
  (FORMAT NIL "~a~a" (STUMPWM::PRINT-MODS FKEY)
          (STUMPWM::KEYSYM->STUMPWM-NAME (STUMPWM::KEY-KEYSYM FKEY))))

Consider prepending a double-quoted description identifying it. Then, the car is the description and the cdr is the instruction to evaluate.

Eval: (setf stumpwm::print-key (cons "original" stumpwm::print-key))
("original" DEFUN STUMPWM::PRINT-KEY (FKEY)
 (FORMAT NIL "~a~a" (STUMPWM::PRINT-MODS FKEY)
         (STUMPWM::KEYSYM->STUMPWM-NAME (STUMPWM::KEY-KEYSYM FKEY))))
Eval: (cdr stumpwm::print-key)
(DEFUN STUMPWM::PRINT-KEY (FKEY)
  (FORMAT NIL "~a~a" (STUMPWM::PRINT-MODS FKEY)
          (STUMPWM::KEYSYM->STUMPWM-NAME (STUMPWM::KEY-KEYSYM FKEY))))

# Typing and storing the replacement stumpwm::print-key.

Consider storing the replacement in memory with the same name as the function itself (An introspective approach for defun).

The replacement pairs a conditional with part of the original (The original and a replacement for stumpwm::print-key). Perhaps start by typing in the original (Typing and storing the original stumpwm::print-key), then duplicate it (Re-listing rather than re-arranging).

Eval: stumpwm::print-key
("original" DEFUN STUMPWM::PRINT-KEY (FKEY)
 (FORMAT NIL "~a~a" (STUMPWM::PRINT-MODS FKEY)
         (STUMPWM::KEYSYM->STUMPWM-NAME (STUMPWM::KEY-KEYSYM FKEY))))
Eval: (setf stumpwm::print-key (cons stumpwm::print-key (read-from-string (format nil "~s" stumpwm::print-key)))
(("original" DEFUN STUMPWM::PRINT-KEY (FKEY)
 (FORMAT NIL "~a~a" (STUMPWM::PRINT-MODS FKEY)
         (STUMPWM::KEYSYM->STUMPWM-NAME (STUMPWM::KEY-KEYSYM FKEY))))
"original" DEFUN STUMPWM::PRINT-KEY (FKEY)
 (FORMAT NIL "~a~a" (STUMPWM::PRINT-MODS FKEY)
         (STUMPWM::KEYSYM->STUMPWM-NAME (STUMPWM::KEY-KEYSYM FKEY))))

Consider changing the description of the abdexter half to indicate it is the replacement, leaving the dexter half as the original.

Eval: (setf (caar stumpwm::print-key) "replacement")

Confirm the reference with car and cdr, then consider using "Control-k" and "Control-y" rather than retyping the reference later.

Eval: (car (cddddr (car stumpwm::print-key)))
(FORMAT NIL "~a~a" (STUMPWM::PRINT-MODS FKEY)
        (STUMPWM::KEYSYM->STUMPWM-NAME (STUMPWM::KEY-KEYSYM FKEY)))

As usual, begin a sublist by pairing the reference with nil, then abdextrally pair the additional items.

Eval: (setf (car (cddddr (car stumpwm::print-key))) (cons (car (cddddr (car stumpwm::print-key))) nil))
Eval: (setf (car (cddddr (car stumpwm::print-key))) (cons "All else" (car (cddddr (car stumpwm::print-key)))))
Eval: (setf (car (cddddr (car stumpwm::print-key))) (cons '(eq t Fkey) (car (cddddr (car stumpwm::print-key)))))
Eval: (setf (car (cddddr (car stumpwm::print-key))) (cons 'if (car (cddddr (car stumpwm::print-key)))))
Eval: (car (cddddr (car stumpwm::print-key)))
(IF (EQ T FKEY)
    "All else"
    (FORMAT NIL "~a~a" (STUMPWM::PRINT-MODS FKEY)
            (STUMPWM::KEYSYM->STUMPWM-NAME (STUMPWM::KEY-KEYSYM FKEY))))

Confirm the replacement instruction, and then evaluate it to replace stumpwm::print-key.

Eval: (car stumpwm::print-key)
("replacement" DEFUN STUMPWM::PRINT-KEY (FKEY)
 (IF (EQ T FKEY)
     "All else"
     (FORMAT NIL "~a~a" (STUMPWM::PRINT-MODS FKEY)
             (STUMPWM::KEYSYM->STUMPWM-NAME (STUMPWM::KEY-KEYSYM FKEY)))))
Eval: (eval (cdar stumpwm::print-key))

After assigning a prefix to stumpwm::*input-map* (Make a list of command buttons), typing the prefix then a question mark "?" reveals the button list for editing commands (Reveal button list for text editing). Though, the prefix for the keymap works only when without a prompt.

# Resources

The intent of Hypertext Markup (HTML) is two-fold: mark text of content when helpful (markup), and reference other content (links). HTML is simply punctuation marks written as names instead of singular symbols, but akin to proofreader marks.

Content marked with HTML remains readable as plain text. The alternate view is supposed to be supplementary for the content rather than necessary.

An HTML viewer (computer program) provides an alternate view by leaving out the marks and making adjustments to spacing (f.e. line height or indentation) and text (f.e. drawn thicker or askewed). The people who wrote that computer program decide the default characteristics for the spacing and drawing of the text.

The intended use of Cascading Stylesheets (CSS) is for changing the default characteristics of the HTML marks (spacing and drawing) that have been decided by the computer programmers of a specific HTML viewer.

CSS has nothing do with the document content. CSS is only a convenient means for changing the default preferences of the computer program (HTML viewer) without having to rewrite the computer program.

# Markup a CSS stylesheet

A stylesheet for stylesheet documentation, a.k.a. a hybrid CSS+HTML document.

The "style" of Cascading Style Sheet refers to expression rather than decoration, because CSS is for changing the default spacing and drawing of HTML marked regions of plain text documents. Therefore, CSS actually describes the characteristics of HTML marks rather than the document.

The intent of a CSS stylesheet is documented with comments embraced by /* and */. Comments can be marked up with HTML, whereby documentation for a stylesheet can have an alternate view in an HTML viewer.

A well-documented stylesheet inevitably links to itself for providing samples of its rules within its documentation. Therefore, a "stylesheet stylesheet" such as this one is "the mother of all stylesheets", as it precedes and begets all thereafter.

# PDF: portable document format

Portable Document Format (PDF) describes how to layout text and images, and is plain text. Basic notes for PDF version 1.4, mostly with the purpose of combining images into a single PDF document.

# ed and emacs, an approach

For many decades, emacs (Editing MACroS) has provided split-view management of documents (viewing and editing). It also excels with memory management of any sequence of typing or list of commands by storage in "registers", or complete repetition by a single press of any button desired (a.k.a. keyboard macros). The Emacs command "append-to-buffer" provides a means for selectively transferring content from any view of Emacs (whether a document or otherwise) to any other view, bypassing its own copy/paste or "registers".

On the other hand, the text editor "ed" reveals any fragments of any number of documents when requested, in any order, gradually filling the screen only as needed. Each line is called forth by its number, so the line number is an intuitive command that shows that line of text. With "ed", there is no need for moving a text cursor, no need for selecting text, and no need for scrolling.

Any comma-separated range of lines is a command for calling forth that range of lines, f.e. 31,35p will "print" lines 31 to 35 on the screen. Line numbers are optionally revealed when requesting lines (f.e. 31,35n), and similarly so in search results. Specify a generic line number with plus or minus, f.e. -4 for the fourth line before the current line, or for a range of lines, f.e. -5,+5p to "print" the range of lines of text before and after the current line. The last line requested automatically becomes the current line.

Thereby with "ed", views of text emerge naturally from requested fragments of familiar documents: command, lines of text, command, lines of text, etc. That is, the typed command remains visible and serves as an introduction for the lines listed by it (when any).

A document can be viewed one screenful at a time (with z), or by an arbitrary number of lines (f.e. z30 for the next 30 lines), from anywhere within a document (f.e. 42z30n for the 30 lines starting from line 42, and numbered).

Search results are listable, or traversable one at time by line number in any order desired, and repeatable without retyping the search pattern. In addition to mere search and replace, a set of commands can be applied to all search results or interactively queried for each one. For example, search for a pattern, but also specifiy a different pattern for replacing in the results, all as one command, and either immediately or selectively.

As aforementioned, the editing commands typed in "ed" remain visible, thereby keeping a history of how a document was edited (optionally with the lines of text before and after they were modified) would be possible... if only there was a means for saving those proceedings.

By using "ed" for its naturally emerging document views within the "shell-mode" of Emacs, the "ed" program gains a separate dedicated buffer from Emacs recording that history of all editing with "ed", along with robust command editing (from the text editing commands of Emacs) when typing its own commands. Of course, the aforementioned keyboard macros from Emacs means commands within "ed" are automatically added to any recorded sequence of tasks, and naturally so. No special effort needed, nothing new to learn, automatically incorporated.

Evoking "ed" within shell-mode with sudo (super-user do) means the ability to edit restricted system documents without having to do "sudo emacs", thereby the super-user role remains optional within Emacs.

With the "!" command provided by "ed", evocation of external commands are possible from within "ed", and their results optionally inserted into that document wherever desired. Evoking "ed" as super-user (t.i. "sudo ed") also means there is no longer any need to type sudo for each and every command that requires super-user privileges, because the "!" command of "ed" will invoke external commands with the same privileges by which "ed" itself was invoked.

The split-view management of Emacs provides the opportunity for multiple full-screen layouts of several such instances of "ed" and "sudo ed" in shell-mode, intermixed with any other activities within Emacs, f.e. email, web browsing, directory listings, etc. As each instance has its own dedicated buffer, the editing history of commands used in "ed" or "sudo ed" can be saved for review or potential selective restoration of edited documents (for when lines were listed before and after editing them). And of course, repetition of super-user tasks, editing or otherwise, becomes possible (and naturally so) by means of the aforementioned keyboard macros of Emacs.

Using "sudo ed" within shell-mode of Emacs enables responsible, recordable (t.i. record keeping), and administrative editing of documents or evocation of commands with access to copious amounts of copy/paste access (a.k.a. "registers"), and ridiculously easy on-the-fly record/play of any sequence of typing and commands... readily assigned to any button desired, as many as needed.

# Scroll instead of clear screen

A "command line interface" (CLI) has been an interactive means for typing instructions into the computer. Any command typed is either immediately invoked, or invoked after typing a specific button such as "Do" or "Engage". Sometimes the Enter button or Return button is conscripted when lacking a specific button for command invocation.

The command line is at the bottom and the lines of text are shifted upward as each command is issued, like handwritten notes or a typewriter. Any results might also be drawn on additional lines after the command, shifting the lines upward further.

Only the most recent lines of text are shown. Any prior lines beyond what can fit on the screen are no longer drawn. A common command provided in a command line interface is clear for eliminating all the text that has been drawn above the command line.

Sometimes a CLI peculiarly begins with the command line at the top and then gradually shifts it downward towards the bottom. From then on, additional lines of text are shifted upwards as done with a consistent CLI.

For such a CLI constantly shifting the location of its command line, the clear command eliminates all drawn text and replaces the command line to the top again for repeating its incongruent descent.

Establish the bottom as the consistent location for the command line by drawing enough blank lines (f.e. with echo) to fill the screen from top to bottom instead of using the clear command (scroll, a script for the ash CLI).

# Clear the screen while keeping
# the command line at the bottom.

line_count=70
while [ $line_count -gt 0 ]
do
echo
line_count=$(($line_count - 1))
done

# generational and archæological loss of the computer medium

Writing and reading is the basis of the computer medium. Freedom of expression, t.i. the result of a person taking on the responsibility of speaking for itself, is what has been curiously missing with the commodity computers sold to the everyday person. Choice is often the only opportunity given to the purchaser of a computer, choosing amongst decisions already made by the software developers.

The skill of writing and reading has been impressed upon as many people as possible, and has become an expected means of learning and communicating. However, the computer medium is sold as a means of looking and pointing at options thought of by somebody else, failing at integrating with the flow of thoughts and actions of the everyday person implementing the computer medium. Paying money for a computer and then having applications do what somebody else wanted to do can only be a novelty, merely entertaining a person whose desires were never asked.

A computer application, a type of software, is an example of grouping basic commands for a specific task. Obviously, that is very useful for the person who groups them, and less so for a person when they are grouped by someone else.

Sometimes a single command is a group of other commands rather than emerging from new computer programming. A list of commands can be saved for later recall as a single command, f.e. by repeating the sequence of commands the person has just done.

Arbitrary actions with a pointer are prone to misinterpretation when part of automating repetitious activities. A shared command whose composition can never be explored, whose list of subcommands is forbidden from discovery, is an insincere gift that will fail to support the everyday person to correct it, simplify it, or adapt it for personal comfort.

Ultimately, personal expression is supported by writing and reading, impeded by insincere sharing, and essentially neutralized by having only choices. Sharing an approach inspires and supports the emergence of new approaches, with dissimilarity possible though unrequired.

The computer medium is inferior (f.e. when compared with pen and paper) for promoting self-education and cultural growth when it is distributed as an unexplorable trade secret providing a kiosk of choices rather than unrestrictedly adaptable by the everyday person for each moment of life.

# The everyday person should never have a PC

A personal computer (PC) is a computer for one person in an office at work rather than a shared computer like a data terminal. A company provides the PC for use by the employee in the office, and the "home PC" for working from home. The everyday person was never supposed to have a home work computer.

Curiously, many operating systems provide no place for typing a command from personal recall or personal notes. Buttonboards usually have no dedicated "prompt" or "command" button for immediately specifying commands.

Instead, an abbreviation or pseudonym for a command is typed, though without any place to type it. That typically involves holding one or more buttons, a randomly logical concoction at the bottom of the buttonboard.

With no dedicated buttons on the buttonboard for all commands and nothing displayed on the screen when typing the abbreviations, there is only hope of what command will be invoked.

Conventionally, pre-categorized menus gradually reveal sublistings of commands. The aforementioned invisible typing of their abbreviations have been the only means for bypassing the interminable spelunking of those labyrinthine menus.

Silly, but that is how a home personal computer has been since forever it seems. But then again, it is work.

A personal computer can be repurposed into a personalizable computer (...no need to change the world) for the everyday person. The personalizable computer can then be an impromptu interface for other computers by means of VNC or remote desktop programs.

Everyone is an everyday person, even a computer programmer. A computer personalizable with a few computer instructions rather than book-length computer programming is less busywork for everyone, and immediate ease for any pursuit.

# Recipes and pseudocode

An approach is a recipe or pseudocode, and its application is the result.

A recipe declares an intent by means of a list of ingredients and events that have been effective for producing a desired result. An application is the result of the recipe, a final presentation either palatable or inedible.

A computer application is typically an approach applied by someone else for the results desired by that other person. With a computer, an application of an approach is invariable, but pseudocode is by definition a recipe and therefore an adaptable approach. The pseudocode is the gist and intentions, the springboard for a variety of forms, thereby distinct from any specific attempt.

Life is variable. The predefined results of applications are inapplicable to the ever changing flow of events. On the other hand, an approach is guidance for transitioning through a moment, retaining opportunity for adaptation with each jump.

# Intention is distinct from documentation

Too often computer programs have been said to be lacking documentation, but it is also without expression of intent. Without intent and motivation, there is no pursuit, there is no follow through. Without well thought out desires recorded, a set of computer program instructions are without a foundation.

Code is, by definition, ambiguous. Documentation of the code that emerges is the recording of decisions for using certain computer instructions, experiences with alternatives, or suggestions of potential alternatives.

A computer programming language is merely a set of symbols or codewords. A computer is simply a machine, a piece of hardware, there is no possible communication with it. Instead, such a "language" is merely a writing system for a person briefly recording a set of instructions. Computer programming without documentation is as informative as a quote taken out of context.

Ingredients are fabricated within the computer memory, or perhaps parts of the computer hardware are activated with it. Even then, the phrases and terms need to be interpreted as a specified sequence of toggle switches within the circuitry of that machine, typically a barebones coding with only two letters in its alphabet and no phonemes because it is never spoken.

In other words, the computer is just a tool chosen for applying an appoach. Punctuation symbols and code words of computer programming record mere gesticulations of the person applying the approach. Therefore, the approach or purpose is inherently underivable from the computer coding, as it is no more than the pattern on a wall of toggled switches.

An approach must be recorded before or as it is applied if it is ever to be known by anyone else, as many archeologists have lamented. Minimizing it by shedding its context of intent and motivation deprives everyone of its meaning, even the later self of the person applying it.

To reiterate, there is no communication possible with a "computer language", for it is only a writing system intended for toggling switches for a result rather than sharing an understanding with another person. A computer program is merely one adaptation of an approach, one choreographed dance for a feeling, forever unrevealing of its own inception.

# An operatable system

A computer is a medium for writing and reading, with the writing reduced to mere presses of labeled buttons for each letter of an alphabet. There is no other skill needed for operating a computer, though there are sometimes other means besides a buttonboard.

A computer is operatable, and automatable, when it is capable of restoring what has been recorded within its medium. That is, a computer recording the actions done with it in the moment and then repeating those actions upon request is being operated.

A system of programs operating on their own, especially when unmodifiable, is an "operating system". Somebody else's program is somebody else's operation of a computer, recorded from some other moment for that other person.

As a computer program is a proxy for the person who created it, vetting a computer program is the same as trusting the person who wrote it, perhaps a complete stranger. A computer virus is merely a computer program. A system readily operating on its own, t.i. an operating system, is operating for the interests and intentions of the people who wrote the programs.

In contrast, an "operatable system" does nothing until it is operated, so known programs can be the only programs ever activated or automated, per the decisions made by the person operating the computer.

There is no denying the various computer mediums are archeologically unsound. That makes it all the more important for using the computer medium as freely as possible during this transition beyond the computer medium itself for more sustainable, sharable, and perusable recording mediums. The medium of pen and paper (as an example of the latter) preceded the computer medium, and is destined to continue beyond the computer medium during the search for other millenially persisting recording mediums like pen and paper, clay tablets, and stone structures.

The unadaptable predetermined decisions of the operating-system/application paradigm is worthless for the everyday person, who is the core of any people, the core of any culture. This is evident by companies creating applications for their own use, with the employee (an everyday person) making do with what is available while waiting for those applications.

An operating system is non-functioning without its applications, and developing an application is a tangent away from the flow of the moment. Without documentation, there is no hope of adapting someone else's program for the current moment. There is only choice of the decisions made by someone else, without opportunity for freedom of expression by the person choosing.

A core characteristic of the computer medium is that of immediate and exact duplication of any of its recordings, thereby the freedom for trial and dismissal without loss or corruption of the original version. That is the opportunity of self improvement with the freedom of saving and reviewing inspirations and influences, and sharing those with the community for discussion and accelerating cultural development.

# Design is a collection of foreign decisions

Voting is choosing amongst a set of pre-made decisions. A decision is inherently presumed acceptable, regardless of whether it is desirable. Choosing from someone else's menu is choosing from someone else's comfort, perhaps a selection of someone else's abilities. A vote or a choice is at most the wiggling of a toe tag, nothing like personal expression as there is no opportunity for a personal decision.

Design is a set of decisions. Somebody else's design is somebody else's decisions. Ultimately, a design is a past, foreign to the present, an opportunity for reflection and release. The adaptation of a set of decisions is the conversion of it into a new approach, perhaps a setup for a eventual spin-off or even a prequel.

# Computer displays: punchcard or GUI

Punchcard is a recording medium readable by computers and people, a type of memory card, t.i. a memcard. A punchcard can be a piece of cardboard with holes made from a holepunch tool, by either a person or a machine. The holes and the lack thereof are arranged along rows and columns of a grid, and can be detected by either machinary or a person feeling a card, or by a person visually perceiving the arrangement of the holes in a card.

A "graphical user interface" (GUI) is an oblique phrase for any object with drawings on it, essentially for only visual interpretation rather than physical or aural. For example, a sheet of paper, or a sheet of glass, or a grid of lights. Text and other shapes are drawn with lines or with dots, perhaps by coloring each square of a grid.

Obviously, shape is visibly noticeable only when there are at least two distinctive colors; corollarily, there are no distinctions with only one color. Text and other shapes can be drawn with only two colors available, commonly referred to as a foreground color for the most important areas and a background color for less important areas. Additional colors allow for more distinctions, thereby more variety of lines and dots for text and other shapes. Notably, an extraneous use of distinction is distracting or muddling.

A drawing, t.i. a graphical recording, using more than two colors on a grid bound by having only a single color per square (t.i. a dot) can record a greater variety than a punchcard using only one hole shape. Similarly, more than one physically distinguishable hole shape would increase the variety for a punchcard.

Notably, the raised dots of braille pressed into paper are the inverse of a hole, and provides such a variety potentially detectable by machines, too. Furthermore, the eight-dot version of braille is equivalent to the eight-bits of a byte, thereby suggesting bytes might be readily perceived visually and physically. The million symbols or characters of Unicode is one step away from that, each represented by one or more bytes, f.e. with the UTF-8 or UTF-32 formats.

A touchscreen is a transparent overlay for a graphical display, such as on top of a sheet of paper or on top of a grid of lights. The drawings of text and shapes, or the lack thereof, beneath the screen are coordinated with the same areas of the transparent screen overlaying them. The transparent screen detects physical touch, and those touches are related with the areas on the graphical display. While that physical action with the overlay is imitative of recording information on a punchcard, an unshapable graphical display remains unreadable physically.

# pet rocks: wasteful manufacturing

[ This is eventually for a section of notes about the wastefulness of products, and the characteristics of a worthwhile product. ]

Some factors:

[ A collection of formerly useful products is comparable to a collection of interesting looking rocks, also known as pet rocks. Such a collection of novel contraptions might be worthy for a museum, but is more of a reflection of prior personal interests (perhaps no longer accurately representing). ]


More:
HyperText Markup Language (HTML)
markup a CSS stylesheet
basic PDF 1.4
approaches for documenting binary files
file transfer, find, and grep
ssh key generation and use
notes about emacs : essentials and elaborate
installing emacs
email in emacs
ImageMagick command-line options for convert and mogrify (or magick as of 7.x)
Examples of ImageMagick Usage (6.x)