Commit db0fe475 authored by Per Bothner's avatar Per Bothner

New specificaton for "Sematic prompts".

parent ba3a5e27
* Name: semantic-prompts
* Start Date: 2019-05-11
# Summary
Escape codes and conventions for semantic marking of
commands (as in shells and other REPLs) and their components
(prompts, user inputs, and output).
# Motivation
The user interaction in shells and other [REPL applications](https://en.wikipedia.org/wiki/Read-eval-print loop) is a sequence of commands,
where each _command_ is a sequence of _user input_ (one or more lines typed by the user) and command output (from the application).
The input lines will usually contain _prompt_ sections emitted
by the application, usually at the beginning of the first line.
This protocal defines a way for an application to specify to a terminal
the start and end of commands and their parts: input, promp, and output.
This can enable useful features like visual separation/highlighting
of commands; folding (a button to hide long command output);
searching or copying of command input or output; or indication of return status.
This specification is an extension of the protocol
first implemented by [FinalTerm](https://github.com/p-e-w/finalterm) and
then later by [iterm2](https://iterm2.com/documentation-shell-integration.html).
Other similar prior art is known for
[Extraterm](http://extraterm.org/) and [DomTerm](http://domterm.org/Wire-byte-protocol.html).
# Detail
A command sequence may be nested withing the output section of
another command, for example when the user types a shell command
to invoke some other REPL application. To help track this
nesting we make use of an optional _application identifier_ (`aid`)
which can be an arbirary string specified by the application.
It is suggested that the `aid` be (or contain) the process id of the
application; if that is unavailable, the name of the application.
## Commands
`OSC "133;F\007"`
> Do a _fresh-line_: If the cursor is the initial column
> (left, assuming left-to-right writing), do nothing.
> Otherwise, do the equivalent of `"\r\n"`.
`OSC "133;A"` _options_ `"\007"`
> First do a _fresh-line_.
> Then start a new command, beginning with the prompt.
`OSC "133;E"` _options_ `"\007"`
> Same as `OSC "133;A"` but may first implicitly terminate a previous command:
> If the _options_ specify an `aid` and there is an active (open)
> command with matching `aid`, finish the innermost such command
> (as well as any other commands nested more deeply).
> Otherwise, treat as an `aid` whose value is the empty string.
`OSC "133;P"` _options_ `"\007"`
> Start of secondary prompt. This is used for multi-line prompts,
> right-side prompts, and prompts for continuation lines.
`OSC "133;B"` _options_ `"\007"`
> End of prompt and start of user input, terminated
> by a `OSC "133;C"`.
`OSC "133;I"` _options_ `"\007"`
> End of prompt and start of user input, terminated
> by end-of-line.
`OSC "133;C"` _options_ `"\007"`
> End of input, and start of output.
`OSC "133;D"` [`";"` _exit-code_] _options_ `"\007"`
> End of current command.
> The optional _exit-code_ is an integer value that reports
> an exit code from the command. This should be a non-negative integer,
> where 0 means successful completion, and non-zero for failure.
## General options syntax
Options have the general format:
> _options_ ::= (`";"` _option_)*
In general, an _option_ can be any string of characters not including control characters (value less than 32) or semicolon. Usually the will have the form of a _named-option_:
_named-option_ ::= _option-name_ `"="` _value_
A terminal must ignore an _option_ whose _option-name_ it doesn't recognize.
**Issue**: Alternative specification: If a terminal doesn't recognize an _option-name_ it should ignore it _and_ any subsequernt options.
**Issue**: Maybe allow _value_ to be a quoted string, with C-style escapes?
## Standard options
`aid=` _value_
> The current _application identifier_.
`click-move=` _value_
> The _value_ can be `line` or other options to be determined later.
> This is a request from the application to the terminal to
> translate clicks in the input area to cursor movement.
> The terminal is free to ignore this option.
> See separate discussion below.
`move-keys=` _left_ `","` _right_ [`","` _up_, `","` _down_]
> Specify key sequences to use for `click-move` mode when
> translating clicks to cursor motion.
> The defaults are the standard arrow-key sequences: `CSI D` etc.
## Input lines
The structure of an input line is an optional initial prompt,
followed by a possibly-empty user input area,
followed by "background area", followed by an optional final prompt.
### End of input / start of output
The `OSC "133;C"` command can be used to explicitly end
the input area and begin the output area. However, some applications
don't provide a convenient way to emit that command.
That is why we also specify an _implicit_ way to end the input area.
It is easy in the common case of a single input line, but we
can also deal with multiple lines: If the cursor is on a fresh (empty) line
and we see either `OSC "133;P"` or `OSC "133;I"` then this is the
start of a continuation input line. If we see anything else,
it is the start of the output area (or end of command).
### Input vs background
The blank area between the input area and the right prompt (if any)
or the end of line is the _background area_. There may be actual
spaces (explicitly typed by the user) at the end of the input
are, but it is desirable for the terminal to be able distinguish these
from the background:
- Selected text should include explicit spaces but not background space.
- You may want a distinct styling for actual input text.
- A terminal may want to handle mouse clicks in the input area
different from those in the background.
A terminal can manage this distinction using
a special logical style for text in the input area.
Input text echoed by the application should gets this style.
Care must be taken when deleting characters: All deletion should be
done with either Delete Character (`CSI P`) or Erase in Line (`CSI K`),
but _not_ by overwriting with a space. If the application
needs to write a final (right) prompt, it should move the
cursor in position using Cursor Forward (`CSI C`), not by writing spaces.
### Prompts
An application should emit each prompt string as a single
undivided sequence, not containing cursor motion
(including no carriage return or line-feed).
A prompt starts with a `'OSC 133;A'` or `'OSC 133;E'` sequence
(for the initial prompt), or `'OSC 133;P'` (for subsequent prompts).
It must end with `'OSC 133;B'` or `'OSC 133;I'` or
end-of-line (only for final/right prompts).
Initial indentation (such as emitted by `fish`) should
treated and delimited as prompts, if possible.
If there is a right prompt in an input line that wraps around (logical
line wider than screen width), the prompt should be written at
the end of the final screen line, not the first. This allows
line-wrap indicators to be correct.
**Issue**: Possibly add a way to mark indentation as distict from prompts.
## Cursor motion from mouse clicks
People new to shells and similar REPLs usually expect that they can
move the input cursor using a mouse click, and are surprised when it doesn't.
Experienced shell users also sometimes want this ability,
for example making an edit to a long command. It is possible for
an application (or input library) to implement xterm-style mouse support,
but there are disadvantages:
- There is some per-application implementation effort to add mouse support.
This may be infeasible if you don't have source-code access or
the skills to modify the application.
- The xterm mouse support is too coarse grain. If an application
requests mouse reporting, it disables the default mouse behavior
for selection-by-drag and for context menus (third-button click).
It is difficult for an application to re-enable that functionality.
However, if an application supports cursor movement using
the arrow keys (or some other key sequence), then it is easy for the
terminal to translate a mouse click to the appropriate key sequence.
Moving the cursor within the current input line is requested
by the `click-move=line` option. If the terminal supports this
feature, it is activated when the user does an unmodified
button-1 (left) click in an input line containing the cursor.
(If the click is in the left prompt, it is treated at the first character
of the input area; if it is to the right of input area (in the background area or right prompt) it is treated as just after the input area.)
The terminal calculates the character position of the click
minus the character position of cursor. (Character position is
like column position, but double-width characters only count one.)
If the count is positive, that many _right_ sequences (by default `CSI C`)
are sent; if negative, that many _left_ sequences (by default `CSI D`).
**Issue:** Some input editors can edit a multi-line input area,
and you can navigate between the lines. Translating clicks
to _down_/_up_ sequences is more complicated;
we'll discuss it a future revision, after some more experimentation.
# Open Questions
See the paragraphs starting with **Issue:**.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment