alter history sub-command handling

This deprecates the use of long options for history sub-commands (e.g.,
`history --delete`) in favor of proper sub-commands (e.g., `history
delete`). It also eliminates the short options for those sub-commands.

Also change option processing to allow options anywhere on the command
line to match how the vast majority of fish builtins handle flags.

Replace --with-time with --show-time.

Fixes #3367
This commit is contained in:
Kurtis Rader 2016-09-10 20:42:52 -07:00
parent 02ba7933e0
commit 76c73aa8ce
9 changed files with 288 additions and 154 deletions

View file

@ -2,39 +2,45 @@
\subsection history-synopsis Synopsis
\fish{synopsis}
history ( -s | --search ) [ -t | --with-time ] [ -e | --exact | -p | --prefix | -c | --contains ] [ "search string"... ]
history ( -d | --delete ) [ -t | --with-time ] [ -e | --exact | -p | --prefix | -c | --contains ] "search string"...
history ( -m | --merge )
history ( -s | --save )
history ( -l | --clear )
history search [ --show-time ] [ --exact | --prefix | --contains ] [ "search string"... ]
history delete [ --show-time ] [ --exact | --prefix | --contains ] "search string"...
history merge
history save
history clear
history ( -h | --help )
\endfish
\subsection history-description Description
`history` is used to list, search and delete the history of commands used.
`history` is used to search, delete, and otherwise manipulate the history of interactive commands.
The following commands are available:
Note that for backwards compatibility each subcommand can also be specified as a long option. For example, rather than `history search` you can type `history --search`. Those long options are deprecated and will be removed in a future release.
- `-s` or `--search` returns history items matching the search string. If no search string is provided it returns all history items. This is the default operation if no other operation is specified. The `--contains` search option will be used if you don't specify a different search option. Entries are ordered newest to oldest. If stdout is attached to a tty the output will be piped through your pager by the history function. The history builtin simply writes the results to stdout.
The following operations (sub-commands) are available:
- `-d` or `--delete` deletes history items. Without the `--prefix` or `--contains` options, the exact match will be deleted. With either of these options, a prompt will be displayed before any items are deleted asking you which entries are to be deleted. You can enter the word "all" to delete all matching entries. You can enter a single ID (the number in square brackets) to delete just that single entry. You can enter more than one ID separated by a space to delete multiple entries. Just press [enter] to not delete anything. Note that the interactive delete behavior is a feature of the history function. The history builtin only supports bulk deletion.
- `search` returns history items matching the search string. If no search string is provided it returns all history items. This is the default operation if no other operation is specified. You only have to explicitly say `history search` if you wish to search for one of the subcommands. The `--contains` search option will be used if you don't specify a different search option. Entries are ordered newest to oldest. If stdout is attached to a tty the output will be piped through your pager by the history function. The history builtin simply writes the results to stdout.
- `-m` or `--merge` immediately incorporates history changes from other sessions. Ordinarily `fish` ignores history changes from sessions started after the current one. This command applies those changes immediately.
- `delete` deletes history items. Without the `--prefix` or `--contains` options, the exact match will be deleted. With either of these options, a prompt will be displayed before any items are deleted asking you which entries are to be deleted. You can enter the word "all" to delete all matching entries. You can enter a single ID (the number in square brackets) to delete just that single entry. You can enter more than one ID separated by a space to delete multiple entries. Just press [enter] to not delete anything. Note that the interactive delete behavior is a feature of the history function. The history builtin only supports bulk deletion.
- `-v` or `--save` saves all changes in the history file. The shell automatically saves the history file; this option is provided for internal use.
- `merge` immediately incorporates history changes from other sessions. Ordinarily `fish` ignores history changes from sessions started after the current one. This command applies those changes immediately.
- `-l` or `--clear` clears the history file. A prompt is displayed before the history is erased asking you to confirm you really want to clear all history unless `builtin history` is used.
- `save` immediately writes all changes to the history file. The shell automatically saves the history file; this option is provided for internal use and should not normally need to be used by the user.
- `clear` clears the history file. A prompt is displayed before the history is erased asking you to confirm you really want to clear all history unless `builtin history` is used.
The following options are available:
These flags can appear before or immediately after on 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.
- `-e` or `--exact` searches or deletes items in the history that exactly match the specified text string. This is the default for the `--delete` flag.
- `-p` or `--prefix` searches or deletes items in the history that begin with the specified text string. This is not currently supported by the `--delete` flag.
- `-t` or `--with-time` outputs the date and time ("%Y-%m-%d %H:%M:%S") history items were recorded at on a line starting with "#" before each history entry.
- `-t` or `--show-time` outputs the date and time ("%Y-%m-%d %H:%M:%S") history items were recorded at on a line starting with "#" before each history entry. Note that `--with-time` is also allowed but is deprecated and will be removed at a future date.
- `-h` or `--help` display help for this command.
\subsection history-examples Example

