history: Allow deleting ranges

This allows giving a range like "5..7".

It works in combination with more (including overlapping) ranges or
single indices.

Fixes #9736

(cherry picked from commit 65769bf8c8)
This commit is contained in:
Fabian Boehm 2023-06-10 15:23:29 +02:00 committed by David Adam
parent 446a41e23a
commit c54d48f3f9
3 changed files with 41 additions and 14 deletions

View File

@ -29,7 +29,7 @@ The following operations (sub-commands) are available:
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 unless you use the ``--reverse`` flag. 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. 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 unless you use the ``--reverse`` flag. 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.
**delete** **delete**
Deletes history items. The ``--contains`` search option will be used if you don't specify a different search option. If you don't specify ``--exact`` 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 ``--exact --case-sensitive`` deletion. Deletes history items. The ``--contains`` search option will be used if you don't specify a different search option. If you don't specify ``--exact`` 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, or an ID range 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 ``--exact --case-sensitive`` deletion.
**merge** **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. 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.

View File

@ -132,12 +132,13 @@ function history --description "display or manipulate interactive command histor
for i in (seq $found_items_count) for i in (seq $found_items_count)
printf "[%s] %s\n" $i $found_items[$i] printf "[%s] %s\n" $i $found_items[$i]
end end
echo "" echo
echo "Enter nothing to cancel the delete, or" echo "Enter nothing to cancel the delete, or"
echo "Enter one or more of the entry IDs separated by a space, or" echo "Enter one or more of the entry IDs or ranges like '5..12', separated by a space."
echo "Enter \"all\" to delete all the matching entries." echo "For example '7 10..15 35 788..812'."
echo "" echo "Enter 'all' to delete all the matching entries."
read --local --prompt "echo 'Delete which entries? > '" choice echo
read --local --prompt "echo 'Delete which entries? '" choice
echo '' echo ''
if test -z "$choice" if test -z "$choice"
@ -154,16 +155,42 @@ function history --description "display or manipulate interactive command histor
return return
end end
set -l choices
for i in (string split " " -- $choice) for i in (string split " " -- $choice)
if test -z "$i" # Expand ranges like 577..580
or not string match -qr '^[1-9][0-9]*$' -- $i if set -l inds (string match -rg '^([1-9][0-9]*)\.\.([1-9][0-9]*)' -- $i)
or test $i -gt $found_items_count if test $inds[1] -gt $found_items_count
printf "Ignoring invalid history entry ID \"%s\"\n" $i or test $inds[1] -gt $inds[2]
printf (_ "Ignoring invalid history entry ID \"%s\"\n") $i
continue continue
end end
printf "Deleting history entry %s: \"%s\"\n" $i $found_items[$i] set -l indexes (seq $inds[1] 1 $inds[2])
builtin history delete --exact --case-sensitive -- "$found_items[$i]" if set -q indexes[1]
set -a choices $indexes
end
continue
end
if string match -qr '^[1-9][0-9]*$' -- $i
and test $i -lt $found_items_count
set -a choices $i
else
printf (_ "Ignoring invalid history entry ID \"%s\"\n") $i
continue
end
end
if not set -q choices[1]
return 1
end
set choices (path sort -u -- $choices)
echo Deleting choices: $choices
for x in $choices
printf "Deleting history entry %s: \"%s\"\n" $x $found_items[$x]
builtin history delete --exact --case-sensitive -- "$found_items[$x]"
end end
builtin history save builtin history save
end end

View File

@ -111,9 +111,9 @@ expect_re("history delete -p 'echo hello'\r\n")
expect_re("\[1\] echo hello AGAIN\r\n") expect_re("\[1\] echo hello AGAIN\r\n")
expect_re("\[2\] echo hello again\r\n\r\n") expect_re("\[2\] echo hello again\r\n\r\n")
expect_re( expect_re(
'Enter nothing to cancel.*\r\nEnter "all" to delete all the matching entries\.\r\n' 'Enter nothing to cancel the delete, or\r\nEnter one or more of the entry IDs or ranges like \'5..12\', separated by a space.\r\nFor example \'7 10..15 35 788..812\'.\r\nEnter \'all\' to delete all the matching entries.\r\n'
) )
expect_re("Delete which entries\? >") expect_re("Delete which entries\? ")
sendline("1") sendline("1")
expect_prompt('Deleting history entry 1: "echo hello AGAIN"\r\n') expect_prompt('Deleting history entry 1: "echo hello AGAIN"\r\n')