builtin commandline: add option to determine if pager is fully disclosed

Use the remaining_to_disclose count to determine if all completions
are shown (allows consistent behavior between short and long completion
lists).

Closes #8485
This commit is contained in:
thibault 2021-11-24 18:03:20 -05:00 committed by Johannes Altmanninger
parent 4a575b26f5
commit ceade1629d
6 changed files with 18 additions and 1 deletions

View file

@ -65,6 +65,7 @@ Scripting improvements
- An oversight prevented all syntax checks from running on commands given to ``fish -c`` (:issue:`8171`). This includes checks like e.g. ``exec`` not being allowed in a pipeline and ``$$`` not being a valid variable. Most of these would have triggered an assert or other error before.
- ``fish_indent`` now correctly reformats tokens that end with a backslash followed by a newline (:issue:`8197`).
- ``commandline`` gained an ``--is-valid`` option to check if the commandline is syntactically valid and complete. This allows basic implementation of transient prompts (:issue:`8142`).
- ``commandline`` gained an ``--paging-full-mode`` option to check if the pager is showing all the possible lines (no "5 more rows" message) (:issue:`8485`).
- List expansion correctly reports an error when used with all zero indexes (:issue:`8213`).
- Running ``fish`` with a directory instead of a script as argument (e.g. ``fish .``) no longer leads to an infinite loop. Instead it errors out immediately (:issue:`8258`)
- Some error messages occuring after fork, like "text file busy" have been replaced by bespoke error messages for fish (like "File is currently open for writing"). This also restores error messages with current glibc versions that removed sys_errlist (:issue:`8234`, :issue:`4183`).

View file

@ -61,6 +61,8 @@ The following options output metadata about the commandline state:
- ``-P`` or ``--paging-mode`` evaluates to true if the commandline is showing pager contents, such as tab completions
- ``--paging-full-mode`` evaluates to true if the commandline is showing pager contents, such as tab completions and all lines are shown (no "<n> more rows" message)
- ``--is-valid`` returns true when the commandline is syntactically valid and complete. If it is, it would be executed when the ``execute`` bind function is called. If the commandline is incomplete, it returns 2, if it is erroneus, it returns 1.
Example

View file

@ -19,6 +19,7 @@ complete -c commandline -s C -l cursor -d "Set/get cursor position, not buffer c
complete -c commandline -s L -l line -d "Print the line that the cursor is on"
complete -c commandline -s S -l search-mode -d "Return true if performing a history search"
complete -c commandline -s P -l paging-mode -d "Return true if showing pager content"
complete -c commandline -l paging-full-mode -d "Return true if pager is showing all content"
complete -c commandline -l is-valid -d "Return true if the command line is syntactically valid and complete"

View file

@ -143,6 +143,7 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
bool line_mode = false;
bool search_mode = false;
bool paging_mode = false;
bool paging_full_mode = false;
bool is_valid = false;
const wchar_t *begin = nullptr, *end = nullptr;
const wchar_t *override_buffer = nullptr;
@ -167,6 +168,7 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
{L"line", no_argument, nullptr, 'L'},
{L"search-mode", no_argument, nullptr, 'S'},
{L"paging-mode", no_argument, nullptr, 'P'},
{L"paging-full-mode", no_argument, nullptr, 'F'},
{L"is-valid", no_argument, nullptr, 1},
{nullptr, 0, nullptr, 0}};
@ -239,6 +241,10 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
paging_mode = true;
break;
}
case 'F': {
paging_full_mode = true;
break;
}
case 1: {
is_valid = true;
break;
@ -323,7 +329,7 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
}
if ((buffer_part || tokenize || cut_at_cursor) &&
(cursor_mode || line_mode || search_mode || paging_mode) &&
(cursor_mode || line_mode || search_mode || paging_mode || paging_full_mode) &&
// Special case - we allow to get/set cursor position relative to the process/job/token.
!(buffer_part && cursor_mode)) {
streams.err.append_format(BUILTIN_ERR_COMBO, argv[0]);
@ -366,6 +372,11 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
return commandline_get_state().pager_mode ? 0 : 1;
}
if (paging_full_mode) {
auto state = commandline_get_state();
return (state.pager_mode && state.pager_fully_disclosed) ? 0 : 1;
}
// At this point we have (nearly) exhausted the options which always operate on the true command
// line. Now we respect the possibility of a transient command line due to evaluating a wrapped
// completion. Don't do this in cursor_mode: it makes no sense to move the cursor based on a

View file

@ -2741,6 +2741,7 @@ void reader_data_t::update_commandline_state() const {
snapshot->history = this->history;
snapshot->selection = this->get_selection();
snapshot->pager_mode = !this->current_page_rendering.screen_data.empty();
snapshot->pager_fully_disclosed = this->current_page_rendering.remaining_to_disclose == 0;
snapshot->search_mode = this->history_search.active();
snapshot->initialized = true;
}

View file

@ -257,6 +257,7 @@ struct commandline_state_t {
maybe_t<source_range_t> selection{}; // visual selection, or none if none
std::shared_ptr<history_t> history{}; // current reader history, or null if not interactive
bool pager_mode{false}; // pager is visible
bool pager_fully_disclosed{false}; // pager already shows everything if possible
bool search_mode{false}; // pager is visible and search is active
bool initialized{false}; // if false, the reader has not yet been entered
};