View file

@ -1,10 +1,23 @@
complete -c history -r -l prefix --description "Match items starting with prefix"
complete -c history -r -l contains --description "Match items containing string"
complete -c history -l search -s s --description "Prints commands from history matching query"
complete -c history -l delete -s d --description "Deletes commands from history matching query"
complete -c history -l clear --description "Clears history file"
complete -c history -l merge -s m --description "Incorporate history changes from other sessions"
complete -c history -l exact -s e --description "Match items in the history that are identicial"
complete -c history -l with-time -s t --description "Output with timestamps"
# Note that when a completion file is sourced a new block scope is created so `set -l` works.
set -l __fish_history_all_commands search delete save merge clear
# --save is not completed; it is for internal use
# Note that these options are only valid with the "search" and "delete" subcommands.
complete -c history -n '__fish_seen_subcommand_from search delete' \
-s p -l prefix -d "Match items beginning with the string"
complete -c history -n '__fish_seen_subcommand_from search delete' \
-s c -l contains -d "Match items containing the string"
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"
# We don't include a completion for the "save" subcommand because it should not be used
# interactively.
complete -f -c history -n "not __fish_seen_subcommand_from $__fish_history_all_commands" \
-a search -d "Prints commands from history matching the strings"
complete -f -c history -n "not __fish_seen_subcommand_from $__fish_history_all_commands" \
-a delete -d "Deletes commands from history matching the strings"
complete -f -c history -n "not __fish_seen_subcommand_from $__fish_history_all_commands" \
-a merge -d "Incorporate history changes from other sessions"
complete -f -c history -n "not __fish_seen_subcommand_from $__fish_history_all_commands" \
-a clear -d "Clears history file"

View file

