fish-shell/share/functions/abbr.fish
Radomír Bosák 1fbcb1ee9d Add the possibility to rename abbreviations
The abbr function doesn't have the possiblity to rename abbreviations.
You have to delete the old one and create a new one. This commit adds
this functionality and uses the syntax:

abbr -r OLD_KEY NEW_KEY

Fixes #2155.
2016-12-01 14:42:20 -08:00

200 lines
6.7 KiB
Fish

function abbr --description "Manage abbreviations"
# 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
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
# 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