1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
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]
if test $needs_arg = single
set mode_arg $argv[1]
set needs_arg no
else if test $needs_arg = coalesce
set mode_arg "$argv"
set needs_arg no
set -e argv
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 coalesce
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]
end
set -e argv[1]
end
if test $needs_arg != no
printf ( _ "%s: option requires an argument -- %s\n" ) abbr $mode_flag >&2
return 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 test -z "$mode"
if set -q argv[1]
set mode 'add'
set mode_arg "$argv"
set -e argv
else
set mode 'show'
end
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 'erase'
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
# Disable newline splitting
set -lx IFS ''
__fish_abbr_parse_entry $i key value
# Check to see if either key or value has a leading dash
# If so, we need to write --
set -l opt_double_dash ''
switch $key ; case '-*'; set opt_double_dash ' --'; end
switch $value ; case '-*'; set opt_double_dash ' --'; end
echo abbr$opt_double_dash (__fish_abbr_escape "$key") (__fish_abbr_escape "$value")
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_escape
# Prettify the common case: if everything is alphanumeric,
# we do not need escapes.
# Do this by deleting alnum characters, and check if there's anything left.
# Note we need to preserve spaces, so spaces are not considered alnum
if test -z (echo -n "$argv" | tr -d '[:alnum:]_')
echo $argv
else
# Escape via single quotes
# printf is nice for stripping the newline that sed outputs
printf "'%s'" (echo -n $argv | sed -e s,\\\\,\\\\\\\\,g -e s,\',\\\\\',g)
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
set -l IFS '= '
switch $__input
case '=*'
# read will skip any leading ='s, but we don't want that
set __input " $__input"
set __key _
set IFS '='
case ' =*'
set __key _
set IFS '='
end
# use read -z to avoid splitting on newlines
# I think we can safely assume there will be no NULs in the input
printf "%s" $__input | read -z $__key $__value
return 0
end
|