@ -1,29 +1,78 @@
#
# Wrap the builtin history command to provide additional functionality.
#
# This function is meant to mimic the `set_hist_cmd` function in *src/builtin.cpp*.
# In particular the error message should be identical in both locations.
function __fish_set_hist_cmd --no-scope-shadowing
if set -q hist_cmd[1]
set -l msg (printf (_ "you cannot do both '%ls' and '%ls' in the same invocation") \
$hist_cmd $argv[1])
printf (_ "%ls: Invalid combination of options,\n%ls\n") $cmd $msg >&2
return 1
end
set hist_cmd $argv[1]
return 0
end
function __fish_unexpected_hist_args --no-scope-shadowing
if test -n "$search_mode"
or test -n "$show_time"
printf (_ "%ls: you cannot use any options with the %ls command\n") $cmd $hist_cmd >&2
return 0
end
if set -q argv[1]
printf (_ "%ls: %ls command expected %d args, got %d\n") \
$cmd $hist_cmd 0 (count $argv) >&2
return 0
end
return 1
end
function history --description "display or manipulate interactive command history"
set -l cmd
set -l cmd $_
set -l cmd history
set -l hist_cmd
set -l search_mode
set -l with_time
set -l show_time
# Check for a recognized subcommand as the first argument.
if set -q argv[1]
and not string match -q -- '-*' $argv[1]
switch $argv[1]
case search delete merge save clear
set hist_cmd $argv[1]
set -e argv[1]
end
end
# The "set cmd $cmd xyz" lines are to make it easy to detect if the user specifies more than one
# subcommand.
#
# 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).
while set -q argv[1]
switch $argv[1]
case -d --delete
set cmd $cmd delete
case -v --save
set cmd $cmd save
case -l --clear
set cmd $cmd clear
case -s --search
set cmd $cmd search
case -m --merge
set cmd $cmd merge
case --delete
__fish_set_hist_cmd delete
or return
case --save
__fish_set_hist_cmd save
or return
case --clear
__fish_set_hist_cmd clear
or return
case --search
__fish_set_hist_cmd search
or return
case --merge
__fish_set_hist_cmd merge
or return
case -h --help
set cmd $cmd help
case -t --with-time
set with_time -t
builtin history --help
return
case -t --show-time --with-time
set show_time -t
case -p --prefix
set search_mode --prefix
case -c --contains
@ -39,15 +88,23 @@ function history --description "display or manipulate interactive command histor
set -e argv[1]
end
if not set -q cmd[1]
set cmd search # default to "search" if the user didn't explicitly specify a command
else if set -q cmd[2]
printf (_ "You cannot specify multiple commands: %s\n") "$cmd"
return 1
# If a history command has not already been specified check the first non-flag argument for a
# command. This allows the flags to appear before or after the subcommand.
if not set -q hist_cmd[1]
and set -q argv[1]
switch $argv[1]
case search delete merge save clear
set hist_cmd $argv[1]
set -e argv[1]
end
end
switch $cmd
case search
if not set -q hist_cmd[1]
set hist_cmd search # default to "search" if the user didn't specify a subcommand
end
switch $hist_cmd
case search # search the interactive command history
test -z "$search_mode"
and set search_mode "--contains"
@ -55,12 +112,12 @@ function history --description "display or manipulate interactive command histor
set -l pager less
set -q PAGER
and set pager $PAGER
builtin history --search $search_mode $with_time -- $argv | eval $pager
builtin history search $search_mode $show_time -- $argv | eval $pager
else
builtin history --search $search_mode $with_time -- $argv
builtin history search $search_mode $show_time -- $argv
end
case delete # Interactively delete history
case delete # interactively delete history
# TODO: Fix this to deal with history entries that have multiple lines.
if not set -q argv[1]
printf (_ "You must specify at least one search term when deleting entries\n") >&2
@ -71,13 +128,13 @@ function history --description "display or manipulate interactive command histor
and set search_mode "--exact"
if test $search_mode = "--exact"
builtin history --delete $search_mode $argv
builtin history delete $search_mode $argv
return
end
# TODO: Fix this so that requesting history entries with a timestamp works:
# set -l found_items (builtin history --search $search_mode $with_time -- $argv)
set -l found_items (builtin history --search $search_mode -- $argv)
# set -l found_items (builtin history search $search_mode $show_time -- $argv)
set -l found_items (builtin history search $search_mode -- $argv)
if set -q found_items[1]
set -l found_items_count (count $found_items)
for i in (seq $found_items_count)
@ -98,8 +155,8 @@ function history --description "display or manipulate interactive command histor
if test "$choice" = "all"
printf "Deleting all matching entries!\n"
builtin history --delete $search_mode -- $argv
builtin history --save
builtin history delete $search_mode -- $argv
builtin history save
return
end
@ -112,45 +169,38 @@ function history --description "display or manipulate interactive command histor
end
printf "Deleting history entry %s: \"%s\"\n" $i $found_items[$i]
builtin history --delete "$found_items[$i]"
builtin history delete "$found_items[$i]"
end
builtin history --save
builtin history save
end
case save
if test -n "$search_mode"
or test -n "$with_time"
printf (_ "history: you cannot use any options with %s command\n") save >&2
return 1
end
builtin history --save -- $argv
case save # save our interactive command history to the persistent history
__fish_unexpected_hist_args $argv
and return 1
case merge
if test -n "$search_mode"
or test -n "$with_time"
printf (_ "history: you cannot use any options with %s command\n") merge >&2
return 1
end
builtin history --merge -- $argv
builtin history save -- $argv
case help
builtin history --help
case merge # merge the persistent interactive command history with our history
__fish_unexpected_hist_args $argv
and return 1
case clear
# Erase the entire history.
if test -n "$search_mode"
or test -n "$with_time"
printf (_ "history: you cannot use any options with %s command\n") clear >&2
return 1
end
builtin history merge -- $argv
case clear # clear the interactive command history
__fish_unexpected_hist_args $argv
and return 1
printf (_ "If you enter 'yes' your entire interactive command history will be erased\n")
read --local --prompt "echo 'Are you sure you want to clear history? (yes/no) '" choice
if test "$choice" = "yes"
builtin history --clear -- $argv
builtin history clear -- $argv
and printf (_ "Command history cleared!")
else
printf (_ "You did not say 'yes' so I will not clear your command history\n")
end
case '*'
printf "%ls: unexpected subcommand '%ls'\n" $cmd $hist_cmd
return 2
end
end

