aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-29 20:25:39 +0200
committeruser <user@clank>2026-08-29 20:25:39 +0200
commit31c32f9c20e3dd5045fa053fc8e7e606a8139397 (patch)
tree007bf1dfe01b8beda4bd5d00642f060d759d519c /docs
parentarch: sign the packages and the database, and say whose key (diff)
downloadslosh-31c32f9c20e3dd5045fa053fc8e7e606a8139397.tar.gz
slosh-31c32f9c20e3dd5045fa053fc8e7e606a8139397.tar.xz
slosh-31c32f9c20e3dd5045fa053fc8e7e606a8139397.zip
docs: less wordy
Diffstat (limited to 'docs')
-rw-r--r--docs/config.md21
-rw-r--r--docs/design.md5
-rw-r--r--docs/index.md30
-rw-r--r--docs/keys.md5
-rw-r--r--docs/layouts.md73
-rw-r--r--docs/panes.md58
-rw-r--r--docs/scripting.md5
-rw-r--r--docs/shaders.md42
-rw-r--r--docs/windows.md15
-rw-r--r--docs/workspaces.md78
10 files changed, 125 insertions, 207 deletions
diff --git a/docs/config.md b/docs/config.md
index 86cfc79..d768e3a 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -61,9 +61,8 @@ config that was never opened and a config with nothing wrong look identical.
It is the loader, not a second implementation of it: the only checker that
cannot drift from what a session does is the one a session uses. The single
-difference is how many problems each reports: a session has one status line and
-shows the first, and a linter that stopped at the first mistake would make you
-run it once per mistake.
+difference: a session's status line shows the first problem, the checker shows
+them all.
## include
@@ -136,10 +135,8 @@ padding 0 2 // vertical, horizontal
padding 2 0 0 1 // top, right, bottom, left
```
-A number means the same thing however many of them you write, so `padding 1`,
-`padding 1 1` and `padding 1 1 1 1` are one padding rather than three. Three
-values is refused: CSS reads it as top/horizontal/bottom, and a line whose
-meaning you have to look up is a line nobody can read.
+Three values is refused: CSS reads it as top/horizontal/bottom, and a line
+whose meaning you have to look up is a line nobody can read.
## Compact
@@ -193,12 +190,10 @@ picks its own: 10,000 *bytes*, which measures at 622 lines of an 80-column pane,
less than one `make` run. `scrollback` is that number replaced with the one every
other multiplexer settled on.
-The two limits work together because either can be reached first and neither can
-see what the other depends on: a line count cannot know how wide your terminal is
-or how many styles a program used, and a byte count cannot know how many lines
-that bought. Whichever bites first wins. Both are estimates: history is pruned a
-page at a time (a page is about 400KB of grid), so a pane keeps a little more
-than it was told, never less.
+Whichever limit bites first wins: a line count cannot know how wide your
+terminal is, and a byte count cannot know how many lines it bought. Both are
+estimates: history is pruned a page (about 400KB of grid) at a time, so a pane
+keeps a little more than it was told, never less.
What the ceiling costs, measured on a pane filled with styled output:
diff --git a/docs/design.md b/docs/design.md
index bf1d412..458858c 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -91,9 +91,8 @@ line breaks carry meaning: a paragraph, a list, a diagram of a pane. A comment
that runs long is a thing for a person to fix.
The Python is the opposite: left entirely at ruff's defaults. The C here was
-hand-formatted into a house style worth arguing for; the Python was not, and a
-formatter of that kind is only worth having when there is nothing left to argue
-about. Every knob turned would be an argument to have again later. It cost a 60%
+hand-formatted into a house style worth arguing for; the Python was not, and
+every knob turned would be an argument to have again later. It cost a 60%
reformat of the test suite, once.
**Python imports are sorted and C includes are not**, which is not an
diff --git a/docs/index.md b/docs/index.md
index ad90c7f..960ebf7 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -16,11 +16,9 @@ brew install slosh
### Linux
-The same tap works under [Homebrew on
-Linux](https://docs.brew.sh/Homebrew-on-Linux), or build from source. That
-needs [zig](https://ziglang.org) 0.16 and nothing else: no cmake, no
-autotools, no libraries. The result is one static binary that runs on any
-distro.
+Build from source. That needs [zig](https://ziglang.org) 0.16 and nothing
+else: no cmake, no autotools, no libraries. The result is one static binary
+that runs on any distro.
```bash
make vendor # build the vendored terminal core (once, a couple of minutes)
@@ -32,6 +30,28 @@ sudo make install
(The source build works on a mac too; Homebrew is simply the shorter road
there.)
+#### Arch
+
+A pacman repository serves built, signed packages. Enroll the signing key
+(fingerprint `0F67C909938CFFA8A76B59FD8D69B55A0E9056B9`; the same key is
+`contrib/arch/slosh.asc` in git, so the two copies can be compared):
+
+```sh
+curl -fsSLO https://slosh.foo/arch/slosh.asc
+sudo pacman-key --add slosh.asc
+sudo pacman-key --lsign-key 0F67C909938CFFA8A76B59FD8D69B55A0E9056B9
+```
+
+then, in `/etc/pacman.conf`:
+
+```ini
+[slosh]
+Server = https://slosh.foo/arch/$arch
+```
+
+and `pacman -Sy slosh`. Details, and the PKGBUILD for building it yourself:
+`contrib/arch/README.md` in the source tree.
+
### Windows
Windows 10/11, x86-64 and ARM64, as one `slosh.exe`. Panes are ConPTYs and
diff --git a/docs/keys.md b/docs/keys.md
index 5afc1b5..84422d1 100644
--- a/docs/keys.md
+++ b/docs/keys.md
@@ -49,9 +49,8 @@ it did not (`+7 more, in docs/keys.md`), which is the table below.
**`x`/`X`, `p`/`P`, `w`/`W` and `f`/`F` are deliberately shifted pairs on one
letter.** Close this pane / close this tab; run a command / tag this pane; go
to a project / write this project down; float this pane / float a fresh one.
-The shifted half is the same verb on a bigger thing, or the thing you reach
-for within a moment of the other, so the shift is less to remember than a
-second letter would have been.
+The shifted half is the same verb on a bigger thing, so the shift is less to
+remember than a second letter would have been.
`X` says how many panes went with the tab, since most of them were not the one you
were looking at. On the **last** tab it refuses and points at `q` instead: a key
diff --git a/docs/layouts.md b/docs/layouts.md
index a2d22b3..0e66f7b 100644
--- a/docs/layouts.md
+++ b/docs/layouts.md
@@ -21,26 +21,18 @@ slosh --layout project.layout
## What to call them
-**`*.layout`**, and a project's is `slosh.layout`. The syntax is still the same
-KDL subset the config uses, one parser reads both files, and for a while the
-files were `*.layout.kdl` on the argument that the extension should say so.
-The argument lost to a collision: zellij speaks the same syntax under that
-same extension with a different schema, and to anyone arriving from there
-`.kdl` said *whose* file it is, and naming the wrong owner is worse than not
-naming the parser. The name says what the file is; `slosh --check` says how
-it was read. (Point your editor's KDL highlighting at `*.layout`; it *is*
-still KDL underneath.) The old spelling is still found by the project scan,
-never written.
+**`*.layout`**, and a project's is `slosh.layout`. The syntax is the same KDL
+subset the config uses — one parser reads both files — but the extension is
+not `.kdl`: zellij speaks KDL layouts with a different schema, and naming the
+wrong owner is worse than not naming the parser. Point your editor's KDL
+highlighting at `*.layout`. The old `*.layout.kdl` spelling is still found by
+the project scan, never written.
A filename cannot enforce anything, so **the document decides which schema it is
held to, not the flag that read it**. `slosh --check` reads what is in front of
-it: a file with `layout` or `tab` at the top of it is checked as a layout, and a
-config handed to the same flag is still checked as a config. A file too broken to
-parse at all is judged by its name, because by then there is nothing else left to
-read. One flag rather than a `--check-layout` beside it: naming the schema is the
-part you wanted the checker to do, and the answer it used to give (`this is a
-layout, not a config`) replied to a question about a file with the name of
-another flag.
+it: a file with `layout` or `tab` at the top is checked as a layout, a config
+handed to the same flag is still checked as a config, and a file too broken to
+parse at all is judged by its name, there being nothing else left to read.
```
$ slosh --check project.layout
@@ -64,12 +56,9 @@ $ slosh --check broken.layout
broken.layout: 6 problems
```
-Those are the mistakes a layout can make that still parses: a property no pane
-has, a `split=` that is neither direction, a `weight=` that is not a number the
-engine will honour, a `true`/`false` written some other way, a `purpose=` on a
-split (which would tag nothing, because a split runs nothing) and a child node
-that is not a `pane`. Last comes `this layout declares no tabs`, reported at the
-end rather than first so it reads as the summary it is.
+Those are the mistakes a layout can make that still parses. `this layout
+declares no tabs` comes last rather than first, so it reads as the summary it
+is.
Loading is the other half of the same answer:
@@ -79,9 +68,7 @@ slosh: config.kdl: this is a config, not a layout: `gap` is a setting
```
A config handed to `--layout` is named for what it is instead of refused for
-having no tabs, which is true of it in the least useful way. Both answers come
-from the same list of settings the loader reads, so the two cannot disagree about
-which file is which.
+having no tabs, which is true of it in the least useful way.
## The shape
@@ -105,10 +92,9 @@ which file is which.
- `purpose=`: a label for tooling; see below.
**A relative `cwd=` in a layout *file* resolves against that file's own
-directory**, never against the directory you started the session from. It is the
-rule [`include`](config.md#include) already follows for configs, applied to the
-other half of the same syntax: the two documents share a parser, so they should
-not disagree about what a relative path is. A layout with no `cwd=` anywhere
+directory**, never against the directory you started the session from. It is
+the rule [`include`](config.md#include) already follows, applied to the other
+half of the same syntax. A layout with no `cwd=` anywhere
starts in the file's directory too, so the common case needs no `cwd=` at all. An
absolute path is unchanged, and `~` is still your home directory.
@@ -129,14 +115,11 @@ layout {
```
Clone that repo somewhere else and the tab still opens on the checkout, with the
-pane that said `src` still in the checkout's `src`. The alternative (absolute
-paths, or a `$PROJECT` of our own to expand) makes the file personal to one
-machine, or makes you learn a variable to say "here".
+pane that said `src` still in the checkout's `src`.
-A layout that arrives as *text* over the socket has no file, and so no directory
-to be relative to. Relative paths in it keep the meaning they had before there
-was a base: relative to wherever the session is. Inventing one for text would
-mean guessing on behalf of whoever sent it.
+A layout that arrives as *text* over the socket has no file, and so no
+directory to be relative to; relative paths in it resolve against wherever the
+session is.
A full annotated example is
`config/example.layout`.
@@ -214,9 +197,7 @@ empty document, because an empty layout is a plausible answer for a tab you clos
a minute ago and a silent one for a typo in an id.
A dump records `focus=true` in **every** tab, not only the one you were looking
-at. It used to ask the session's current tab which pane was focused whichever tab
-it was writing, so restoring a six-tab session put you back where you were in one
-tab and wherever the file happened to begin in the other five.
+at, so restoring a six-tab session puts you back where you were in all six.
## Applying one to a running session
@@ -259,17 +240,13 @@ the layout rather than from whatever the program decides to print.
`C-a P` gives the focused pane one from the keyboard (see
[keys](keys.md#defaults)) and **a purpose an operator typed counts as declared,
-so it locks like one from a file**. The lock is not about which door the label
-came through, it is about the label coming from outside the pane at all: you named
-that pane `service:web` on purpose, and the shell in it printing a title is not an
-argument for renaming it.
+so it locks like one from a file**: you named that pane `service:web` on
+purpose, and the shell in it printing a title is not an argument for renaming
+it.
**Setting a purpose to nothing unlocks it**, from a layout, the API or `C-a P`
with the field cleared, and hands the label back to the program to describe
-itself again. Before that, a lock held over an empty string was the one state
-nothing could get out of: the pane carried no label, and the lock was what kept
-the program from supplying one. It is the same shape as clearing a pane's name,
-and worth more than a second verb whose whole job is taking a lock off.
+itself again — the same shape as clearing a pane's name.
The [finder](panes.md#finding-a-pane) matches on purposes as well as titles, and
`{"cmd":"panes"}` reports them.
diff --git a/docs/panes.md b/docs/panes.md
index 4161d2f..04127bd 100644
--- a/docs/panes.md
+++ b/docs/panes.md
@@ -12,11 +12,9 @@ looking at is drawn.
Splitting the same direction again gives three equal shares rather than
1/2 + 1/4 + 1/4.
- **A new pane starts in the directory the pane it came out of is in**, not where
- the session was started. Splitting inside a project to run one more thing and
- landing in whatever directory the server was launched from is wrong on its own;
- it was wrong on disk as well, because a saved
- [project layout](workspaces.md) then carried an absolute `cwd=` pointing at
- somewhere else entirely.
+ the session was started. Landing somewhere else is wrong on screen and worse
+ on disk: a saved [project layout](workspaces.md) would carry an absolute
+ `cwd=` pointing somewhere else entirely.
- **Resize** with `C-a H J K L`: the boundary moves the way you press, whichever
side of it you are on. Sizes are *weights*, so a resized layout survives the
window changing size.
@@ -29,15 +27,14 @@ looking at is drawn.
A turn that would squeeze a pane under the floor is refused with a word.
- **`C-a z`** fills the tab with one pane and back; **`C-a m`** puts one away
into a strip along the bottom, still running. Each put-away pane sits there
- as a **miniature pane frame** (a frame is what a pane looks like here, so
- a shrunken one reads as exactly what it is) and clicking it anywhere
- brings the pane back:
+ as a **miniature pane frame**, and clicking it anywhere brings the pane
+ back:
- ```
- ╭────────────╮ ╭─────────────────╮
- │ ▬ server │ │ ▬ agent [!] │
- ╰────────────╯ ╰─────────────────╯
- ```
+```
+╭────────────╮ ╭─────────────────╮
+│ ▬ server │ │ ▬ agent [!] │
+╰────────────╯ ╰─────────────────╯
+```
## The mouse
@@ -55,9 +52,9 @@ nothing you click can disagree with what is on screen.
land. The rest of the edge does nothing when clicked.
- **The top row is the drag handle, and its handle splits upward.** Clicking a
pane's header to focus it never splits it. Its handle goes as near the middle
- of the row as the row allows: centred when the row is empty, and against the
- title when the title is holding the middle, since the title keeps its own cells
- for the double-click rename. Arming an edge leaves the name, the buttons and a
+ of the row as the row allows: centred when the row is empty, beside the title
+ when the title holds the middle (the title keeps its cells for the
+ double-click rename). Arming an edge leaves the name, the buttons and a
dead pane's epitaph legible: the heavy rule goes round them.
- **Drag the gap between panes** to move that boundary. Where two gaps cross,
drag the crossing to move both at once. With `gap 0` there is no gap to
@@ -101,11 +98,8 @@ nothing you click can disagree with what is on screen.
rather than dropping it at the end.
- Click a tab to switch, `+` to open one, a pane to focus it, and the marks in a
frame's corner to minimise (`▬`), zoom (`□`) or close (`✕`) it.
-- **A tab in the strip has no `✕`** and closes with `C-a X` instead. A mark per tab
- would cost two columns of every tab on every frame, forever, for a verb pressed
- rarely, the same arithmetic that took the per-pane `+` away. A pane's marks
- earn their cells because there is one set of them and it is where you are
- looking.
+- **A tab in the strip has no `✕`** and closes with `C-a X` instead: a mark per
+ tab would cost two columns of every tab, forever, for a verb pressed rarely.
- Hovering anything says what it does, in a word, in the status line.
## Floating a pane
@@ -129,9 +123,8 @@ like any shell, and un-floating lands it beside the pane it was opened over.
- **`C-a H J K L` move a focused float** instead of moving a boundary, since
a float has no boundary to move. **`=` (or `+`) grows it and `-` shrinks
it** about its own centre, so it stays under your eyes; on a tiled pane
- `-` still splits. Equalize lives on `0` for this reason: `+` arrives as a
- bare `=` on terminals that do not report shift for punctuation, and two
- verbs on one key survive only until that happens.
+ `-` still splits. Equalize lives on `0` because `+` arrives as a bare `=`
+ on terminals that do not report shift for punctuation.
- **It casts a shadow** on what it covers, which is how you tell a float from
a tile at a glance. `float_shadow 0` in the config turns it off, and a
`states { floating { … } }` chain colours floats on top of that.
@@ -203,16 +196,15 @@ with two lines saying what ran and how it ended, and two buttons:
```
**The command is written down because `[re-run]` is one button.** Without it,
-pressing it is a guess, most of all in a tab that a [project's
-layout](workspaces.md) built, where the command was never typed into that pane to
-be scrolled back to. A pane running the session's shell has no command to name
-and gets the exit line alone.
+pressing it is a guess — most of all in a tab a [project's
+layout](workspaces.md) built, where the command was never typed to be scrolled
+back to. A pane running the session's shell has no command to name and gets the
+exit line alone.
-`[re-run]` (or `C-a r`) runs the same command again in the same pane, keeping the
-previous run above it in the scrollback. So the two notes turn a pane you re-run
-into a log of what ran rather than a pile of identical epitaphs, and a command
-that failed while you were looking elsewhere still has its error message when you
-get back, while a mistyped command in a fresh session no longer closes it.
+`[re-run]` (or `C-a r`) runs the same command again in the same pane, keeping
+the previous run above it in the scrollback: a pane you re-run becomes a log of
+what ran, and a command that failed while you were looking elsewhere still has
+its error message when you get back.
Which panes stay is one setting, `keep_dead`: `commands` (the default), `all`,
or `none`.
diff --git a/docs/scripting.md b/docs/scripting.md
index d03184d..54c41ce 100644
--- a/docs/scripting.md
+++ b/docs/scripting.md
@@ -30,13 +30,12 @@ Panes and tabs are addressed by **id**, so a background tab is scriptable.
| `focus` | `id` |
| `close` `rerun` | `id`, or 0 for the focused pane |
| `clear-shaders` | `id`, or 0 for the focused pane; answers `cleared:0\|1`. The way back from a pane that painted itself unreadable |
-| `new-tab` `select-tab` `close-tab` `move-tab` `set-name` | tabs, by `id` or `index` |
-| `set-name target="pane"` | a pane's name, which outranks the title its program sets |
+| `new-tab` `select-tab` `close-tab` `move-tab` | tabs, by `id` or `index` |
| `move-pane` | `id` of the pane, `tab` id to move it into (`0` for a tab of its own, with an optional `name`), `dir:"cols"\|"rows"`. The pane keeps running: same pty, same scrollback |
| `float` | bare: toggle a pane [floating](panes.md#floating-a-pane) (`id`, or 0 for the focused one). With any of `x` `y` `w` `h` it *places*: floats first when tiled, re-places when floating, never un-floats; omitted fields keep their value |
| `new-float` | a fresh floating shell over the current tab, centred, in the focused pane's directory; answers `id` |
| `set-name` | `target:"tab"` (the default, because that is what this verb has always meant) or `"pane"`, `id`, `name`. A pane accepts 0 for the focused one. A pane's name wins over the title the program sets, so this is how a program that keeps announcing something stale gets overruled; an empty `name` clears it and hands the label back. Refusals say `no such pane` or `no such tab`, so a mistyped target is visible in the reply |
-| `set-purpose` | `target:"pane"\|"tab"`, `id` (or 0 for the focused pane, and the tab you are in), `purpose`. An empty `purpose` clears the slot *and* unlocks it, handing the label back to the program, because a lock held over an empty string was a state nothing could get out of |
+| `set-purpose` | `target:"pane"\|"tab"`, `id` (or 0 for the focused pane, and the tab you are in), `purpose`. An empty `purpose` clears the slot *and* unlocks it, handing the label back to the program |
| `dump-layout` `apply-layout` | see [layouts](layouts.md). `dump-layout` takes `tab` (0 for every tab), `relative_to` to write every `cwd=` under that directory instead of absolute, and `suspend` (`as-is` `none` `commands` `all`); it answers `kdl` `panes` `suspended`, and an unknown `tab` is an error rather than an empty document |
| `workspaces` | the projects on disk and which of them are open: `roots` says whether any are configured at all, and each entry has `name` `path` `purpose` `layout` (a file path, or "") `mtime` `tab` (0 when closed). See [workspaces](workspaces.md) |
| `open-workspace` | `name` or `path`, and `suspended`; answers `tab` `purpose` `path` `created` `tabs` `honoured`. Already open means focused, with `created:false` |
diff --git a/docs/shaders.md b/docs/shaders.md
index d06aa3c..8be513a 100644
--- a/docs/shaders.md
+++ b/docs/shaders.md
@@ -74,10 +74,9 @@ shaders {
`PI` being a half turn is what makes a radian-shaped formula port across as
written: `sin(TAU * x / cols)` is one cycle over the pane's width, `PI / 2` is a
quarter turn, `PI / 6` is thirty degrees. It is also *more* exact than radians
-could be in a language with no fractions: a sixth of a turn is 30 whole degrees,
-where `3.14159 / 6` in integers is 0. For the same reason there is no `deg2rad`
-or `rad2deg`: there is one angle unit, and a conversion could only lose the angle
-or invent a second scale to disagree with.
+could be in a language with no fractions: a sixth of a turn is 30 whole
+degrees, where `3.14159 / 6` in integers is 0. There is one angle unit, so
+there is no `deg2rad` or `rad2deg`.
There are no loops and no recursion, on purpose: a config cannot spin and there
is nothing to sandbox. An expression that does not compile drops that one shader
@@ -149,29 +148,22 @@ chrome> include "contrib/chrome/shine.kdl" a file, the way a config includes
chrome> :load shine the same, for the presets that ship with it
```
-`:paste` prints the document back as a `shaders { }` block with `where=` on every
-entry, and that block can be typed straight back in, which is the point of
-borrowing the syntax rather than inventing one. A test reads it off the screen,
-clears the pane, types it back and compares the cells.
+`:paste` prints the document back as a `shaders { }` block with `where=` on
+every entry, and that block can be typed straight back in, which is the point
+of borrowing the syntax rather than inventing one. The reply counts
+(`1 chrome, 1 content`) say where the passes went, which is the only way to see
+that an entry's `where=` did what you meant.
-The text is a **document**: what it says replaces both chains, the way naming
-`shaders { }` in a config replaces the block rather than adding to it. The reply
-counts (`1 chrome, 1 content`) say where the passes went, which is the only way to
-see that an entry's `where=` did what you meant.
+Nothing in the prompt parses KDL: a file goes over by path and a pasted block
+via a temporary file, because the session already has the parser and a second
+reader would be a second opinion.
-Nothing in the prompt parses KDL. A file goes over by path and a pasted block via a
-temporary file, because the session already has the parser, and a second reader of
-a config file would be a second opinion about what it says, exactly where comments
-meet quoted strings.
-
-It is a readline prompt, so editing, up/down and ctrl-r work as they do in a shell,
-and history is kept between runs in `$XDG_DATA_HOME/slosh/shader-repl.history`.
-The chains only, since `:quit` is not something you want to press up past. Tab
-completes the commands, the shader names, the property keys, the expression
-language's own variables, constants and functions, and filenames after `:load`.
-`:help` prints the same list at once. A test checks that list against
-`src/shader.c` and `src/expr.c`, because a completion list that has gone stale
-reads as "that is all there is".
+It is a readline prompt: editing, up/down and ctrl-r work as in a shell, and
+history is kept between runs in `$XDG_DATA_HOME/slosh/shader-repl.history`
+(the chains only, since `:quit` is not something you want to press up past).
+Tab completes the commands, the shader names, the property keys, the
+expression language's variables, constants and functions, and filenames after
+`:load`; `:help` prints the same list at once.
**Off by default.** It needs `in_band_shaders true`, because a program that can
restyle the session it happens to be running in is a hazard first and a
diff --git a/docs/windows.md b/docs/windows.md
index c1901cd..2f076da 100644
--- a/docs/windows.md
+++ b/docs/windows.md
@@ -145,14 +145,11 @@ the session on the one program that misbehaves. Whoever finishes last frees.
something on it is not an EOF anywhere.
- **No editor is guaranteed.** `C-a e` prefers whichever console editor is
actually installed — `nvim`, `vim`, `vi`, `nano`, `micro`, `hx`, `edit` —
- because the obvious fallback is the wrong shape: `notepad` is a GUI program,
- so a pane running it draws nothing and looks broken. Microsoft Edit (`edit`)
- is a console program, so it fills a pane like any other editor: from Windows
- 11 24H2 there is a usable editor without installing one. It comes last of the
- console editors because it arrives on its own, and so says nothing about what
- you want, where having fetched nvim does. Older Windows does not ship it, so
- if nothing is found slosh still opens notepad, and says so, rather than
- leaving you an empty pane to puzzle over. `EDITOR` and the config's `editor`
- are honoured ahead of the search.
+ because `notepad` is a GUI program: a pane running it draws nothing and looks
+ broken. Microsoft Edit (`edit`) ships from Windows 11 24H2 and fills a pane
+ like any other editor; it comes last because it arrives on its own, and so
+ says nothing about what you want. If nothing is found, slosh still opens
+ notepad, and says so, rather than leaving an empty pane to puzzle over.
+ `EDITOR` and the config's `editor` are honoured ahead of the search.
- **`--check`, `--dump-config`, layouts, workspaces and shaders** are
unaffected: they never touched a pty or a socket.
diff --git a/docs/workspaces.md b/docs/workspaces.md
index 2dbce4d..134b8b2 100644
--- a/docs/workspaces.md
+++ b/docs/workspaces.md
@@ -1,40 +1,12 @@
# Workspaces
-A **project** is a directory on disk. A **workspace** is the tab it occupies in a
-session. Two words rather than one because the two have different lifetimes: the
-project outlives every session and is checked into git, the workspace lasts until
-you close the tab.
+slosh has the concept of **workspaces**. Essentially a workspace is a
+pane layout that represents a project. slosh will scan your config's `project_roots`
+folder(s) for two kinds of sub folders: ones that have a `slosh.layout` file, and
+ones that have a `.git` but no `slosh.layout`. in the latter case our project picker
+can still pick it up and help you provision a new `slosh.layout`.
-[Finding a pane](panes.md#finding-a-pane) starts from the complaint this answers:
-tabs stop being navigation somewhere around six projects. The finder answers
-*where is that pane*; this answers the question before it: which of the things you
-work on is this tab about, and what does opening one mean. `C-a w`, a name, enter,
-and the tab arrives arranged, because the project itself said how.
-
-## What counts as a project
-
-A subdirectory of a configured root with one of two markers in it:
-
-| marker | what it is |
-|---|---|
-| `slosh.layout` | a *declared* project: it says what it needs open |
-| `.git` | an *inferred* one: you work here, but you have not said how |
-
-Anything else is not a project, and nothing is guessed from what is inside it.
-
-**`.git` counts because otherwise the list is empty on the day you configure the
-feature.** A picker that only knows declared projects shows nothing until you have
-written a layout, and there is nowhere to write one from: you would need the
-picker to get there. The inferred half is also the invitation: such a project reads
-`.git · no layout` in the picker, and `C-a W` is how it stops being one.
-
-**A directory that is a project is never descended into.** That is what keeps the
-scan out of `node_modules`, a vendored checkout or a submodule without a rule about
-any of their names: they are under a project, so the walk stops above them. A skip
-list is a list of the directories that were fashionable when it was written; this
-holds for the ones nobody has invented yet.
-
-## Where they live
+## Configuration options
Two settings, both in your [config](config.md):
@@ -45,29 +17,7 @@ project_layout "~/.config/slosh/project.layout"
`project_roots` takes more than one directory because people have more than one
(work in one tree, everything else in another), and `depth` is how many levels below
-each root to look, 2 by default, 1 to 8. Two is `~/dev/thing` and
-`~/dev/org/thing`, which is where checkouts actually sit.
-
-**No roots configured and the feature is dormant.** Nothing is scanned, `C-a w`
-says which setting is missing rather than opening an empty picker, and `workspaces`
-answers `roots: false`, because "you have no projects" and "you never said where
-they are" are different facts, and a tool that cannot tell them apart reports the
-wrong one.
-
-`project_layout` is what a project with no file of its own opens as. **Relative
-paths in it bind to the project being opened, not to the directory the file lives
-in**, deliberately the opposite of the rule for a layout you name yourself, where
-a relative `cwd=` is relative to that file ([layouts](layouts.md#the-shape)). The
-whole point of one shared layout is that `cwd="."` means *this* project; bound to
-itself it would open every project in `~/.config/slosh`. Unset, a project opens
-as one pane running your shell in it.
-
-**Nothing sniffs `package.json` or `Cargo.toml` to guess what to run.** A table
-mapping manifests to commands is wrong for somebody the day it ships (the repo
-with two package managers, the one whose dev server is behind a make target) and
-stale for everybody a year later. `project_layout` is that table with your name on
-it, covering the projects you have rather than the ones a heuristic imagined, and a
-project that disagrees with it carries its own file.
+each root to look, 2 by default, 1 to 8.
## From the keyboard
@@ -145,11 +95,9 @@ otherwise: a shell's history and an editor's buffers are not in it.
**Over the API, writing over a layout that is already there is refused without
`force`; from the keyboard `C-a W` replaces it and the toast says `replaced`.**
-That asymmetry is not an oversight in either direction. A key cannot pass a flag,
-and the operator pressing it is looking at the tab being written; the file is
-committed text, so the diff is the confirmation and the replacement stays
-reviewable after the fact. A script has none of that (no witness, no glance at
-the screen) so it says so in the request.
+The asymmetry is deliberate: the operator pressing the key is looking at the
+tab being written, and the file is committed text, so the diff is the
+confirmation. A script has no witness, so it says so in the request.
`save-workspace` also takes `path`, for a tab that is not a workspace yet: that is
how a hand-arranged tab becomes a project's layout without opening it through the
@@ -218,9 +166,9 @@ Every one of them is in the bare dispatcher too, so `slosh -s work cmd
workspaces` and `slosh -s work cmd open-workspace api` do the same from a shell
without quoting JSON ([scripting](scripting.md#the-control-socket)).
-`open-workspace` is idempotent, which is the property that makes it safe to call
-from a script that does not know whether it ran already: asking twice focuses the
-tab rather than building a second one. `suspended:true` opens the layout with every
+`open-workspace` is idempotent: asking twice focuses the tab rather than
+building a second one, so a script that does not know whether it already ran is
+safe. `suspended:true` opens the layout with every
pane suspended whatever the file said: the *open ten projects, run zero processes*
case, which is a different question from the one the project answered about which
of its own panes are expensive.