mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
osc: add support for OSC 133;A (prompt markers)
This patch adds support for the OSC-133;A sequence, introduced by FinalTerm and implemented by iTerm2, Kitty and more. See https://iterm2.com/documentation-one-page.html#documentation-escape-codes.html. The shell emits the OSC just before printing the prompt. This lets the terminal know where, in the scrollback, there are prompts. We implement this using a simple boolean in the row struct ("this row has a prompt"). The prompt marker must be reflowed along with the text on window resizes. In an ideal world, erasing, or overwriting the cell where the OSC was emitted, would remove the prompt mark. Since we don't store this information in the cell struct, we can't do that. The best we can do is reset it in erase_line(). This works well enough in the "normal" screen, when used with a "normal" shell. It doesn't really work in fullscreen apps, on the alt screen. But that doesn't matter since we don't support jumping between prompts on the alt screen anyway. To be able to jump between prompts, two new key bindings have been added: prompt-prev and prompt-next, bound to ctrl+shift+z and ctrl+shift+x respectively. prompt-prev will jump to the previous, not currently visible, prompt, by moving the viewport, ensuring the prompt is at the top of the screen. prompt-next jumps to the next prompt, visible or not. Again, by moving the viewport to ensure the prompt is at the top of the screen. If we're at the bottom of the scrollback, the viewport is instead moved as far down as possible. Closes #30
This commit is contained in:
parent
96f23b4c64
commit
bdb79e8b9f
15 changed files with 285 additions and 18 deletions
|
|
@ -47,10 +47,13 @@
|
||||||
* `-Dsystemd-units-dir=<path>` meson command line option.
|
* `-Dsystemd-units-dir=<path>` meson command line option.
|
||||||
* Support for custom environment variables in `foot.ini`
|
* Support for custom environment variables in `foot.ini`
|
||||||
([#1070][1070]).
|
([#1070][1070]).
|
||||||
|
* Support for jumping to previous/next prompt (requires shell
|
||||||
|
integration). By default bound to `ctrl`+`shift`+`z` and
|
||||||
|
`ctrl`+`shift`+`x` respectively ([#30][30]).
|
||||||
|
|
||||||
[1058]: https://codeberg.org/dnkl/foot/issues/1058
|
[1058]: https://codeberg.org/dnkl/foot/issues/1058
|
||||||
[1070]: https://codeberg.org/dnkl/foot/issues/1070
|
[1070]: https://codeberg.org/dnkl/foot/issues/1070
|
||||||
|
[30]: https://codeberg.org/dnkl/foot/issues/30
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
||||||
54
README.md
54
README.md
|
|
@ -24,6 +24,9 @@ The fast, lightweight and minimalistic Wayland terminal emulator.
|
||||||
1. [Mouse](#mouse)
|
1. [Mouse](#mouse)
|
||||||
1. [Server (daemon) mode](#server-daemon-mode)
|
1. [Server (daemon) mode](#server-daemon-mode)
|
||||||
1. [URLs](#urls)
|
1. [URLs](#urls)
|
||||||
|
1. [Shell integration](#shell-integration)
|
||||||
|
1. [Current working directory](#current-working-directory)
|
||||||
|
1. [Jumping between prompts](#jumping-between-prompts)
|
||||||
1. [Alt/meta](#alt-meta)
|
1. [Alt/meta](#alt-meta)
|
||||||
1. [Backspace](#backspace)
|
1. [Backspace](#backspace)
|
||||||
1. [Keypad](#keypad)
|
1. [Keypad](#keypad)
|
||||||
|
|
@ -157,13 +160,21 @@ These are the default shortcuts. See `man foot.ini` and the example
|
||||||
<kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>n</kbd>
|
<kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>n</kbd>
|
||||||
: Spawn a new terminal. If the shell has been [configured to emit the
|
: Spawn a new terminal. If the shell has been [configured to emit the
|
||||||
OSC 7 escape
|
OSC 7 escape
|
||||||
sequence](https://codeberg.org/dnkl/foot/wiki#user-content-how-to-configure-my-shell-to-emit-the-osc-7-escape-sequence),
|
sequence](https://codeberg.org/dnkl/foot/wiki#user-content-spawning-new-terminal-instances-in-the-current-working-directory),
|
||||||
the new terminal will start in the current working directory.
|
the new terminal will start in the current working directory.
|
||||||
|
|
||||||
<kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>u</kbd>
|
<kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>u</kbd>
|
||||||
: Enter URL mode, where all currently visible URLs are tagged with a
|
: Enter URL mode, where all currently visible URLs are tagged with a
|
||||||
jump label with a key sequence that will open the URL.
|
jump label with a key sequence that will open the URL.
|
||||||
|
|
||||||
|
<kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>z</kbd>
|
||||||
|
: Jump to the previous, currently not visible, prompt. Requires [shell
|
||||||
|
integration](https://codeberg.org/dnkl/foot/wiki#user-content-jumping-between-prompts).
|
||||||
|
|
||||||
|
<kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>x</kbd>
|
||||||
|
: Jump to the next prompt. Requires [shell
|
||||||
|
integration](https://codeberg.org/dnkl/foot/wiki#user-content-jumping-between-prompts).
|
||||||
|
|
||||||
|
|
||||||
#### Scrollback search
|
#### Scrollback search
|
||||||
|
|
||||||
|
|
@ -296,6 +307,44 @@ Jump label colors, the URL underline color, and the letters used in
|
||||||
the jump label key sequences can be configured.
|
the jump label key sequences can be configured.
|
||||||
|
|
||||||
|
|
||||||
|
## Shell integration
|
||||||
|
|
||||||
|
### Current working directory
|
||||||
|
|
||||||
|
New foot terminal instances (bound to
|
||||||
|
<kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>n</kbd> by default) will open in
|
||||||
|
the current working directory, **if** the shell in the “parent”
|
||||||
|
terminal reports directory changes.
|
||||||
|
|
||||||
|
This is done with the OSC-7 escape sequence. Most shells can be
|
||||||
|
scripted to do this, if they do not support it natively. See the
|
||||||
|
[wiki](https://codeberg.org/dnkl/foot/wiki#user-content-spawning-new-terminal-instances-in-the-current-working-directory)
|
||||||
|
for details.
|
||||||
|
|
||||||
|
|
||||||
|
### Jumping between prompts
|
||||||
|
|
||||||
|
Foot can move the current viewport to focus prompts of already
|
||||||
|
executed commands (bound to
|
||||||
|
<kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>z</kbd>/<kbd>x</kbd> by
|
||||||
|
default).
|
||||||
|
|
||||||
|
For this to work, the shell needs to emit an OSC-133;A
|
||||||
|
(`\E]133;A\E\\`) sequence before each prompt.
|
||||||
|
|
||||||
|
In zsh, one way to do this is to add a `precmd` hook:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
precmd() {
|
||||||
|
print -Pn "\e]133;A\e\\"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the
|
||||||
|
[wiki](https://codeberg.org/dnkl/foot/wiki#user-content-jumping-between-prompts)
|
||||||
|
for details, and examples for other shells.
|
||||||
|
|
||||||
|
|
||||||
## Alt/meta
|
## Alt/meta
|
||||||
|
|
||||||
By default, foot prefixes _Meta characters_ with ESC. This corresponds
|
By default, foot prefixes _Meta characters_ with ESC. This corresponds
|
||||||
|
|
@ -392,7 +441,7 @@ with the terminal emulator itself. Foot implements the following OSCs:
|
||||||
supported)
|
supported)
|
||||||
* `OSC 2` - change window title
|
* `OSC 2` - change window title
|
||||||
* `OSC 4` - change color palette
|
* `OSC 4` - change color palette
|
||||||
* `OSC 7` - report CWD
|
* `OSC 7` - report CWD (see [shell integration](#shell-integration))
|
||||||
* `OSC 8` - hyperlink
|
* `OSC 8` - hyperlink
|
||||||
* `OSC 9` - desktop notification
|
* `OSC 9` - desktop notification
|
||||||
* `OSC 10` - change (default) foreground color
|
* `OSC 10` - change (default) foreground color
|
||||||
|
|
@ -408,6 +457,7 @@ with the terminal emulator itself. Foot implements the following OSCs:
|
||||||
* `OSC 112` - reset cursor color
|
* `OSC 112` - reset cursor color
|
||||||
* `OSC 117` - reset highlight background color
|
* `OSC 117` - reset highlight background color
|
||||||
* `OSC 119` - reset highlight foreground color
|
* `OSC 119` - reset highlight foreground color
|
||||||
|
* `OSC 133` - [shell integration](#shell-integration)
|
||||||
* `OSC 555` - flash screen (**foot specific**)
|
* `OSC 555` - flash screen (**foot specific**)
|
||||||
* `OSC 777` - desktop notification (only the `;notify` sub-command of
|
* `OSC 777` - desktop notification (only the `;notify` sub-command of
|
||||||
OSC 777 is supported.)
|
OSC 777 is supported.)
|
||||||
|
|
|
||||||
15
commands.c
15
commands.c
|
|
@ -19,23 +19,14 @@ cmd_scrollback_up(struct terminal *term, int rows)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const struct grid *grid = term->grid;
|
const struct grid *grid = term->grid;
|
||||||
const int offset = grid->offset;
|
|
||||||
const int view = grid->view;
|
const int view = grid->view;
|
||||||
const int grid_rows = grid->num_rows;
|
const int grid_rows = grid->num_rows;
|
||||||
const int screen_rows = term->rows;
|
|
||||||
|
|
||||||
int scrollback_start = (offset + screen_rows) & (grid_rows - 1);
|
|
||||||
|
|
||||||
/* Part of the scrollback may be uninitialized */
|
|
||||||
while (grid->rows[scrollback_start] == NULL) {
|
|
||||||
scrollback_start++;
|
|
||||||
scrollback_start &= grid_rows - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The view row number in scrollback relative coordinates. This is
|
/* The view row number in scrollback relative coordinates. This is
|
||||||
* the maximum number of rows we’re allowed to scroll */
|
* the maximum number of rows we’re allowed to scroll */
|
||||||
int view_sb_rel = view - scrollback_start + grid_rows;
|
int sb_start = grid_sb_start_ignore_uninitialized(grid, term->rows);
|
||||||
view_sb_rel &= grid_rows - 1;
|
int view_sb_rel =
|
||||||
|
grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, view);
|
||||||
|
|
||||||
rows = min(rows, view_sb_rel);
|
rows = min(rows, view_sb_rel);
|
||||||
if (rows == 0)
|
if (rows == 0)
|
||||||
|
|
|
||||||
4
config.c
4
config.c
|
|
@ -115,6 +115,8 @@ static const char *const binding_action_map[] = {
|
||||||
[BIND_ACTION_SHOW_URLS_LAUNCH] = "show-urls-launch",
|
[BIND_ACTION_SHOW_URLS_LAUNCH] = "show-urls-launch",
|
||||||
[BIND_ACTION_SHOW_URLS_PERSISTENT] = "show-urls-persistent",
|
[BIND_ACTION_SHOW_URLS_PERSISTENT] = "show-urls-persistent",
|
||||||
[BIND_ACTION_TEXT_BINDING] = "text-binding",
|
[BIND_ACTION_TEXT_BINDING] = "text-binding",
|
||||||
|
[BIND_ACTION_PROMPT_PREV] = "prompt-prev",
|
||||||
|
[BIND_ACTION_PROMPT_NEXT] = "prompt-next",
|
||||||
|
|
||||||
/* Mouse-specific actions */
|
/* Mouse-specific actions */
|
||||||
[BIND_ACTION_SELECT_BEGIN] = "select-begin",
|
[BIND_ACTION_SELECT_BEGIN] = "select-begin",
|
||||||
|
|
@ -2663,6 +2665,8 @@ add_default_key_bindings(struct config *conf)
|
||||||
{BIND_ACTION_FONT_SIZE_RESET, m_ctrl, {{XKB_KEY_KP_0}}},
|
{BIND_ACTION_FONT_SIZE_RESET, m_ctrl, {{XKB_KEY_KP_0}}},
|
||||||
{BIND_ACTION_SPAWN_TERMINAL, m_ctrl_shift, {{XKB_KEY_n}}},
|
{BIND_ACTION_SPAWN_TERMINAL, m_ctrl_shift, {{XKB_KEY_n}}},
|
||||||
{BIND_ACTION_SHOW_URLS_LAUNCH, m_ctrl_shift, {{XKB_KEY_u}}},
|
{BIND_ACTION_SHOW_URLS_LAUNCH, m_ctrl_shift, {{XKB_KEY_u}}},
|
||||||
|
{BIND_ACTION_PROMPT_PREV, m_ctrl_shift, {{XKB_KEY_z}}},
|
||||||
|
{BIND_ACTION_PROMPT_NEXT, m_ctrl_shift, {{XKB_KEY_x}}},
|
||||||
};
|
};
|
||||||
|
|
||||||
conf->bindings.key.count = ALEN(bindings);
|
conf->bindings.key.count = ALEN(bindings);
|
||||||
|
|
|
||||||
|
|
@ -677,6 +677,9 @@ All _OSC_ sequences begin with *\\E]*, sometimes abbreviated _OSC_.
|
||||||
| \\E] 119 \\E\\
|
| \\E] 119 \\E\\
|
||||||
: xterm
|
: xterm
|
||||||
: Reset selection foreground color
|
: Reset selection foreground color
|
||||||
|
| \\E] 133 ; A \\E\\
|
||||||
|
: FinalTerm
|
||||||
|
: Mark start of shell prompt
|
||||||
| \\E] 555 \\E\\
|
| \\E] 555 \\E\\
|
||||||
: foot
|
: foot
|
||||||
: Flash the entire terminal (foot extension)
|
: Flash the entire terminal (foot extension)
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,13 @@ default) available; see *foot.ini*(5).
|
||||||
*ctrl*+*shift*+*u*
|
*ctrl*+*shift*+*u*
|
||||||
Activate URL mode, allowing you to "launch" URLs.
|
Activate URL mode, allowing you to "launch" URLs.
|
||||||
|
|
||||||
|
*ctrl*+*shift*+*z*
|
||||||
|
Jump to the previous, currently not visible, prompt. Requires
|
||||||
|
shell integration.
|
||||||
|
|
||||||
|
*ctrl*+*shift*+*x*
|
||||||
|
Jump to the next prompt. Requires shell integration.
|
||||||
|
|
||||||
## SCROLLBACK SEARCH
|
## SCROLLBACK SEARCH
|
||||||
|
|
||||||
*ctrl*+*r*
|
*ctrl*+*r*
|
||||||
|
|
@ -370,6 +377,38 @@ commented out will usually be installed to */etc/xdg/foot/foot.ini*.
|
||||||
|
|
||||||
For more information, see *foot.ini*(5).
|
For more information, see *foot.ini*(5).
|
||||||
|
|
||||||
|
# SHELL INTEGRATION
|
||||||
|
|
||||||
|
## Current working directory
|
||||||
|
|
||||||
|
New foot terminal instances (bound to *ctrl*+*shift*+*n* by default)
|
||||||
|
will open in the current working directory, if the shell in the
|
||||||
|
“parent” terminal reports directory changes.
|
||||||
|
|
||||||
|
This is done with the OSC-7 escape sequence. Most shells can be
|
||||||
|
scripted to do this, if they do not support it natively. See the wiki
|
||||||
|
(https://codeberg.org/dnkl/foot/wiki#user-content-spawning-new-terminal-instances-in-the-current-working-directory)
|
||||||
|
for details.
|
||||||
|
|
||||||
|
|
||||||
|
## Jumping between prompts
|
||||||
|
|
||||||
|
Foot can move the current viewport to focus prompts of already
|
||||||
|
executed commands (bound to *ctrl*+*shift*+*z*/*x* by default).
|
||||||
|
|
||||||
|
For this to work, the shell needs to emit an OSC-133;A
|
||||||
|
(*\\E]133;A\\E\\\\*) sequence before each prompt.
|
||||||
|
|
||||||
|
In zsh, one way to do this is to add a _precmd_ hook:
|
||||||
|
|
||||||
|
*precmd() {
|
||||||
|
print -Pn "\\e]133;A\\e\\\\"
|
||||||
|
}*
|
||||||
|
|
||||||
|
See the wiki
|
||||||
|
(https://codeberg.org/dnkl/foot/wiki#user-content-jumping-between-prompts)
|
||||||
|
for details, and examples for other shells.
|
||||||
|
|
||||||
# TERMINFO
|
# TERMINFO
|
||||||
|
|
||||||
Client applications use the terminfo identifier specified by the
|
Client applications use the terminfo identifier specified by the
|
||||||
|
|
|
||||||
|
|
@ -773,6 +773,14 @@ e.g. *search-start=none*.
|
||||||
jump label with a key sequence that will place the URL in the
|
jump label with a key sequence that will place the URL in the
|
||||||
clipboard. Default: _none_.
|
clipboard. Default: _none_.
|
||||||
|
|
||||||
|
*prompt-prev*
|
||||||
|
Jump to the previous, currently not visible, prompt (requires
|
||||||
|
shell integration, see *foot*(1)). Default: _Control+Shift+z_.
|
||||||
|
|
||||||
|
*prompt-next*
|
||||||
|
Jump the next prompt (requires shell integration, see
|
||||||
|
*foot*(1)). Default: _Control+Shift+x_.
|
||||||
|
|
||||||
# SECTION: search-bindings
|
# SECTION: search-bindings
|
||||||
|
|
||||||
This section lets you override the default key bindings used in
|
This section lets you override the default key bindings used in
|
||||||
|
|
|
||||||
2
foot.ini
2
foot.ini
|
|
@ -146,6 +146,8 @@
|
||||||
# show-urls-launch=Control+Shift+u
|
# show-urls-launch=Control+Shift+u
|
||||||
# show-urls-copy=none
|
# show-urls-copy=none
|
||||||
# show-urls-persistent=none
|
# show-urls-persistent=none
|
||||||
|
# prompt-prev=Control+Shift+z
|
||||||
|
# prompt-next=Control+Shift+x
|
||||||
# noop=none
|
# noop=none
|
||||||
|
|
||||||
[search-bindings]
|
[search-bindings]
|
||||||
|
|
|
||||||
40
grid.c
40
grid.c
|
|
@ -24,6 +24,7 @@
|
||||||
* scrollback, with the *highest* number being at the bottom of the
|
* scrollback, with the *highest* number being at the bottom of the
|
||||||
* screen, where new input appears.
|
* screen, where new input appears.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
grid_row_abs_to_sb(const struct grid *grid, int screen_rows, int abs_row)
|
grid_row_abs_to_sb(const struct grid *grid, int screen_rows, int abs_row)
|
||||||
{
|
{
|
||||||
|
|
@ -43,6 +44,38 @@ int grid_row_sb_to_abs(const struct grid *grid, int screen_rows, int sb_rel_row)
|
||||||
return abs_row;
|
return abs_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
grid_sb_start_ignore_uninitialized(const struct grid *grid, int screen_rows)
|
||||||
|
{
|
||||||
|
int scrollback_start = grid->offset + screen_rows;
|
||||||
|
scrollback_start &= grid->num_rows - 1;
|
||||||
|
|
||||||
|
while (grid->rows[scrollback_start] == NULL) {
|
||||||
|
scrollback_start++;
|
||||||
|
scrollback_start &= grid->num_rows - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return scrollback_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
grid_row_abs_to_sb_precalc_sb_start(const struct grid *grid, int sb_start,
|
||||||
|
int abs_row)
|
||||||
|
{
|
||||||
|
int rebased_row = abs_row - sb_start + grid->num_rows;
|
||||||
|
rebased_row &= grid->num_rows - 1;
|
||||||
|
return rebased_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
grid_row_sb_to_abs_precalc_sb_start(const struct grid *grid, int sb_start,
|
||||||
|
int sb_rel_row)
|
||||||
|
{
|
||||||
|
int abs_row = sb_rel_row + sb_start;
|
||||||
|
abs_row &= grid->num_rows - 1;
|
||||||
|
return abs_row;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ensure_row_has_extra_data(struct row *row)
|
ensure_row_has_extra_data(struct row *row)
|
||||||
{
|
{
|
||||||
|
|
@ -196,6 +229,7 @@ grid_snapshot(const struct grid *grid)
|
||||||
clone_row->cells = xmalloc(grid->num_cols * sizeof(clone_row->cells[0]));
|
clone_row->cells = xmalloc(grid->num_cols * sizeof(clone_row->cells[0]));
|
||||||
clone_row->linebreak = row->linebreak;
|
clone_row->linebreak = row->linebreak;
|
||||||
clone_row->dirty = row->dirty;
|
clone_row->dirty = row->dirty;
|
||||||
|
clone_row->prompt_marker = row->prompt_marker;
|
||||||
|
|
||||||
for (int c = 0; c < grid->num_cols; c++)
|
for (int c = 0; c < grid->num_cols; c++)
|
||||||
clone_row->cells[c] = row->cells[c];
|
clone_row->cells[c] = row->cells[c];
|
||||||
|
|
@ -286,6 +320,7 @@ grid_row_alloc(int cols, bool initialize)
|
||||||
row->dirty = false;
|
row->dirty = false;
|
||||||
row->linebreak = true;
|
row->linebreak = true;
|
||||||
row->extra = NULL;
|
row->extra = NULL;
|
||||||
|
row->prompt_marker = false;
|
||||||
|
|
||||||
if (initialize) {
|
if (initialize) {
|
||||||
row->cells = xcalloc(cols, sizeof(row->cells[0]));
|
row->cells = xcalloc(cols, sizeof(row->cells[0]));
|
||||||
|
|
@ -344,6 +379,7 @@ grid_resize_without_reflow(
|
||||||
|
|
||||||
new_row->dirty = old_row->dirty;
|
new_row->dirty = old_row->dirty;
|
||||||
new_row->linebreak = false;
|
new_row->linebreak = false;
|
||||||
|
new_row->prompt_marker = old_row->prompt_marker;
|
||||||
|
|
||||||
if (new_cols > old_cols) {
|
if (new_cols > old_cols) {
|
||||||
/* Clear "new" columns */
|
/* Clear "new" columns */
|
||||||
|
|
@ -503,6 +539,7 @@ _line_wrap(struct grid *old_grid, struct row **new_grid, struct row *row,
|
||||||
/* Scrollback is full, need to re-use a row */
|
/* Scrollback is full, need to re-use a row */
|
||||||
grid_row_reset_extra(new_row);
|
grid_row_reset_extra(new_row);
|
||||||
new_row->linebreak = true;
|
new_row->linebreak = true;
|
||||||
|
new_row->prompt_marker = false;
|
||||||
|
|
||||||
tll_foreach(old_grid->sixel_images, it) {
|
tll_foreach(old_grid->sixel_images, it) {
|
||||||
if (it->item.pos.row == *row_idx) {
|
if (it->item.pos.row == *row_idx) {
|
||||||
|
|
@ -834,6 +871,9 @@ grid_resize_and_reflow(
|
||||||
xassert(new_col_idx + amount <= new_cols);
|
xassert(new_col_idx + amount <= new_cols);
|
||||||
xassert(from + amount <= old_cols);
|
xassert(from + amount <= old_cols);
|
||||||
|
|
||||||
|
if (from == 0)
|
||||||
|
new_row->prompt_marker = old_row->prompt_marker;
|
||||||
|
|
||||||
memcpy(
|
memcpy(
|
||||||
&new_row->cells[new_col_idx], &old_row->cells[from],
|
&new_row->cells[new_col_idx], &old_row->cells[from],
|
||||||
amount * sizeof(struct cell));
|
amount * sizeof(struct cell));
|
||||||
|
|
|
||||||
7
grid.h
7
grid.h
|
|
@ -25,6 +25,12 @@ void grid_resize_and_reflow(
|
||||||
int grid_row_abs_to_sb(const struct grid *grid, int screen_rows, int abs_row);
|
int grid_row_abs_to_sb(const struct grid *grid, int screen_rows, int abs_row);
|
||||||
int grid_row_sb_to_abs(const struct grid *grid, int screen_rows, int sb_rel_row);
|
int grid_row_sb_to_abs(const struct grid *grid, int screen_rows, int sb_rel_row);
|
||||||
|
|
||||||
|
int grid_sb_start_ignore_uninitialized(const struct grid *grid, int screen_rows);
|
||||||
|
int grid_row_abs_to_sb_precalc_sb_start(
|
||||||
|
const struct grid *grid, int sb_start, int abs_row);
|
||||||
|
int grid_row_sb_to_abs_precalc_sb_start(
|
||||||
|
const struct grid *grid, int sb_start, int sb_rel_row);
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
grid_row_absolute(const struct grid *grid, int row_no)
|
grid_row_absolute(const struct grid *grid, int row_no)
|
||||||
{
|
{
|
||||||
|
|
@ -37,7 +43,6 @@ grid_row_absolute_in_view(const struct grid *grid, int row_no)
|
||||||
return (grid->view + row_no) & (grid->num_rows - 1);
|
return (grid->view + row_no) & (grid->num_rows - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline struct row *
|
static inline struct row *
|
||||||
_grid_row_maybe_alloc(struct grid *grid, int row_no, bool alloc_if_null)
|
_grid_row_maybe_alloc(struct grid *grid, int row_no, bool alloc_if_null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
83
input.c
83
input.c
|
|
@ -23,8 +23,9 @@
|
||||||
#define LOG_MODULE "input"
|
#define LOG_MODULE "input"
|
||||||
#define LOG_ENABLE_DBG 0
|
#define LOG_ENABLE_DBG 0
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "config.h"
|
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "grid.h"
|
||||||
#include "keymap.h"
|
#include "keymap.h"
|
||||||
#include "kitty-keymap.h"
|
#include "kitty-keymap.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
|
|
@ -335,6 +336,86 @@ execute_binding(struct seat *seat, struct terminal *term,
|
||||||
term_to_slave(term, binding->aux->text.data, binding->aux->text.len);
|
term_to_slave(term, binding->aux->text.data, binding->aux->text.len);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case BIND_ACTION_PROMPT_PREV: {
|
||||||
|
if (term->grid != &term->normal)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
struct grid *grid = term->grid;
|
||||||
|
const int sb_start =
|
||||||
|
grid_sb_start_ignore_uninitialized(grid, term->rows);
|
||||||
|
|
||||||
|
/* Check each row from current view-1 (that is, the first
|
||||||
|
* currently not visible row), up to, and including, the
|
||||||
|
* scrollback start */
|
||||||
|
for (int r_sb_rel =
|
||||||
|
grid_row_abs_to_sb_precalc_sb_start(
|
||||||
|
grid, sb_start, grid->view) - 1;
|
||||||
|
r_sb_rel >= 0; r_sb_rel--)
|
||||||
|
{
|
||||||
|
const int r_abs =
|
||||||
|
grid_row_sb_to_abs_precalc_sb_start(grid, sb_start, r_sb_rel);
|
||||||
|
|
||||||
|
const struct row *row = grid->rows[r_abs];
|
||||||
|
xassert(row != NULL);
|
||||||
|
|
||||||
|
if (!row->prompt_marker)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
grid->view = r_abs;
|
||||||
|
term_damage_view(term);
|
||||||
|
render_refresh(term);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BIND_ACTION_PROMPT_NEXT: {
|
||||||
|
if (term->grid != &term->normal)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
struct grid *grid = term->grid;
|
||||||
|
const int num_rows = grid->num_rows;
|
||||||
|
|
||||||
|
if (grid->view == grid->offset) {
|
||||||
|
/* Already at the bottom */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check each row from view+1, to the bottom of the scrollback */
|
||||||
|
for (int r_abs = (grid->view + 1) & (num_rows - 1);
|
||||||
|
;
|
||||||
|
r_abs = (r_abs + 1) & (num_rows - 1))
|
||||||
|
{
|
||||||
|
const struct row *row = grid->rows[r_abs];
|
||||||
|
xassert(row != NULL);
|
||||||
|
|
||||||
|
if (!row->prompt_marker) {
|
||||||
|
if (r_abs == grid->offset + term->rows - 1) {
|
||||||
|
/* We’ve reached the bottom of the scrollback */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sb_start = grid_sb_start_ignore_uninitialized(grid, term->rows);
|
||||||
|
int ofs_sb_rel =
|
||||||
|
grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, grid->offset);
|
||||||
|
int new_view_sb_rel =
|
||||||
|
grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, r_abs);
|
||||||
|
|
||||||
|
new_view_sb_rel = min(ofs_sb_rel, new_view_sb_rel);
|
||||||
|
grid->view = grid_row_sb_to_abs_precalc_sb_start(
|
||||||
|
grid, sb_start, new_view_sb_rel);
|
||||||
|
|
||||||
|
term_damage_view(term);
|
||||||
|
render_refresh(term);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
case BIND_ACTION_SELECT_BEGIN:
|
case BIND_ACTION_SELECT_BEGIN:
|
||||||
selection_start(
|
selection_start(
|
||||||
term, seat->mouse.col, seat->mouse.row, SELECTION_CHAR_WISE, false);
|
term, seat->mouse.col, seat->mouse.row, SELECTION_CHAR_WISE, false);
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ enum bind_action_normal {
|
||||||
BIND_ACTION_SHOW_URLS_LAUNCH,
|
BIND_ACTION_SHOW_URLS_LAUNCH,
|
||||||
BIND_ACTION_SHOW_URLS_PERSISTENT,
|
BIND_ACTION_SHOW_URLS_PERSISTENT,
|
||||||
BIND_ACTION_TEXT_BINDING,
|
BIND_ACTION_TEXT_BINDING,
|
||||||
|
BIND_ACTION_PROMPT_PREV,
|
||||||
|
BIND_ACTION_PROMPT_NEXT,
|
||||||
|
|
||||||
/* Mouse specific actions - i.e. they require a mouse coordinate */
|
/* Mouse specific actions - i.e. they require a mouse coordinate */
|
||||||
BIND_ACTION_SELECT_BEGIN,
|
BIND_ACTION_SELECT_BEGIN,
|
||||||
|
|
|
||||||
34
osc.c
34
osc.c
|
|
@ -869,6 +869,40 @@ osc_dispatch(struct terminal *term)
|
||||||
term->colors.use_custom_selection = term->conf->colors.use_custom.selection;
|
term->colors.use_custom_selection = term->conf->colors.use_custom.selection;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 133:
|
||||||
|
/*
|
||||||
|
* Shell integration; see
|
||||||
|
* https://iterm2.com/documentation-escape-codes.html (Shell
|
||||||
|
* Integration/FinalTerm)
|
||||||
|
*
|
||||||
|
* [PROMPT]prompt% [COMMAND_START] ls -l
|
||||||
|
* [COMMAND_EXECUTED]
|
||||||
|
* -rw-r--r-- 1 user group 127 May 1 2016 filename
|
||||||
|
* [COMMAND_FINISHED]
|
||||||
|
*/
|
||||||
|
switch (string[0]) {
|
||||||
|
case 'A':
|
||||||
|
LOG_DBG("FTCS_PROMPT: %dx%d",
|
||||||
|
term->grid->cursor.point.row,
|
||||||
|
term->grid->cursor.point.col);
|
||||||
|
|
||||||
|
term->grid->cur_row->prompt_marker = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
LOG_DBG("FTCS_COMMAND_START");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
LOG_DBG("FTCS_COMMAND_EXECUTED");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
LOG_DBG("FTCS_COMMAND_FINISHED");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 555:
|
case 555:
|
||||||
osc_flash(term);
|
osc_flash(term);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1812,6 +1812,7 @@ erase_line(struct terminal *term, struct row *row)
|
||||||
{
|
{
|
||||||
erase_cell_range(term, row, 0, term->cols - 1);
|
erase_cell_range(term, row, 0, term->cols - 1);
|
||||||
row->linebreak = true;
|
row->linebreak = true;
|
||||||
|
row->prompt_marker = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -116,9 +116,13 @@ struct row_data {
|
||||||
|
|
||||||
struct row {
|
struct row {
|
||||||
struct cell *cells;
|
struct cell *cells;
|
||||||
|
struct row_data *extra;
|
||||||
|
|
||||||
bool dirty;
|
bool dirty;
|
||||||
bool linebreak;
|
bool linebreak;
|
||||||
struct row_data *extra;
|
|
||||||
|
/* Shell integration */
|
||||||
|
bool prompt_marker;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sixel {
|
struct sixel {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue