mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-14 14:03:58 +00:00
e9b5505169
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
220 lines
7.8 KiB
Fish
220 lines
7.8 KiB
Fish
#
|
|
# 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 history
|
|
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]
|
|
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 --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
|
|
builtin history --help
|
|
return
|
|
case -t --show-time '--show-time=*' --with-time '--with-time=*'
|
|
set show_time $argv[1]
|
|
case -p --prefix
|
|
set search_mode --prefix
|
|
case -c --contains
|
|
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
|
|
|
|
# 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
|
|
|
|
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"
|
|
|
|
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 $max_count -- $argv | eval $pager
|
|
else
|
|
builtin history search $search_mode $show_time $max_count -- $argv
|
|
end
|
|
|
|
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
|
|
return 1
|
|
end
|
|
|
|
test -z "$search_mode"
|
|
and set search_mode "--exact"
|
|
|
|
if test $search_mode = "--exact"
|
|
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 $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)
|
|
printf "[%s] %s\n" $i $found_items[$i]
|
|
end
|
|
echo ""
|
|
echo "Enter nothing to cancel the delete, or"
|
|
echo "Enter one or more of the entry IDs separated by a space, or"
|
|
echo "Enter \"all\" to delete all the matching entries."
|
|
echo ""
|
|
read --local --prompt "echo 'Delete which entries? > '" choice
|
|
echo ''
|
|
|
|
if test -z "$choice"
|
|
printf "Cancelling the delete!\n"
|
|
return
|
|
end
|
|
|
|
if test "$choice" = "all"
|
|
printf "Deleting all matching entries!\n"
|
|
builtin history delete $search_mode -- $argv
|
|
builtin history save
|
|
return
|
|
end
|
|
|
|
for i in (string split " " -- $choice)
|
|
if test -z "$i"
|
|
or not string match -qr '^[1-9][0-9]*$' -- $i
|
|
or test $i -gt $found_items_count
|
|
printf "Ignoring invalid history entry ID \"%s\"\n" $i
|
|
continue
|
|
end
|
|
|
|
printf "Deleting history entry %s: \"%s\"\n" $i $found_items[$i]
|
|
builtin history delete "$found_items[$i]"
|
|
end
|
|
builtin history save
|
|
end
|
|
|
|
case save # save our interactive command history to the persistent history
|
|
__fish_unexpected_hist_args $argv
|
|
and return 1
|
|
|
|
builtin history save -- $argv
|
|
|
|
case merge # merge the persistent interactive command history with our history
|
|
__fish_unexpected_hist_args $argv
|
|
and return 1
|
|
|
|
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
|
|
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
|