mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-03-27 14:45:13 +08: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
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
\subsection history-synopsis Synopsis
|
\subsection history-synopsis Synopsis
|
||||||
\fish{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 delete [ --show-time ] [ --exact | --prefix | --contains ] "search string"...
|
||||||
history merge
|
history merge
|
||||||
history save
|
history save
|
||||||
@ -30,7 +30,7 @@ The following operations (sub-commands) are available:
|
|||||||
|
|
||||||
The following options 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.
|
- `-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.
|
- `-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.
|
- `-h` or `--help` display help for this command.
|
||||||
|
|
||||||
\subsection history-examples Example
|
\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"
|
-s e -l exact -d "Match items identical to the string"
|
||||||
complete -c history -n '__fish_seen_subcommand_from search delete' \
|
complete -c history -n '__fish_seen_subcommand_from search delete' \
|
||||||
-s t -l show-time -d "Output with timestamps"
|
-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
|
# We don't include a completion for the "save" subcommand because it should not be used
|
||||||
# interactively.
|
# interactively.
|
||||||
|
@ -34,6 +34,7 @@ function history --description "display or manipulate interactive command histor
|
|||||||
set -l hist_cmd
|
set -l hist_cmd
|
||||||
set -l search_mode
|
set -l search_mode
|
||||||
set -l show_time
|
set -l show_time
|
||||||
|
set -l max_count
|
||||||
|
|
||||||
# Check for a recognized subcommand as the first argument.
|
# Check for a recognized subcommand as the first argument.
|
||||||
if set -q argv[1]
|
if set -q argv[1]
|
||||||
@ -78,11 +79,24 @@ function history --description "display or manipulate interactive command histor
|
|||||||
set search_mode --contains
|
set search_mode --contains
|
||||||
case -e --exact
|
case -e --exact
|
||||||
set search_mode --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 --
|
case --
|
||||||
set -e argv[1]
|
set -e argv[1]
|
||||||
break
|
break
|
||||||
case '*'
|
case '*'
|
||||||
break
|
if string match -r -- '-\d+' $argv[1]
|
||||||
|
set max_count $argv[1]
|
||||||
|
set -e argv[1]
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
set -e argv[1]
|
set -e argv[1]
|
||||||
end
|
end
|
||||||
@ -107,13 +121,14 @@ function history --description "display or manipulate interactive command histor
|
|||||||
test -z "$search_mode"
|
test -z "$search_mode"
|
||||||
and set search_mode "--contains"
|
and set search_mode "--contains"
|
||||||
|
|
||||||
|
echo "builtin history search $search_mode $show_time $max_count -- $argv" >>/tmp/x
|
||||||
if isatty stdout
|
if isatty stdout
|
||||||
set -l pager less
|
set -l pager less
|
||||||
set -q PAGER
|
set -q PAGER
|
||||||
and set pager $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
|
else
|
||||||
builtin history search $search_mode $show_time -- $argv
|
builtin history search $search_mode $show_time $max_count -- $argv
|
||||||
end
|
end
|
||||||
|
|
||||||
case delete # interactively delete history
|
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);
|
int argc = builtin_count_args(argv);
|
||||||
hist_cmd_t hist_cmd = HIST_NOOP;
|
hist_cmd_t hist_cmd = HIST_NOOP;
|
||||||
history_search_type_t search_type = (history_search_type_t)-1;
|
history_search_type_t search_type = (history_search_type_t)-1;
|
||||||
|
long max_items = LONG_MAX;
|
||||||
bool history_search_type_defined = false;
|
bool history_search_type_defined = false;
|
||||||
const wchar_t *show_time_format = NULL;
|
const wchar_t *show_time_format = NULL;
|
||||||
|
|
||||||
// TODO: Remove the long options that correspond to subcommands (e.g., '--delete') on or after
|
// 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).
|
// 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'},
|
const struct woption long_options[] = {{L"prefix", no_argument, NULL, 'p'},
|
||||||
{L"contains", no_argument, NULL, 'c'},
|
{L"contains", no_argument, NULL, 'c'},
|
||||||
{L"help", no_argument, NULL, 'h'},
|
{L"help", no_argument, NULL, 'h'},
|
||||||
{L"show-time", optional_argument, NULL, 't'},
|
{L"show-time", optional_argument, NULL, 't'},
|
||||||
{L"with-time", optional_argument, NULL, 't'},
|
{L"with-time", optional_argument, NULL, 't'},
|
||||||
{L"exact", no_argument, NULL, 'e'},
|
{L"exact", no_argument, NULL, 'e'},
|
||||||
|
{L"max", required_argument, NULL, 'n'},
|
||||||
{L"delete", no_argument, NULL, 1},
|
{L"delete", no_argument, NULL, 1},
|
||||||
{L"search", no_argument, NULL, 2},
|
{L"search", no_argument, NULL, 2},
|
||||||
{L"save", no_argument, NULL, 3},
|
{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";
|
show_time_format = w.woptarg ? w.woptarg : L"# %c%n";
|
||||||
break;
|
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': {
|
case 'h': {
|
||||||
builtin_print_help(parser, streams, cmd, streams.out);
|
builtin_print_help(parser, streams, cmd, streams.out);
|
||||||
return STATUS_BUILTIN_OK;
|
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;
|
return STATUS_BUILTIN_ERROR;
|
||||||
}
|
}
|
||||||
case '?': {
|
case '?': {
|
||||||
streams.err.append_format(BUILTIN_ERR_UNKNOWN, cmd, argv[w.woptind - 1]);
|
// Try to parse it as a number; e.g., "-123".
|
||||||
return STATUS_BUILTIN_ERROR;
|
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"); }
|
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.
|
// 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.
|
// Note that this can be simplified after we eliminate allowing subcommands as flags.
|
||||||
// See the TODO above regarding the `long_options` array.
|
// 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;
|
int status = STATUS_BUILTIN_OK;
|
||||||
switch (hist_cmd) {
|
switch (hist_cmd) {
|
||||||
case HIST_SEARCH: {
|
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;
|
status = STATUS_BUILTIN_ERROR;
|
||||||
}
|
}
|
||||||
break;
|
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,
|
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);
|
// scoped_lock locker(lock);
|
||||||
if (search_args.empty()) {
|
if (search_args.empty()) {
|
||||||
// Start at one because zero is the current command.
|
// 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)) {
|
if (!format_history_record(this->item_at_index(i), show_time_format, streams)) {
|
||||||
return false;
|
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)) {
|
if (!format_history_record(searcher.current_item(), show_time_format, streams)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (--max_items == 0) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ class history_t {
|
|||||||
|
|
||||||
// Searches history.
|
// Searches history.
|
||||||
bool search(history_search_type_t search_type, wcstring_list_t search_args,
|
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!
|
// Enable / disable automatic saving. Main thread only!
|
||||||
void disable_automatic_saving();
|
void disable_automatic_saving();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user