2019-07-09 16:26:36 +02:00
|
|
|
#include "commands.h"
|
|
|
|
|
|
|
|
|
|
#define LOG_MODULE "commands"
|
2019-07-10 14:45:00 +02:00
|
|
|
#define LOG_ENABLE_DBG 0
|
2019-07-09 16:26:36 +02:00
|
|
|
#include "log.h"
|
|
|
|
|
#include "grid.h"
|
2020-05-19 18:49:42 +02:00
|
|
|
#include "render.h"
|
|
|
|
|
#include "selection.h"
|
|
|
|
|
#include "terminal.h"
|
2021-02-23 09:28:43 +01:00
|
|
|
#include "url-mode.h"
|
2020-05-01 11:46:24 +02:00
|
|
|
#include "util.h"
|
2019-07-09 16:26:36 +02:00
|
|
|
|
Add an optional build-time switch to disable scrollback support
This change introduces a new `scrollback` Meson build option (enabled
by default) that lets foot be compiled without scrollback history.
When the option is off, `FOOT_HAVE_SCROLLBACK` is left
undefined and the relevant code is excluded from the build,
producing a slimmer terminal for use cases that do not need it.
With scrollback disabled:
- The `[scrollback]` section in `foot.ini` and its key bindings
become no-ops.
- In-terminal search is removed,
along with the "pipe scrollback" action, the scrollback indicator,
and their colors/overlays.
- IME hooks for the search box, mouse-wheel scrollback handling,
and related `terminal` state are compiled out.
- Selection auto-scroll (the timer that scrolls the viewport while
a drag-selection extends past the visible area) is removed,
since with no scrollback there is nowhere to scroll to.
The associated function declarations,
`enum selection_scroll_direction`,
the `auto_scroll` field on `terminal::selection`,
and their init/teardown sites are all excluded from the build.
To keep action enumerations stable across build configurations,
two range markers (`BIND_ACTION_PIPE_FIRST` / `BIND_ACTION_PIPE_LAST`)
are introduced so that pipe-action handling does not depend on
`PIPE_SCROLLBACK` being present. The build summary and
`foot --version` now report `+scrollback` or `-scrollback`,
and the config tests have been updated to account for optional section.
2026-05-15 15:51:01 +10:00
|
|
|
#if defined(FOOT_HAVE_SCROLLBACK)
|
2019-07-09 16:26:36 +02:00
|
|
|
void
|
2019-07-10 09:15:37 +02:00
|
|
|
cmd_scrollback_up(struct terminal *term, int rows)
|
2019-07-09 16:26:36 +02:00
|
|
|
{
|
2019-07-10 09:15:37 +02:00
|
|
|
if (term->grid == &term->alt)
|
|
|
|
|
return;
|
2021-02-23 09:28:43 +01:00
|
|
|
if (urls_mode_is_active(term))
|
|
|
|
|
return;
|
2019-07-10 09:15:37 +02:00
|
|
|
|
commands: refactor scrollback up/down
When moving the viewport in the scrollback (i.e. “scrolling”), we need
to ensure the viewport is not moved past the beginning, or end, of the
scrollback.
This was previously accomplish by first limiting the number of lines
to scroll to the number of visible rows (i.e the viewport _size_), and
by adjusting the viewport after moving it, to ensure it doesn’t point
into an uninitialized scrollback area etc.
I.e. the implementation was _reactive_.
This patch rewrites the logic to be _proactive_; we now calculate
_where_ the beginning (or end) of the scrollback is, and then how many
lines there is from there, to the viewport. This is our _maximum_
number of lines to scroll.
When done correctly (which I hope this patch does), this allows us to
remove _all_ checks after moving the viewport - we already _know_ it’s
correct, and valid.
As a bonus, we can remove the old limit, where scrolling was only
allowed to be at most a single page.
2022-02-23 18:59:06 +01:00
|
|
|
const struct grid *grid = term->grid;
|
|
|
|
|
const int view = grid->view;
|
|
|
|
|
const int grid_rows = grid->num_rows;
|
2019-07-10 14:28:20 +02:00
|
|
|
|
2022-05-29 11:11:52 +02:00
|
|
|
/* The view row number in scrollback relative coordinates. This is
|
2024-02-06 12:36:45 +01:00
|
|
|
* the maximum number of rows we're allowed to scroll */
|
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
2022-06-15 18:44:23 +02:00
|
|
|
int sb_start = grid_sb_start_ignore_uninitialized(grid, term->rows);
|
|
|
|
|
int view_sb_rel =
|
|
|
|
|
grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, view);
|
2019-07-10 09:29:36 +02:00
|
|
|
|
2022-05-29 11:11:52 +02:00
|
|
|
rows = min(rows, view_sb_rel);
|
commands: refactor scrollback up/down
When moving the viewport in the scrollback (i.e. “scrolling”), we need
to ensure the viewport is not moved past the beginning, or end, of the
scrollback.
This was previously accomplish by first limiting the number of lines
to scroll to the number of visible rows (i.e the viewport _size_), and
by adjusting the viewport after moving it, to ensure it doesn’t point
into an uninitialized scrollback area etc.
I.e. the implementation was _reactive_.
This patch rewrites the logic to be _proactive_; we now calculate
_where_ the beginning (or end) of the scrollback is, and then how many
lines there is from there, to the viewport. This is our _maximum_
number of lines to scroll.
When done correctly (which I hope this patch does), this allows us to
remove _all_ checks after moving the viewport - we already _know_ it’s
correct, and valid.
As a bonus, we can remove the old limit, where scrolling was only
allowed to be at most a single page.
2022-02-23 18:59:06 +01:00
|
|
|
if (rows == 0)
|
|
|
|
|
return;
|
2020-02-21 23:35:43 +01:00
|
|
|
|
commands: refactor scrollback up/down
When moving the viewport in the scrollback (i.e. “scrolling”), we need
to ensure the viewport is not moved past the beginning, or end, of the
scrollback.
This was previously accomplish by first limiting the number of lines
to scroll to the number of visible rows (i.e the viewport _size_), and
by adjusting the viewport after moving it, to ensure it doesn’t point
into an uninitialized scrollback area etc.
I.e. the implementation was _reactive_.
This patch rewrites the logic to be _proactive_; we now calculate
_where_ the beginning (or end) of the scrollback is, and then how many
lines there is from there, to the viewport. This is our _maximum_
number of lines to scroll.
When done correctly (which I hope this patch does), this allows us to
remove _all_ checks after moving the viewport - we already _know_ it’s
correct, and valid.
As a bonus, we can remove the old limit, where scrolling was only
allowed to be at most a single page.
2022-02-23 18:59:06 +01:00
|
|
|
int new_view = (view + grid_rows) - rows;
|
|
|
|
|
new_view &= grid_rows - 1;
|
|
|
|
|
|
|
|
|
|
xassert(new_view != view);
|
|
|
|
|
xassert(grid->rows[new_view] != NULL);
|
2019-07-10 16:36:10 +02:00
|
|
|
#if defined(_DEBUG)
|
|
|
|
|
for (int r = 0; r < term->rows; r++)
|
commands: refactor scrollback up/down
When moving the viewport in the scrollback (i.e. “scrolling”), we need
to ensure the viewport is not moved past the beginning, or end, of the
scrollback.
This was previously accomplish by first limiting the number of lines
to scroll to the number of visible rows (i.e the viewport _size_), and
by adjusting the viewport after moving it, to ensure it doesn’t point
into an uninitialized scrollback area etc.
I.e. the implementation was _reactive_.
This patch rewrites the logic to be _proactive_; we now calculate
_where_ the beginning (or end) of the scrollback is, and then how many
lines there is from there, to the viewport. This is our _maximum_
number of lines to scroll.
When done correctly (which I hope this patch does), this allows us to
remove _all_ checks after moving the viewport - we already _know_ it’s
correct, and valid.
As a bonus, we can remove the old limit, where scrolling was only
allowed to be at most a single page.
2022-02-23 18:59:06 +01:00
|
|
|
xassert(grid->rows[(new_view + r) & (grid->num_rows - 1)] != NULL);
|
2019-07-10 16:36:10 +02:00
|
|
|
#endif
|
|
|
|
|
|
2022-04-27 19:18:43 +01:00
|
|
|
LOG_DBG("scrollback UP: %d -> %d (offset = %d, rows = %d)",
|
|
|
|
|
view, new_view, offset, grid_rows);
|
2019-08-04 19:06:49 +02:00
|
|
|
|
2020-05-19 18:49:42 +02:00
|
|
|
selection_view_up(term, new_view);
|
2019-07-09 16:26:36 +02:00
|
|
|
term->grid->view = new_view;
|
|
|
|
|
|
commands: refactor scrollback up/down
When moving the viewport in the scrollback (i.e. “scrolling”), we need
to ensure the viewport is not moved past the beginning, or end, of the
scrollback.
This was previously accomplish by first limiting the number of lines
to scroll to the number of visible rows (i.e the viewport _size_), and
by adjusting the viewport after moving it, to ensure it doesn’t point
into an uninitialized scrollback area etc.
I.e. the implementation was _reactive_.
This patch rewrites the logic to be _proactive_; we now calculate
_where_ the beginning (or end) of the scrollback is, and then how many
lines there is from there, to the viewport. This is our _maximum_
number of lines to scroll.
When done correctly (which I hope this patch does), this allows us to
remove _all_ checks after moving the viewport - we already _know_ it’s
correct, and valid.
As a bonus, we can remove the old limit, where scrolling was only
allowed to be at most a single page.
2022-02-23 18:59:06 +01:00
|
|
|
if (rows < term->rows) {
|
|
|
|
|
term_damage_scroll(
|
|
|
|
|
term, DAMAGE_SCROLL_REVERSE_IN_VIEW,
|
|
|
|
|
(struct scroll_region){0, term->rows}, rows);
|
|
|
|
|
term_damage_rows_in_view(term, 0, rows - 1);
|
2019-08-04 19:06:49 +02:00
|
|
|
} else
|
|
|
|
|
term_damage_view(term);
|
|
|
|
|
|
2021-02-06 11:47:59 +01:00
|
|
|
render_refresh_urls(term);
|
2019-07-24 20:09:49 +02:00
|
|
|
render_refresh(term);
|
2019-07-09 16:26:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2019-07-10 09:15:37 +02:00
|
|
|
cmd_scrollback_down(struct terminal *term, int rows)
|
2019-07-09 16:26:36 +02:00
|
|
|
{
|
2019-07-10 09:15:37 +02:00
|
|
|
if (term->grid == &term->alt)
|
|
|
|
|
return;
|
2021-02-23 09:28:43 +01:00
|
|
|
if (urls_mode_is_active(term))
|
|
|
|
|
return;
|
2019-07-10 09:15:37 +02:00
|
|
|
|
commands: refactor scrollback up/down
When moving the viewport in the scrollback (i.e. “scrolling”), we need
to ensure the viewport is not moved past the beginning, or end, of the
scrollback.
This was previously accomplish by first limiting the number of lines
to scroll to the number of visible rows (i.e the viewport _size_), and
by adjusting the viewport after moving it, to ensure it doesn’t point
into an uninitialized scrollback area etc.
I.e. the implementation was _reactive_.
This patch rewrites the logic to be _proactive_; we now calculate
_where_ the beginning (or end) of the scrollback is, and then how many
lines there is from there, to the viewport. This is our _maximum_
number of lines to scroll.
When done correctly (which I hope this patch does), this allows us to
remove _all_ checks after moving the viewport - we already _know_ it’s
correct, and valid.
As a bonus, we can remove the old limit, where scrolling was only
allowed to be at most a single page.
2022-02-23 18:59:06 +01:00
|
|
|
const struct grid *grid = term->grid;
|
|
|
|
|
const int offset = grid->offset;
|
|
|
|
|
const int view = grid->view;
|
|
|
|
|
const int grid_rows = grid->num_rows;
|
|
|
|
|
const int screen_rows = term->rows;
|
|
|
|
|
|
|
|
|
|
const int scrollback_end = offset;
|
|
|
|
|
|
|
|
|
|
/* Number of rows to scroll, without going past the scrollback end */
|
|
|
|
|
int max_rows = 0;
|
|
|
|
|
if (view <= scrollback_end)
|
|
|
|
|
max_rows = scrollback_end - view;
|
|
|
|
|
else
|
|
|
|
|
max_rows = offset + (grid_rows - view);
|
|
|
|
|
|
|
|
|
|
rows = min(rows, max_rows);
|
|
|
|
|
if (rows == 0)
|
2019-07-10 14:42:48 +02:00
|
|
|
return;
|
|
|
|
|
|
commands: refactor scrollback up/down
When moving the viewport in the scrollback (i.e. “scrolling”), we need
to ensure the viewport is not moved past the beginning, or end, of the
scrollback.
This was previously accomplish by first limiting the number of lines
to scroll to the number of visible rows (i.e the viewport _size_), and
by adjusting the viewport after moving it, to ensure it doesn’t point
into an uninitialized scrollback area etc.
I.e. the implementation was _reactive_.
This patch rewrites the logic to be _proactive_; we now calculate
_where_ the beginning (or end) of the scrollback is, and then how many
lines there is from there, to the viewport. This is our _maximum_
number of lines to scroll.
When done correctly (which I hope this patch does), this allows us to
remove _all_ checks after moving the viewport - we already _know_ it’s
correct, and valid.
As a bonus, we can remove the old limit, where scrolling was only
allowed to be at most a single page.
2022-02-23 18:59:06 +01:00
|
|
|
int new_view = (view + rows) & (grid_rows - 1);
|
2019-07-10 09:29:36 +02:00
|
|
|
|
commands: refactor scrollback up/down
When moving the viewport in the scrollback (i.e. “scrolling”), we need
to ensure the viewport is not moved past the beginning, or end, of the
scrollback.
This was previously accomplish by first limiting the number of lines
to scroll to the number of visible rows (i.e the viewport _size_), and
by adjusting the viewport after moving it, to ensure it doesn’t point
into an uninitialized scrollback area etc.
I.e. the implementation was _reactive_.
This patch rewrites the logic to be _proactive_; we now calculate
_where_ the beginning (or end) of the scrollback is, and then how many
lines there is from there, to the viewport. This is our _maximum_
number of lines to scroll.
When done correctly (which I hope this patch does), this allows us to
remove _all_ checks after moving the viewport - we already _know_ it’s
correct, and valid.
As a bonus, we can remove the old limit, where scrolling was only
allowed to be at most a single page.
2022-02-23 18:59:06 +01:00
|
|
|
xassert(new_view != view);
|
|
|
|
|
xassert(grid->rows[new_view] != NULL);
|
2019-07-10 16:36:10 +02:00
|
|
|
#if defined(_DEBUG)
|
|
|
|
|
for (int r = 0; r < term->rows; r++)
|
commands: refactor scrollback up/down
When moving the viewport in the scrollback (i.e. “scrolling”), we need
to ensure the viewport is not moved past the beginning, or end, of the
scrollback.
This was previously accomplish by first limiting the number of lines
to scroll to the number of visible rows (i.e the viewport _size_), and
by adjusting the viewport after moving it, to ensure it doesn’t point
into an uninitialized scrollback area etc.
I.e. the implementation was _reactive_.
This patch rewrites the logic to be _proactive_; we now calculate
_where_ the beginning (or end) of the scrollback is, and then how many
lines there is from there, to the viewport. This is our _maximum_
number of lines to scroll.
When done correctly (which I hope this patch does), this allows us to
remove _all_ checks after moving the viewport - we already _know_ it’s
correct, and valid.
As a bonus, we can remove the old limit, where scrolling was only
allowed to be at most a single page.
2022-02-23 18:59:06 +01:00
|
|
|
xassert(grid->rows[(new_view + r) & (grid_rows - 1)] != NULL);
|
2019-07-10 16:36:10 +02:00
|
|
|
#endif
|
2019-07-10 09:29:36 +02:00
|
|
|
|
2022-04-27 19:18:43 +01:00
|
|
|
LOG_DBG("scrollback DOWN: %d -> %d (offset = %d, rows = %d)",
|
|
|
|
|
view, new_view, offset, grid_rows);
|
2019-08-04 19:06:49 +02:00
|
|
|
|
2020-05-19 18:49:42 +02:00
|
|
|
selection_view_down(term, new_view);
|
2019-07-09 16:26:36 +02:00
|
|
|
term->grid->view = new_view;
|
|
|
|
|
|
commands: refactor scrollback up/down
When moving the viewport in the scrollback (i.e. “scrolling”), we need
to ensure the viewport is not moved past the beginning, or end, of the
scrollback.
This was previously accomplish by first limiting the number of lines
to scroll to the number of visible rows (i.e the viewport _size_), and
by adjusting the viewport after moving it, to ensure it doesn’t point
into an uninitialized scrollback area etc.
I.e. the implementation was _reactive_.
This patch rewrites the logic to be _proactive_; we now calculate
_where_ the beginning (or end) of the scrollback is, and then how many
lines there is from there, to the viewport. This is our _maximum_
number of lines to scroll.
When done correctly (which I hope this patch does), this allows us to
remove _all_ checks after moving the viewport - we already _know_ it’s
correct, and valid.
As a bonus, we can remove the old limit, where scrolling was only
allowed to be at most a single page.
2022-02-23 18:59:06 +01:00
|
|
|
if (rows < term->rows) {
|
|
|
|
|
term_damage_scroll(
|
|
|
|
|
term, DAMAGE_SCROLL_IN_VIEW,
|
|
|
|
|
(struct scroll_region){0, term->rows}, rows);
|
|
|
|
|
term_damage_rows_in_view(term, term->rows - rows, screen_rows - 1);
|
2019-08-04 19:06:49 +02:00
|
|
|
} else
|
|
|
|
|
term_damage_view(term);
|
|
|
|
|
|
2021-02-06 11:47:59 +01:00
|
|
|
render_refresh_urls(term);
|
2019-07-24 20:09:49 +02:00
|
|
|
render_refresh(term);
|
2019-07-09 16:26:36 +02:00
|
|
|
}
|
Add an optional build-time switch to disable scrollback support
This change introduces a new `scrollback` Meson build option (enabled
by default) that lets foot be compiled without scrollback history.
When the option is off, `FOOT_HAVE_SCROLLBACK` is left
undefined and the relevant code is excluded from the build,
producing a slimmer terminal for use cases that do not need it.
With scrollback disabled:
- The `[scrollback]` section in `foot.ini` and its key bindings
become no-ops.
- In-terminal search is removed,
along with the "pipe scrollback" action, the scrollback indicator,
and their colors/overlays.
- IME hooks for the search box, mouse-wheel scrollback handling,
and related `terminal` state are compiled out.
- Selection auto-scroll (the timer that scrolls the viewport while
a drag-selection extends past the visible area) is removed,
since with no scrollback there is nowhere to scroll to.
The associated function declarations,
`enum selection_scroll_direction`,
the `auto_scroll` field on `terminal::selection`,
and their init/teardown sites are all excluded from the build.
To keep action enumerations stable across build configurations,
two range markers (`BIND_ACTION_PIPE_FIRST` / `BIND_ACTION_PIPE_LAST`)
are introduced so that pipe-action handling does not depend on
`PIPE_SCROLLBACK` being present. The build summary and
`foot --version` now report `+scrollback` or `-scrollback`,
and the config tests have been updated to account for optional section.
2026-05-15 15:51:01 +10:00
|
|
|
#endif /* FOOT_HAVE_SCROLLBACK */
|