mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 21:44:16 +00:00
ee1d310651
* Implement `history search --reverse` It should be possible to have `history search` output ordered oldest to newest like nearly every other shell including bash, ksh, zsh, and csh. We can't make this the default because too many people expect the current behavior. This simply makes it possible for people to define their own abbreviations or functions that provide behavior they are likely used to if they are transitioning to fish from another shell. This also fixes a bug in the `history` function with respect to how it handles the `-n` / `--max` flag. Fixes #4354 * Fix comment for format_history_record()
190 lines
6.8 KiB
Fish
190 lines
6.8 KiB
Fish
#
|
|
# Wrap the builtin history command to provide additional functionality.
|
|
#
|
|
function __fish_unexpected_hist_args --no-scope-shadowing
|
|
if test -n "$search_mode"
|
|
or set -q show_time[1]
|
|
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 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 history
|
|
|
|
set -l options --exclusive 'c,e,p' --exclusive 'S,D,M,V,C' --exclusive 't,T'
|
|
set -a options 'h/help' 'c/contains' 'e/exact' 'p/prefix'
|
|
set -a options 'C/case-sensitive' 'R/reverse' 'z/null' 't/show-time=?' 'n#max'
|
|
# This long option is deprecated and here solely for legacy compatibility. People should use
|
|
# -t or --show-time now.
|
|
set -a options 'T-with-time=?'
|
|
# The following options are deprecated and will be removed in the next major release.
|
|
# Note that they do not have usable short flags.
|
|
set -a options 'S-search' 'D-delete' 'M-merge' 'V-save' 'X-clear'
|
|
argparse -n $cmd $options -- $argv
|
|
or return
|
|
|
|
if set -q _flag_help
|
|
__fish_print_help history
|
|
return 0
|
|
end
|
|
|
|
set -l hist_cmd
|
|
set -l show_time
|
|
|
|
set -l max_count
|
|
set -q _flag_max
|
|
set max_count -n$_flag_max
|
|
|
|
set -q _flag_with_time
|
|
and set -l _flag_show_time $_flag_with_time
|
|
if set -q _flag_show_time[1]
|
|
set show_time --show-time=$_flag_show_time
|
|
else if set -q _flag_show_time
|
|
set show_time --show-time
|
|
end
|
|
|
|
set -q _flag_prefix
|
|
and set -l search_mode --prefix
|
|
set -q _flag_contains
|
|
and set -l search_mode --contains
|
|
set -q _flag_exact
|
|
and set -l search_mode --exact
|
|
|
|
if set -q _flag_delete
|
|
set hist_cmd delete
|
|
else if set -q _flag_save
|
|
set hist_cmd save
|
|
else if set -q _flag_clear
|
|
set hist_cmd clear
|
|
else if set -q _flag_search
|
|
set hist_cmd search
|
|
else if set -q _flag_merge
|
|
set hist_cmd merge
|
|
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]
|
|
if contains $argv[1] 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"
|
|
|
|
if isatty stdout
|
|
set -l pager less
|
|
set -q PAGER
|
|
and set pager $PAGER
|
|
builtin history search $search_mode $show_time $max_count $_flag_case_sensitive $_flag_reverse $_flag_null -- $argv | eval $pager
|
|
else
|
|
builtin history search $search_mode $show_time $max_count $_flag_case_sensitive $_flag_reverse $_flag_null -- $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 "--contains"
|
|
|
|
if test $search_mode = "--exact"
|
|
builtin history delete $search_mode $_flag_case_sensitive $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 $_flag_case_sensitive --null -- $argv | while read -lz x
|
|
set found_items $found_items $x
|
|
end
|
|
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"
|
|
for item in $found_items
|
|
builtin history delete --exact --case-sensitive -- $item
|
|
end
|
|
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 --exact --case-sensitive -- "$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
|