diff --git a/README.md b/README.md index e04985f6..eff6fda0 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,14 @@ zsh-abbr has commands to add, rename, and erase abbreviations; to add abbreviati % gco[Enter] # expands and accepts git checkout ``` - The ABBREVIATION must be only one word long. + The ABBREVIATION may be more than one word long. + + ```shell + % abbr "git cp"="git cherry-pick" + % git cp[Space] # expands as git cherry-pick + % abbr g=git + % g[Space]cp[Space] # expands to git cherry-pick + ``` As with aliases, to include whitespace, quotation marks, or other special characters like `;`, `|`, or `&` in the EXPANSION, quote the EXPANSION or `\`-escape the characters as necessary. diff --git a/man/man1/abbr.1 b/man/man1/abbr.1 index 04ed11e8..a854a093 100644 --- a/man/man1/abbr.1 +++ b/man/man1/abbr.1 @@ -54,6 +54,8 @@ Will error rather than overwrite an existing abbreviation. Will warn if the abbreviation would replace an existing command. To add in spite of the warning, use [\fI\-\-force\fR]. +May be multiple words. Quote or escape word delimiters. + .IP \(bu \fBclear\-session\fR or \fBc\fR diff --git a/tests/abbr.ztr b/tests/abbr.ztr index 39ad916d..20ac6677 100644 --- a/tests/abbr.ztr +++ b/tests/abbr.ztr @@ -1,4 +1,3 @@ - # Tests require ztr # https://github.com/olets/zsh-test-runner # Run the suite by sourcing it or by passing it to `zsh` @@ -9,6 +8,9 @@ ABBR_USER_ABBREVIATIONS_FILE=${0:A:h}/abbreviations.$RANDOM touch $ABBR_USER_ABBREVIATIONS_FILE test_abbr_abbreviation="zsh_abbr_test" +test_abbr_abbreviation_2="zsh_abbr_test_2" +test_abbr_abbreviation_multiword="zsh_abbr_test second_word" +test_abbr_abbreviation_multiword_2="zsh_abbr_test other_second_word" test_abbr_expansion="zsh abbr test" source ${0:A:h}/../zsh-abbr.zsh @@ -24,59 +26,143 @@ ztr test '[[ ${#ABBR_REGULAR_USER_ABBREVIATIONS} == 0 ]]' \ "Can erase an abbreviation" \ "Dependencies: add" +abbr add $test_abbr_abbreviation_multiword=$test_abbr_expansion +abbr erase $test_abbr_abbreviation_multiword +ztr test '[[ ${#ABBR_REGULAR_USER_ABBREVIATIONS} == 0 ]]' \ + "Can erase a multi-word abbreviation" \ + "Dependencies: add" + abbr add $test_abbr_abbreviation=$test_abbr_expansion -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$test_abbr_abbreviation]} == $test_abbr_expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation}]} == ${(qqq)test_abbr_expansion} ]]' \ "Can add an abbreviation with the add flag" \ "Dependencies: erase" abbr erase $test_abbr_abbreviation +abbr add $test_abbr_abbreviation_multiword=$test_abbr_expansion +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation_multiword}]} == ${(qqq)test_abbr_expansion} ]]' \ + "Can add a multi-word abbreviation with the add flag" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation_multiword + abbr add -g $test_abbr_abbreviation=$test_abbr_expansion -ztr test '[[ ${(Q)ABBR_GLOBAL_USER_ABBREVIATIONS[$test_abbr_abbreviation]} == $test_abbr_expansion ]]' \ +ztr test '[[ ${ABBR_GLOBAL_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation}]} == ${(qqq)test_abbr_expansion} ]]' \ "Can add a global abbreviation with the add flag" \ "Dependencies: erase" abbr erase $test_abbr_abbreviation +abbr add -g $test_abbr_abbreviation_multiword=$test_abbr_expansion +ztr test '[[ ${ABBR_GLOBAL_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation_multiword}]} == ${(qqq)test_abbr_expansion} ]]' \ + "Can add a multi-word global abbreviation with the add flag" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation_multiword + abbr add -S $test_abbr_abbreviation=$test_abbr_expansion -ztr test '[[ ${(Q)ABBR_REGULAR_SESSION_ABBREVIATIONS[$test_abbr_abbreviation]} == $test_abbr_expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_SESSION_ABBREVIATIONS[${(qqq)test_abbr_abbreviation}]} == ${(qqq)test_abbr_expansion} ]]' \ "Can add a regular session abbreviation with the add flag" \ "Dependencies: erase" abbr erase $test_abbr_abbreviation +abbr add -S $test_abbr_abbreviation_multiword=$test_abbr_expansion +ztr test '[[ ${ABBR_REGULAR_SESSION_ABBREVIATIONS[${(qqq)test_abbr_abbreviation_multiword}]} == ${(qqq)test_abbr_expansion} ]]' \ + "Can add a multi-word regular session abbreviation with the add flag" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation_multiword + abbr add -S -g $test_abbr_abbreviation=$test_abbr_expansion -ztr test '[[ ${(Q)ABBR_GLOBAL_SESSION_ABBREVIATIONS[$test_abbr_abbreviation]} == $test_abbr_expansion ]]' \ +ztr test '[[ ${ABBR_GLOBAL_SESSION_ABBREVIATIONS[${(qqq)test_abbr_abbreviation}]} == ${(qqq)test_abbr_expansion} ]]' \ "Can add a global session abbreviation with the add flag" \ "Dependencies: erase" abbr erase $test_abbr_abbreviation +abbr add -S -g $test_abbr_abbreviation_multiword=$test_abbr_expansion +ztr test '[[ ${ABBR_GLOBAL_SESSION_ABBREVIATIONS[${(qqq)test_abbr_abbreviation_multiword}]} == ${(qqq)test_abbr_expansion} ]]' \ + "Can add a multi-word global session abbreviation with the add flag" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation_multiword + abbr $test_abbr_abbreviation=$test_abbr_expansion -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$test_abbr_abbreviation]} == $test_abbr_expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation}]} == ${(qqq)test_abbr_expansion} ]]' \ "Can add an abbreviation without the add flag" \ "Dependencies: erase" abbr erase $test_abbr_abbreviation +abbr $test_abbr_abbreviation_multiword=$test_abbr_expansion +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation_multiword}]} == ${(qqq)test_abbr_expansion} ]]' \ + "Can add a multi-word abbreviation without the add flag" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation_multiword + abbr -S $test_abbr_abbreviation=$test_abbr_expansion abbr clear-session ztr test '[[ ${#ABBR_REGULAR_SESSION_ABBREVIATIONS} == 0 ]]' \ "Can clear session abbreviations" -abbr $test_abbr_abbreviation=$test_abbr_expansion +abbr add $test_abbr_abbreviation=$test_abbr_expansion ztr test '[[ $(abbr expand $test_abbr_abbreviation) == $test_abbr_expansion ]]' \ "Can expand an abbreviation in a script" \ "Dependencies: erase" abbr erase $test_abbr_abbreviation +abbr add -g $test_abbr_abbreviation=$test_abbr_expansion +ztr test '[[ $(abbr expand $test_abbr_abbreviation) == $test_abbr_expansion ]]' \ + "Can expand a global abbreviation in a script" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation + +abbr add -S $test_abbr_abbreviation=$test_abbr_expansion +ztr test '[[ $(abbr expand $test_abbr_abbreviation) == $test_abbr_expansion ]]' \ + "Can expand a session abbreviation in a script" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation + +abbr add -S -g $test_abbr_abbreviation=$test_abbr_expansion +ztr test '[[ $(abbr expand $test_abbr_abbreviation) == $test_abbr_expansion ]]' \ + "Can expand a global session abbreviation in a script" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation + +abbr $test_abbr_abbreviation_multiword=$test_abbr_expansion +ztr test '[[ $(abbr expand $test_abbr_abbreviation_multiword) == $test_abbr_expansion ]]' \ + "Can expand a multi-word abbreviation in a script" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation_multiword + abbr $test_abbr_abbreviation=$test_abbr_expansion -abbr rename $test_abbr_abbreviation ${test_abbr_abbreviation}_new -ztr test '! (( ${+ABBR_REGULAR_USER_ABBREVIATIONS[$test_abbr_abbreviation]} )) \ - && [[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[${test_abbr_abbreviation}_new]} == $test_abbr_expansion ]]' \ - "Can rename an abbreviation" \ +abbr rename $test_abbr_abbreviation $test_abbr_abbreviation_2 +ztr test '! (( ${+ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation}]} )) \ + && [[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation_2}]} == ${(qqq)test_abbr_expansion} ]]' \ + "Can rename a single-word abbreviation to another single word" \ "Dependencies: erase" -abbr erase ${test_abbr_abbreviation}_new +abbr erase $test_abbr_abbreviation_2 + +abbr $test_abbr_abbreviation=$test_abbr_expansion +abbr rename $test_abbr_abbreviation $test_abbr_abbreviation_multiword +ztr test '! (( ${+ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation}]} )) \ + && [[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation_multiword}]} == ${(qqq)test_abbr_expansion} ]]' \ + "Can rename an single-word abbreviation to multiple words" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation_multiword + +abbr $test_abbr_abbreviation_multiword=$test_abbr_expansion +abbr rename $test_abbr_abbreviation_multiword $test_abbr_abbreviation_multiword_2 +ztr test '! (( ${+ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation_multiword}]} )) \ + && [[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation_multiword_2}]} == ${(qqq)test_abbr_expansion} ]]' \ + "Can rename an multi-word abbreviation to different words" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation_multiword_2 + +abbr $test_abbr_abbreviation_multiword=$test_abbr_expansion +abbr rename $test_abbr_abbreviation_multiword $test_abbr_abbreviation +ztr test '! (( ${+ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation_multiword}]} )) \ + && [[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation}]} == ${(qqq)test_abbr_expansion} ]]' \ + "Can rename an multi-word abbreviation to a single word" \ + "Dependencies: erase" +abbr erase $test_abbr_abbreviation abbreviation=a expansion="b'c'd" abbr $abbreviation=$expansion -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} == $expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} == ${(qqq)expansion} ]]' \ "Double-quoted single quotes in the expansion are preserved" \ "Dependencies: erase" abbr erase $abbreviation @@ -84,7 +170,7 @@ abbr erase $abbreviation abbreviation=a expansion='b"c"d' abbr $abbreviation=$expansion -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} == $expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} == ${(qqq)expansion} ]]' \ "Single-quoted double quotes in the expansion are preserved" \ "Dependencies: erase" abbr erase $abbreviation @@ -92,7 +178,7 @@ abbr erase $abbreviation abbreviation=a expansion='b'cd abbr $abbreviation=$expansion -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} == $expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} == ${(qqq)expansion} ]]' \ "Bare single quotes at the start of the expansion are swallowed" \ "Dependencies: erase" abbr erase $abbreviation @@ -100,7 +186,7 @@ abbr erase $abbreviation abbreviation=a expansion=b'c'd abbr $abbreviation=$expansion -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} == $expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} == ${(qqq)expansion} ]]' \ "Bare single quotes in the middle of the expansion are swallowed" \ "Dependencies: erase" abbr erase $abbreviation @@ -108,7 +194,7 @@ abbr erase $abbreviation abbreviation=a expansion="b"cd abbr $abbreviation=$expansion -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} == $expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} == ${(qqq)expansion} ]]' \ "Bare double quotes at the start of the expansion are swallowed" \ "Dependencies: erase" abbr erase $abbreviation @@ -116,7 +202,7 @@ abbr erase $abbreviation abbreviation=a expansion=b"c"d abbr $abbreviation=$expansion -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} == $expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} == ${(qqq)expansion} ]]' \ "Bare double quotes in the middle of the expansion are swallowed" \ "Dependencies: erase" abbr erase $abbreviation @@ -125,7 +211,7 @@ abbreviation=zsh_abbr_test_alias expansion=abc alias $abbreviation=$expansion abbr import-aliases -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} == $expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} == ${(qqq)expansion} ]]' \ "Can import aliases" \ "Dependencies: erase" abbr erase $abbreviation @@ -138,7 +224,7 @@ abbreviation=zsh_abbr_test_alias expansion="a b" alias $abbreviation=$expansion abbr import-aliases -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} == $expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} == ${(qqq)expansion} ]]' \ "Can import a multi-word alias" \ "Dependencies: erase" abbr erase $abbreviation @@ -151,7 +237,7 @@ abbreviation=zsh_abbr_test_alias expansion="a \"b\"" alias $abbreviation=$expansion abbr import-aliases -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} == $expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} == ${(qqq)expansion} ]]' \ "Can import a double-quoted alias with escaped double quotation marks" \ "Dependencies: erase" abbr erase $abbreviation @@ -164,7 +250,7 @@ abbreviation=zsh_abbr_test_alias expansion='a "b"' alias $abbreviation=$expansion abbr import-aliases -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} == $expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} == ${(qqq)expansion} ]]' \ "Can import a single-quoted alias with double quotation marks" \ "Dependencies: erase" abbr erase $abbreviation @@ -177,7 +263,7 @@ abbreviation=zsh_abbr_test_alias expansion="a 'b'" alias $abbreviation=$expansion abbr import-aliases -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} == $expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} == ${(qqq)expansion} ]]' \ "Can import a double-quoted alias with single quotation marks" \ "Dependencies: erase" abbr erase $abbreviation @@ -189,39 +275,39 @@ ztr test '[[ -z $(abbr expand $test_abbr_abbreviation) ]]' \ "Can delete a user abbreviation from outside abbr without unexpected retention" echo "abbr add $test_abbr_abbreviation='$test_abbr_expansion'" > $ABBR_USER_ABBREVIATIONS_FILE -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[$test_abbr_abbreviation]} == $test_abbr_expansion ]]' \ +ztr test '[[ ${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)test_abbr_abbreviation}]} == ${(qqq)test_abbr_expansion} ]]' \ "Can add a user abbreviation from outside abbr without data loss" \ "Dependencies: erase" abbr erase $test_abbr_abbreviation abbr import-git-aliases --file ${0:A:h}/test-gitconfig -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[test-subcommand]} == "git status" ]] \ - && [[ ${(Q)ABBR_GLOBAL_USER_ABBREVIATIONS[gtest-subcommand]} == "git status" ]]' \ +ztr test '[[ $(abbr expand test-subcommand) == "git status" ]] \ + && [[ $(abbr expand gtest-subcommand) == "git status" ]]' \ "Can import single-word subcommand Git aliases" \ - "Dependencies: erase" + "Dependencies: erase, expand" abbr erase test-subcommand abbr erase gtest-subcommand -ztr test '[[ ${(Q)ABBR_REGULAR_USER_ABBREVIATIONS[test-subcommand-multiword]} == "git checkout main" ]] \ - && [[ ${(Q)ABBR_GLOBAL_USER_ABBREVIATIONS[gtest-subcommand-multiword]} == "git checkout main" ]]' \ +ztr test '[[ $(abbr expand test-subcommand-multiword) == "git checkout main" ]] \ + && [[ $(abbr expand gtest-subcommand-multiword) == "git checkout main" ]]' \ "Can import multi-word subcommand Git aliases" \ - "Dependencies: erase" -abbr erase test-subcommand-multiword -abbr erase gtest-subcommand-multiword + "Dependencies: erase, expand" +abbr erase test-subcommand-multi-word +abbr erase gtest-subcommand-multi-word -ztr test '(( ! ${+ABBR_REGULAR_USER_ABBREVIATIONS[test-command]} )) \ - && (( ! ${+ABBR_GLOBAL_USER_ABBREVIATIONS[gtest-command]} ))' \ +ztr test '(( ! ${+ABBR_REGULAR_USER_ABBREVIATIONS["test-command"]} )) \ + && (( ! ${+ABBR_GLOBAL_USER_ABBREVIATIONS["gtest-command"]} ))' \ "Cannot import command Git aliases" \ "Dependencies: erase" -ztr test '(( ! ${+ABBR_REGULAR_USER_ABBREVIATIONS[test-function]} )) \ - && (( ! ${+ABBR_GLOBAL_USER_ABBREVIATIONS[gtest-function]} ))' \ +ztr test '(( ! ${+ABBR_REGULAR_USER_ABBREVIATIONS["test-function"]} )) \ + && (( ! ${+ABBR_GLOBAL_USER_ABBREVIATIONS["gtest-function"]} ))' \ "Cannot import single-line function Git aliases" \ "Dependencies: erase" -ztr test '(( ! ${+ABBR_REGULAR_USER_ABBREVIATIONS[test-function-multiline]} )) \ - && (( ! ${+ABBR_GLOBAL_USER_ABBREVIATIONS[gtest-function-multiline]} ))' \ +ztr test '(( ! ${+ABBR_REGULAR_USER_ABBREVIATIONS["test-function-multiline"]} )) \ + && (( ! ${+ABBR_GLOBAL_USER_ABBREVIATIONS["gtest-function-multiline"]} ))' \ "Cannot import multi-line function Git aliases" \ "Dependencies: erase" diff --git a/zsh-abbr.zsh b/zsh-abbr.zsh index 20c6acb0..2f5e5868 100755 --- a/zsh-abbr.zsh +++ b/zsh-abbr.zsh @@ -93,8 +93,8 @@ _abbr() { abbreviation=${(q)abbreviation} expansion=${(q)expansion} fi - - if ! [[ $abbreviation && $expansion && $abbreviation != $1 ]]; then + + if [[ -z $abbreviation || -z $expansion || $abbreviation == $1 ]]; then _abbr:util_error "abbr add: Requires abbreviation and expansion" return fi @@ -135,14 +135,14 @@ _abbr() { if [[ $scope != 'user' ]]; then if [[ $type != 'regular' ]]; then - if (( ${+ABBR_GLOBAL_SESSION_ABBREVIATIONS[$abbreviation]} )); then + if (( ${+ABBR_GLOBAL_SESSION_ABBREVIATIONS[${(qqq)abbreviation}]} )); then (( ABBR_DEBUG )) && 'builtin' 'echo' " Found a global session abbreviation" abbreviations_sets+=( ABBR_GLOBAL_SESSION_ABBREVIATIONS ) fi fi if [[ $type != 'global' ]]; then - if (( ${+ABBR_REGULAR_SESSION_ABBREVIATIONS[$abbreviation]} )); then + if (( ${+ABBR_REGULAR_SESSION_ABBREVIATIONS[${(qqq)abbreviation}]} )); then (( ABBR_DEBUG )) && 'builtin' 'echo' " Found a regular session abbreviation" abbreviations_sets+=( ABBR_REGULAR_SESSION_ABBREVIATIONS ) fi @@ -155,7 +155,7 @@ _abbr() { source ${ABBR_TMPDIR}global-user-abbreviations fi - if (( ${+ABBR_GLOBAL_USER_ABBREVIATIONS[$abbreviation]} )); then + if (( ${+ABBR_GLOBAL_USER_ABBREVIATIONS[${(qqq)abbreviation}]} )); then (( ABBR_DEBUG )) && 'builtin' 'echo' " Found a global user abbreviation" abbreviations_sets+=( ABBR_GLOBAL_USER_ABBREVIATIONS ) fi @@ -166,7 +166,7 @@ _abbr() { source ${ABBR_TMPDIR}regular-user-abbreviations fi - if (( ${+ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} )); then + if (( ${+ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}]} )); then (( ABBR_DEBUG )) && 'builtin' 'echo' " Found a regular user abbreviation" abbreviations_sets+=( ABBR_REGULAR_USER_ABBREVIATIONS ) fi @@ -174,25 +174,25 @@ _abbr() { fi if ! (( ${#abbreviations_sets} )); then - _abbr:util_error "abbr erase: No${type:+ $type}${scope:+ $scope} abbreviation \`$abbreviation\` found" + _abbr:util_error "abbr erase: No${type:+ $type}${scope:+ $scope} abbreviation \`${(Q)abbreviation}\` found" elif [[ ${#abbreviations_sets} == 1 ]]; then verb_phrase="Would erase" if ! (( dry_run )); then verb_phrase="Erased" - unset "${abbreviations_sets}[${(b)abbreviation}]" # quotation marks required + unset "${abbreviations_sets}[${(b)${(qqq)abbreviation}}]" # quotation marks required if [[ $abbreviations_sets =~ USER ]]; then _abbr:util_sync_user fi fi - _abbr:util_log_unless_quiet "$success_color$verb_phrase$reset_color $(_abbr:util_set_to_typed_scope $abbreviations_sets) \`$abbreviation\`" + _abbr:util_log_unless_quiet "$success_color$verb_phrase$reset_color $(_abbr:util_set_to_typed_scope $abbreviations_sets) \`${(Q)abbreviation}\`" else verb_phrase="Did not erase" (( dry_run )) && verb_phrase="Would not erase" - message="$error_color$verb_phrase$reset_color abbreviation \`$abbreviation\`. Please specify one of\\n" + message="$error_color$verb_phrase$reset_color abbreviation \`${(Q)abbreviation}\`. Please specify one of\\n" for abbreviations_set in $abbreviations_sets; do message+=" $(_abbr:util_set_to_typed_scope $abbreviations_set)\\n" @@ -427,15 +427,15 @@ _abbr() { if [[ $scope == 'session' ]]; then if [[ $type == 'global' ]]; then - expansion=${ABBR_GLOBAL_SESSION_ABBREVIATIONS[$current_abbreviation]} + expansion=${ABBR_GLOBAL_SESSION_ABBREVIATIONS[${(qqq)current_abbreviation}]} else - expansion=${ABBR_REGULAR_SESSION_ABBREVIATIONS[$current_abbreviation]} + expansion=${ABBR_REGULAR_SESSION_ABBREVIATIONS[${(qqq)current_abbreviation}]} fi else if [[ $type == 'global' ]]; then - expansion=${ABBR_GLOBAL_USER_ABBREVIATIONS[$current_abbreviation]} + expansion=${ABBR_GLOBAL_USER_ABBREVIATIONS[${(qqq)current_abbreviation}]} else - expansion=${ABBR_REGULAR_USER_ABBREVIATIONS[$current_abbreviation]} + expansion=${ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)current_abbreviation}]} fi fi @@ -443,7 +443,7 @@ _abbr() { _abbr:util_add $new_abbreviation $expansion _abbr:erase $current_abbreviation else - _abbr:util_error "abbr rename: No${type:+ $type}${scope:+ $scope} abbreviation \`$current_abbreviation\` exists" + _abbr:util_error "abbr rename: No${type:+ $type}${scope:+ $scope} abbreviation \`${(Q)current_abbreviation}\` exists" fi } @@ -462,13 +462,8 @@ _abbr() { expansion=$2 success=0 - if [[ ${(w)#abbreviation} > 1 ]]; then - _abbr:util_error "abbr add: ABBREVIATION (\`$abbreviation\`) must be only one word" - return - fi - if [[ ${abbreviation%=*} != $abbreviation ]]; then - _abbr:util_error "abbr add: ABBREVIATION (\`$abbreviation\`) may not contain an equals sign" + _abbr:util_error "abbr add: ABBREVIATION (\`${(Q)abbreviation}\`) may not contain an equals sign" return fi @@ -480,7 +475,7 @@ _abbr() { _abbr:util_check_command $abbreviation || return if ! (( dry_run )); then - ABBR_GLOBAL_SESSION_ABBREVIATIONS[$abbreviation]=$expansion + ABBR_GLOBAL_SESSION_ABBREVIATIONS[${(qqq)${(Q)abbreviation}}]=${(qqq)${(Q)expansion}} fi success=1 @@ -492,7 +487,7 @@ _abbr() { _abbr:util_check_command $abbreviation || return if ! (( dry_run )); then - ABBR_REGULAR_SESSION_ABBREVIATIONS[$abbreviation]=$expansion + ABBR_REGULAR_SESSION_ABBREVIATIONS[${(qqq)${(Q)abbreviation}}]=${(qqq)${(Q)expansion}} fi success=1 @@ -510,7 +505,7 @@ _abbr() { _abbr:util_check_command $abbreviation || return if ! (( dry_run )); then - ABBR_GLOBAL_USER_ABBREVIATIONS[$abbreviation]=$expansion + ABBR_GLOBAL_USER_ABBREVIATIONS[${(qqq)${(Q)abbreviation}}]=${(qqq)${(Q)expansion}} _abbr:util_sync_user fi @@ -528,7 +523,7 @@ _abbr() { typed_scope=$(_abbr:util_set_to_typed_scope ABBR_REGULAR_USER_ABBREVIATIONS) if ! (( dry_run )); then - ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]=$expansion + ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)${(Q)abbreviation}}]=${(qqq)${(Q)expansion}} _abbr:util_sync_user fi @@ -541,12 +536,12 @@ _abbr() { verb_phrase="Added" (( dry_run )) && verb_phrase="Would add" - _abbr:util_log_unless_quiet "$success_color$verb_phrase$reset_color the $typed_scope \`$abbreviation\`" + _abbr:util_log_unless_quiet "$success_color$verb_phrase$reset_color the $typed_scope \`${(Q)abbreviation}\`" else verb_phrase="Did not" (( dry_run )) && verb_phrase="Would not" - _abbr:util_error "$verb_phrase add the $typed_scope \`$abbreviation\` because it already exists" + _abbr:util_error "$verb_phrase add the $typed_scope \`${(Q)abbreviation}\` because it already exists" fi } @@ -635,12 +630,12 @@ _abbr() { verb_phrase="will now expand" (( dry_run )) && verb_phrase="would now expand" - _abbr:util_log_unless_quieter "\`$abbreviation\` $verb_phrase as an abbreviation" + _abbr:util_log_unless_quieter "\`${(Q)abbreviation}\` $verb_phrase as an abbreviation" else verb_phrase="Did not" (( dry_run )) && verb_phrase="Would not" - _abbr:util_warn "$verb_phrase add the abbreviation \`$abbreviation\` because a command with the same name exists" + _abbr:util_warn "$verb_phrase add the abbreviation \`${(Q)abbreviation}\` because a command with the same name exists" return 1 fi fi @@ -764,13 +759,13 @@ _abbr() { typeset -p ABBR_GLOBAL_USER_ABBREVIATIONS > ${ABBR_TMPDIR}global-user-abbreviations for abbreviation in ${(iko)ABBR_GLOBAL_USER_ABBREVIATIONS}; do expansion=${ABBR_GLOBAL_USER_ABBREVIATIONS[$abbreviation]} - 'builtin' 'echo' "abbr -g ${abbreviation}=${(qqq)${(Q)expansion}}" >> "$user_updated" + 'builtin' 'echo' "abbr -g $abbreviation=$expansion" >> "$user_updated" done typeset -p ABBR_REGULAR_USER_ABBREVIATIONS > ${ABBR_TMPDIR}regular-user-abbreviations for abbreviation in ${(iko)ABBR_REGULAR_USER_ABBREVIATIONS}; do expansion=${ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} - 'builtin' 'echo' "abbr ${abbreviation}=${(qqq)${(Q)expansion}}" >> $user_updated + 'builtin' 'echo' "abbr $abbreviation=$expansion" >> $user_updated done mv $user_updated $ABBR_USER_ABBREVIATIONS_FILE @@ -1006,21 +1001,22 @@ _abbr_no_color() { _abbr_cmd_expansion() { emulate -LR zsh - # cannout support debug message + # cannot support debug message local abbreviation local expansion abbreviation=$1 - expansion=${ABBR_REGULAR_SESSION_ABBREVIATIONS[$abbreviation]} + + expansion=$ABBR_REGULAR_SESSION_ABBREVIATIONS[${(qqq)abbreviation}] if [[ ! $expansion ]]; then _abbr_create_files source ${ABBR_TMPDIR}regular-user-abbreviations - expansion=${ABBR_REGULAR_USER_ABBREVIATIONS[$abbreviation]} + expansion=$ABBR_REGULAR_USER_ABBREVIATIONS[${(qqq)abbreviation}] fi - 'builtin' 'echo' - $expansion + 'builtin' 'echo' - ${(Q)expansion} } _abbr_create_files() { @@ -1047,21 +1043,21 @@ _abbr_debugger() { _abbr_global_expansion() { emulate -LR zsh - # cannout support debug message + # cannot support debug message local abbreviation local expansion abbreviation=$1 - expansion=${ABBR_GLOBAL_SESSION_ABBREVIATIONS[$abbreviation]} + expansion=${ABBR_GLOBAL_SESSION_ABBREVIATIONS[${(qqq)abbreviation}]} if [[ ! $expansion ]]; then _abbr_create_files source ${ABBR_TMPDIR}global-user-abbreviations - expansion=${ABBR_GLOBAL_USER_ABBREVIATIONS[$abbreviation]} + expansion=${ABBR_GLOBAL_USER_ABBREVIATIONS[${(qqq)abbreviation}]} fi - 'builtin' 'echo' - $expansion + 'builtin' 'echo' - ${(Q)expansion} } _abbr_init() { @@ -1143,7 +1139,7 @@ _abbr_job_push() { } function _abbr_job_push:next_job_name() { - # cannout support debug message + # cannot support debug message 'command' 'ls' -t ${ABBR_TMPDIR}jobs | tail -1 } @@ -1156,7 +1152,7 @@ _abbr_job_push() { 'builtin' 'echo' "abbr: A job added at $(strftime '%T %b %d %Y' ${next_job%.*}) has timed out." 'builtin' 'echo' "The job was related to $(cat $next_job_path)." 'builtin' 'echo' "This could be the result of manually terminating an abbr activity, for example during session startup." - 'builtin' 'echo' "If you believe it reflects a abbr bug, please report it at https://github.com/olets/zsh-abbr/issues/new" + 'builtin' 'echo' "If you believe it reflects an abbr bug, please report it at https://github.com/olets/zsh-abbr/issues/new" 'builtin' 'echo' 'command' 'rm' $next_job_path &>/dev/null @@ -1188,7 +1184,7 @@ _abbr_job_push() { _abbr_job_name() { emulate -LR zsh - # cannout support debug message + # cannot support debug message 'builtin' 'echo' "$(date +%s).$RANDOM" } @@ -1285,27 +1281,33 @@ _abbr_widget_expand() { emulate -LR zsh local expansion - local word - local words - local -i word_count + local abbreviation + local -i i + local preceding_lbuffer + local -a words - words=(${(z)LBUFFER}) - word=$words[-1] - word_count=${#words} + expansion=$(_abbr_cmd_expansion "$LBUFFER") - if [[ $word_count == 1 ]]; then - expansion=$(_abbr_cmd_expansion $word) + if [[ -n $expansion ]]; then + LBUFFER=$expansion + return fi - if [[ ! $expansion ]]; then - expansion=$(_abbr_global_expansion $word) - fi + words=(${(z)LBUFFER}) + + while (( i < ${#words} )); do + abbreviation=${words:$i} + expansion=$(_abbr_global_expansion "$abbreviation") - if [[ -n $expansion ]]; then - local preceding_lbuffer - preceding_lbuffer=${LBUFFER%%$word} - LBUFFER=$preceding_lbuffer${(Q)expansion} - fi + if [[ -n $expansion ]]; then + preceding_lbuffer=${LBUFFER%%$abbreviation} + + LBUFFER=$preceding_lbuffer$expansion + break + fi + + (( i++ )) + done } _abbr_widget_expand_and_accept() {