aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-17 13:53:57 +0200
committeruser <user@clank>2026-08-17 13:53:57 +0200
commit2f9135d2810cfb38ccdd4f07e895c66430d066fe (patch)
tree2816a6c2addf8c8181dddc51faa308188beccb10 /docs
parentsl0ppty: `set-name target="pane"`, so a script can overrule a program's title (diff)
downloadslosh-2f9135d2810cfb38ccdd4f07e895c66430d066fe.tar.gz
slosh-2f9135d2810cfb38ccdd4f07e895c66430d066fe.tar.xz
slosh-2f9135d2810cfb38ccdd4f07e895c66430d066fe.zip
sl0ppty: double-click a word to select it
`pane_select_word()` was written and never wired to anything: no declaration, no caller, no way to reach it. This is the rest of it -- the gesture, the setting, and the tests. **The word is defined by what it stops at, not by what it is made of.** Anything that is not blank and not a listed separator belongs to a word, so CJK, accented letters and emoji need no table and come out whole; whitespace always separates, listed or not, because a double-click that selected the line would be a different gesture arrived at by surprise. Wide glyphs continue the run they are in rather than each being their own word -- otherwise every CJK character is a word. `word_separators` defaults to `"'`()[]{}<>;,|`, and what it leaves *out* is the decision: `/ . - _ : = @ # % ? & + ~ $` stay inside words, so a path, a dotted name, a snake_case identifier, a key=value pair, a URL and `src/app.c:1234` are each one thing you double-clicked to copy whole. `:` is the difference between copying an error location and copying half of one, which is why kitty keeps it too. The gesture reuses what selecting already has: the press starts a selection at the cell -- which anchors a drag out of the double-click -- then widens it to the word, and the release path that already copies a drag copies this. So the word *is* the copy, in the one place that rule lives, and the highlight is the copied span rather than an approximation of it. Tracked per cell as well as per pane, so clicking two different words quickly selects the second rather than everything between them. A program that asked for the mouse still keeps its clicks, with shift as the escape hatch, exactly as the drag has it. **One thing this needed on the way: quoted values were dumped unescaped.** The default separator set opens with a quote, and `cb_add(&b, "key \"%s\"\n", ...)` wrote it raw -- so `--dump-config` produced a file that no longer parsed, breaking the property the dump exists for. The escaping loop already existed inside `cb_chord`, for the same reason and with the reasoning written down; it is now `cb_qval`/`cb_qstr` and every string setting goes through it: the marks, `shell`, `editor`, `shader_dir`, `project_roots`, `project_layout`. Latent for all of those, load-bearing for this one. **And `--dump-config` does not do what four comments and the docs said it did.** It calls `config_dump_defaults()`: every setting with its *default*, never the value your config gives it. The function name was the honest one. Corrected in `docs/config.md`, `config/config.kdl`, `main.c`, `config.c`, `app.c` and the test's own docstring, rather than changing what the flag does -- starting a config from it is the documented use, and `--check` is what reads yours. There is no way to ask for the effective config; that is a gap, not a lie, and it can be a flag when somebody wants it. Verified: 22 checks in `tests/test_clipboard.py`. An error location, an identifier stopping at a bracket, a URL, a word inside quotes and a run of CJK; the highlight being exactly as wide as the copy; a separator, a blank cell and a single click each leaving the clipboard alone; two clicks on different cells not being a double; two slow clicks not being one; the separator set honoured from a config, including a quote and a backslash carried through KDL escaping; a word in a scrolled pane coming from the row on screen; and a mouse-tracking program keeping its double-clicks until shift takes them back. Three of those failed first because the test asked for the answer twice -- a second `worded()` call is a second pair of clicks -- and one because it mapped string indices to columns without counting wide glyphs as two.
Diffstat (limited to 'docs')
-rw-r--r--docs/config.md11
-rw-r--r--docs/panes.md6
2 files changed, 12 insertions, 5 deletions
diff --git a/docs/config.md b/docs/config.md
index a197052..db9da89 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -22,10 +22,11 @@ plugin that replaced one already loaded needs a new session.
## Two files worth knowing
-- **`sl0ppty --dump-config`** writes every setting with the value it currently
- has. It is generated from the code, so it cannot drift from the defaults, and
- it is a supported way to start a config:
- `sl0ppty --dump-config > ~/.config/sl0ppty/config.kdl`.
+- **`sl0ppty --dump-config`** writes every setting with its *default* value —
+ not the value your config gives it. It is generated from the code, so it
+ cannot drift, and it is a supported way to start a config:
+ `sl0ppty --dump-config > ~/.config/sl0ppty/config.kdl`. To see what your own
+ file does, `sl0ppty --check` reads it and reports what it understood.
- **`config/config.kdl`**
in the source tree is the same list with the *reasoning* attached — what each
setting is for, what it cost to get right, and which ones are opinions. When
@@ -110,7 +111,7 @@ theme { frame_focus "#00ff88" } // ...but that one colour is mine
|---|---|
| geometry | `gap` `gap_aspect` `padding` `rounded` `title_align` `title_inset` `min_pane` `min_split` |
| chrome | `status_bar` `status_line` `status_pad` `hints` `version_banner` `pane_buttons` `bell_indicator` and the marks (`zoom_mark` `zoom_on_mark` `close_mark` `min_mark` `newtab_mark` `bell_mark`) |
-| behaviour | `focus_follows_mouse` `scroll_lines` `scrollback` `scrollback_bytes` `toast_ms` `hover_delay_ms` `double_click_ms` `anim_ms` `modal_scrim` `dim_unfocused` `keep_dead` `in_band_shaders` `shell` `editor` `shader_dir` |
+| behaviour | `focus_follows_mouse` `scroll_lines` `scrollback` `scrollback_bytes` `toast_ms` `hover_delay_ms` `double_click_ms` `word_separators` `anim_ms` `modal_scrim` `dim_unfocused` `keep_dead` `in_band_shaders` `shell` `editor` `shader_dir` |
| colour | `theme { }` |
| effects | `shaders { }`, `states { }` — see [shaders](shaders.md) and [chrome](chrome.md) |
| keys | `keys { }` — see [keys](keys.md) |
diff --git a/docs/panes.md b/docs/panes.md
index 70dafc7..fd3bcee 100644
--- a/docs/panes.md
+++ b/docs/panes.md
@@ -119,6 +119,12 @@ either, whatever its width says.
- **Select text to copy it.** Release the mouse and it is on your clipboard,
sent to your terminal over ssh as well as locally. Middle click pastes.
+- **Double-click a word to select it**, and it is copied the same way a drag is:
+ the highlight *is* the copy. What counts as one word is `word_separators`,
+ which lists what a word stops at rather than what it is made of — so
+ `src/app.c:1234`, `https://a.b/c?d=1`, `snake_case` and a run of CJK each come
+ out whole, while a quote or a bracket ends one. A click on a blank cell or on
+ a separator selects nothing and leaves your clipboard as it was.
- **Images work.** Kitty graphics pass through to your terminal, including the
half of the protocol other multiplexers drop, where a program uploads an image
once and places it every frame. Your terminal's cell size is carried through to