mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
add a flag to limit history search results
This adds a flag to the `history search` command to limit the number of matching entries to the first "n". The default is unlimited. This is mostly useful in conjunction with aliases (i.e., functions) that are intended to report the "n" most recent matching history entries without piping the result through the user's pager. Fixes #3244
This commit is contained in:
parent
c2a8de4873
commit
e9b5505169
6 changed files with 58 additions and 12 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
\subsection history-synopsis Synopsis
|
||||
\fish{synopsis}
|
||||
history search [ --show-time ] [ --exact | --prefix | --contains ] [ "search string"... ]
|
||||
history search [ --show-time ] [ --exact | --prefix | --contains ] [ --max=n ] [ "search string"... ]
|
||||
history delete [ --show-time ] [ --exact | --prefix | --contains ] "search string"...
|
||||
history merge
|
||||
history save
|
||||
|
@ -30,7 +30,7 @@ The following operations (sub-commands) are available:
|
|||
|
||||
The following options are available:
|
||||
|
||||
These flags can appear before or immediately after on of the sub-commands listed above.
|
||||
These flags can appear before or immediately after one of the sub-commands listed above.
|
||||
|
||||
- `-c` or `--contains` searches or deletes items in the history that contain the specified text string. This is the default for the `--search` flag. This is not currently supported by the `--delete` flag.
|
||||
|
||||
|
@ -40,6 +40,8 @@ These flags can appear before or immediately after on of the sub-commands listed
|
|||
|
||||
- `-t` or `--show-time` prepends each history entry with the date and time the entry was recorded . By default it uses the strftime format `# %c%n`. You can specify another format; e.g., `--show-time='%Y-%m-%d %H:%M:%S '` or `--show-time='%a%I%p'`. The short option, `-t` doesn't accept a stftime format string; it only uses the default format. Any strftime format is allowed, including `%s` to get the raw UNIX seconds since the epoch. Note that `--with-time` is also allowed but is deprecated and will be removed at a future date.
|
||||
|
||||
- `-<number>` `-n <number>` or `--max=<number>` limits the matched history items to the first "n" matching entries. This is only valid for `history search`.
|
||||
|
||||
- `-h` or `--help` display help for this command.
|
||||
|
||||
\subsection history-examples Example
|
||||
|
|
|
@ -10,6 +10,8 @@ complete -c history -n '__fish_seen_subcommand_from search delete' \
|
|||
-s e -l exact -d "Match items identical to the string"
|
||||
complete -c history -n '__fish_seen_subcommand_from search delete' \
|
||||
-s t -l show-time -d "Output with timestamps"
|
||||
complete -c history -n '__fish_seen_subcommand_from search' \
|
||||
-s n -l max -d "Limit output to the first 'n' matches"
|
||||
|
||||
# We don't include a completion for the "save" subcommand because it should not be used
|
||||
# interactively.
|
||||
|
|
|
@ -34,6 +34,7 @@ function history --description "display or manipulate interactive command histor
|
|||
set -l hist_cmd
|
||||
set -l search_mode
|
||||
set -l show_time
|
||||
set -l max_count
|
||||
|
||||
# Check for a recognized subcommand as the first argument.
|
||||
if set -q argv[1]
|
||||
|
@ -78,12 +79,25 @@ function history --description "display or manipulate interactive command histor
|
|||
set search_mode --contains
|
||||
case -e --exact
|
||||
set search_mode --exact
|
||||
case -n --max
|
||||
if string match -- '-n?*' $argv[1]
|
||||
or string match -- '--max=*' $argv[1]
|
||||
set max_count $argv[1]
|
||||
else
|
||||
set max_count $argv[1] $argv[2]
|
||||
set -e argv[1]
|
||||
end
|
||||
case --
|
||||
set -e argv[1]
|
||||
break
|
||||
case '*'
|
||||
if string match -r -- '-\d+' $argv[1]
|
||||
set max_count $argv[1]
|
||||
set -e argv[1]
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
set -e argv[1]
|
||||
end
|
||||
|
||||
|
@ -107,13 +121,14 @@ function history --description "display or manipulate interactive command histor
|
|||
test -z "$search_mode"
|
||||
and set search_mode "--contains"
|
||||
|
||||
echo "builtin history search $search_mode $show_time $max_count -- $argv" >>/tmp/x
|
||||
if isatty stdout
|
||||
set -l pager less
|
||||
set -q PAGER
|
||||
and set pager $PAGER
|
||||
builtin history search $search_mode $show_time -- $argv | eval $pager
|
||||
builtin history search $search_mode $show_time $max_count -- $argv | eval $pager
|
||||
else
|
||||
builtin history search $search_mode $show_time -- $argv
|
||||
builtin history search $search_mode $show_time $max_count -- $argv
|
||||
end
|
||||
|
||||
case delete # interactively delete history
|
||||
|
|
|
@ -2846,18 +2846,20 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
|
|||
int argc = builtin_count_args(argv);
|
||||
hist_cmd_t hist_cmd = HIST_NOOP;
|
||||
history_search_type_t search_type = (history_search_type_t)-1;
|
||||
long max_items = LONG_MAX;
|
||||
bool history_search_type_defined = false;
|
||||
const wchar_t *show_time_format = NULL;
|
||||
|
||||
// TODO: Remove the long options that correspond to subcommands (e.g., '--delete') on or after
|
||||
// 2017-10 (which will be a full year after these flags have been deprecated).
|
||||
const wchar_t *short_options = L":mepcht";
|
||||
const wchar_t *short_options = L":mn:epcht";
|
||||
const struct woption long_options[] = {{L"prefix", no_argument, NULL, 'p'},
|
||||
{L"contains", no_argument, NULL, 'c'},
|
||||
{L"help", no_argument, NULL, 'h'},
|
||||
{L"show-time", optional_argument, NULL, 't'},
|
||||
{L"with-time", optional_argument, NULL, 't'},
|
||||
{L"exact", no_argument, NULL, 'e'},
|
||||
{L"max", required_argument, NULL, 'n'},
|
||||
{L"delete", no_argument, NULL, 1},
|
||||
{L"search", no_argument, NULL, 2},
|
||||
{L"save", no_argument, NULL, 3},
|
||||
|
@ -2923,6 +2925,17 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
|
|||
show_time_format = w.woptarg ? w.woptarg : L"# %c%n";
|
||||
break;
|
||||
}
|
||||
case 'n': {
|
||||
wchar_t *end = 0;
|
||||
max_items = wcstol(w.woptarg, &end, 10);
|
||||
if (!(*w.woptarg != L'\0' && *end == L'\0')) {
|
||||
streams.err.append_format(
|
||||
_(L"%ls: max value '%ls' is not a valid number\n"), argv[0],
|
||||
w.woptarg);
|
||||
return STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'h': {
|
||||
builtin_print_help(parser, streams, cmd, streams.out);
|
||||
return STATUS_BUILTIN_OK;
|
||||
|
@ -2932,13 +2945,26 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
|
|||
return STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
case '?': {
|
||||
// Try to parse it as a number; e.g., "-123".
|
||||
wchar_t *end = 0;
|
||||
max_items = wcstol(argv[w.woptind - 1] + 1, &end, 10);
|
||||
if (!(argv[w.woptind - 1][1] != L'\0' && *end == L'\0')) {
|
||||
streams.err.append_format(BUILTIN_ERR_UNKNOWN, cmd, argv[w.woptind - 1]);
|
||||
return STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
w.nextchar = NULL;
|
||||
break;
|
||||
}
|
||||
default: { DIE("unexpected retval from wgetopt_long"); }
|
||||
}
|
||||
}
|
||||
|
||||
if (max_items <= 0) {
|
||||
streams.err.append_format(_(L"%ls: max value '%ls' is not a valid number\n"), argv[0],
|
||||
w.woptarg);
|
||||
return STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
|
||||
// If a history command hasn't already been specified via a flag check the first word.
|
||||
// Note that this can be simplified after we eliminate allowing subcommands as flags.
|
||||
// See the TODO above regarding the `long_options` array.
|
||||
|
@ -2963,7 +2989,7 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
|
|||
int status = STATUS_BUILTIN_OK;
|
||||
switch (hist_cmd) {
|
||||
case HIST_SEARCH: {
|
||||
if (!history->search(search_type, args, show_time_format, streams)) {
|
||||
if (!history->search(search_type, args, show_time_format, max_items, streams)) {
|
||||
status = STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -1415,11 +1415,11 @@ static bool format_history_record(const history_item_t &item, const wchar_t *sho
|
|||
}
|
||||
|
||||
bool history_t::search(history_search_type_t search_type, wcstring_list_t search_args,
|
||||
const wchar_t *show_time_format, io_streams_t &streams) {
|
||||
const wchar_t *show_time_format, long max_items, io_streams_t &streams) {
|
||||
// scoped_lock locker(lock);
|
||||
if (search_args.empty()) {
|
||||
// Start at one because zero is the current command.
|
||||
for (int i = 1; !this->item_at_index(i).empty(); ++i) {
|
||||
for (int i = 1; !this->item_at_index(i).empty() && max_items; ++i, --max_items) {
|
||||
if (!format_history_record(this->item_at_index(i), show_time_format, streams)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1439,6 +1439,7 @@ bool history_t::search(history_search_type_t search_type, wcstring_list_t search
|
|||
if (!format_history_record(searcher.current_item(), show_time_format, streams)) {
|
||||
return false;
|
||||
}
|
||||
if (--max_items == 0) return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -227,7 +227,7 @@ class history_t {
|
|||
|
||||
// Searches history.
|
||||
bool search(history_search_type_t search_type, wcstring_list_t search_args,
|
||||
const wchar_t *show_time_format, io_streams_t &streams);
|
||||
const wchar_t *show_time_format, long max_items, io_streams_t &streams);
|
||||
|
||||
// Enable / disable automatic saving. Main thread only!
|
||||
void disable_automatic_saving();
|
||||
|
|
Loading…
Reference in a new issue