commandline --selection-start and --selection-end implementation

Fixes #9197
This commit is contained in:
Sergei Shilovsky 2022-10-05 19:51:00 +03:00 committed by GitHub
parent dcf52dbba5
commit e274ef6c0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 2 deletions

View file

@ -26,6 +26,12 @@ The following options are available:
If no argument is given, the current cursor position is printed, otherwise the argument is interpreted as the new cursor position.
If one of the options **-j**, **-p** or **-t** is given, the position is relative to the respective substring instead of the entire command line buffer.
**-B** or **--selection-start**
Get current position of the selection start in the buffer.
**-E** or **--selection-end**
Get current position of the selection end in the buffer.
**-f** or **--function**
Causes any additional arguments to be interpreted as input functions, and puts them into the queue, so that they will be read before any additional actual key presses are.
This option cannot be combined with any other option.

View file

@ -16,6 +16,8 @@ complete -c commandline -s o -l tokenize -d "Print each token on a separate line
complete -c commandline -s I -l input -d "Specify command to operate on"
complete -c commandline -s C -l cursor -d "Set/get cursor position, not buffer contents"
complete -c commandline -s B -l selection-start -d "Get current selection starting position"
complete -c commandline -s E -l selection-end -d "Get current selection ending position"
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"

View file

@ -142,6 +142,8 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
bool tokenize = false;
bool cursor_mode = false;
bool selection_start_mode = false;
bool selection_end_mode = false;
bool line_mode = false;
bool search_mode = false;
bool paging_mode = false;
@ -152,7 +154,7 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
const auto &ld = parser.libdata();
static const wchar_t *const short_options = L":abijpctforhI:CLSsP";
static const wchar_t *const short_options = L":abijpctforhI:CBELSsP";
static const struct woption long_options[] = {{L"append", no_argument, nullptr, 'a'},
{L"insert", no_argument, nullptr, 'i'},
{L"replace", no_argument, nullptr, 'r'},
@ -167,6 +169,8 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
{L"help", no_argument, nullptr, 'h'},
{L"input", required_argument, nullptr, 'I'},
{L"cursor", no_argument, nullptr, 'C'},
{L"selection-start", no_argument, nullptr, 'B'},
{L"selection-end", no_argument, nullptr, 'E'},
{L"line", no_argument, nullptr, 'L'},
{L"search-mode", no_argument, nullptr, 'S'},
{L"paging-mode", no_argument, nullptr, 'P'},
@ -227,6 +231,14 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
cursor_mode = true;
break;
}
case 'B': {
selection_start_mode = true;
break;
}
case 'E': {
selection_end_mode = true;
break;
}
case 'L': {
line_mode = true;
break;
@ -274,7 +286,7 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
// Check for invalid switch combinations.
if (buffer_part || cut_at_cursor || append_mode || tokenize || cursor_mode || line_mode ||
search_mode || paging_mode) {
search_mode || paging_mode || selection_start_mode || selection_end_mode) {
streams.err.append_format(BUILTIN_ERR_COMBO, argv[0]);
builtin_print_error_trailer(parser, streams.err, cmd);
return STATUS_INVALID_ARGS;
@ -324,6 +336,12 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
}
// Check for invalid switch combinations.
if ((selection_start_mode || selection_end_mode) && (argc - w.woptind)) {
streams.err.append_format(BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
builtin_print_error_trailer(parser, streams.err, cmd);
return STATUS_INVALID_ARGS;
}
if ((search_mode || line_mode || cursor_mode || paging_mode) && (argc - w.woptind > 1)) {
streams.err.append_format(BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
builtin_print_error_trailer(parser, streams.err, cmd);
@ -379,6 +397,24 @@ maybe_t<int> builtin_commandline(parser_t &parser, io_streams_t &streams, const
return (state.pager_mode && state.pager_fully_disclosed) ? 0 : 1;
}
if (selection_start_mode) {
if (!rstate.selection) {
return STATUS_CMD_ERROR;
}
source_offset_t start = rstate.selection->start;
streams.out.append_format(L"%lu\n", static_cast<unsigned long>(start));
return STATUS_CMD_OK;
}
if (selection_end_mode) {
if (!rstate.selection) {
return STATUS_CMD_ERROR;
}
source_offset_t end = rstate.selection->end();
streams.out.append_format(L"%lu\n", static_cast<unsigned long>(end));
return STATUS_CMD_OK;
}
// 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