mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-28 20:34:07 +08:00
8e8e63144b
The usage is still the same, but it's a lot more robust, and also no longer assumes $fish_user_abbreviations must be a universal variable. This also fixes the unexpected error output when calling `abbr -a` with no existing abbreviations. Calling `abbr -a` with an abbreviation that already exists now silently overwrites the abbreviation, just like `function` and `bind` do, instead of complaining.
158 lines
3.6 KiB
Fish
158 lines
3.6 KiB
Fish
function abbr --description "Manage abbreviations"
|
|
if not set -q argv[1]
|
|
__fish_print_help abbr
|
|
return 1
|
|
end
|
|
|
|
# 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]
|
|
if test $needs_arg = yes
|
|
set mode_arg $argv[1]
|
|
set needs_arg no
|
|
else
|
|
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 yes
|
|
case '-r' '--remove'
|
|
set new_mode remove
|
|
set needs_arg yes
|
|
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]
|
|
end
|
|
set -e argv[1]
|
|
end
|
|
if test $needs_arg = yes
|
|
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'
|
|
set -l key
|
|
set -l value
|
|
__fish_abbr_parse_entry $mode_arg key value
|
|
# ensure the key contains at least one non-space character
|
|
set -l IFS \n\ \t
|
|
printf '%s' $key | read -lz key_ _
|
|
if test -z "$key_"
|
|
printf ( _ "%s: abbreviation must have a non-empty 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 $mode_arg
|
|
return 0
|
|
|
|
case 'remove'
|
|
set -l key
|
|
__fish_abbr_parse_entry $mode_arg key
|
|
if set -l idx (__fish_abbr_get_by_key $key)
|
|
set -e fish_user_abbreviations[$idx]
|
|
return 0
|
|
else
|
|
printf ( _ "%s: no such abbreviation '%s'\n" ) abbr $key >&2
|
|
return 2
|
|
end
|
|
|
|
case 'show'
|
|
for i in $fish_user_abbreviations
|
|
echo abbr -a \'$i\'
|
|
end
|
|
return 0
|
|
|
|
case 'list'
|
|
for i in $fish_user_abbreviations
|
|
set -l key
|
|
__fish_abbr_parse_entry $i key
|
|
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 -l count (count $fish_user_abbreviations)
|
|
if test $count -gt 0
|
|
set -l key
|
|
__fish_abbr_parse_entry $argv[1] key
|
|
set -l IFS \n # ensure newline splitting is enabled
|
|
for i in (seq $count)
|
|
set -l key_i
|
|
__fish_abbr_parse_entry $fish_user_abbreviations[$i] key_i
|
|
if test "$key" = "$key_i"
|
|
echo $i
|
|
return 0
|
|
end
|
|
end
|
|
end
|
|
return 1
|
|
end
|
|
|
|
function __fish_abbr_parse_entry -S -a __input __key __value
|
|
if test -z "$__key"
|
|
set __key _
|
|
end
|
|
if test -z "$__value"
|
|
set __value _
|
|
end
|
|
switch $__input
|
|
case '=*'
|
|
# read will skip any leading ='s, but we don't want that
|
|
set __input " $__input"
|
|
set __key _
|
|
end
|
|
# use read -z to avoid splitting on newlines
|
|
# I think we can safely assume there will be no NULs in the input
|
|
set -l IFS =
|
|
printf "%s" $__input | read -z $__key $__value
|
|
return 0
|
|
end
|