mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-30 14:53:11 +00:00
17dff8c569
Rewrite the `abbr` function to store each abbreviation in a separate variable. This greatly improves the efficiency. For the common case it is 5x faster. For pathological cases it is upwards of 100x faster. Most people should be able to unconditionally define abbreviations in their config.fish without a noticable slow down. Fixes #4048
206 lines
6.8 KiB
Fish
206 lines
6.8 KiB
Fish
function abbr_old --description "Manage abbreviations using old fish 2.x scheme."
|
|
# parse arguments
|
|
set -l mode
|
|
set -l mode_flag # the flag that was specified, for better errors
|
|
set -l mode_arg
|
|
set -l needs_arg no
|
|
while set -q argv[1]
|
|
set -l new_mode
|
|
switch $argv[1]
|
|
case '-h' '--help'
|
|
__fish_print_help abbr
|
|
return 0
|
|
case '-a' '--add'
|
|
set new_mode add
|
|
set needs_arg multi
|
|
case '-r' '--rename'
|
|
set new_mode rename
|
|
set needs_arg double
|
|
case '-e' '--erase'
|
|
set new_mode erase
|
|
set needs_arg single
|
|
case '-l' '--list'
|
|
set new_mode list
|
|
case '-s' '--show'
|
|
set new_mode show
|
|
case '--'
|
|
set -e argv[1]
|
|
break
|
|
case '-*'
|
|
printf ( _ "%s: invalid option -- %s\n" ) abbr $argv[1] >&2
|
|
return 1
|
|
case '*'
|
|
break
|
|
end
|
|
if test -n "$mode" -a -n "$new_mode"
|
|
# we're trying to set two different modes
|
|
printf ( _ "%s: %s cannot be specified along with %s\n" ) abbr $argv[1] $mode_flag >&2
|
|
return 1
|
|
end
|
|
set mode $new_mode
|
|
set mode_flag $argv[1]
|
|
set -e argv[1]
|
|
end
|
|
|
|
# If run with no options, treat it like --add if we have an argument, or
|
|
# --show if we do not have an argument
|
|
if not set -q mode[1]
|
|
if set -q argv[1]
|
|
set mode add
|
|
set needs_arg multi
|
|
else
|
|
set mode show
|
|
end
|
|
end
|
|
|
|
if test $needs_arg = single
|
|
set mode_arg $argv[1]
|
|
set needs_arg no
|
|
set -e argv[1]
|
|
else if test $needs_arg = double
|
|
# Pull the two parameters from argv.
|
|
# * leave argv non-empty, if there are more than two arguments
|
|
# * leave needs_arg set to double if there is not enough arguments
|
|
if set -q argv[1]
|
|
set param1 $argv[1]
|
|
set -e argv[1]
|
|
if set -q argv[1]
|
|
set param2 $argv[1]
|
|
set needs_arg no
|
|
set -e argv[1]
|
|
end
|
|
end
|
|
else if test $needs_arg = multi
|
|
set mode_arg $argv
|
|
set needs_arg no
|
|
set -e argv
|
|
end
|
|
if test $needs_arg != no
|
|
printf ( _ "%s: option requires an argument -- %s\n" ) abbr $mode_flag >&2
|
|
return 1
|
|
end
|
|
|
|
# none of our modes want any excess arguments
|
|
if set -q argv[1]
|
|
printf ( _ "%s: Unexpected argument -- %s\n" ) abbr $argv[1] >&2
|
|
return 1
|
|
end
|
|
|
|
switch $mode
|
|
case 'add'
|
|
# Convert from old "key=value" syntax
|
|
# TODO: This should be removed later
|
|
if not set -q mode_arg[2]
|
|
and string match -qr '^[^ ]+=' -- $mode_arg
|
|
set mode_arg (string split "=" -- $mode_arg)
|
|
end
|
|
|
|
# Bail out early if the exact abbr is already in
|
|
set -q fish_user_abbreviations
|
|
and contains -- "$mode_arg" $fish_user_abbreviations
|
|
and return 0
|
|
|
|
set -l key $mode_arg[1]
|
|
set -e mode_arg[1]
|
|
set -l value "$mode_arg"
|
|
# Because we later store "$key $value", there can't be any spaces in the key
|
|
if string match -q "* *" -- $key
|
|
printf ( _ "%s: abbreviation cannot have spaces in the key\n" ) abbr >&2
|
|
return 1
|
|
end
|
|
if test -z "$value"
|
|
printf ( _ "%s: abbreviation must have a value\n" ) abbr >&2
|
|
return 1
|
|
end
|
|
if set -l idx (__fish_abbr_get_by_key $key)
|
|
# erase the existing abbreviation
|
|
set -e fish_user_abbreviations[$idx]
|
|
end
|
|
if not set -q fish_user_abbreviations
|
|
# initialize as a universal variable, so we can skip the -U later
|
|
# and therefore work properly if someone sets this as a global variable
|
|
set -U fish_user_abbreviations
|
|
end
|
|
set fish_user_abbreviations $fish_user_abbreviations "$key $value"
|
|
return 0
|
|
|
|
case 'rename'
|
|
set -l old_name $param1
|
|
set -l new_name $param2
|
|
|
|
# if the target name already exists, throw an error
|
|
if set -l idx (__fish_abbr_get_by_key $new_name)
|
|
printf ( _ "%s: abbreviation '%s' already exists, cannot rename\n" ) abbr $new_name >&2
|
|
return 2
|
|
end
|
|
|
|
# Because we later store "$key $value", there can't be any spaces in the key
|
|
if string match -q "* *" -- $new_name
|
|
printf ( _ "%s: abbreviation cannot have spaces in the key\n" ) abbr >&2
|
|
return 1
|
|
end
|
|
|
|
set -l idx (__fish_abbr_get_by_key $old_name)
|
|
or begin
|
|
printf ( _ "%s: no such abbreviation '%s'\n" ) abbr $old_name >&2
|
|
return 2
|
|
end
|
|
|
|
set -l value (string split " " -m 1 -- $fish_user_abbreviations[$idx])[2]
|
|
set fish_user_abbreviations[$idx] "$new_name $value"
|
|
return 0
|
|
|
|
case 'erase'
|
|
if set -l idx (__fish_abbr_get_by_key $mode_arg)
|
|
set -e fish_user_abbreviations[$idx]
|
|
return 0
|
|
else
|
|
printf ( _ "%s: no such abbreviation '%s'\n" ) abbr $mode_arg >&2
|
|
return 2
|
|
end
|
|
|
|
case 'show'
|
|
for i in $fish_user_abbreviations
|
|
set -l opt_double_dash
|
|
set -l kv (string split " " -m 1 -- $i)
|
|
set -l key $kv[1]
|
|
set -l value $kv[2]
|
|
|
|
# Check to see if either key or value has a leading dash
|
|
# If so, we need to write --
|
|
string match -q -- '-*' $key $value
|
|
and set opt_double_dash '--'
|
|
echo abbr $opt_double_dash (string escape -- $key $value)
|
|
end
|
|
return 0
|
|
|
|
case 'list'
|
|
for i in $fish_user_abbreviations
|
|
set -l key (string split " " -m 1 -- $i)[1]
|
|
printf "%s\n" $key
|
|
end
|
|
return 0
|
|
end
|
|
end
|
|
|
|
function __fish_abbr_get_by_key
|
|
if not set -q argv[1]
|
|
echo "__fish_abbr_get_by_key: expected one argument, got none" >&2
|
|
return 2
|
|
end
|
|
|
|
set -q fish_user_abbreviations
|
|
or return 1
|
|
|
|
# Going through all entries is still quicker than calling `seq`
|
|
set -l keys
|
|
for kv in $fish_user_abbreviations
|
|
# If this does not match, we have screwed up before and the error should be reported
|
|
set keys $keys (string split " " -m 1 -- $kv)[1]
|
|
end
|
|
if set -l idx (contains -i -- $argv[1] $keys)
|
|
echo $idx
|
|
return 0
|
|
end
|
|
return 1
|
|
end
|