View file

@ -455,7 +455,7 @@ class BindingParser:
readable_command += 'CTRL - '
if alt:
readable_command += 'ALT - '
if result == '':
return 'unknown-control-sequence'
@ -654,7 +654,9 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_delete_history_item(self, history_item_text):
# It's really lame that we always return success here
out, err = run_fish_cmd('builtin history --save --delete -- ' + escape_fish_cmd(history_item_text))
cmd = ('builtin history delete --exact -- %s; builtin history save' %
escape_fish_cmd(history_item_text))
out, err = run_fish_cmd(cmd)
return True
def do_set_prompt_function(self, prompt_func):

View file

@ -471,7 +471,6 @@ static int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv)
streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0],
long_options[opt_index].name);
builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
case 'a': {
@ -2776,6 +2775,21 @@ static int builtin_return(parser_t &parser, io_streams_t &streams, wchar_t **arg
enum hist_cmd_t { HIST_NOOP, HIST_SEARCH, HIST_DELETE, HIST_CLEAR, HIST_MERGE, HIST_SAVE };
static hist_cmd_t hist_string_to_cmd(const wchar_t *hist_command) {
if (wcscmp(hist_command, L"search") == 0) {
return HIST_SEARCH;
} else if (wcscmp(hist_command, L"delete") == 0) {
return HIST_DELETE;
} else if (wcscmp(hist_command, L"merge") == 0) {
return HIST_MERGE;
} else if (wcscmp(hist_command, L"save") == 0) {
return HIST_SAVE;
} else if (wcscmp(hist_command, L"clear") == 0) {
return HIST_CLEAR;
}
return HIST_NOOP;
}
static const wcstring hist_cmd_to_string(hist_cmd_t hist_cmd) {
switch (hist_cmd) {
case HIST_NOOP:
@ -2802,8 +2816,8 @@ static bool set_hist_cmd(wchar_t *const cmd, hist_cmd_t *hist_cmd, hist_cmd_t su
if (*hist_cmd != HIST_NOOP) {
wchar_t err_text[1024];
swprintf(err_text, sizeof(err_text) / sizeof(wchar_t),
_(L"You cannot do both '%ls' and '%ls' in the same '%ls' invocation\n"),
hist_cmd_to_string(*hist_cmd).c_str(), hist_cmd_to_string(sub_cmd).c_str(), cmd);
_(L"you cannot do both '%ls' and '%ls' in the same invocation"),
hist_cmd_to_string(*hist_cmd).c_str(), hist_cmd_to_string(sub_cmd).c_str());
streams.err.append_format(BUILTIN_ERR_COMBO2, cmd, err_text);
return false;
}
@ -2812,15 +2826,14 @@ static bool set_hist_cmd(wchar_t *const cmd, hist_cmd_t *hist_cmd, hist_cmd_t su
return true;
}
#define CHECK_FOR_UNEXPECTED_HIST_OPTIONS(hist_cmd) \
if (history_search_type_defined || with_time) { \
streams.err.append_format(_(L"history: you cannot use any options with %ls command\n"), \
hist_cmd_to_string(hist_cmd).c_str()); \
status = STATUS_BUILTIN_ERROR; \
break; \
}
#define CHECK_FOR_UNEXPECTED_HIST_ARGS(hist_cmd) \
if (history_search_type_defined || show_time) { \
streams.err.append_format( \
_(L"%ls: you cannot use any options with the %ls command\n"), \
cmd, hist_cmd_to_string(hist_cmd).c_str()); \
status = STATUS_BUILTIN_ERROR; \
break; \
} \
if (args.size() != 0) { \
streams.err.append_format(BUILTIN_ERR_ARG_COUNT, cmd, \
hist_cmd_to_string(hist_cmd).c_str(), 0, args.size()); \
@ -2835,60 +2848,63 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
hist_cmd_t hist_cmd = HIST_NOOP;
history_search_type_t search_type = (history_search_type_t)-1;
bool history_search_type_defined = false;
bool with_time = false;
bool show_time = false;
static const struct woption long_options[] = {{L"delete", no_argument, 0, 'd'},
{L"search", no_argument, 0, 's'},
{L"prefix", no_argument, 0, 'p'},
{L"contains", no_argument, 0, 'c'},
{L"save", no_argument, 0, 'v'},
{L"clear", no_argument, 0, 'l'},
{L"merge", no_argument, 0, 'm'},
{L"help", no_argument, 0, 'h'},
{L"with-time", no_argument, 0, 't'},
{L"exact", no_argument, 0, 'e'},
{0, 0, 0, 0}};
// 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 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", no_argument, NULL, 't'},
{L"with-time", no_argument, NULL, 't'},
{L"exact", no_argument, NULL, 'e'},
{L"delete", no_argument, NULL, 1},
{L"search", no_argument, NULL, 2},
{L"save", no_argument, NULL, 3},
{L"clear", no_argument, NULL, 4},
{L"merge", no_argument, NULL, 5},
{NULL, 0, NULL, 0}};
history_t *history = reader_get_history();
// Use the default history if we have none (which happens if invoked non-interactively, e.g.
// from webconfig.py.
if (!history) history = &history_t::history_with_name(L"fish");
int opt = 0;
int opt_index = 0;
int opt;
wgetopter_t w;
while ((opt = w.wgetopt_long(argc, argv, L"+despcvlmht", long_options, &opt_index)) != EOF) {
while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
switch (opt) {
case 's': {
if (!set_hist_cmd(cmd, &hist_cmd, HIST_SEARCH, streams)) {
return STATUS_BUILTIN_ERROR;
}
break;
}
case 'm': {
if (!set_hist_cmd(cmd, &hist_cmd, HIST_MERGE, streams)) {
return STATUS_BUILTIN_ERROR;
}
break;
}
case 'v': {
if (!set_hist_cmd(cmd, &hist_cmd, HIST_SAVE, streams)) {
return STATUS_BUILTIN_ERROR;
}
break;
}
case 'd': {
case 1: {
if (!set_hist_cmd(cmd, &hist_cmd, HIST_DELETE, streams)) {
return STATUS_BUILTIN_ERROR;
}
break;
}
case 'l': {
case 2: {
if (!set_hist_cmd(cmd, &hist_cmd, HIST_SEARCH, streams)) {
return STATUS_BUILTIN_ERROR;
}
break;
}
case 3: {
if (!set_hist_cmd(cmd, &hist_cmd, HIST_SAVE, streams)) {
return STATUS_BUILTIN_ERROR;
}
break;
}
case 4: {
if (!set_hist_cmd(cmd, &hist_cmd, HIST_CLEAR, streams)) {
return STATUS_BUILTIN_ERROR;
}
break;
}
case 5: {
if (!set_hist_cmd(cmd, &hist_cmd, HIST_MERGE, streams)) {
return STATUS_BUILTIN_ERROR;
}
break;
}
case 'p': {
search_type = HISTORY_SEARCH_TYPE_PREFIX;
history_search_type_defined = true;
@ -2905,28 +2921,40 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
break;
}
case 't': {
with_time = true;
show_time = true;
break;
}
case 'h': {
builtin_print_help(parser, streams, cmd, streams.out);
return STATUS_BUILTIN_OK;
}
case ':': {
streams.err.append_format(BUILTIN_ERR_MISSING, cmd, argv[w.woptind - 1]);
return STATUS_BUILTIN_ERROR;
}
case '?': {
streams.err.append_format(BUILTIN_ERR_UNKNOWN, cmd, argv[w.woptind - 1]);
return STATUS_BUILTIN_ERROR;
}
default: {
streams.err.append_format(BUILTIN_ERR_UNKNOWN, cmd, argv[w.woptind - 1]);
return STATUS_BUILTIN_ERROR;
}
default: { DIE("unexpected retval from wgetopt_long"); }
}
}
// Everything after the flags is an argument for a subcommand (e.g., a search term).
// 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.
if (hist_cmd == HIST_NOOP && w.woptind < argc) {
hist_cmd = hist_string_to_cmd(argv[w.woptind]);
if (hist_cmd != HIST_NOOP) {
w.woptind++;
}
}
// Every argument that we haven't consumed already is an argument for a subcommand (e.g., a
// search term).
const wcstring_list_t args(argv + w.woptind, argv + argc);
// Establish appropriate defaults for unspecified options.
// Establish appropriate defaults.
if (hist_cmd == HIST_NOOP) hist_cmd = HIST_SEARCH;
if (!history_search_type_defined) {
if (hist_cmd == HIST_SEARCH) search_type = HISTORY_SEARCH_TYPE_CONTAINS;
@ -2936,7 +2964,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, with_time, streams)) {
if (!history->search(search_type, args, show_time, streams)) {
status = STATUS_BUILTIN_ERROR;
}
break;
@ -2946,7 +2974,7 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
// this time we expect the non-exact deletions to be handled only by the history
// function's interactive delete feature.
if (search_type != HISTORY_SEARCH_TYPE_EXACT) {
streams.err.append_format(_(L"builtin history --delete only supports --exact\n"));
streams.err.append_format(_(L"builtin history delete only supports --exact\n"));
status = STATUS_BUILTIN_ERROR;
break;
}
@ -2960,20 +2988,17 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
break;
}
case HIST_CLEAR: {
CHECK_FOR_UNEXPECTED_HIST_OPTIONS(hist_cmd)
CHECK_FOR_UNEXPECTED_HIST_ARGS(hist_cmd)
history->clear();
history->save();
break;
}
case HIST_MERGE: {
CHECK_FOR_UNEXPECTED_HIST_OPTIONS(hist_cmd)
CHECK_FOR_UNEXPECTED_HIST_ARGS(hist_cmd)
history->incorporate_external_changes();
break;
}
case HIST_SAVE: {
CHECK_FOR_UNEXPECTED_HIST_OPTIONS(hist_cmd)
CHECK_FOR_UNEXPECTED_HIST_ARGS(hist_cmd)
history->save();
break;

View file

@ -1,7 +1,24 @@
history: you cannot use any options with clear command
history: you cannot use any options with merge command
history: Invalid combination of options,
you cannot do both 'search' and 'merge' in the same invocation
history: you cannot use any options with the clear command
history: you cannot use any options with the merge command
history: save command expected 0 args, got 1
history: you cannot use any options with save command
history: you cannot use any options with clear command
history: you cannot use any options with the save command
history: you cannot use any options with the clear command
history: merge command expected 0 args, got 1
history: clear command expected 0 args, got 2
history: you cannot use any options with the clear command
history: you cannot use any options with the merge command
history: save command expected 0 args, got 1
history: you cannot use any options with the clear command
history: you cannot use any options with the merge command
history: Invalid combination of options,
you cannot do both 'search' and 'merge' in the same invocation
history: you cannot use any options with the save command
history: you cannot use any options with the clear command
history: merge command expected 0 args, got 1
history: clear command expected 0 args, got 2
history: you cannot use any options with the save command
history: you cannot use any options with the merge command

View file

@ -43,15 +43,6 @@ expect_prompt -re {start2\r\necho start1; builtin history; echo end1\r\nend2\r\n
puts stderr "first history command not detected as expected"
}
# ==========
# Verify asking for two different actions produces an error.
send "builtin history --search --merge\r"
expect_prompt -re {\r\nYou cannot do both 'search' and 'merge' in the same 'history' invocation\r\n} {
puts "invalid attempt at multiple history commands detected"
} unmatched {
puts stderr "invalid attempt at multiple history commands not detected"
}
# ==========
# The following tests verify the behavior of the history function.
# ==========

View file

@ -1,6 +1,5 @@
empty history detected as expected
first history command detected as expected
invalid attempt at multiple history commands detected
history function explicit search succeeded
history function implicit search succeeded
history function implicit search with timestamps succeeded

View file

@ -1,13 +1,44 @@
# Verify that specifying unexpected options or arguments results in an error.
# First using the legacy, now deprecated, long options to specify a
# subcommand.
# First with the history function.
history --search --merge
history --clear --contains
history --merge -t
history --save xyz
# Now with the history builtin.
builtin history --save --prefix
builtin history --clear --with-time
builtin history --merge xyz
builtin history --clear abc def
# Now do a history command that should succeed.
builtin history --merge
# Put a blank line in the stderr output to separate the above sequence from
# the following sequence of tests.
echo >&2
# Now using the preferred subcommand form. Note that we support flags before
# or after the subcommand name so test both variants.
# First with the history function.
history clear --contains
history merge -t
history save xyz
history --prefix clear
history --with-time merge
echo >&2
# Now with the history builtin.
builtin history --search --merge
builtin history save --prefix
builtin history clear --with-time
builtin history merge xyz
builtin history clear abc def
builtin history --contains save
builtin history -t merge
# Now do a history command that should succeed so we exit with a zero,
# success, status.
builtin history save