Rio
adr/0118-language-picked-by-hand.mdRaw Markdown · GitHub ↗

ADR-0118: A buffer's language can be picked by hand

  • Status: Accepted
  • Date: 2026-09-16
  • Deciders: jka
  • Decision: D112

Context

A buffer's highlighter came from its file name alone (ADR-0032, ADR-0046): the exact file name, then the extension, then the name with its last suffix removed. rio never looks at the content, so there is no shebang or modeline detection. Two cases had no remedy. Code pasted into an untitled buffer was always plain text, and a file whose name suggests the wrong language was always highlighted wrongly.

The list of languages is not fixed. Every installed syntax extension (ADR-0039) adds one, so any control that lists them is data-driven and unbounded. ADR-0092 retired the last menu of that shape.

Decision

View ▸ Language… opens the shared bounded picker (ADR-0092) next to Theme…. Its rows are Auto-detect, labelled with what the file name would give, then Plain Text, then every language the registry knows, shipped or installed. The list is built when the picker opens, and the picker starts on the buffer's current choice.

The choice belongs to the buffer, not to the editor group or the file type:

  • It is GUI view state, held with the buffer like its modified flag (ADR-0022). The core is not involved, and the choice follows the buffer when it moves to another group.
  • It has three forms: detect by file name (the default), no highlighting, or a named language.
  • It persists through Save As and renames until the user picks Auto-detect again. A hand-picked language is a statement about the content, and a new name does not withdraw it.
  • It is not saved in the session. A session restores file paths only and does not restore untitled buffers at all, so after a restart detection by name applies again.
  • If the named language disappears, for example because its syntax extension was removed, the buffer falls back to detection by name without an error.

A buffer is re-highlighted whenever its path changes, whether by Save As or a rename, so an untitled buffer saved as foo.tcl is highlighted as Tcl at once.

Alternatives considered

A View ▸ Language submenu, which was the original proposal. The cascade would grow with every installed syntax extension, and over-tall Tk menus misbehave on X11. ADR-0092 replaced the theme cascade with a picker for exactly that reason.

Detecting the language from content, such as a shebang line. It would help extension-less scripts, but it is a separate question from a manual override and was left out of this step. A hand pick covers pasted code, which content sniffing would only guess at.

Remembering the choice across restarts. Sessions store paths, not per-buffer view state, and the main case (an untitled buffer) is not restored anyway. Detecting by name again after a restart is the least surprising behaviour.

Consequences

  • Pasted code and misnamed files can be highlighted correctly without renaming anything.
  • The syntax registry has to answer two questions besides "which scanner fits this path": the names of all registered languages, and the scanner for a given name.
  • A hand pick outlives a rename, so a user who renames notes.txt to notes.tcl after picking Plain Text keeps plain text until they choose Auto-detect.
  • A choice lasts only for the running session. If users want it kept, a per-file override would need a home in the session data.
  • Shebang detection remains open, as ADR-0046 already noted.