summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkj_sh6042025-12-25 21:33:50 -0500
committerkj_sh6042025-12-25 21:33:50 -0500
commitec1c2263aa8b60b7645f33a22b3881727be335c0 (patch)
treebf74f4efa2e585cc670a66240524da610a475bba
parent698f33c146248930aa70cb7c0c836112e3215633 (diff)
feat: zsh-abbr
-rw-r--r--.config/shell/.zshrc1
-rw-r--r--.config/shell/zsh-abbr/zsh-abbr.plugin.zsh2
-rw-r--r--.config/shell/zsh-abbr/zsh-abbr.zsh2040
-rwxr-xr-x.config/shell/zsh-abbr/zsh-job-queue/zsh-job-queue.plugin.zsh2
-rwxr-xr-x.config/shell/zsh-abbr/zsh-job-queue/zsh-job-queue.zsh279
5 files changed, 2324 insertions, 0 deletions
diff --git a/.config/shell/.zshrc b/.config/shell/.zshrc
index ed99e27..22c5e9e 100644
--- a/.config/shell/.zshrc
+++ b/.config/shell/.zshrc
@@ -14,6 +14,7 @@ source_if_exists ~/.config/shell/git-prompts/kj_sh604-with-attempt-at-fish-style
14source_if_exists ~/.config/shell/zsh-autosuggestions/zsh-autosuggestions.zsh 14source_if_exists ~/.config/shell/zsh-autosuggestions/zsh-autosuggestions.zsh
15source_if_exists ~/.config/shell/zsh-fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh 15source_if_exists ~/.config/shell/zsh-fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh
16source_if_exists ~/.config/shell/zsh-history-substring-search/zsh-history-substring-search.zsh 16source_if_exists ~/.config/shell/zsh-history-substring-search/zsh-history-substring-search.zsh
17source_if_exists ~/.config/shell/zsh-abbr/zsh-abbr.zsh
17 18
18# source personal posix functions 19# source personal posix functions
19source_if_exists ~/.config/shell/posix-functions/create_POSIX_dotenv.sh 20source_if_exists ~/.config/shell/posix-functions/create_POSIX_dotenv.sh
diff --git a/.config/shell/zsh-abbr/zsh-abbr.plugin.zsh b/.config/shell/zsh-abbr/zsh-abbr.plugin.zsh
new file mode 100644
index 0000000..1c915ff
--- /dev/null
+++ b/.config/shell/zsh-abbr/zsh-abbr.plugin.zsh
@@ -0,0 +1,2 @@
1fpath+=${0:A:h}/completions
2source ${0:A:h}/zsh-abbr.zsh
diff --git a/.config/shell/zsh-abbr/zsh-abbr.zsh b/.config/shell/zsh-abbr/zsh-abbr.zsh
new file mode 100644
index 0000000..89e342b
--- /dev/null
+++ b/.config/shell/zsh-abbr/zsh-abbr.zsh
@@ -0,0 +1,2040 @@
1#!/usr/bin/env zsh
2
3# abbreviation management for zsh, inspired by fish shell and enhanced
4# https://github.com/olets/zsh-abbr
5# v6.4.0
6# Copyright (c) 2019-present Henry Bley-Vroman
7
8
9# CONFIGURATION
10# -------------
11
12# Should `abbr-load` run before every `abbr` command? (default true)
13typeset -gi ABBR_AUTOLOAD=${ABBR_AUTOLOAD:-1}
14
15# Log debugging messages?
16typeset -gi ABBR_DEBUG=${ABBR_DEBUG:-0}
17
18# Whether to add default bindings (expand on SPACE, expand and accept on ENTER,
19# add CTRL for normal SPACE/ENTER; in incremental search mode expand on CTRL+SPACE)
20# (default true)
21typeset -gi ABBR_DEFAULT_BINDINGS=${ABBR_DEFAULT_BINDINGS:-1}
22
23# Behave as if `--dry-run` was passed? (default false)
24typeset -gi ABBR_DRY_RUN=${ABBR_DRY_RUN:-0}
25
26# See ABBR_SET_LINE_CURSOR
27typeset -g ABBR_LINE_CURSOR_MARKER=${ABBR_LINE_CURSOR_MARKER:-%}
28
29# See ABBR_SET_EXPANSION_CURSOR
30typeset -g ABBR_EXPANSION_CURSOR_MARKER=${ABBR_EXPANSION_CURSOR_MARKER:-$ABBR_LINE_CURSOR_MARKER}
31
32# Behave as if `--force` was passed? (default false)
33typeset -gi ABBR_FORCE=${ABBR_FORCE:-0}
34
35# Check whether you could have used an abbreviation? (default false)
36# See also ABBR_LOG_AVAILABLE_ABBREVIATION
37typeset -gi ABBR_GET_AVAILABLE_ABBREVIATION=${ABBR_GET_AVAILABLE_ABBREVIATION:-0}
38
39# Log anything found by ABBR_GET_AVAILABLE_ABBREVIATION? (default false)
40typeset -gi ABBR_LOG_AVAILABLE_ABBREVIATION=${ABBR_LOG_AVAILABLE_ABBREVIATION:-0}
41
42# If ABBR_LOG_AVAILABLE_ABBREVIATION is non-zero, should
43# it log come _after_ the command output? (default false)
44typeset -gi ABBR_LOG_AVAILABLE_ABBREVIATION_AFTER=${ABBR_LOG_AVAILABLE_ABBREVIATION_AFTER:-0}
45
46# Should abbr-expand-and-accept push the unexpanded line to the shell history? (default false)
47# If true, if abbr-expand-and-accept expands an abbreviation there will be two history entries:
48# the first is line with the abbreviation, the second is what was run (with the expansion).
49# With this caveat: if ABBR_EXPAND_PUSH_ABBREVIATION_TO_HISTORY is true, abbr-expand-and-accept
50# will only push the line with the abbreviation to history if it's different from what abbr-expand
51# pushed to history. That is, if you
52# % abbr a=b
53# % a[Enter]
54# the history will be
55# abbr a=b
56# a
57# b
58# not
59# abbr a=b
60# a
61# a
62# b
63typeset -gi ABBR_EXPAND_AND_ACCEPT_PUSH_ABBREVIATED_LINE_TO_HISTORY=${ABBR_EXPAND_AND_ACCEPT_PUSH_ABBREVIATED_LINE_TO_HISTORY:-0}
64
65# Should abbr-expand push the abbreviation to the shell history? (default false)
66typeset -gi ABBR_EXPAND_PUSH_ABBREVIATION_TO_HISTORY=${ABBR_EXPAND_PUSH_ABBREVIATION_TO_HISTORY:-0}
67
68# Regular abbreviations expand when in command position, even if not at start of line
69# Experimental. Currently teats all `;`, `&`, `|`, and all reduplications (e.g. `&&`, `||`) as command delimiters.
70#
71# 0 to disable (default)
72# 1 to enable, with warning on shell startup
73# 2 to enable without warning
74typeset -gi ABBR_EXPERIMENTAL_COMMAND_POSITION_REGULAR_ABBREVIATIONS=${ABBR_EXPERIMENTAL_COMMAND_POSITION_REGULAR_ABBREVIATIONS:-0}
75if (( ABBR_EXPERIMENTAL_COMMAND_POSITION_REGULAR_ABBREVIATIONS == 1 )); then
76 'builtin' 'print' "abbr: You have set ABBR_EXPERIMENTAL_COMMAND_POSITION_REGULAR_ABBREVIATIONS=1. This feature is *experimental* and may have unexpected or undesired results. If it graduates from experimental, the variable name will change.\nYou can suppress this message while still enabling the feature by setting\n\n ABBR_EXPERIMENTAL_COMMAND_POSITION_REGULAR_ABBREVIATIONS=2\n"
77fi
78
79# Limitation: doesn't support the user changing their hist_ignore_space setting interactively
80typeset -gi _abbr_hist_ignore_space
81_abbr_hist_ignore_space=$options[hist_ignore_space]
82
83# Behave as if `--quiet` was passed? (default false)
84typeset -gi ABBR_QUIET=${ABBR_QUIET:-0}
85
86# Behave as if `--quieter` was passed? (default false)
87typeset -gi ABBR_QUIETER=${ABBR_QUIETER:-0}
88
89# In expansions, replace the first instance of ABBR_LINE_CURSOR_MARKER with the cursor
90typeset -gi ABBR_SET_LINE_CURSOR=${ABBR_SET_LINE_CURSOR:-0}
91
92# In expansions, replace the first instance of ABBR_EXPANSION_CURSOR_MARKER with the cursor
93typeset -gi ABBR_SET_EXPANSION_CURSOR=${ABBR_SET_EXPANSION_CURSOR:-0}
94
95# Function for splitting strings into abbreviation candidates
96# Default: split into words with shell grammar.
97# NB in my testing on zsh 5.9 (x86_64-apple-darwin21.3.0),
98# [[ ${${(k)functions}[(Ie)ABBR_SPLIT_FN]} == 0 ]]
99# can be significantly more performant than
100# (( ${${(k)functions}[(Ie)ABBR_SPLIT_FN]} == 0 ))
101if [[ ${${(k)functions}[(Ie)ABBR_SPLIT_FN]} == 0 ]]; then
102 function ABBR_SPLIT_FN() {
103 REPLY=( ${(z)*} )
104 }
105fi
106
107# The directory temp files are stored in
108typeset -g _abbr_tmpdir=${${ABBR_TMPDIR:-${${TMPDIR:-/tmp}%/}/zsh-abbr}%/}/
109if [[ ${(%):-%#} == '#' ]]; then
110 _abbr_tmpdir=${${ABBR_TMPDIR:-${${TMPDIR:-/tmp}%/}/zsh-abbr-privileged-users}%/}/
111fi
112
113# The file abbreviations are stored in
114typeset -g ABBR_USER_ABBREVIATIONS_FILE=$ABBR_USER_ABBREVIATIONS_FILE
115if [[ -z $ABBR_USER_ABBREVIATIONS_FILE ]]; then
116 # Legacy support for the zsh-abbr < v5.0.0 default
117 ABBR_USER_ABBREVIATIONS_FILE=${XDG_CONFIG_HOME:-$HOME/.config}/zsh/abbreviations
118
119 if [[ ! -f $ABBR_USER_ABBREVIATIONS_FILE ]]; then
120 ABBR_USER_ABBREVIATIONS_FILE=${XDG_CONFIG_HOME:-$HOME/.config}/zsh-abbr/user-abbreviations
121 fi
122fi
123
124if [[ ${(t)ABBR_REGULAR_ABBREVIATION_SCALAR_PREFIXES} == ${${(t)ABBR_REGULAR_ABBREVIATION_SCALAR_PREFIXES}#array} ]]; then
125 typeset -ga ABBR_REGULAR_ABBREVIATION_SCALAR_PREFIXES=( 'sudo ' )
126fi
127
128if [[ ${(t)ABBR_REGULAR_ABBREVIATION_GLOB_PREFIXES} == ${${(t)ABBR_REGULAR_ABBREVIATION_GLOB_PREFIXES}#array} ]]; then
129 typeset -ga ABBR_REGULAR_ABBREVIATION_GLOB_PREFIXES=( ' ' )
130fi
131
132# FUNCTIONS
133# ---------
134
135abbr() {
136 emulate -LR zsh
137
138 _abbr_debugger
139
140 {
141 local action
142 local -a args
143 local asterisk
144 local -i dry_run
145 local error_color
146 local -i force
147 local -i has_error
148 local job_id
149 local logs_silent_when_quiet
150 local logs_silent_when_quieter
151 local opt
152 local output
153 local -i quiet
154 local -i quieter
155 local release_date
156 local REPLY
157 local scope
158 local -i should_exit
159 local success_color
160 local type
161 local version
162 local warn_color
163
164 asterisk=$*
165 dry_run=$ABBR_DRY_RUN
166 force=$ABBR_FORCE
167 quiet=$ABBR_QUIET
168 quiet=$(( ABBR_QUIETER || ABBR_QUIET ))
169 quieter=$ABBR_QUIETER
170 release_date="November 27 2025"
171 version="zsh-abbr version 6.4.0"
172
173 # Deprecation notices for values that could be meaningfully set after initialization
174 # Example form:
175 # (( ${+DEPRECATED_VAL} )) && _abbr_warn_deprecation DEPRECATED_VAL VAL
176 # VAL=$DEPRECATED_VAL
177
178 if (( ABBR_LOADING_USER_ABBREVIATIONS )); then
179 quiet=1
180 quieter=1
181 elif ! _abbr_no_color; then
182 error_color="$fg[red]"
183 success_color="$fg[green]"
184 # @DUPE (nearly) abbr, _abbr_log_available_abbreviation, _abbr_warn_deprecation
185 warn_color="$fg[yellow]"
186 fi
187
188 _abbr:add() {
189 _abbr_debugger
190
191 local abbreviation
192 local expansion
193
194 if [[ $# > 1 ]]; then
195 _abbr:util_error "abbr add: Expected one argument, got $#: $*"
196 return
197 fi
198
199 abbreviation=${1%%=*}
200 expansion=${1#*=}
201
202 if ! (( ABBR_LOADING_USER_ABBREVIATIONS )); then
203 abbreviation=${(q)abbreviation}
204 expansion=${(q)expansion}
205 fi
206
207 if [[ -z $abbreviation || -z $expansion || $abbreviation == $1 ]]; then
208 _abbr:util_error "abbr add: Requires abbreviation and expansion"
209 return
210 fi
211
212 _abbr:util_add $abbreviation $expansion
213 }
214
215 _abbr:git() {
216 _abbr_debugger
217
218 local abbreviation
219 local expansion
220 local type_saved
221
222 if [[ $# > 1 ]]; then
223 _abbr:util_error "abbr add: Expected one argument, got $#: $*"
224 return
225 fi
226
227 abbreviation=${1%%=*}
228 expansion=${1#*=}
229 type_saved=$type
230
231 type='regular'
232 _abbr:add ${abbreviation}="git $expansion"
233
234 type='global'
235 _abbr:add "git ${abbreviation}"="git $expansion"
236
237 type=$type_saved
238 }
239
240 _abbr:clear_session() {
241 _abbr_debugger
242
243 if [[ $# > 0 ]]; then
244 _abbr:util_error "abbr clear-session: Unexpected argument"
245 return
246 fi
247
248 ABBR_REGULAR_SESSION_ABBREVIATIONS=( )
249 ABBR_GLOBAL_SESSION_ABBREVIATIONS=( )
250 }
251
252 _abbr:erase() {
253 _abbr_debugger
254
255 local abbreviation
256 local abbreviations_set
257 local -a abbreviations_sets
258 local message
259 local verb_phrase
260
261 local REPLY
262
263 if [[ $# > 1 ]]; then
264 _abbr:util_error "abbr erase: Expected one argument"
265 return
266 elif [[ $# < 1 ]]; then
267 _abbr:util_error "abbr erase: Erase must be passed an abbreviation"
268 return
269 fi
270
271 abbreviation=$1
272
273 if [[ $scope != 'user' ]]; then
274 if [[ $type != 'regular' ]]; then
275 if (( ${+ABBR_GLOBAL_SESSION_ABBREVIATIONS[${(qqq)${(Q)abbreviation}}]} )); then
276 (( ABBR_DEBUG )) && 'builtin' 'echo' " Found a global session abbreviation"
277 abbreviations_sets+=( ABBR_GLOBAL_SESSION_ABBREVIATIONS )
278 fi
279 fi
280
281 if [[ $type != 'global' ]]; then
282 if (( ${+ABBR_REGULAR_SESSION_ABBREVIATIONS[${(qqq)${(Q)abbreviation}}]} )); then
283 (( ABBR_DEBUG )) && 'builtin' 'echo' " Found a regular session abbreviation"
284 abbreviations_sets+=( ABBR_REGULAR_SESSION_ABBREVIATIONS )
285 fi
286 fi
287 fi
288
289 if [[ $scope != 'session' ]]; then
290 if [[ $type != 'regular' ]]; then
291 if ! (( ABBR_LOADING_USER_ABBREVIATIONS )); then
292 source ${_abbr_tmpdir}global-user-abbreviations
293 fi
294
295 if (( ${+ABBR_GLOBAL_USER_ABBREVIATIONS[${(qqq)${(Q)abbreviation}}]} )); then
296 (( ABBR_DEBUG )) && 'builtin' 'echo' " Found a global user abbreviation"
297 abbreviations_sets+=( ABBR_GLOBAL_USER_ABBREVIATIONS )
298 fi
299 fi
300
301 if [[ $type != 'global' ]]; then
302 if ! (( ABBR_LOADING_USER_ABBREVIATIONS )); then
303 source ${_abbr_tmpdir}regular-user-abbreviations
304 fi
305
306 if (( ${+ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)${(Q)abbreviation}}]} )); then
307 (( ABBR_DEBUG )) && 'builtin' 'echo' " Found a regular user abbreviation"
308 abbreviations_sets+=( ABBR_REGULAR_USER_ABBREVIATIONS )
309 fi
310 fi
311 fi
312
313 if ! (( ${#abbreviations_sets} )); then
314 _abbr:util_error "abbr erase: No${type:+ $type}${scope:+ $scope} abbreviation \`${(Q)abbreviation}\` found"
315 elif (( ${#abbreviations_sets} == 1 )); then
316 verb_phrase="Would erase"
317
318 if ! (( dry_run )); then
319 verb_phrase="Erased"
320 unset "${abbreviations_sets}[${(qqq)${(Q)abbreviation}}]" # quotation marks required
321
322 if [[ $abbreviations_sets =~ USER ]]; then
323 _abbr:util_sync_user
324 fi
325 fi
326
327 _abbr:util_set_to_typed_scope $abbreviations_sets
328 _abbr:util_log_unless_quiet "$success_color$verb_phrase$reset_color $REPLY \`${(Q)abbreviation}\`"
329 else
330 verb_phrase="Did not erase"
331 (( dry_run )) && verb_phrase="Would not erase"
332
333 message="$error_color$verb_phrase$reset_color abbreviation \`${(Q)abbreviation}\`. Please specify one of\\n"
334
335 for abbreviations_set in $abbreviations_sets; do
336 _abbr:util_set_to_typed_scope $abbreviations_set
337 message+=" $REPLY\\n"
338 done
339
340 _abbr:util_error $message
341 fi
342 }
343
344 _abbr:expand() {
345 _abbr_debugger
346
347 local expansion
348
349 if ! (( $# )); then
350 _abbr:util_error "abbr expand: requires an argument"
351 return
352 fi
353
354 expansion=$(_abbr:expansion $*)
355
356 if [[ -z $expansion ]]; then
357 return 1
358 fi
359
360 _abbr:util_print $expansion
361 }
362
363 _abbr:expansion() {
364 _abbr_debugger
365
366 local abbreviation
367 local expansion
368
369 if ! (( $# )); then
370 _abbr:util_error "_abbr:expansion requires an argument"
371 return
372 fi
373
374 abbreviation=$*
375
376 expansion=$(_abbr_regular_expansion "$abbreviation")
377
378 if [[ ! "$expansion" ]]; then
379 expansion=$(_abbr_global_expansion "$abbreviation" 1)
380 fi
381
382 if [[ ! "$expansion" ]]; then
383 _abbr_create_files
384 source ${_abbr_tmpdir}global-user-abbreviations
385 expansion=$(_abbr_global_expansion "$abbreviation" 0)
386 fi
387
388 'builtin' 'echo' - $expansion
389 }
390
391 _abbr:export_aliases() {
392 _abbr_debugger
393
394 local type_saved
395
396 type_saved=$type
397
398 if [[ $# > 0 ]]; then
399 _abbr:util_error "abbr export-aliases: Unexpected argument"
400 return
401 fi
402
403 include_expansion=1
404 session_prefix="alias"
405 user_prefix="alias"
406
407 _abbr:util_list $include_expansion $session_prefix $user_prefix
408 }
409
410 _abbr:import_aliases() {
411 _abbr_debugger
412
413 local alias_to_import
414 local abbreviation
415 local expansion
416 local saved_type
417
418 typeset -a aliases_to_import
419
420 saved_type=$type
421
422 if [[ $# > 0 ]]; then
423 _abbr:util_error "abbr import-aliases: Unexpected argument"
424 return
425 fi
426
427 if [[ $saved_type != 'global' ]]; then
428 aliases_to_import=( ${(f)"$('builtin' 'alias' -r)"} )
429 # this quotation mark to fix syntax highlighting "
430 for alias_to_import in $aliases_to_import; do
431 _abbr:util_import_alias $alias_to_import
432 done
433 fi
434
435 if [[ $saved_type != 'regular' ]]; then
436 type='global'
437
438 aliases_to_import=( ${(f)"$('builtin' 'alias' -g)"} )
439 # this quotation mark to fix syntax highlighting "
440 for alias_to_import in $aliases_to_import; do
441 _abbr:util_import_alias $alias_to_import
442 done
443 fi
444
445 type=$saved_type
446 }
447
448 _abbr:import_fish() {
449 _abbr_debugger
450
451 local abbreviation
452 local abbreviations
453 local expansion
454 local input_file
455
456 if [[ $# != 1 ]]; then
457 _abbr:util_error "abbr import-fish: requires exactly one argument"
458 return
459 fi
460
461 input_file=$1
462 abbreviations=( ${(f)"$(<$input_file)"} )
463 # this quotation mark to fix syntax highlighting "
464
465 for abbreviation in $abbreviations; do
466 def=${line#* -- }
467 abbreviation=${def%% *}
468 expansion=${def#* }
469
470 _abbr:util_add $abbreviation $expansion
471 done
472 }
473
474 _abbr:import_git_aliases() {
475 _abbr_debugger
476
477 local config_file
478 local git_alias
479 local prefix
480 local -a git_aliases
481
482 while (( $# )); do
483 case $1 in
484 "--file")
485 if [[ -z $2 ]]; then
486 _abbr:util_error "abbr import-git-aliases: --file requires a file path"
487 return
488 fi
489
490 config_file=$2
491
492 shift 2
493 ;;
494 "--prefix")
495 if [[ -z $2 ]]; then
496 _abbr:util_error "abbr import-git-aliases: --prefix requires a prefix string"
497 return
498 fi
499
500 prefix=$2
501
502 shift 2
503 ;;
504 *)
505 _abbr:util_error "abbr import-git-aliases: Unexpected argument"
506 return
507 esac
508 done
509
510 if [[ -n $config_file ]]; then
511 if [[ ! -f $config_file ]]; then
512 _abbr:util_error "abbr import-git-aliases: Config file not found"
513 return
514 fi
515
516 git_aliases=( ${(ps|\nalias.|)"$(git config --file $config_file --get-regexp '^alias\.')"} )
517 else
518 git_aliases=( ${(ps|\nalias.|)"$(git config --get-regexp '^alias\.')"} )
519 fi
520
521 for git_alias in $git_aliases; do
522 key=${${git_alias%% *}#alias.}
523 value=${git_alias#* }
524
525 if [[ ${value[1]} == '!' ]]; then
526 verb_phrase="Did not"
527 ((dry_run)) && verb_phrase="Would not"
528
529 _abbr:util_warn "$verb_phrase import the Git alias \`$key\` because its expansion is a function"
530 else
531 if ! (( ABBR_LOADING_USER_ABBREVIATIONS )); then
532 key=${(q)key}
533 value=${(q)value}
534 fi
535
536 _abbr:util_add "$prefix$key" "git $value"
537 fi
538 done
539 }
540
541 _abbr:list() {
542 _abbr_debugger
543
544 local -i include_expansion
545
546 if [[ $# > 0 ]]; then
547 _abbr:util_error "abbr list definitions: Unexpected argument"
548 return
549 fi
550
551 include_expansion=1
552
553 _abbr:util_list $include_expansion
554 }
555
556 _abbr:list_abbreviations() {
557 _abbr_debugger
558
559 if [[ $# > 0 ]]; then
560 _abbr:util_error "abbr list: Unexpected argument"
561 return
562 fi
563
564 _abbr:util_list
565 }
566
567 _abbr:list_commands() {
568 _abbr_debugger
569
570 local -i include_expansion
571 local session_prefix
572 local user_prefix
573
574 if [[ $# > 0 ]]; then
575 _abbr:util_error "abbr list commands: Unexpected argument"
576 return
577 fi
578
579 include_expansion=1
580 session_prefix="abbr -S"
581 user_prefix=abbr
582
583 _abbr:util_list $include_expansion $session_prefix $user_prefix
584 }
585
586 _abbr:print_version() {
587 _abbr_debugger
588
589 if [[ $# > 0 ]]; then
590 _abbr:util_error "abbr version: Unexpected argument"
591 return
592 fi
593
594 _abbr:util_print $version
595 }
596
597 _abbr:profile() {
598 _abbr_debugger
599
600 local zsh_version
601
602 if [[ $# > 0 ]]; then
603 _abbr:util_error "abbr version: Unexpected argument"
604 return
605 fi
606
607 zsh_version=$(zsh --version)
608
609 _abbr:util_print $version
610 _abbr:util_print $zsh_version
611 _abbr:util_print "OSTYPE $OSTYPE"
612 }
613
614 _abbr:rename() {
615 _abbr_debugger
616
617 local err
618 local expansion
619 local new
620 local old
621
622 if [[ $# != 2 ]]; then
623 _abbr:util_error "abbr rename: Requires exactly two arguments"
624 return
625 fi
626
627 current_abbreviation=$1
628 new_abbreviation=$2
629 job_group='_abbr:rename'
630
631 expansion=$(_abbr:expansion $current_abbreviation)
632
633 if [[ -n $expansion ]]; then
634 _abbr:util_add $new_abbreviation $expansion
635
636 if (( $? )); then
637 _abbr:util_error "abbr rename: ${type:+$type }${scope:+$scope }abbreviation \`${(Q)current_abbreviation}\` left untouched"
638 return 1
639 fi
640
641 _abbr:erase $current_abbreviation
642 else
643 _abbr:util_error "abbr rename: No${type:+ $type}${scope:+ $scope} abbreviation \`${(Q)current_abbreviation}\` exists"
644 fi
645 }
646
647 _abbr:util_add() {
648 _abbr_debugger
649
650 local abbreviation
651 local abbreviations_set
652 local cmd
653 local expansion
654 local existing_expansion
655 local job_group
656 local -a success
657 local typed_scope
658 local verb_phrase
659
660 local REPLY
661
662 abbreviation=$1
663 expansion=$2
664 success=0
665
666 verb_phrase="Added"
667 (( dry_run )) && verb_phrase="Would add"
668
669 if [[ ${abbreviation%=*} != $abbreviation ]]; then
670 _abbr:util_error "abbr add: ABBREVIATION (\`${(Q)abbreviation}\`) may not contain an equals sign"
671 # this quotation mark to fix syntax highlighting "
672 return 1
673 fi
674
675 if [[ $scope == 'session' ]]; then
676 if [[ $type == 'global' ]]; then
677 abbreviations_set=ABBR_GLOBAL_SESSION_ABBREVIATIONS
678 else
679 abbreviations_set=ABBR_REGULAR_SESSION_ABBREVIATIONS
680 fi
681 else
682 if [[ $type == 'global' ]]; then
683 abbreviations_set=ABBR_GLOBAL_USER_ABBREVIATIONS
684
685 if ! (( ABBR_LOADING_USER_ABBREVIATIONS )); then
686 source ${_abbr_tmpdir}global-user-abbreviations
687 fi
688 else
689 abbreviations_set=ABBR_REGULAR_USER_ABBREVIATIONS
690
691 if ! (( ABBR_LOADING_USER_ABBREVIATIONS )); then
692 source ${_abbr_tmpdir}regular-user-abbreviations
693 fi
694 fi
695 fi
696
697 _abbr:util_set_to_typed_scope $abbreviations_set
698 typed_scope=$REPLY
699
700 existing_expansion=${${(P)abbreviations_set}[${(qqq)${(Q)abbreviation}}]}
701
702 if [[ -n $existing_expansion ]]; then
703 if (( ! force )); then
704 verb_phrase="Did not add"
705 (( dry_run )) && verb_phrase="Would not add"
706
707 _abbr:util_error "$verb_phrase the $typed_scope \`${(Q)abbreviation}\`. It already has an expansion"
708 # this quotation mark to fix syntax highlighting "
709 return 2
710 fi
711
712 verb_phrase="Redefined"
713 (( dry_run )) && verb_phrase="Would redefine"
714 fi
715
716 _abbr:util_check_command $abbreviation || return 3
717
718 if ! (( dry_run )); then
719 eval $abbreviations_set'[${(qqq)${(Q)abbreviation}}]=${(qqq)${(Q)expansion}}'
720 fi
721
722 if [[ $scope != 'session' ]]; then
723 _abbr:util_sync_user
724 fi
725
726 _abbr:util_log_unless_quiet "$success_color$verb_phrase$reset_color the $typed_scope \`${(Q)abbreviation}\`"
727 # this quotation mark to fix syntax highlighting "
728 }
729
730 _abbr:util_alias() {
731 _abbr_debugger
732
733 local abbreviation
734 local abbreviations_set
735 local expansion
736
737 abbreviations_set=$1
738
739 for abbreviation in ${(iko)${(P)abbreviations_set}}; do
740 expansion=${${(P)abbreviations_set}[$abbreviation]}
741
742 alias_definition="alias "
743 if [[ $type == 'global' ]]; then
744 alias_definition+="-g "
745 fi
746 alias_definition+="$abbreviation='$expansion'"
747
748 'builtin' 'print' "$alias_definition"
749 done
750 }
751
752 _abbr:util_bad_options() {
753 _abbr_debugger
754
755 _abbr:util_error "abbr: Illegal combination of options"
756 }
757
758 _abbr:util_error() {
759 _abbr_debugger
760
761 has_error=1
762 logs_silent_when_quiet+="${logs_silent_when_quiet:+\\n}$error_color$@$reset_color"
763 should_exit=1
764 }
765
766 _abbr:util_import_alias() {
767 local abbreviation
768 local expansion
769
770 abbreviation=${1%%=*}
771 expansion=${1#*=}
772
773 _abbr:util_add $abbreviation "$('builtin' 'echo' $expansion)"
774 }
775
776 _abbr:util_check_command() {
777 _abbr_debugger
778
779 local abbreviation
780
781 abbreviation=$1
782
783 (( ABBR_LOADING_USER_ABBREVIATIONS )) && return 0
784
785 (( force && quieter )) && return 0
786
787 # Warn if abbreviation would interfere with system command use, e.g. `cp="git cherry-pick"`
788 # To add regardless, use --force
789
790 if (( $+commands[$abbreviation] && ! $+aliases[$abbreviation] )); then
791 if (( force )); then
792 verb_phrase="will now expand"
793 (( dry_run )) && verb_phrase="would now expand"
794
795 _abbr:util_log_unless_quieter "\`${(Q)abbreviation}\` $verb_phrase as an abbreviation"
796 # this quotation mark to fix syntax highlighting "
797 else
798 verb_phrase="Did not"
799 (( dry_run )) && verb_phrase="Would not"
800
801 _abbr:util_warn "$verb_phrase add the abbreviation \`${(Q)abbreviation}\` because a command with the same name exists"
802 # this quotation mark to fix syntax highlighting "
803 return 1
804 fi
805 fi
806 }
807
808 _abbr:util_list() {
809 _abbr_debugger
810
811 local abbreviation
812 local abbreviation_set
813 local -a abbreviations_sets
814 local expansion
815 local -i include_expansion
816 local session_prefix
817 local user_prefix
818
819 include_expansion=$1
820 session_prefix=$2
821 user_prefix=$3
822
823 # DUPE (nearly) completions/_abbr's __abbr_describe_abbreviations, zsh-abbr.zsh's _abbr:util_list
824
825 if [[ $scope != 'session' ]]; then
826 if [[ $type != 'regular' ]]; then
827 abbreviations_sets+=( ABBR_GLOBAL_USER_ABBREVIATIONS )
828 fi
829
830 if [[ $type != 'global' ]]; then
831 abbreviations_sets+=( ABBR_REGULAR_USER_ABBREVIATIONS )
832 fi
833 fi
834
835 if [[ $scope != 'user' ]]; then
836 if [[ $type != 'regular' ]]; then
837 abbreviations_sets+=( ABBR_GLOBAL_SESSION_ABBREVIATIONS )
838 fi
839
840 if [[ $type != 'global' ]]; then
841 abbreviations_sets+=( ABBR_REGULAR_SESSION_ABBREVIATIONS )
842 fi
843 fi
844
845 for abbreviation_set in $abbreviations_sets; do
846 for abbreviation in ${(iko)${(P)abbreviation_set}}; do
847 (( include_expansion )) && expansion=${${(P)abbreviation_set}[$abbreviation]}
848 _abbr:util_list_item $abbreviation $expansion ${user_prefix:+$user_prefix -g}
849 done
850 done
851
852 # DUPE end
853 }
854
855 _abbr:util_list_item() {
856 _abbr_debugger
857
858 local abbreviation
859 local expansion
860 local prefix
861
862 abbreviation=$1
863 expansion=$2
864 prefix=$3
865
866 result=$abbreviation
867
868 if [[ $expansion ]]; then
869 result+="=${(qqq)${(Q)expansion}}"
870 fi
871
872 if [[ $prefix ]]; then
873 result="$prefix $result"
874 fi
875
876 _abbr:util_print $result
877 }
878
879 _abbr:util_log_unless_quiet() {
880 _abbr_debugger
881
882 logs_silent_when_quiet+="${logs_silent_when_quiet:+\\n}$1"
883 }
884
885 _abbr:util_log_unless_quieter() {
886 _abbr_debugger
887
888 logs_silent_when_quieter+="${logs_silent_when_quieter:+\\n}$1"
889 }
890
891 _abbr:util_print() {
892 _abbr_debugger
893
894 output+="${output:+\\n}$1"
895 }
896
897 _abbr:util_set_once() {
898 _abbr_debugger
899
900 local option
901 local value
902
903 option=$1
904 value=$2
905
906 if [[ "${(P)option}" ]]; then # quoted for syntax highlighting
907 return 1
908 fi
909
910 eval $option=$value
911 }
912
913 _abbr:util_sync_user() {
914 _abbr_debugger
915
916 (( ABBR_LOADING_USER_ABBREVIATIONS )) && return
917
918 local abbreviation
919 local expansion
920 local user_updated
921
922 user_updated=$(mktemp ${_abbr_tmpdir}regular-user-abbreviations_updated.XXXXXX)
923
924 typeset -p ABBR_GLOBAL_USER_ABBREVIATIONS > ${_abbr_tmpdir}global-user-abbreviations
925 for abbreviation in ${(iko)ABBR_GLOBAL_USER_ABBREVIATIONS}; do
926 expansion=${ABBR_GLOBAL_USER_ABBREVIATIONS[$abbreviation]}
927 'builtin' 'echo' "abbr -g $abbreviation=$expansion" >> "$user_updated"
928 done
929
930 typeset -p ABBR_REGULAR_USER_ABBREVIATIONS > ${_abbr_tmpdir}regular-user-abbreviations
931 for abbreviation in ${(iko)ABBR_REGULAR_USER_ABBREVIATIONS}; do
932 expansion=${ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]}
933 'builtin' 'echo' "abbr $abbreviation=$expansion" >> $user_updated
934 done
935
936 'command' 'mv' $user_updated $ABBR_USER_ABBREVIATIONS_FILE
937 }
938
939 _abbr:util_set_to_typed_scope() {
940 _abbr_debugger
941
942 local abbreviations_set
943 abbreviations_set=$1
944
945 REPLY=${${${${abbreviations_set:l}%s}#abbr_}//_/ }
946 }
947
948 _abbr:util_usage() {
949 _abbr_debugger
950
951 'command' 'man' abbr 2>/dev/null || 'command' 'man' ${ABBR_SOURCE_PATH}/man/man1/abbr.1
952 }
953
954 _abbr:util_warn() {
955 _abbr_debugger
956
957 logs_silent_when_quiet+="${logs_silent_when_quiet:+\\n}$warn_color$@$reset_color"
958 }
959
960 for opt in "$@"; do
961 if (( should_exit )); then
962 return
963 fi
964
965 case $opt in
966 "add"|\
967 "a")
968 _abbr:util_set_once action add || args+=( $opt )
969 shift
970 ;;
971 "git"|\
972 "g")
973 _abbr:util_set_once action git || args+=( $opt )
974 shift
975 ;;
976 "clear-session"|\
977 "c")
978 _abbr:util_set_once action clear_session || args+=( $opt )
979 shift
980 ;;
981 "--dry-run")
982 dry_run=1
983 shift
984 ;;
985 "erase"|\
986 "e")
987 _abbr:util_set_once action erase || args+=( $opt )
988 shift
989 ;;
990 "expand"|\
991 "x")
992 _abbr:util_set_once action expand || args+=( $opt )
993 shift
994 ;;
995 "export-aliases")
996 _abbr:util_set_once action export_aliases || args+=( $opt )
997 shift
998 ;;
999 "--force"|\
1000 "-f")
1001 force=1
1002 shift
1003 ;;
1004 "--global"|\
1005 "-g")
1006 _abbr:util_set_once type global || args+=( $opt )
1007 shift
1008 ;;
1009 "help"|\
1010 "--help")
1011 _abbr:util_usage
1012 should_exit=1
1013 shift
1014 ;;
1015 "import-aliases")
1016 _abbr:util_set_once action import_aliases || args+=( $opt )
1017 shift
1018 ;;
1019 "import-fish")
1020 _abbr:util_set_once action import_fish || args+=( $opt )
1021 shift
1022 ;;
1023 "import-git-aliases")
1024 _abbr:util_set_once action import_git_aliases || args+=( $opt )
1025 shift
1026 ;;
1027 "list")
1028 _abbr:util_set_once action list || args+=( $opt )
1029 shift
1030 ;;
1031 "list-abbreviations"|\
1032 "l")
1033 _abbr:util_set_once action list_abbreviations || args+=( $opt )
1034 shift
1035 ;;
1036 "list-commands"|\
1037 "L"|\
1038 "-L")
1039 # -L option is to match the builtin alias's `-L`
1040 _abbr:util_set_once action list_commands || args+=( $opt )
1041 shift
1042 ;;
1043 "load")
1044 _abbr_load_user_abbreviations
1045 should_exit=1
1046 shift
1047 ;;
1048 "profile")
1049 _abbr:util_set_once action profile || args+=( $opt )
1050 shift
1051 ;;
1052 "--quiet"|\
1053 "-q")
1054 quiet=1
1055 shift
1056 ;;
1057 "--quieter"|\
1058 "-qq")
1059 quiet=1
1060 quieter=1
1061 shift
1062 ;;
1063 "--regular"|\
1064 "-r")
1065 _abbr:util_set_once type regular || args+=( $opt )
1066 shift
1067 ;;
1068 "rename"|\
1069 "R")
1070 _abbr:util_set_once action rename || args+=( $opt )
1071 shift
1072 ;;
1073 "--session"|\
1074 "-S")
1075 _abbr:util_set_once scope session || args+=( $opt )
1076 shift
1077 ;;
1078 "--user"|\
1079 "-U")
1080 _abbr:util_set_once scope user || args+=( $opt )
1081 shift
1082 ;;
1083 "version"|\
1084 "--version"|\
1085 "-v")
1086 _abbr:util_set_once action print_version || args+=( $opt )
1087 shift
1088 ;;
1089 "--")
1090 shift
1091 args+=( $@ )
1092 break
1093 ;;
1094 *)
1095 args+=( $opt )
1096 shift
1097 ;;
1098 esac
1099 done
1100
1101 if ! (( should_exit )); then
1102 if [[ -z $action ]]; then
1103 if (( ${#args} )); then
1104 action=add
1105 else
1106 action=list
1107 fi
1108 fi
1109
1110 if ! (( ABBR_LOADING_USER_ABBREVIATIONS )) && [[ $scope != 'session' ]]; then
1111 job-queue__zsh-abbr push zsh-abbr $action
1112 job_id=$REPLY
1113
1114 if (( ABBR_AUTOLOAD )); then
1115 _abbr_load_user_abbreviations
1116 fi
1117 fi
1118
1119 _abbr:${action} $args
1120 has_error=$?
1121 fi
1122
1123 if ! (( ABBR_LOADING_USER_ABBREVIATIONS )); then
1124 job-queue__zsh-abbr pop zsh-abbr $job_id
1125 fi
1126
1127 if ! (( quiet )); then
1128 if [[ -n $logs_silent_when_quiet ]]; then
1129 output=$logs_silent_when_quiet${output:+\\n$output}
1130 fi
1131 fi
1132
1133 if ! (( quieter )); then
1134 if [[ -n $logs_silent_when_quieter ]]; then
1135 output=$logs_silent_when_quieter${output:+\\n$output}
1136 fi
1137 fi
1138
1139 if (( has_error )); then
1140 [[ -n $output ]] && 'builtin' 'print' $output >&2
1141 return 1
1142 else
1143 if (( dry_run && ! ABBR_TESTING )); then
1144 output+="\\n${warn_color}Dry run. Changes not saved.$reset_color"
1145 fi
1146
1147 [[ -n $output ]] && 'builtin' 'print' $output >&1
1148 return 0
1149 fi
1150 }
1151}
1152
1153_abbr_no_color() {
1154 local -a shell_vars
1155 local -i found
1156
1157 shell_vars=( ${(k)parameters} )
1158
1159 found=$(( ! $shell_vars[(Ie)NO_COLOR] ))
1160
1161 return $found
1162}
1163
1164_abbr_regular_expansion() {
1165 {
1166 emulate -LR zsh
1167
1168 # cannot support debug message
1169
1170 local -a REPLY
1171 local abbreviation
1172 local expansion
1173
1174 _abbr_regular_expansion:get_expansion() {
1175 {
1176 # cannot support debug message
1177
1178 _abbr_regular_expansion:get_expansion:get_prefixed_expansion() {
1179 # cannot support debug message
1180
1181 local abbreviation
1182 local abbreviation_sans_prefix
1183 local prefix_match
1184 local prefix_pattern
1185 local -a prefixes
1186 local -i use_globbing
1187
1188 abbreviation=$1
1189 use_globbing=$2
1190
1191 # setopt extended_glob
1192
1193 prefixes=( $ABBR_REGULAR_ABBREVIATION_SCALAR_PREFIXES )
1194
1195 (( use_globbing )) && prefixes=( $ABBR_REGULAR_ABBREVIATION_GLOB_PREFIXES )
1196
1197 while [[ ! $expansion ]] && (( #prefixes )); do
1198 prefix_pattern=$prefixes[1]
1199 shift prefixes
1200
1201 abbreviation_sans_prefix="${abbreviation#$prefix_pattern}"
1202
1203 if (( use_globbing )); then
1204 # Trim $prefix_pattern, _as a glob_ (`$~globparam` vs `$stringparam`)_, from $abbreviation
1205 abbreviation_sans_prefix=${abbreviation#$~prefix_pattern}
1206 fi
1207
1208 prefix_match=${abbreviation%$abbreviation_sans_prefix}
1209
1210 # $abbreviation_sans_prefix is now the full $abbreviation if $abbreviation doesn't start with a prefix,
1211 # or a $abbreviation with the prefix trimmed if $abbreviation does start with a prefix
1212
1213 if (( session )); then
1214 expansion=$ABBR_REGULAR_SESSION_ABBREVIATIONS[${(qqq)abbreviation_sans_prefix}]
1215 else
1216 expansion=$ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation_sans_prefix}]
1217 fi
1218
1219 if [[ -n $prefix_match ]]; then
1220 if [[ ! $expansion ]]; then
1221 expansion=$(_abbr_regular_expansion:get_expansion:get_prefixed_expansion $abbreviation_sans_prefix 1)
1222 fi
1223
1224 if [[ ! $expansion ]]; then
1225 expansion=$(_abbr_regular_expansion:get_expansion:get_prefixed_expansion $abbreviation_sans_prefix 0)
1226 fi
1227 fi
1228
1229 if [[ ! $expansion ]]; then
1230 continue
1231 fi
1232
1233 # Re-prepend anything trimmed off during the prefix check
1234 expansion="${(qqq)prefix_match}$expansion"
1235 # this quotation mark to fix syntax highlighting "
1236 done
1237
1238 'builtin' 'echo' - $expansion
1239 }
1240
1241 # this quotation mark to fix syntax highlighting "
1242
1243 local abbreviation
1244 local expansion
1245 local -i session
1246
1247 abbreviation=$1
1248 session=$2
1249
1250 if (( session )); then
1251 expansion=$ABBR_REGULAR_SESSION_ABBREVIATIONS[${(qqq)abbreviation}] # this bracket to fix syntax highlighting }
1252 else
1253 expansion=$ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}] # this bracket to fix syntax highlighting }
1254 fi
1255
1256 if [[ ! $expansion ]]; then
1257 expansion=$(_abbr_regular_expansion:get_expansion:get_prefixed_expansion $abbreviation 1)
1258 fi
1259
1260 if [[ ! $expansion ]]; then
1261 expansion=$(_abbr_regular_expansion:get_expansion:get_prefixed_expansion $abbreviation 0)
1262 fi
1263
1264 'builtin' 'echo' - $expansion
1265 } always {
1266 unfunction -m _abbr_regular_expansion:get_expansion:get_prefixed_expansion
1267 }
1268 }
1269
1270 abbreviation=$1
1271
1272 # DUPE _abbr_global_expansion, _abbr_regular_expansion
1273 # do not expand empty string or all-whitespace string
1274 ABBR_SPLIT_FN $abbreviation
1275 [[ -n $REPLY ]] || return
1276
1277 expansion=$(_abbr_regular_expansion:get_expansion $abbreviation 1)
1278
1279 if [[ ! $expansion ]]; then
1280 _abbr_create_files
1281 source ${_abbr_tmpdir}regular-user-abbreviations
1282 expansion=$(_abbr_regular_expansion:get_expansion $abbreviation 0)
1283 fi
1284
1285 'builtin' 'echo' - ${(Q)expansion}
1286 } always {
1287 unfunction -m _abbr_regular_expansion:get_expansion
1288 }
1289}
1290
1291_abbr_create_files() {
1292 emulate -LR zsh
1293
1294 # cannot support debug message
1295
1296 [[ -d $_abbr_tmpdir ]] || mkdir -p $_abbr_tmpdir
1297
1298 [[ -f ${_abbr_tmpdir}regular-user-abbreviations ]] || touch ${_abbr_tmpdir}regular-user-abbreviations
1299
1300 [[ -f ${_abbr_tmpdir}global-user-abbreviations ]] || touch ${_abbr_tmpdir}global-user-abbreviations
1301}
1302
1303_abbr_debugger() {
1304 emulate -LR zsh
1305
1306 # user abbreviations are loaded on every git subcommand, making noise
1307 (( ABBR_LOADING_USER_ABBREVIATIONS && ! ABBR_INITIALIZING )) && return
1308
1309 (( ABBR_DEBUG )) && 'builtin' 'echo' - $funcstack[2]
1310}
1311
1312_abbr_global_expansion() {
1313 emulate -LR zsh
1314
1315 # cannot support debug message
1316
1317 # `_abbr_global_expansion … 0` must always be preceded by creating and sourcing files
1318 # search this file for examples
1319
1320 local -a REPLY
1321 local abbreviation
1322 local expansion
1323 local -i session
1324
1325 abbreviation=$1
1326 session=$2
1327
1328 # DUPE _abbr_global_expansion, _abbr_regular_expansion
1329 # do not expand empty string or all-whitespace string
1330 ABBR_SPLIT_FN $abbreviation
1331 [[ -n $REPLY ]] || return
1332
1333 if (( session )); then
1334 expansion=${ABBR_GLOBAL_SESSION_ABBREVIATIONS[${(qqq)abbreviation}]}
1335 else
1336 expansion=${ABBR_GLOBAL_USER_ABBREVIATIONS[${(qqq)abbreviation}]}
1337 fi
1338
1339 'builtin' 'echo' - ${(Q)expansion}
1340}
1341
1342_abbr_load_user_abbreviations() {
1343 emulate -LR zsh
1344
1345 {
1346 _abbr_debugger
1347
1348 function _abbr_load_user_abbreviations:setup() {
1349 _abbr_debugger
1350
1351 ABBR_REGULAR_USER_ABBREVIATIONS=( )
1352 ABBR_GLOBAL_USER_ABBREVIATIONS=( )
1353
1354 _abbr_create_files
1355 }
1356
1357 function _abbr_load_user_abbreviations:load() {
1358 _abbr_debugger
1359
1360 local cmd
1361 local -a cmds
1362 local -i shwordsplit_on
1363 local -a words
1364
1365 typeset -gi ABBR_LOADING_USER_ABBREVIATIONS
1366
1367 shwordsplit_on=0
1368
1369 if [[ $options[shwordsplit] = on ]]; then
1370 shwordsplit_on=1
1371 fi
1372
1373 # Load saved user abbreviations
1374 if [[ -f $ABBR_USER_ABBREVIATIONS_FILE ]]; then
1375 unsetopt shwordsplit
1376
1377 cmds=( ${(f)"$(<$ABBR_USER_ABBREVIATIONS_FILE)"} )
1378
1379 for cmd in $cmds; do
1380 words=( ${(z)cmd} ) # this bracket for syntax highlighting }
1381
1382 # Only execute abbr commands
1383 if (( ${#words} > 1 )) && [[ ${words[1]} == abbr ]]; then
1384 abbr ${words:1}
1385 fi
1386 done
1387
1388 if (( shwordsplit_on )); then
1389 setopt shwordsplit
1390 fi
1391 unset shwordsplit_on
1392 else
1393 mkdir -p ${ABBR_USER_ABBREVIATIONS_FILE:A:h}
1394 touch $ABBR_USER_ABBREVIATIONS_FILE
1395 fi
1396
1397 typeset -p ABBR_REGULAR_USER_ABBREVIATIONS > ${_abbr_tmpdir}regular-user-abbreviations
1398 typeset -p ABBR_GLOBAL_USER_ABBREVIATIONS > ${_abbr_tmpdir}global-user-abbreviations
1399 }
1400
1401 ABBR_LOADING_USER_ABBREVIATIONS=1
1402 _abbr_load_user_abbreviations:setup
1403 _abbr_load_user_abbreviations:load
1404 unset ABBR_LOADING_USER_ABBREVIATIONS
1405 return
1406 } always {
1407 unfunction -m _abbr_load_user_abbreviations:setup
1408 unfunction -m _abbr_load_user_abbreviations:load
1409 }
1410}
1411
1412_abbr_get_available_abbreviation() {
1413 {
1414 _abbr_get_available_abbreviation:regular() {
1415 {
1416 # cannot support debug message
1417
1418 _abbr_get_available_abbreviation:regular:prefixed() {
1419 # cannot support debug message
1420
1421 local expansion
1422 local expansion_sans_prefix
1423 local prefix_match
1424 local prefix_pattern
1425 local -a prefixes
1426 local -i use_globbing
1427
1428 expansion=$1
1429 use_globbing=$2
1430
1431 prefixes=( $ABBR_REGULAR_ABBREVIATION_SCALAR_PREFIXES )
1432
1433 (( use_globbing )) && prefixes=( $ABBR_REGULAR_ABBREVIATION_GLOB_PREFIXES )
1434
1435 while [[ ! $ABBR_UNUSED_ABBREVIATION ]] && (( #prefixes )); do
1436 prefix_pattern=$prefixes[1]
1437 shift prefixes
1438
1439 expansion_sans_prefix="${expansion#$prefix_pattern}"
1440
1441 if (( use_globbing )); then
1442 # Trim $prefix_pattern, _as a glob_ (`$~globparam` vs `$stringparam`)_, from $expansion
1443 expansion_sans_prefix=${expansion#$~prefix_pattern}
1444 fi
1445
1446 prefix_match=${expansion%$expansion_sans_prefix}
1447
1448 # $expansion_sans_prefix is now the full $expansion if $expansion doesn't start with a prefix,
1449 # or a $expansion with the prefix trimmed if $expansion does start with a prefix
1450
1451 if (( session )); then
1452 ABBR_UNUSED_ABBREVIATION=${(Q)${(k)ABBR_REGULAR_SESSION_ABBREVIATIONS[(re)${(qqq)expansion_sans_prefix}]}}
1453 else
1454 ABBR_UNUSED_ABBREVIATION=${(Q)${(k)ABBR_REGULAR_USER_ABBREVIATIONS[(re)${(qqq)expansion_sans_prefix}]}}
1455 fi
1456
1457 if [[ -n $prefix_match ]]; then
1458 ABBR_UNUSED_ABBREVIATION_PREFIX+=$prefix_match
1459
1460 if [[ ! $ABBR_UNUSED_ABBREVIATION ]]; then
1461 _abbr_get_available_abbreviation:regular:prefixed $expansion_sans_prefix 1
1462 fi
1463
1464 if [[ ! $ABBR_UNUSED_ABBREVIATION ]]; then
1465 _abbr_get_available_abbreviation:regular:prefixed $expansion_sans_prefix 0
1466 fi
1467 fi
1468 done
1469 }
1470
1471 local expansion
1472 local -i session
1473
1474 expansion=$1
1475 session=$2
1476
1477 if (( session )); then
1478 ABBR_UNUSED_ABBREVIATION=${(Q)${(k)ABBR_REGULAR_SESSION_ABBREVIATIONS[(re)${(qqq)expansion}]}}
1479 else
1480 ABBR_UNUSED_ABBREVIATION=${(Q)${(k)ABBR_REGULAR_USER_ABBREVIATIONS[(re)${(qqq)expansion}]}}
1481 fi
1482
1483 if [[ -z $ABBR_UNUSED_ABBREVIATION ]]; then
1484 ABBR_UNUSED_ABBREVIATION_PREFIX=
1485 _abbr_get_available_abbreviation:regular:prefixed $expansion 1
1486 fi
1487
1488 if [[ -z $ABBR_UNUSED_ABBREVIATION ]]; then
1489 ABBR_UNUSED_ABBREVIATION_PREFIX=
1490 _abbr_get_available_abbreviation:regular:prefixed $expansion 0
1491 fi
1492
1493 if [[ -n $ABBR_UNUSED_ABBREVIATION ]]; then
1494 return
1495 fi
1496
1497 ABBR_UNUSED_ABBREVIATION_PREFIX=
1498 } always {
1499 unfunction -m _abbr_get_available_abbreviation:regular:prefixed
1500 }
1501 }
1502
1503 local expansion
1504 local -i i
1505 local -a REPLY
1506 local -a words
1507
1508 expansion=$LBUFFER
1509
1510 # Look for regular session abbreviation
1511 _abbr_get_available_abbreviation:regular $expansion 1
1512
1513 if [[ -n $ABBR_UNUSED_ABBREVIATION ]]; then
1514 ABBR_UNUSED_ABBREVIATION_EXPANSION=$expansion
1515 ABBR_UNUSED_ABBREVIATION_SCOPE=session
1516 ABBR_UNUSED_ABBREVIATION_TYPE=regular
1517 return
1518 fi
1519
1520 # Look for regular user abbreviation
1521 _abbr_get_available_abbreviation:regular $expansion 0
1522
1523 if [[ -n $ABBR_UNUSED_ABBREVIATION ]]; then
1524 ABBR_UNUSED_ABBREVIATION_EXPANSION=$expansion
1525 ABBR_UNUSED_ABBREVIATION_SCOPE=user
1526 ABBR_UNUSED_ABBREVIATION_TYPE=regular
1527 return
1528 fi
1529
1530 ABBR_SPLIT_FN $LBUFFER
1531 words=( $REPLY )
1532
1533 # Look for global session abbreviation
1534
1535 while [[ -z $ABBR_UNUSED_ABBREVIATION ]] && (( i < ${#words} )); do
1536 expansion=${words:$i}
1537 ABBR_UNUSED_ABBREVIATION=${(Q)${(k)ABBR_GLOBAL_SESSION_ABBREVIATIONS[(re)${(qqq)expansion}]}}
1538 (( i++ ))
1539 done
1540
1541 if [[ -n $ABBR_UNUSED_ABBREVIATION ]]; then
1542 ABBR_UNUSED_ABBREVIATION_EXPANSION=$expansion
1543 ABBR_UNUSED_ABBREVIATION_SCOPE=session
1544 ABBR_UNUSED_ABBREVIATION_TYPE=global
1545 return
1546 fi
1547
1548 # Look for global user abbreviation
1549
1550 i=0
1551 while [[ -z $ABBR_UNUSED_ABBREVIATION ]] && (( i < ${#words} )); do
1552 expansion=${words:$i}
1553 ABBR_UNUSED_ABBREVIATION=${(Q)${(k)ABBR_GLOBAL_USER_ABBREVIATIONS[(re)${(qqq)expansion}]}}
1554 (( i++ ))
1555 done
1556
1557 if [[ -n $ABBR_UNUSED_ABBREVIATION ]]; then
1558 ABBR_UNUSED_ABBREVIATION_EXPANSION=$expansion
1559 ABBR_UNUSED_ABBREVIATION_SCOPE=user
1560 ABBR_UNUSED_ABBREVIATION_TYPE=global
1561 fi
1562 } always {
1563 unfunction -m _abbr_get_available_abbreviation:regular
1564 }
1565}
1566
1567_abbr_log_available_abbreviation() {
1568 [[ -z $ABBR_UNUSED_ABBREVIATION || -z $ABBR_UNUSED_ABBREVIATION_EXPANSION ]] && \
1569 return
1570
1571 local message
1572
1573 # @DUPE (nearly) abbr, _abbr_log_available_abbreviation, _abbr_warn_deprecation
1574 local warn_color
1575 if ! _abbr_no_color; then
1576 warn_color="$fg[yellow]"
1577 fi
1578
1579 message="abbr: \`$ABBR_UNUSED_ABBREVIATION\`${ABBR_UNUSED_ABBREVIATION_PREFIX:+, prefixed with \`$ABBR_UNUSED_ABBREVIATION_PREFIX\`,} is your $ABBR_UNUSED_ABBREVIATION_TYPE $ABBR_UNUSED_ABBREVIATION_SCOPE abbreviation for \`$ABBR_UNUSED_ABBREVIATION_EXPANSION\`"
1580
1581 if ! _abbr_no_color; then
1582 message="$warn_color$message$reset_color"
1583 fi
1584
1585 'builtin' 'print' $message
1586}
1587
1588# WIDGETS
1589# -------
1590
1591# returns 1 if the cursor wasn't placed and the entire buffer expanded,
1592# 2 if the entire buffer expanded and the cursor was placed
1593# 3 if only part of the buffer expanded and the cursor was placed
1594# 0 otherwise
1595abbr-expand() {
1596 emulate -LR zsh
1597
1598 local -a REPLY
1599 local abbreviation
1600 local -a cmds
1601 local expansion
1602 local -i i
1603 local -i j
1604 local -i k
1605 local -i matched_full_buffer
1606 local -i ret
1607 local -a subcmds
1608 local -a words
1609
1610 ABBR_UNUSED_ABBREVIATION=
1611 ABBR_UNUSED_ABBREVIATION_EXPANSION=
1612 ABBR_UNUSED_ABBREVIATION_PREFIX=
1613 ABBR_UNUSED_ABBREVIATION_SCOPE=
1614 ABBR_UNUSED_ABBREVIATION_TYPE=
1615
1616 # Check for regular expansion
1617 # Supports <=v6.3.x "from the start of the line" sense of regular
1618 # (match against entire LBUFFER) and (roughly) "command-position"
1619 # sense (matching against righ-most command in LBUFFER).
1620
1621 cmds=( $LBUFFER )
1622
1623 if (( ABBR_EXPERIMENTAL_COMMAND_POSITION_REGULAR_ABBREVIATIONS )); then
1624 # Treat all `;`, `&`, `|`, and all reduplications (e.g. `&&`, `||`) as command delimiters
1625 subcmds=( ${(s.;.)LBUFFER//[&|]/;} )
1626
1627 if (( ${#subcmds} > 1 )); then
1628 cmds+=( ${subcmds[-1]} )
1629 fi
1630 fi
1631
1632 while [[ -z $expansion ]] && (( k < ${#cmds} )); do
1633 abbreviation=${cmds[-1]}
1634 expansion=$(_abbr_regular_expansion "$abbreviation")
1635 (( k++ ))
1636 done
1637
1638 if [[ -n $expansion ]]; then
1639 # BEGIN DUPE abbr-expand 2x with differences
1640 # if it expanded and this widget can push to history
1641 (( ABBR_EXPAND_PUSH_ABBREVIATION_TO_HISTORY )) && print -s $abbreviation
1642 LBUFFER=${LBUFFER%%$abbreviation}
1643 if (( ABBR_SET_EXPANSION_CURSOR )) && [[ $expansion != ${expansion/$ABBR_EXPANSION_CURSOR_MARKER} ]]; then
1644 LBUFFER=${expansion%%$ABBR_EXPANSION_CURSOR_MARKER*}
1645 RBUFFER=${expansion#*$ABBR_EXPANSION_CURSOR_MARKER}$RBUFFER
1646 ret=2 # DUPE difference
1647 else
1648 LBUFFER+=$expansion
1649 ret=1 # DUPE difference
1650 fi
1651 return $ret
1652 # END DUPE abbr-expand 2x with differences
1653 fi
1654
1655 ABBR_SPLIT_FN $LBUFFER
1656 words=( $REPLY )
1657
1658 # Check for global session expansion
1659
1660 # first check the full LBUFFER, then trim words off the front
1661 while [[ -z $expansion ]] && (( i < ${#words} )); do
1662 abbreviation=${words:$i}
1663 expansion=$(_abbr_global_expansion "$abbreviation" 1)
1664 (( i++ ))
1665 done
1666
1667 if [[ -z $expansion ]]; then
1668 # Check for global user expansion
1669
1670 i=0
1671
1672 _abbr_create_files
1673 source ${_abbr_tmpdir}global-user-abbreviations
1674
1675 # first check the full LBUFFER, then trim words off the front
1676 while [[ -z $expansion ]] && (( i < ${#words} )); do
1677 abbreviation=${words:$i}
1678 expansion=$(_abbr_global_expansion "$abbreviation" 0)
1679 (( i++ ))
1680 done
1681 fi
1682
1683 if [[ -z $expansion ]]; then
1684 # No expansion found. See if one was available
1685
1686 (( ABBR_GET_AVAILABLE_ABBREVIATION )) && _abbr_get_available_abbreviation
1687
1688 return $ret
1689 fi
1690
1691 # BEGIN DUPE abbr-expand 2x with differences
1692 # if it expanded and this widget can push to history
1693 (( ABBR_EXPAND_PUSH_ABBREVIATION_TO_HISTORY )) && print -s $abbreviation
1694 LBUFFER=${LBUFFER%%$abbreviation}
1695 if (( ABBR_SET_EXPANSION_CURSOR )) && [[ $expansion != ${expansion/$ABBR_EXPANSION_CURSOR_MARKER} ]]; then
1696 LBUFFER+=${expansion%%$ABBR_EXPANSION_CURSOR_MARKER*}
1697 RBUFFER=${expansion#*$ABBR_EXPANSION_CURSOR_MARKER}$RBUFFER
1698 ret=3 # DUPE difference
1699 else
1700 LBUFFER+=$expansion
1701 fi
1702 return $ret
1703 # END DUPE abbr-expand 2x with differences
1704}
1705
1706abbr-expand-and-accept() {
1707 emulate -LR zsh
1708
1709 # do not support debug message
1710
1711 local -i entire_buffer_expanded
1712 local -i hist_ignore
1713 local buffer
1714 local trailing_space
1715
1716 trailing_space=${LBUFFER##*[^[:IFSSPACE:]]}
1717
1718 if [[ $_abbr_hist_ignore_space == on ]] && [[ $BUFFER[1] == ' ' ]]; then
1719 hist_ignore=1
1720 fi
1721
1722 if [[ -z $trailing_space ]]; then
1723 buffer=$BUFFER
1724
1725 abbr-expand
1726
1727 # If changing this, abbr-expand may need to change
1728 (( $? == 1 || $? == 2 )) && entire_buffer_expanded=1
1729
1730 # if it expanded and this widget can push to history
1731 if (( ! hist_ignore )) && [[ $BUFFER != $buffer ]] && (( ABBR_EXPAND_AND_ACCEPT_PUSH_ABBREVIATED_LINE_TO_HISTORY )); then
1732 # if abbr-expand didn't already push the abbreviated line to history
1733 if (( ABBR_EXPAND_PUSH_ABBREVIATION_TO_HISTORY )); then
1734 (( ! entire_buffer_expanded )) && print -s $buffer
1735 else
1736 print -s $buffer
1737 fi
1738 fi
1739 fi
1740
1741 _abbr_accept-line
1742}
1743
1744abbr-expand-and-insert() {
1745 emulate -LR zsh
1746
1747 local buffer
1748 local -i cursor_was_placed
1749
1750 abbr-expand
1751
1752 # If changing this, abbr-expand may need to change
1753 (( $? == 2 || $? == 3 )) && cursor_was_placed=1
1754 (( cursor_was_placed )) && return
1755
1756 if (( ABBR_SET_LINE_CURSOR )) && [[ $BUFFER != ${BUFFER/$ABBR_LINE_CURSOR_MARKER} ]]; then
1757 buffer=$BUFFER
1758
1759 LBUFFER=${buffer%%$ABBR_LINE_CURSOR_MARKER*}
1760 RBUFFER=${buffer#*$ABBR_LINE_CURSOR_MARKER}
1761
1762 return
1763 fi
1764
1765 zle self-insert
1766}
1767
1768# DEPRECATION
1769# -----------
1770
1771_abbr_warn_deprecation() {
1772 emulate -LR zsh
1773
1774 _abbr_debugger
1775
1776 local callstack
1777 local deprecated
1778 local message
1779 local replacement
1780
1781 # @DUPE (nearly) abbr, _abbr_log_available_abbreviation, _abbr_warn_deprecation
1782 local warn_color
1783 if ! _abbr_no_color; then
1784 warn_color="$fg[yellow]"
1785 fi
1786
1787 deprecated=$1
1788 replacement=$2
1789 callstack=$3
1790
1791 message="$deprecated is deprecated.${replacement:+ Please use $replacement instead.}"
1792
1793 if [[ -n $callstack ]]; then
1794 message+="\\n${warn_color}Called by \`$callstack\`$reset_color"
1795 fi
1796
1797 'builtin' 'print' $message
1798}
1799
1800# INITIALIZATION
1801# --------------
1802
1803_abbr_init() {
1804 emulate -LR zsh
1805
1806 local job_id
1807
1808 {
1809 local log_available_abbreviation_hook
1810 local REPLY
1811
1812 log_available_abbreviation_hook=preexec
1813 (( ABBR_LOG_AVAILABLE_ABBREVIATION_AFTER )) && log_available_abbreviation_hook=precmd
1814
1815 typeset -g ABBR_UNUSED_ABBREVIATION
1816 typeset -g ABBR_UNUSED_ABBREVIATION_EXPANSION
1817 typeset -g ABBR_UNUSED_ABBREVIATION_PREFIX
1818 typeset -g ABBR_UNUSED_ABBREVIATION_SCOPE
1819 typeset -g ABBR_UNUSED_ABBREVIATION_TYPE
1820 typeset -gA ABBR_GLOBAL_SESSION_ABBREVIATIONS
1821 typeset -gA ABBR_GLOBAL_USER_ABBREVIATIONS
1822 typeset -gi ABBR_INITIALIZING
1823 typeset -gA ABBR_REGULAR_SESSION_ABBREVIATIONS
1824 typeset -gA ABBR_REGULAR_USER_ABBREVIATIONS
1825
1826 ABBR_INITIALIZING=1
1827 ABBR_REGULAR_SESSION_ABBREVIATIONS=( )
1828 ABBR_GLOBAL_SESSION_ABBREVIATIONS=( )
1829
1830 _abbr_init:dependencies() {
1831 emulate -LR zsh
1832
1833 _abbr_debugger
1834
1835 # if installed with Homebrew, will not have .gitmodules
1836 if [[ -f ${ABBR_SOURCE_PATH}/.gitmodules && ! -f ${ABBR_SOURCE_PATH}/zsh-job-queue/zsh-job-queue.zsh ]]; then
1837 'builtin' 'print' abbr: Finishing installing dependencies
1838 'command' 'git' submodule update --init --recursive &>/dev/null
1839 fi
1840
1841 if ! [[ -f ${ABBR_SOURCE_PATH}/zsh-job-queue/zsh-job-queue.zsh ]]; then
1842 'builtin' 'print' abbr: There was a problem finishing installing dependencies
1843 return 1
1844 fi
1845
1846 source ${ABBR_SOURCE_PATH}/zsh-job-queue/zsh-job-queue.zsh __zsh-abbr
1847 }
1848
1849 _abbr_init:add_widgets() {
1850 emulate -LR zsh
1851
1852 _abbr_debugger
1853
1854 # _abbr_accept-line is called by abbr-expand-and-accept
1855 # h/t https://github.com/ohmyzsh/ohmyzsh/pull/9466/commits/11c1f96155055719e42c3bac7d10c6ef4168a04f
1856 if (( ! ${+functions[_abbr_accept-line]} )); then
1857 case "$widgets[accept-line]" in
1858 # If the accept-line widget was already redefined before zsh-abbr's initialization,
1859 # use the user-defined accept-line widget
1860 user:*)
1861 zle -N _abbr_accept-line_user_defined "${widgets[accept-line]#user:}"
1862 _abbr_accept-line() {
1863 zle _abbr_accept-line_user_defined -- "$@"
1864 }
1865 ;;
1866 # Otherwise use the standard widget
1867 builtin)
1868 _abbr_accept-line() {
1869 zle .accept-line
1870 }
1871 ;;
1872 esac
1873 fi
1874
1875 zle -N abbr-expand
1876 zle -N accept-line abbr-expand-and-accept
1877 zle -N abbr-expand-and-insert
1878 }
1879
1880 _abbr_init:bind_widgets() {
1881 emulate -LR zsh
1882
1883 _abbr_debugger
1884
1885 # spacebar expands abbreviations
1886 bindkey " " abbr-expand-and-insert
1887
1888 # control-spacebar is a normal space
1889 bindkey "^ " magic-space
1890
1891 # when running an incremental search,
1892 # spacebar behaves normally and control-space expands abbreviations
1893 bindkey -M isearch "^ " abbr-expand-and-insert
1894 bindkey -M isearch " " magic-space
1895 }
1896
1897 _abbr_init:deprecations() {
1898 {
1899 emulate -LR zsh
1900
1901 _abbr_debugger
1902
1903 local -A deprecated_widgets
1904
1905 deprecated_widgets=( )
1906
1907 # START Deprecation notices for values that could not be meaningfully set after initialization
1908 # Example form:
1909 # (( ${+DEPRECATED_VAL} )) && _abbr_warn_deprecation DEPRECATED_VAL VAL
1910 # VAL=$DEPRECATED_VAL
1911
1912 # END Deprecation notices for values that could not be meaningfully set after initialization
1913
1914 # START Deprecation notices for functions
1915 # Example form:
1916 # deprecated_fn() {
1917 # _abbr_warn_deprecation deprecated_fn fn
1918 # fn
1919 # }
1920
1921 # END Deprecation notices for functions
1922
1923 # Deprecation notices for zle widgets
1924 _abbr_init:deprecations:widgets() {
1925
1926 # cannot support debug message
1927
1928 local bindkey_declaration
1929 local bindkey_declarations
1930 local replacement
1931 local deprecated
1932
1933 bindkey_declarations=$(bindkey)
1934
1935 # deprecated_widgets is defined in _abbr_init:deprecations
1936 for deprecated replacement in ${(kv)deprecated_widgets}; do
1937 bindkey_declaration=$('builtin' 'echo' $bindkey_declarations | grep $deprecated)
1938
1939 zle -N $deprecated
1940
1941 if [[ -n $bindkey_declaration ]]; then
1942 _abbr_warn_deprecation $deprecated $replacement "bindkey $bindkey_declaration"
1943 fi
1944 done
1945 }
1946
1947 (( ${#deprecated_widgets} )) && {
1948 _abbr_init:deprecations:widgets
1949 }
1950 } always {
1951 unfunction -m _abbr_init:deprecations:widgets
1952 }
1953 }
1954
1955 if ! _abbr_no_color; then
1956 'builtin' 'autoload' -U colors && colors
1957 fi
1958
1959 _abbr_debugger
1960
1961 _abbr_init:dependencies || return
1962
1963 job-queue__zsh-abbr push zsh-abbr initialization
1964 job_id=$REPLY
1965
1966 (( ABBR_LOG_AVAILABLE_ABBREVIATION && ABBR_GET_AVAILABLE_ABBREVIATION )) && {
1967 'builtin' 'autoload' -Uz add-zsh-hook
1968 'add-zsh-hook' $log_available_abbreviation_hook _abbr_log_available_abbreviation
1969 }
1970
1971 _abbr_load_user_abbreviations
1972 _abbr_init:add_widgets
1973 _abbr_init:deprecations
1974 (( ABBR_DEFAULT_BINDINGS )) && _abbr_init:bind_widgets
1975
1976 job-queue__zsh-abbr pop zsh-abbr $job_id
1977 unset ABBR_INITIALIZING
1978 } always {
1979 unfunction -m _abbr_init:add_widgets
1980 unfunction -m _abbr_init:bind_widgets
1981 unfunction -m _abbr_init:dependencies
1982 unfunction -m _abbr_init:deprecations
1983 }
1984}
1985
1986# _abbr_init should remain the last function defined in this file
1987
1988typeset -g ABBR_SOURCE_PATH
1989ABBR_SOURCE_PATH=${0:A:h}
1990_abbr_init
1991
1992# can't unset
1993# unset _abbr_tmpdir
1994
1995# can't unfunction
1996# _abbr_accept-line
1997# _abbr_create_files
1998# _abbr_debugger
1999# _abbr_get_available_abbreviation
2000# _abbr_global_expansion
2001# _abbr_load_user_abbreviations
2002# _abbr_log_available_abbreviation
2003# _abbr_no_color
2004# _abbr_regular_expansion
2005
2006unfunction -m _abbr
2007unfunction -m _abbr_init
2008unfunction -m _abbr_warn_deprecation
2009unfunction -m _abbr:add
2010unfunction -m _abbr:clear_session
2011unfunction -m _abbr:erase
2012unfunction -m _abbr:expand
2013unfunction -m _abbr:expansion
2014unfunction -m _abbr:export_aliases
2015unfunction -m _abbr:git
2016unfunction -m _abbr:import_aliases
2017unfunction -m _abbr:import_fish
2018unfunction -m _abbr:import_git_aliases
2019unfunction -m _abbr:list
2020unfunction -m _abbr:list_abbreviations
2021unfunction -m _abbr:list_commands
2022unfunction -m _abbr:print_version
2023unfunction -m _abbr:profile
2024unfunction -m _abbr:rename
2025unfunction -m _abbr:util_add
2026unfunction -m _abbr:util_alias
2027unfunction -m _abbr:util_bad_options
2028unfunction -m _abbr:util_check_command
2029unfunction -m _abbr:util_error
2030unfunction -m _abbr:util_import_alias
2031unfunction -m _abbr:util_list
2032unfunction -m _abbr:util_list_item
2033unfunction -m _abbr:util_log_unless_quiet
2034unfunction -m _abbr:util_log_unless_quieter
2035unfunction -m _abbr:util_print
2036unfunction -m _abbr:util_set_once
2037unfunction -m _abbr:util_set_to_typed_scope
2038unfunction -m _abbr:util_sync_user
2039unfunction -m _abbr:util_usage
2040unfunction -m _abbr:util_warn
diff --git a/.config/shell/zsh-abbr/zsh-job-queue/zsh-job-queue.plugin.zsh b/.config/shell/zsh-abbr/zsh-job-queue/zsh-job-queue.plugin.zsh
new file mode 100755
index 0000000..6e5ba79
--- /dev/null
+++ b/.config/shell/zsh-abbr/zsh-job-queue/zsh-job-queue.plugin.zsh
@@ -0,0 +1,2 @@
1fpath+=${0:A:h}/completions
2source ${0:A:h}/zsh-job-queue.zsh
diff --git a/.config/shell/zsh-abbr/zsh-job-queue/zsh-job-queue.zsh b/.config/shell/zsh-abbr/zsh-job-queue/zsh-job-queue.zsh
new file mode 100755
index 0000000..5774e78
--- /dev/null
+++ b/.config/shell/zsh-abbr/zsh-job-queue/zsh-job-queue.zsh
@@ -0,0 +1,279 @@
1#!/usr/bin/env zsh
2
3# Cross-session job queues manager for zsh
4# https://zsh-job-queue.olets.dev
5# v3.0.0
6# Copyright (c) 2024 Henry Bley-Vroman
7#
8# Usage:
9#
10# ```
11# id=$(job-queue push <scope> [<job-description> [<support-ticket-url>]])
12# # waits for its turn in the <scope> queue
13# # do some work
14# job-queue pop $id
15# ```
16#
17# Optionally include a suffix argument when sourcing this file
18# source path/to/zsh-job-queue.zsh <suffix>
19# The suffix is appended to the names of the file's exported functions.
20# This can be used, for instance, to distinguish multiple copies
21# of zsh-job-queue.
22#
23# In .zshrc:
24# source path/to/zsh-job-queue/zsh-job-queue.zsh
25# In a plugin which bundles its own (e.g. Git submodule or subtree) copy:
26# source ./zsh-job-queue/zsh-job-queue.zsh __my-plugin
27#
28# Refer to zsh-abbr for an example of the latter
29
30function _job_queue:init"${1:-}"() { # this quotation mark to fix syntax highlighting "
31 zmodload zsh/datetime
32
33 # Log debugging messages?
34 typeset -gi JOB_QUEUE_DEBUG=${JOB_QUEUE_DEBUG:-0}
35
36 # How old does a job have to be to be considered timed out?
37 typeset -gi JOB_QUEUE_TIMEOUT_AGE_SECONDS=${JOB_QUEUE_TIMEOUT_AGE_SECONDS:-30}
38
39 # Temp dir
40 typeset -g JOB_QUEUE_TMPDIR=${${JOB_QUEUE_TMPDIR:-${${TMPDIR:-/tmp}%/}/zsh-job-queue}%/}/
41 typeset -g JOB_QUEUE_PRIVILEGED_TEMPDIR=${${JOB_QUEUE_PRIVILEGED_TEMPDIR:-${JOB_QUEUE_TMPDIR:-${${TMPDIR:-/tmp}%/}/zsh-job-queue-privileged-users}}%/}/
42
43 typeset -g _job_queue_tmpdir=$JOB_QUEUE_TMPDIR
44
45 # Temp dir for privileged users
46 if [[ ${(%):-%#} == '#' ]]; then
47 _job_queue_tmpdir=$JOB_QUEUE_PRIVILEGED_TEMPDIR
48 fi
49}
50
51function job-queue"${1:-}"() { # this quotation mark to fix syntax highlighting "
52 emulate -LR zsh
53
54 {
55 # _job_queue:clear
56 # gets unfunction'd
57 #
58 # @param {string} scope
59 function _job_queue:clear() {
60 emulate -LR zsh
61
62 _job_queue:debugger
63
64 local scope
65 scope=$1
66
67 rm -rf $_job_queue_tmpdir${scope}
68 }
69
70 # gets unfunction'd
71 function _job_queue:debugger() {
72 emulate -LR zsh
73
74 (( JOB_QUEUE_DEBUG )) && 'builtin' 'echo' - $funcstack[2]
75 }
76
77 # gets unfunction'd
78 function _job_queue:help() {
79 emulate -LR zsh
80
81 'command' 'man' job-queue 2>/dev/null || 'command' 'man' ${0:A:h}/man/man1/job-queue.1
82 }
83
84 # _job_queue:pop
85 # gets unfunction'd
86 #
87 # @param {string} scope
88 # @param {string} job_id
89 function _job_queue:pop() {
90 emulate -LR zsh
91
92 _job_queue:debugger
93
94 local scope
95 local job_id
96
97 scope=$1
98 job_id=$2
99
100 'command' 'rm' $_job_queue_tmpdir${scope}/$job_id &>/dev/null
101 }
102
103 # _job_queue:push
104 # gets unfunction'd
105 #
106 # @param {string} scope
107 # @param {string} job_id
108 # @param {string} job_description
109 # @param {string} support_ticket_url
110 function _job_queue:push() {
111 emulate -LR zsh
112
113 {
114 _job_queue:debugger
115
116 local front_of_queue_job_age
117 local front_of_queue_job_id
118 local front_of_queue_job_path
119 local job_description
120 local job_id
121 local scope
122 local support_ticket_url
123
124 _job_queue:generate-id # sets REPLY variable
125 job_id=$REPLY
126
127 scope=$1
128 job_description=$2
129 support_ticket_url=$3
130
131 # gets unfunction'd
132 function _job_queue:push:add_job() {
133 _job_queue:debugger
134
135 if ! [[ -d $_job_queue_tmpdir${scope} ]]; then
136 'command' 'mkdir' -p $_job_queue_tmpdir${scope}
137 fi
138
139 'builtin' 'echo' $job_description > $_job_queue_tmpdir${scope}/$job_id
140 'builtin' 'echo' $support_ticket_url >> $_job_queue_tmpdir${scope}/$job_id
141 }
142
143 # gets unfunction'd
144 function _job_queue:push:get_front_of_queue_job_id() {
145 # cannot support debug message
146
147 'command' 'ls' -t $_job_queue_tmpdir${scope} | 'command' 'tail' -1
148 }
149
150 # gets unfunction'd
151 function _job_queue:push:handle_timeout() {
152 _job_queue:debugger
153
154 local msg
155 local -a msg_data
156 local msg_description
157 local msg_url
158
159 front_of_queue_job_path=$_job_queue_tmpdir${scope}/$front_of_queue_job_id
160
161 msg_data=( ${(f)"$('command' 'cat' $front_of_queue_job_path)"} ) # this quotation mark to improve syntax highlighting "
162 msg_description=$msg_data[1]
163 msg_url=$msg_data[2]
164
165 'builtin' 'echo' "job-queue: A job added at $(strftime '%T %b %d %Y' ${${front_of_queue_job_id%%-*}%%.*}) has timed out."
166
167 msg="The job was related to \`$scope\`"
168
169 if [[ -n $msg_description ]]; then
170 msg+="'s \`$msg_description\`"
171 fi
172
173 msg+="."
174
175 'builtin' 'echo' $msg
176 'builtin' 'echo' "This could be the result of manually terminating an activity in \`$scope\`."
177
178 if [[ -n $msg_url ]]; then
179 'builtin' 'echo' "If you believe it reflects bug in \`$scope\`, please report it at $msg_url"
180 fi
181
182 'builtin' 'echo'
183
184 'command' 'rm' $front_of_queue_job_path &>/dev/null
185 }
186
187 # gets unfunction'd
188 function _job_queue:push:wait_turn() {
189 front_of_queue_job_id=$(_job_queue:push:get_front_of_queue_job_id)
190
191 while [[ $front_of_queue_job_id != $job_id ]]; do
192 front_of_queue_job_id=$(_job_queue:push:get_front_of_queue_job_id)
193
194 front_of_queue_job_age=$(( $EPOCHREALTIME - ${front_of_queue_job_id%%-*} ))
195
196 if (( $front_of_queue_job_age > $JOB_QUEUE_TIMEOUT_AGE_SECONDS )); then
197 _job_queue:push:handle_timeout
198 fi
199
200 'command' 'sleep' 0.01
201 done
202 }
203
204 _job_queue:push:add_job
205 _job_queue:push:wait_turn
206 } always {
207 unfunction -m _job_queue:push:add_job
208 unfunction -m _job_queue:push:get_front_of_queue_job_id
209 unfunction -m _job_queue:push:handle_timeout
210 unfunction -m _job_queue:push:wait_turn
211 }
212 }
213
214 # gets unfunction'd
215 function _job_queue:generate-id() {
216 emulate -LR zsh
217
218 # cannot support debug message
219
220 local uuid
221
222 uuid=$('command' 'uuidgen' 2>/dev/null || 'command' 'cat' /dev/urandom | 'command' 'base64' | 'command' 'tr' -dc '0-9a-zA-Z' | 'command' 'head' -c36)
223
224 REPLY="$EPOCHREALTIME--$uuid"
225 }
226
227 # gets unfunction'd
228 function _job_queue:version() {
229 emulate -LR zsh
230
231 'builtin' 'printf' "zsh-job-queue version %s\n" 3.0.0
232 }
233
234 for opt in "$@"; do
235 case $opt in
236 clear)
237 shift
238 _job_queue:clear $@
239 return
240 ;;
241 "--help"|\
242 help)
243 _job_queue:help
244 return
245 ;;
246 "--version"|\
247 "-v")
248 _job_queue:version
249 return
250 ;;
251 pop)
252 shift
253 _job_queue:pop $@
254 return
255 ;;
256 push)
257 shift
258 _job_queue:push $@
259 return
260 ;;
261 *)
262 'builtin' 'echo' "job-queue: Invalid option $opt"
263 return 1
264 ;;
265 esac
266 done
267 } always {
268 unfunction -m _job_queue:clear
269 unfunction -m _job_queue:debugger
270 unfunction -m _job_queue:help
271 unfunction -m _job_queue:pop
272 unfunction -m _job_queue:push
273 unfunction -m _job_queue:generate-id
274 unfunction -m _job_queue:version
275 }
276}
277
278_job_queue:init${1:-}
279unfunction -m _job_queue:init${1:-}