mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-25 20:33:08 +00:00
rewrite abbr
function
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
This commit is contained in:
parent
7e0833c1e0
commit
17dff8c569
13 changed files with 561 additions and 322 deletions
|
@ -12,6 +12,7 @@ This section is for changes merged to the `major` branch that are not also merge
|
||||||
|
|
||||||
## Other significant changes
|
## Other significant changes
|
||||||
- `read` now requires at least one var name (#4220).
|
- `read` now requires at least one var name (#4220).
|
||||||
|
- `abbr` has been reimplemented to be faster. This means the old `fish_user_abbreviations` variable is ignored (#4048).
|
||||||
|
|
||||||
|
|
||||||
# fish 2.7b1
|
# fish 2.7b1
|
||||||
|
|
|
@ -2,54 +2,57 @@
|
||||||
|
|
||||||
\subsection abbr-synopsis Synopsis
|
\subsection abbr-synopsis Synopsis
|
||||||
\fish{synopsis}
|
\fish{synopsis}
|
||||||
abbr --add word phrase...
|
abbr --add [SCOPE] WORD EXPANSION
|
||||||
abbr --rename word new_word
|
abbr --erase word
|
||||||
|
abbr --rename [SCOPE] OLD_WORD NEW_WORD
|
||||||
abbr --show
|
abbr --show
|
||||||
abbr --list
|
abbr --list
|
||||||
abbr --erase word
|
|
||||||
\endfish
|
\endfish
|
||||||
|
|
||||||
\subsection abbr-description Description
|
\subsection abbr-description Description
|
||||||
|
|
||||||
`abbr` manipulates the list of abbreviations that fish will expand.
|
Abbreviations are user-defined character sequences or words that are replaced with longer phrases after they are entered. For example, a frequently-run command such as `git checkout` can be abbreviated to `gco`. After entering `gco` and pressing @key{Space} or @key{Enter}, the full text `git checkout` will appear in the command line. The `abbr` command manipulates those abbreviations.
|
||||||
|
|
||||||
Abbreviations are user-defined character sequences or words that are replaced with longer phrases after they are entered. For example, a frequently-run command such as `git checkout` can be abbreviated to `gco`. After entering `gco` and pressing @key{Space} or @key{Enter}, the full text `git checkout` will appear in the command line.
|
Each abbreviation is stored in its own global or universal variable. The name consists of the prefix `_fish_abbr_` followed by the WORD after being transformed by `string escape style=var`. The WORD cannot contain a space but all other characters are legal.
|
||||||
|
|
||||||
Abbreviations are stored in a variable named `fish_user_abbreviations`. This is automatically created as a universal variable the first time an abbreviation is created. If you want your abbreviations to be private to a particular fish session you can put the following in your *~/.config/fish/config.fish* file before you define your first abbrevation:
|
Defining an abbreviation with global scope is slightly faster than universal scope (which is the default). But in general you'll only want to use the global scope when defining abbreviations in a startup script like `~/.config/fish/config.fish` like this:
|
||||||
|
|
||||||
\fish
|
\fish
|
||||||
if status --is-interactive
|
if status --is-interactive
|
||||||
set -g fish_user_abbreviations
|
abbr --add --global first 'echo my first abbreviation'
|
||||||
abbr --add first 'echo my first abbreviation'
|
abbr --add --global second 'echo my second abbreviation'
|
||||||
abbr --add second 'echo my second abbreviation'
|
abbr --add --global gco git checkout
|
||||||
# etcetera
|
# etcetera
|
||||||
end
|
end
|
||||||
\endfish
|
\endfish
|
||||||
|
|
||||||
You can create abbreviations directly on the command line and they will be saved automatically and made visible to other fish sessions if `fish_user_abbreviations` is a universal variable. If you keep the variable as universal, `abbr --add` statements in <a href="tutorial.html#tut_startup">config.fish</a> will do nothing but slow down startup slightly.
|
You can create abbreviations interactively and they will be visible to other fish sessions if you use the `-U` or `--universal` flag or don't explicitly specify the scope and the abbreviation isn't already defined with global scope. If you want it to be visible only to the current shell use the `-g` or `--global` flag.
|
||||||
|
|
||||||
\subsection abbr-options Options
|
\subsection abbr-options Options
|
||||||
|
|
||||||
The following parameters are available:
|
The following options are available:
|
||||||
|
|
||||||
- `-a WORD PHRASE` or `--add WORD PHRASE` Adds a new abbreviation, causing WORD to be expanded to PHRASE.
|
- `-a WORD EXPANSION` or `--add WORD EXPANSION` Adds a new abbreviation, causing WORD to be expanded to PHRASE. You can optionally specify `-g` or `--global` to avoid the overhead of universal variables at the expense of not having the definition being immediately visible to other fish shells that are already running. If you don't specify global scope it default to universal. For clarity you can also specify `-U` or `--universal`.
|
||||||
|
|
||||||
- `-r WORD NEW_WORD` or `--rename WORD NEW_WORD` Renames an abbreviation, from WORD to NEW_WORD.
|
- `-r OLD_WORD NEW_WORD` or `--rename OLD_WORD NEW_WORD` Renames an abbreviation, from OLD_WORD to NEW_WORD.
|
||||||
|
|
||||||
- `-s` or `--show` Show all abbreviated words and their expanded phrases in a manner suitable for export and import.
|
- `-s` or `--show` Show all abbreviations in a manner suitable for export and import.
|
||||||
|
|
||||||
- `-l` or `--list` Lists all abbreviated words.
|
- `-l` or `--list` Lists all abbreviated words.
|
||||||
|
|
||||||
- `-e WORD` or `--erase WORD` Erase the abbreviation WORD.
|
- `-e WORD` or `--erase WORD` Erase the abbreviation WORD.
|
||||||
|
|
||||||
Note: fish version 2.1 supported `-a WORD=PHRASE`. This syntax is now deprecated but will still be converted.
|
|
||||||
|
|
||||||
\subsection abbr-example Examples
|
\subsection abbr-example Examples
|
||||||
|
|
||||||
\fish
|
\fish
|
||||||
abbr -a gco git checkout
|
abbr -a -g gco git checkout
|
||||||
\endfish
|
\endfish
|
||||||
Add a new abbreviation where `gco` will be replaced with `git checkout`.
|
Add a new abbreviation where `gco` will be replaced with `git checkout` global to the current shell. This abbreviation will not be automatically visible to other shells unless the same command is run in those shells (such as when executing the commands in config.fish).
|
||||||
|
|
||||||
|
\fish
|
||||||
|
abbr -a -U l less
|
||||||
|
\endfish
|
||||||
|
Add a new abbreviation where `l` will be replaced with `less` univeral so all shells. Note that you omit the `-U` since it is the default.
|
||||||
|
|
||||||
\fish
|
\fish
|
||||||
abbr -r gco gch
|
abbr -r gco gch
|
||||||
|
|
|
@ -4,6 +4,15 @@
|
||||||
# This function is called by the __fish_on_interactive function, which is defined in config.fish.
|
# This function is called by the __fish_on_interactive function, which is defined in config.fish.
|
||||||
#
|
#
|
||||||
function __fish_config_interactive -d "Initializations that should be performed when entering interactive mode"
|
function __fish_config_interactive -d "Initializations that should be performed when entering interactive mode"
|
||||||
|
if not set -q __fish_init_3_x
|
||||||
|
# Perform transitions relevant to going from fish 2.x to 3.x.
|
||||||
|
|
||||||
|
# Migrate old universal abbreviations to the new scheme.
|
||||||
|
abbr_old | source
|
||||||
|
|
||||||
|
set -U __fish_init_3_x
|
||||||
|
end
|
||||||
|
|
||||||
# Make sure this function is only run once.
|
# Make sure this function is only run once.
|
||||||
if set -q __fish_config_interactive_done
|
if set -q __fish_config_interactive_done
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,206 +1,201 @@
|
||||||
function abbr --description "Manage abbreviations"
|
function abbr --description "Manage abbreviations using new fish 3.0 scheme."
|
||||||
# parse arguments
|
set -l options --stop-nonopt --exclusive 'a,r,e,l,s' --exclusive 'g,U'
|
||||||
set -l mode
|
set options $options 'h/help' 'a/add' 'r/rename' 'e/erase' 'l/list' 's/show'
|
||||||
set -l mode_flag # the flag that was specified, for better errors
|
set options $options 'g/global' 'U/universal'
|
||||||
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
|
argparse -n $cmd $options -- $argv
|
||||||
# --show if we do not have an argument
|
or return
|
||||||
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
|
if set -q _flag_help
|
||||||
set mode_arg $argv[1]
|
__fish_print_help abbr
|
||||||
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
|
return 0
|
||||||
end
|
end
|
||||||
return 1
|
|
||||||
|
# If run with no options, treat it like --add if we have arguments, or
|
||||||
|
# --show if we do not have any arguments.
|
||||||
|
set -l _flag_add
|
||||||
|
set -l _flag_show
|
||||||
|
if not set -q _flag_add[1]
|
||||||
|
and not set -q _flag_rename[1]
|
||||||
|
and not set -q _flag_erase[1]
|
||||||
|
and not set -q _flag_list[1]
|
||||||
|
and not set -q _flag_show[1]
|
||||||
|
if set -q argv[1]
|
||||||
|
set _flag_add --add
|
||||||
|
else
|
||||||
|
set _flag_show --show
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l abbr_scope
|
||||||
|
if set -q _flag_global
|
||||||
|
set abbr_scope --global
|
||||||
|
else if set -q _flag_universal
|
||||||
|
set abbr_scope --universal
|
||||||
|
end
|
||||||
|
|
||||||
|
if set -q _flag_add[1]
|
||||||
|
__fish_abbr_add $argv
|
||||||
|
return
|
||||||
|
else if set -q _flag_erase[1]
|
||||||
|
__fish_abbr_erase $argv
|
||||||
|
return
|
||||||
|
else if set -q _flag_rename[1]
|
||||||
|
__fish_abbr_rename $argv
|
||||||
|
return
|
||||||
|
else if set -q _flag_list[1]
|
||||||
|
__fish_abbr_list $argv
|
||||||
|
return
|
||||||
|
else if set -q _flag_show[1]
|
||||||
|
__fish_abbr_show $argv
|
||||||
|
return
|
||||||
|
else
|
||||||
|
printf ( _ "%s: Could not figure out what to do!\n" ) abbr >&2
|
||||||
|
return 127
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function __fish_abbr_add --no-scope-shadowing
|
||||||
|
if not set -q argv[2]
|
||||||
|
printf ( _ "%s %s: Requires at least two arguments\n" ) abbr --add >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# Because of the way abbreviations are expanded there can't be any spaces in the key.
|
||||||
|
set -l abbr_name $argv[1]
|
||||||
|
set -l escaped_abbr_name (string escape -- $abbr_name)
|
||||||
|
if string match -q "* *" -- $abbr_name
|
||||||
|
set -l msg ( _ "%s %s: Abbreviation %s cannot have spaces in the word\n" )
|
||||||
|
printf $msg abbr --add $escaped_abbr_name >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l abbr_val "$argv[2..-1]"
|
||||||
|
set -l abbr_var_name _fish_abbr_(string escape --style=var -- $abbr_name)
|
||||||
|
|
||||||
|
if not set -q $abbr_var_name
|
||||||
|
# We default to the universal scope if the user didn't explicitly specify a scope and the
|
||||||
|
# abbreviation isn't already defined.
|
||||||
|
set -q abbr_scope[1]
|
||||||
|
or set abbr_scope --universal
|
||||||
|
end
|
||||||
|
true # make sure the next `set` command doesn't leak the previous status
|
||||||
|
set $abbr_scope $abbr_var_name $abbr_val
|
||||||
|
end
|
||||||
|
|
||||||
|
function __fish_abbr_erase --no-scope-shadowing
|
||||||
|
if set -q argv[2]
|
||||||
|
printf ( _ "%s %s: Expected one argument\n" ) abbr --erase >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# Because of the way abbreviations are expanded there can't be any spaces in the key.
|
||||||
|
set -l abbr_name $argv[1]
|
||||||
|
set -l escaped_name (string escape -- $abbr_name)
|
||||||
|
if string match -q "* *" -- $abbr_old_name
|
||||||
|
set -l msg ( _ "%s %s: Abbreviation %s cannot have spaces in the word\n" )
|
||||||
|
printf $msg abbr --erase $escaped_name >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l abbr_var_name _fish_abbr_(string escape --style=var -- $abbr_name)
|
||||||
|
|
||||||
|
if not set -q $abbr_var_name
|
||||||
|
printf ( _ "%s %s: No abbreviation named %s\n" ) abbr --erase $escaped_name >&2
|
||||||
|
return 121
|
||||||
|
end
|
||||||
|
|
||||||
|
set -e $abbr_var_name
|
||||||
|
end
|
||||||
|
|
||||||
|
function __fish_abbr_rename --no-scope-shadowing
|
||||||
|
if test (count $argv) -ne 2
|
||||||
|
printf ( _ "%s %s: Requires exactly two arguments\n" ) abbr --rename >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l old_name $argv[1]
|
||||||
|
set -l new_name $argv[2]
|
||||||
|
set -l escaped_old_name (string escape -- $old_name)
|
||||||
|
set -l escaped_new_name (string escape -- $new_name)
|
||||||
|
if string match -q "* *" -- $old_name
|
||||||
|
set -l msg ( _ "%s %s: Abbreviation %s cannot have spaces in the word\n" )
|
||||||
|
printf $msg abbr --rename $escaped_old_name >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
if string match -q "* *" -- $new_name
|
||||||
|
set -l msg ( _ "%s %s: Abbreviation %s cannot have spaces in the word\n" )
|
||||||
|
printf $msg abbr --rename $escaped_new_name >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l old_var_name _fish_abbr_(string escape --style=var -- $old_name)
|
||||||
|
set -l new_var_name _fish_abbr_(string escape --style=var -- $new_name)
|
||||||
|
|
||||||
|
if not set -q $old_var_name
|
||||||
|
printf ( _ "%s %s: No abbreviation named %s\n" ) abbr --rename $escaped_old_name >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
if set -q $new_var_name
|
||||||
|
set -l msg ( _ "%s %s: Abbreviation %s already exists, cannot rename %s\n" )
|
||||||
|
printf $msg abbr --rename $escaped_new_name $escaped_old_name >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l old_var_val $$old_var_name
|
||||||
|
|
||||||
|
if not set -q abbr_scope[1]
|
||||||
|
# User isn't forcing the scope so use the existing scope.
|
||||||
|
if set -ql $old_var_name
|
||||||
|
set abbr_scope --global
|
||||||
|
else
|
||||||
|
set abbr_scope --universal
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
set -e $old_var_name
|
||||||
|
set $abbr_scope $new_var_name $old_var_val
|
||||||
|
end
|
||||||
|
|
||||||
|
function __fish_abbr_list --no-scope-shadowing
|
||||||
|
if set -q argv[1]
|
||||||
|
printf ( _ "%s %s: Unexpected argument -- '%s'\n" ) abbr --erase $argv[1] >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
for var_name in (set --names)
|
||||||
|
string match -q '_fish_abbr_*' $var_name
|
||||||
|
or continue
|
||||||
|
|
||||||
|
set -l abbr_name (string unescape --style=var (string sub -s 12 $var_name))
|
||||||
|
echo $abbr_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function __fish_abbr_show --no-scope-shadowing
|
||||||
|
if set -q argv[1]
|
||||||
|
printf ( _ "%s %s: Unexpected argument -- '%s'\n" ) abbr --erase $argv[1] >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
for var_name in (set --names)
|
||||||
|
string match -q '_fish_abbr_*' $var_name
|
||||||
|
or continue
|
||||||
|
|
||||||
|
set -l abbr_var_name $var_name
|
||||||
|
set -l abbr_name (string unescape --style=var -- (string sub -s 12 $abbr_var_name))
|
||||||
|
set -l abbr_name (string escape --style=script -- $abbr_name)
|
||||||
|
set -l abbr_val $$abbr_var_name
|
||||||
|
set -l abbr_val (string escape --style=script -- $abbr_val)
|
||||||
|
|
||||||
|
if set -ql $abbr_var_name
|
||||||
|
printf 'abbr -a %s -- %s %s\n' -l $abbr_name $abbr_val
|
||||||
|
end
|
||||||
|
if set -qg $abbr_var_name
|
||||||
|
printf 'abbr -a %s -- %s %s\n' -g $abbr_name $abbr_val
|
||||||
|
end
|
||||||
|
if set -qU $abbr_var_name
|
||||||
|
printf 'abbr -a %s -- %s %s\n' -U $abbr_name $abbr_val
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
206
share/functions/abbr_old.fish
Normal file
206
share/functions/abbr_old.fish
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
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
|
34
src/env.cpp
34
src/env.cpp
|
@ -41,6 +41,7 @@
|
||||||
#include "env.h"
|
#include "env.h"
|
||||||
#include "env_universal_common.h"
|
#include "env_universal_common.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
#include "expand.h"
|
||||||
#include "fallback.h" // IWYU pragma: keep
|
#include "fallback.h" // IWYU pragma: keep
|
||||||
#include "fish_version.h"
|
#include "fish_version.h"
|
||||||
#include "history.h"
|
#include "history.h"
|
||||||
|
@ -187,7 +188,7 @@ void var_stack_t::push(bool new_scope) {
|
||||||
// i.e. not if it's just `begin; end` or "--no-scope-shadowing".
|
// i.e. not if it's just `begin; end` or "--no-scope-shadowing".
|
||||||
if (new_scope) {
|
if (new_scope) {
|
||||||
if (!(top_node == this->global_env)) {
|
if (!(top_node == this->global_env)) {
|
||||||
for (auto& var : top_node->env) {
|
for (auto &var : top_node->env) {
|
||||||
if (var.second.exportv) {
|
if (var.second.exportv) {
|
||||||
// This should copy var
|
// This should copy var
|
||||||
node->env.insert(var);
|
node->env.insert(var);
|
||||||
|
@ -603,7 +604,7 @@ static bool variable_is_colon_delimited_var(const wcstring &str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// React to modifying the given variable.
|
/// React to modifying the given variable.
|
||||||
static void react_to_variable_change(const wcstring &key) {
|
static void react_to_variable_change(const wchar_t *op, const wcstring &key) {
|
||||||
// Don't do any of this until `env_init()` has run. We only want to do this in response to
|
// Don't do any of this until `env_init()` has run. We only want to do this in response to
|
||||||
// variables set by the user; e.g., in a script like *config.fish* or interactively or as part
|
// variables set by the user; e.g., in a script like *config.fish* or interactively or as part
|
||||||
// of loading the universal variables for the first time.
|
// of loading the universal variables for the first time.
|
||||||
|
@ -631,37 +632,36 @@ static void react_to_variable_change(const wcstring &key) {
|
||||||
env_set_read_limit();
|
env_set_read_limit();
|
||||||
} else if (key == L"FISH_HISTORY") {
|
} else if (key == L"FISH_HISTORY") {
|
||||||
reader_change_history(history_session_id().c_str());
|
reader_change_history(history_session_id().c_str());
|
||||||
|
} else if (wcsncmp(key.c_str(), L"_fish_abbr_", wcslen(L"_fish_abbr_")) == 0) {
|
||||||
|
update_abbr_cache(op, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Universal variable callback function. This function makes sure the proper events are triggered
|
/// Universal variable callback function. This function makes sure the proper events are triggered
|
||||||
/// when an event occurs.
|
/// when an event occurs.
|
||||||
static void universal_callback(fish_message_type_t type, const wchar_t *name) {
|
static void universal_callback(fish_message_type_t type, const wchar_t *name) {
|
||||||
const wchar_t *str = NULL;
|
const wchar_t *op;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SET:
|
case SET:
|
||||||
case SET_EXPORT: {
|
case SET_EXPORT: {
|
||||||
str = L"SET";
|
op = L"SET";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ERASE: {
|
case ERASE: {
|
||||||
str = L"ERASE";
|
op = L"ERASE";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str) {
|
react_to_variable_change(op, name);
|
||||||
vars_stack().mark_changed_exported();
|
vars_stack().mark_changed_exported();
|
||||||
|
|
||||||
event_t ev = event_t::variable_event(name);
|
event_t ev = event_t::variable_event(name);
|
||||||
ev.arguments.push_back(L"VARIABLE");
|
ev.arguments.push_back(L"VARIABLE");
|
||||||
ev.arguments.push_back(str);
|
ev.arguments.push_back(op);
|
||||||
ev.arguments.push_back(name);
|
ev.arguments.push_back(name);
|
||||||
event_fire(&ev);
|
event_fire(&ev);
|
||||||
}
|
|
||||||
|
|
||||||
if (name) react_to_variable_change(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make sure the PATH variable contains something.
|
/// Make sure the PATH variable contains something.
|
||||||
|
@ -1130,7 +1130,7 @@ int env_set(const wcstring &key, const wchar_t *val, env_mode_flags_t var_mode)
|
||||||
event_fire(&ev);
|
event_fire(&ev);
|
||||||
// debug( 1, L"env_set: return from event firing" );
|
// debug( 1, L"env_set: return from event firing" );
|
||||||
|
|
||||||
react_to_variable_change(key);
|
react_to_variable_change(L"SET", key);
|
||||||
return ENV_OK;
|
return ENV_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1203,7 +1203,7 @@ int env_remove(const wcstring &key, int var_mode) {
|
||||||
if (is_exported) vars_stack().mark_changed_exported();
|
if (is_exported) vars_stack().mark_changed_exported();
|
||||||
}
|
}
|
||||||
|
|
||||||
react_to_variable_change(key);
|
react_to_variable_change(L"ERASE", key);
|
||||||
|
|
||||||
return !erased;
|
return !erased;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1572,37 +1572,39 @@ bool fish_xdm_login_hack_hack_hack_hack(std::vector<std::string> *cmds, int argc
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<const wcstring, const wcstring> abbreviations;
|
||||||
|
void update_abbr_cache(const wchar_t *op, const wcstring varname) {
|
||||||
|
wcstring abbr;
|
||||||
|
if (!unescape_string(varname.substr(wcslen(L"_fish_abbr_")), &abbr, 0, STRING_STYLE_VAR)) {
|
||||||
|
debug(1, L"Abbreviation var '%ls' is not correctly encoded, ignoring it.", varname.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
abbreviations.erase(abbr);
|
||||||
|
if (wcscmp(op, L"ERASE") != 0) {
|
||||||
|
const env_var_t expansion = env_get_string(varname);
|
||||||
|
if (!expansion.missing_or_empty()) {
|
||||||
|
abbreviations.emplace(std::make_pair(abbr, expansion));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool expand_abbreviation(const wcstring &src, wcstring *output) {
|
bool expand_abbreviation(const wcstring &src, wcstring *output) {
|
||||||
if (src.empty()) return false;
|
if (src.empty()) return false;
|
||||||
|
|
||||||
// Get the abbreviations. Return false if we have none.
|
auto abbr = abbreviations.find(src);
|
||||||
env_var_t abbrs = env_get_string(USER_ABBREVIATIONS_VARIABLE_NAME);
|
if (abbr == abbreviations.end()) return false;
|
||||||
if (abbrs.missing_or_empty()) return false;
|
if (output != NULL) output->assign(abbr->second);
|
||||||
|
return true;
|
||||||
|
|
||||||
bool result = false;
|
#if 0
|
||||||
std::vector<wcstring> abbrsv;
|
for (auto abbr : abbreviations) {
|
||||||
tokenize_variable_array(abbrs, abbrsv);
|
if (src == abbr.first) {
|
||||||
for (auto abbr : abbrsv) {
|
// We found a matching abbreviation. Set output to the expansion.
|
||||||
// Abbreviation is expected to be of the form 'foo=bar' or 'foo bar'. Parse out the first =
|
if (output != NULL) output->assign(abbr.second);
|
||||||
// or space. Silently skip on failure (no equals, or equals at the end or beginning). Try to
|
return true;
|
||||||
// avoid copying any strings until we are sure this is a match.
|
|
||||||
size_t equals_pos = abbr.find(L'=');
|
|
||||||
size_t space_pos = abbr.find(L' ');
|
|
||||||
size_t separator = mini(equals_pos, space_pos);
|
|
||||||
if (separator == wcstring::npos || separator == 0 || separator + 1 == abbr.size()) continue;
|
|
||||||
|
|
||||||
// Find the character just past the end of the command. Walk backwards, skipping spaces.
|
|
||||||
size_t cmd_end = separator;
|
|
||||||
while (cmd_end > 0 && iswspace(abbr.at(cmd_end - 1))) cmd_end--;
|
|
||||||
|
|
||||||
// See if this command matches.
|
|
||||||
if (abbr.compare(0, cmd_end, src) == 0) {
|
|
||||||
// Success. Set output to everything past the end of the string.
|
|
||||||
if (output != NULL) output->assign(abbr, separator + 1, wcstring::npos);
|
|
||||||
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,11 +135,10 @@ wcstring replace_home_directory_with_tilde(const wcstring &str);
|
||||||
|
|
||||||
/// Abbreviation support. Expand src as an abbreviation, returning true if one was found, false if
|
/// Abbreviation support. Expand src as an abbreviation, returning true if one was found, false if
|
||||||
/// not. If result is not-null, returns the abbreviation by reference.
|
/// not. If result is not-null, returns the abbreviation by reference.
|
||||||
#define USER_ABBREVIATIONS_VARIABLE_NAME L"fish_user_abbreviations"
|
void update_abbr_cache(const wchar_t *op, const wcstring varnam);
|
||||||
bool expand_abbreviation(const wcstring &src, wcstring *output);
|
bool expand_abbreviation(const wcstring &src, wcstring *output);
|
||||||
|
|
||||||
// Terrible hacks
|
// Terrible hacks
|
||||||
bool fish_xdm_login_hack_hack_hack_hack(std::vector<std::string> *cmds, int argc,
|
bool fish_xdm_login_hack_hack_hack_hack(std::vector<std::string> *cmds, int argc,
|
||||||
const char *const *argv);
|
const char *const *argv);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1610,21 +1610,15 @@ static void test_fuzzy_match(void) {
|
||||||
|
|
||||||
static void test_abbreviations(void) {
|
static void test_abbreviations(void) {
|
||||||
say(L"Testing abbreviations");
|
say(L"Testing abbreviations");
|
||||||
|
|
||||||
const wchar_t *abbreviations =
|
|
||||||
L"gc=git checkout" ARRAY_SEP_STR
|
|
||||||
L"foo=" ARRAY_SEP_STR
|
|
||||||
L"gc=something else" ARRAY_SEP_STR
|
|
||||||
L"=" ARRAY_SEP_STR
|
|
||||||
L"=foo" ARRAY_SEP_STR
|
|
||||||
L"foo" ARRAY_SEP_STR
|
|
||||||
L"foo=bar" ARRAY_SEP_STR
|
|
||||||
L"gx git checkout";
|
|
||||||
|
|
||||||
env_push(true);
|
env_push(true);
|
||||||
|
|
||||||
int ret = env_set(USER_ABBREVIATIONS_VARIABLE_NAME, abbreviations, ENV_LOCAL);
|
const std::vector<std::pair<const wcstring, const wcstring>> abbreviations = {
|
||||||
if (ret != 0) err(L"Unable to set abbreviation variable");
|
{L"gc", L"git checkout"}, {L"foo", L"bar"}, {L"gx", L"git checkout"},
|
||||||
|
};
|
||||||
|
for (auto it : abbreviations) {
|
||||||
|
int ret = env_set(L"_fish_abbr_" + it.first, it.second.c_str(), ENV_LOCAL);
|
||||||
|
if (ret != 0) err(L"Unable to set abbreviation variable");
|
||||||
|
}
|
||||||
|
|
||||||
wcstring result;
|
wcstring result;
|
||||||
if (expand_abbreviation(L"", &result)) err(L"Unexpected success with empty abbreviation");
|
if (expand_abbreviation(L"", &result)) err(L"Unexpected success with empty abbreviation");
|
||||||
|
|
|
@ -1,7 +1,22 @@
|
||||||
abbr: no such abbreviation 'NOT_AN_ABBR'
|
# Test basic add and list of __abbr1
|
||||||
abbr: abbreviation cannot have spaces in the key
|
# Erasing one that doesn't exist should do nothing
|
||||||
abbr: no such abbreviation '__abbr6'
|
abbr --erase: No abbreviation named NOT_AN_ABBR
|
||||||
abbr: abbreviation cannot have spaces in the key
|
# Adding existing __abbr1 should be idempotent
|
||||||
abbr: option requires an argument -- -r
|
# Replacing __abbr1 definition
|
||||||
abbr: Unexpected argument -- __abbr10
|
# __abbr1 -s and --show tests
|
||||||
abbr: abbreviation '__abbr12' already exists, cannot rename
|
# Test erasing __abbr1
|
||||||
|
# Ensure we escape special characters on output
|
||||||
|
# Ensure we handle leading dashes in abbreviation names properly
|
||||||
|
# Test that an abbr word containing spaces is rejected
|
||||||
|
abbr --add: Abbreviation 'a b c' cannot have spaces in the word
|
||||||
|
# Test renaming
|
||||||
|
# Test renaming a nonexistent abbreviation
|
||||||
|
abbr --rename: No abbreviation named __abbr6
|
||||||
|
# Test renaming to a abbreviation with spaces
|
||||||
|
abbr --rename: Abbreviation 'g h i' cannot have spaces in the word
|
||||||
|
# Test renaming without arguments
|
||||||
|
abbr --rename: Requires exactly two arguments
|
||||||
|
# Test renaming with too many arguments
|
||||||
|
abbr --rename: Requires exactly two arguments
|
||||||
|
# Test renaming to existing abbreviation
|
||||||
|
abbr --rename: Abbreviation __abbr12 already exists, cannot rename __abbr11
|
||||||
|
|
|
@ -1,44 +1,42 @@
|
||||||
# Test basic add and list
|
echo '# Test basic add and list of __abbr1' | tee /dev/stderr
|
||||||
abbr __abbr1 alpha beta gamma
|
abbr __abbr1 alpha beta gamma
|
||||||
abbr | grep __abbr1
|
abbr | grep __abbr1
|
||||||
|
|
||||||
# Erasing one that doesn't exist should do nothing
|
echo '# Erasing one that doesn\'t exist should do nothing' | tee /dev/stderr
|
||||||
abbr --erase NOT_AN_ABBR
|
abbr --erase NOT_AN_ABBR
|
||||||
abbr | grep __abbr1
|
abbr | grep __abbr1
|
||||||
|
|
||||||
# Adding existing one should be idempotent
|
echo '# Adding existing __abbr1 should be idempotent' | tee /dev/stderr
|
||||||
abbr __abbr1 alpha beta gamma
|
abbr __abbr1 alpha beta gamma
|
||||||
abbr | grep __abbr1
|
abbr | grep __abbr1
|
||||||
|
|
||||||
# Replacing
|
echo '# Replacing __abbr1 definition' | tee /dev/stderr
|
||||||
abbr __abbr1 delta
|
abbr __abbr1 delta
|
||||||
abbr | grep __abbr1
|
abbr | grep __abbr1
|
||||||
|
|
||||||
# -s and --show tests
|
echo '# __abbr1 -s and --show tests' | tee /dev/stderr
|
||||||
abbr -s | grep __abbr1
|
abbr -s | grep __abbr1
|
||||||
abbr --show | grep __abbr1
|
abbr --show | grep __abbr1
|
||||||
|
|
||||||
# Test erasing
|
echo '# Test erasing __abbr1' | tee /dev/stderr
|
||||||
abbr -e __abbr1
|
abbr -e __abbr1
|
||||||
abbr | grep __abbr1
|
abbr | grep __abbr1
|
||||||
|
|
||||||
# Ensure we escape special characters on output
|
echo '# Ensure we escape special characters on output' | tee /dev/stderr
|
||||||
abbr '~__abbr2' '$xyz'
|
abbr '~__abbr2' '$xyz'
|
||||||
abbr | grep __abbr2
|
abbr | grep __abbr2
|
||||||
abbr -e '~__abbr2'
|
abbr -e '~__abbr2'
|
||||||
|
|
||||||
# Ensure we handle leading dashes in abbreviation names properly
|
echo '# Ensure we handle leading dashes in abbreviation names properly' | tee /dev/stderr
|
||||||
abbr -- '--__abbr3' 'xyz'
|
abbr -- '--__abbr3' 'xyz'
|
||||||
abbr | grep __abbr3
|
abbr | grep __abbr3
|
||||||
abbr -e -- '--__abbr3'
|
abbr -e -- '--__abbr3'
|
||||||
|
|
||||||
# Ensure we are not recognizing later "=" as separators
|
echo '# Test that an abbr word containing spaces is rejected' | tee /dev/stderr
|
||||||
abbr d2 env a=b banana
|
abbr "a b c" "d e f"
|
||||||
abbr -l | string match -q d2; or echo "= test failed"
|
abbr | grep 'a b c'
|
||||||
|
|
||||||
abbr "a b c" "d e f"; or true
|
echo '# Test renaming' | tee /dev/stderr
|
||||||
|
|
||||||
# Test renaming
|
|
||||||
abbr __abbr4 omega
|
abbr __abbr4 omega
|
||||||
abbr | grep __abbr5
|
abbr | grep __abbr5
|
||||||
abbr -r __abbr4 __abbr5
|
abbr -r __abbr4 __abbr5
|
||||||
|
@ -46,26 +44,28 @@ abbr | grep __abbr5
|
||||||
abbr -e __abbr5
|
abbr -e __abbr5
|
||||||
abbr | grep __abbr4
|
abbr | grep __abbr4
|
||||||
|
|
||||||
# Test renaming a nonexistent abbreviation
|
echo '# Test renaming a nonexistent abbreviation' | tee /dev/stderr
|
||||||
abbr -r __abbr6 __abbr; or true
|
abbr -r __abbr6 __abbr
|
||||||
|
|
||||||
# Test renaming to a abbreviation with spaces
|
echo '# Test renaming to a abbreviation with spaces' | tee /dev/stderr
|
||||||
abbr __abbr4 omega
|
abbr __abbr4 omega
|
||||||
abbr -r __abbr4 "g h i"; or true
|
abbr -r __abbr4 "g h i"
|
||||||
abbr -e __abbr4
|
abbr -e __abbr4
|
||||||
|
|
||||||
# Test renaming without arguments
|
echo '# Test renaming without arguments' | tee /dev/stderr
|
||||||
abbr __abbr7 omega
|
abbr __abbr7 omega
|
||||||
abbr -r __abbr7; or true
|
abbr -r __abbr7
|
||||||
|
|
||||||
# Test renaming with too many arguments
|
echo '# Test renaming with too many arguments' | tee /dev/stderr
|
||||||
abbr __abbr8 omega
|
abbr __abbr8 omega
|
||||||
abbr -r __abbr8 __abbr9 __abbr10; or true
|
abbr -r __abbr8 __abbr9 __abbr10
|
||||||
abbr | grep __abbr8
|
abbr | grep __abbr8
|
||||||
abbr | grep __abbr9; or true
|
abbr | grep __abbr9
|
||||||
abbr | grep __abbr10; or true
|
abbr | grep __abbr10
|
||||||
|
|
||||||
# Test renaming to existing abbreviation
|
echo '# Test renaming to existing abbreviation' | tee /dev/stderr
|
||||||
abbr __abbr11 omega11
|
abbr __abbr11 omega11
|
||||||
abbr __abbr12 omega12
|
abbr __abbr12 omega12
|
||||||
abbr -r __abbr11 __abbr12; or true
|
abbr -r __abbr11 __abbr12
|
||||||
|
|
||||||
|
true # the last `abbr` command is expected to fail -- don't let that cause a test failure
|
||||||
|
|
|
@ -1,10 +1,25 @@
|
||||||
abbr __abbr1 'alpha beta gamma'
|
# Test basic add and list of __abbr1
|
||||||
abbr __abbr1 'alpha beta gamma'
|
abbr -a -U -- __abbr1 'alpha beta gamma'
|
||||||
abbr __abbr1 'alpha beta gamma'
|
# Erasing one that doesn't exist should do nothing
|
||||||
abbr __abbr1 delta
|
abbr -a -U -- __abbr1 'alpha beta gamma'
|
||||||
abbr __abbr1 delta
|
# Adding existing __abbr1 should be idempotent
|
||||||
abbr __abbr1 delta
|
abbr -a -U -- __abbr1 'alpha beta gamma'
|
||||||
abbr '~__abbr2' '$xyz'
|
# Replacing __abbr1 definition
|
||||||
abbr -- --__abbr3 xyz
|
abbr -a -U -- __abbr1 delta
|
||||||
abbr __abbr5 omega
|
# __abbr1 -s and --show tests
|
||||||
abbr __abbr8 omega
|
abbr -a -U -- __abbr1 delta
|
||||||
|
abbr -a -U -- __abbr1 delta
|
||||||
|
# Test erasing __abbr1
|
||||||
|
# Ensure we escape special characters on output
|
||||||
|
abbr -a -U -- '~__abbr2' '$xyz'
|
||||||
|
# Ensure we handle leading dashes in abbreviation names properly
|
||||||
|
abbr -a -U -- --__abbr3 xyz
|
||||||
|
# Test that an abbr word containing spaces is rejected
|
||||||
|
# Test renaming
|
||||||
|
abbr -a -U -- __abbr5 omega
|
||||||
|
# Test renaming a nonexistent abbreviation
|
||||||
|
# Test renaming to a abbreviation with spaces
|
||||||
|
# Test renaming without arguments
|
||||||
|
# Test renaming with too many arguments
|
||||||
|
abbr -a -U -- __abbr8 omega
|
||||||
|
# Test renaming to existing abbreviation
|
||||||
|
|
|
@ -46,7 +46,7 @@ or not string match -q '*/share/functions/abbr.fish' $x[1]
|
||||||
or test $x[2] != autoloaded
|
or test $x[2] != autoloaded
|
||||||
or test $x[3] != 1
|
or test $x[3] != 1
|
||||||
or test $x[4] != scope-shadowing
|
or test $x[4] != scope-shadowing
|
||||||
or test $x[5] != 'Manage abbreviations'
|
or test $x[5] != 'Manage abbreviations using new fish 3.0 scheme.'
|
||||||
echo "Unexpected output for 'functions -v -D abbr': $x" >&2
|
echo "Unexpected output for 'functions -v -D abbr': $x" >&2
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue