浏览代码

feat(alias-finder): add cheaper option and apply zstyle options (#11773)

Roeniss Moon 8 月之前
父节点
当前提交
13a8e3d98a

+ 9 - 0
plugins/alias-finder/.zunit.yml

@@ -0,0 +1,9 @@
+tap: false
+directories:
+  tests: tests
+  output: tests/_output
+  support: tests/_support
+time_limit: 0
+fail_fast: false
+allow_risky: false
+verbose: true

+ 21 - 34
plugins/alias-finder/README.md

@@ -2,45 +2,32 @@
 
 
 This plugin searches the defined aliases and outputs any that match the command inputted. This makes learning new aliases easier.
 This plugin searches the defined aliases and outputs any that match the command inputted. This makes learning new aliases easier.
 
 
+## Usage
+
 To use it, add `alias-finder` to the `plugins` array of your zshrc file:
 To use it, add `alias-finder` to the `plugins` array of your zshrc file:
 ```
 ```
 plugins=(... alias-finder)
 plugins=(... alias-finder)
 ```
 ```
 
 
-## Usage
-To see if there is an alias defined for the command, pass it as an argument to `alias-finder`. This can also run automatically before each command you input - add `ZSH_ALIAS_FINDER_AUTOMATIC=true` to your zshrc if you want this.
+To enable it for every single command, set zstyle in your `~/.zshrc`.
 
 
-## Options
+```zsh
+# ~/.zshrc
 
 
-- Use `--longer` or `-l` to allow the aliases to be longer than the input (match aliases if they contain the input).
-- Use `--exact` or `-e` to avoid matching aliases that are shorter than the input.
-
-## Examples
-```
-$ alias-finder "git pull"
-gl='git pull'
-g=git
-```
-```
-$ alias-finder "web_search google oh my zsh"
-google='web_search google'
-```
-```
-$ alias-finder "git commit -v"
-gc="git commit -v"
-g=git
-```
-```
-$ alias-finder -e "git commit -v"
-gc='git commit -v'
-```
-```
-$ alias-finder -l "git commit -v"
-gc='git commit -v'
-'gc!'='git commit -v --amend'
-gca='git commit -v -a'
-'gca!'='git commit -v -a --amend'
-'gcan!'='git commit -v -a --no-edit --amend'
-'gcans!'='git commit -v -a -s --no-edit --amend'
-'gcn!'='git commit -v --no-edit --amend'
+zstyle ':omz:plugins:alias-finder' autoload yes # disabled by default
+zstyle ':omz:plugins:alias-finder' longer yes # disabled by default
+zstyle ':omz:plugins:alias-finder' exact yes # disabled by default
+zstyle ':omz:plugins:alias-finder' cheaper yes # disabled by default
 ```
 ```
+
+As you can see, options are also available with zstyle.
+
+### Options
+
+> In order to clarify, let's say `alias a=abc` has source 'abc' and destination 'a'.
+
+- Use `--longer` or `-l` to include aliases where the source is longer than the input (in other words, the source could contain the whole input).
+- Use `--exact` or `-e` to avoid aliases where the source is shorter than the input (in other words, the source must be the same with the input).
+- Use `--cheaper` or `-c` to avoid aliases where the destination is longer than the input (in other words, the destination must be the shorter than the input).
+
+

+ 47 - 32
plugins/alias-finder/alias-finder.plugin.zsh

@@ -1,44 +1,59 @@
 alias-finder() {
 alias-finder() {
-  local cmd="" exact="" longer="" wordStart="" wordEnd="" multiWordEnd=""
-  for i in $@; do
-    case $i in
+  local cmd=" " exact="" longer="" cheaper="" wordEnd="'{0,1}$" finder="" filter=""
+
+  # build command and options
+  for c in "$@"; do
+    case $c in
+      # TODO: Remove backward compatibility (other than zstyle form)
+      # set options if exist
       -e|--exact) exact=true;;
       -e|--exact) exact=true;;
       -l|--longer) longer=true;;
       -l|--longer) longer=true;;
-      *)
-        if [[ -z $cmd ]]; then
-          cmd=$i
-        else
-          cmd="$cmd $i"
-        fi
-        ;;
+      -c|--cheaper) cheaper=true;;
+      # concatenate cmd
+      *) cmd="$cmd$c " ;;
     esac
     esac
   done
   done
-  cmd=$(sed 's/[].\|$(){}?+*^[]/\\&/g' <<< $cmd) # adds escaping for grep
-  if (( $(wc -l <<< $cmd) == 1 )); then
-    while [[ $cmd != "" ]]; do
-      if [[ $longer = true ]]; then
-        wordStart="'{0,1}"
-      else
-        wordEnd="$"
-        multiWordEnd="'$"
-      fi
-      if [[ $cmd == *" "* ]]; then
-        local finder="'$cmd$multiWordEnd"
-      else
-        local finder=$wordStart$cmd$wordEnd
-      fi
-      alias | grep -E "=$finder"
-      if [[ $exact = true || $longer = true ]]; then
-        break
-      else
-        cmd=$(sed -E 's/ {0,1}[^ ]*$//' <<< $cmd) # removes last word
-      fi
-    done
+
+  zstyle -t ':omz:plugins:alias-finder' longer && longer=true
+  zstyle -t ':omz:plugins:alias-finder' exact && exact=true
+  zstyle -t ':omz:plugins:alias-finder' cheaper && cheaper=true
+
+  # format cmd for grep
+  ## - replace newlines with spaces
+  ## - trim both ends
+  ## - replace multiple spaces with one space
+  ## - add escaping character to special characters
+  cmd=$(echo -n "$cmd" | tr '\n' ' ' | xargs | tr -s '[:space:]' | sed 's/[].\|$(){}?+*^[]/\\&/g')
+
+  if [[ $longer == true ]]; then
+    wordEnd="" # remove wordEnd to find longer aliases
   fi
   fi
+
+  # find with alias and grep, removing last word each time until no more words
+  while [[ $cmd != "" ]]; do
+    finder="'{0,1}$cmd$wordEnd"
+
+    # make filter to find only shorter results than current cmd
+    if [[ $cheaper == true ]]; then
+      cmdLen=$(echo -n "$cmd" | wc -c)
+      filter="^'{0,1}.{0,$((cmdLen - 1))}="
+    fi
+
+    alias | grep -E "$filter" | grep -E "=$finder"
+
+    if [[ $exact == true ]]; then
+      break # because exact case is only one
+    elif [[ $longer = true ]]; then
+      break # because above grep command already found every longer aliases during first cycle
+    fi
+
+    cmd=$(sed -E 's/ {0,}[^ ]*$//' <<< "$cmd") # remove last word
+  done
 }
 }
 
 
 preexec_alias-finder() {
 preexec_alias-finder() {
-  if [[ $ZSH_ALIAS_FINDER_AUTOMATIC = true ]]; then
+  # TODO: Remove backward compatibility (other than zstyle form)
+  zstyle -t ':omz:plugins:alias-finder' autoload && alias-finder $1 || if [[ $ZSH_ALIAS_FINDER_AUTOMATIC = true ]]; then
     alias-finder $1
     alias-finder $1
   fi
   fi
 }
 }

+ 0 - 0
plugins/alias-finder/tests/_output/.gitkeep


+ 0 - 0
plugins/alias-finder/tests/_support/.gitkeep


+ 2 - 0
plugins/alias-finder/tests/_support/bootstrap

@@ -0,0 +1,2 @@
+#!/usr/bin/env zsh
+# Write your bootstrap code here

+ 107 - 0
plugins/alias-finder/tests/test_run.sh

@@ -0,0 +1,107 @@
+#!/usr/bin/env zunit
+
+@setup {
+  load ../alias-finder.plugin.zsh
+
+  set_git_aliases() {
+    unalias -a # all
+    alias g="git"
+    alias gc="git commit"
+    alias gcv="git commit -v"
+    alias gcvs="git commit -v -S"
+  }
+}
+
+@test 'find aliases that contain input' {
+  set_git_aliases
+
+  run alias-finder "git"
+
+  assert "${#lines[@]}" equals 1
+  assert "${lines[1]}" same_as "g=git"
+}
+
+@test 'find aliases that contain input with whitespaces at ends' {
+  set_git_aliases
+
+  run alias-finder "   git     "
+
+  assert "${#lines[@]}" equals 1
+  assert "${lines[1]}" same_as "g=git"
+}
+
+@test 'find aliases that contain multiple words' {
+  set_git_aliases
+
+  run alias-finder "git commit -v"
+
+  assert "${#lines[@]}" equals 3
+  assert "${lines[1]}" same_as "gcv='git commit -v'"
+  assert "${lines[2]}" same_as "gc='git commit'"
+  assert "${lines[3]}" same_as "g=git"
+}
+
+@test 'find alias that is the same with input when --exact option is set' {
+  set_git_aliases
+
+  run alias-finder -e "git"
+
+  assert "${#lines[@]}" equals 1
+  assert "${lines[1]}" same_as "g=git"
+}
+
+@test 'find alias that is the same with multiple words input when --exact option is set' {
+  set_git_aliases
+
+  run alias-finder -e "git commit -v"
+
+  assert "${#lines[@]}" equals 1
+  assert "${lines[1]}" same_as "gcv='git commit -v'"
+}
+
+@test 'find alias that is the same with or longer than input when --longer option is set' {
+  set_git_aliases
+
+  run alias-finder -l "git"
+
+  assert "${#lines[@]}" equals 4
+  assert "${lines[1]}" same_as "g=git"
+  assert "${lines[2]}" same_as "gc='git commit'"
+  assert "${lines[3]}" same_as "gcv='git commit -v'"
+  assert "${lines[4]}" same_as "gcvs='git commit -v -S'"
+}
+
+@test 'find alias that is the same with or longer than multiple words input when --longer option is set' {
+  set_git_aliases
+
+  run alias-finder -l "git commit -v"
+
+  assert "${#lines[@]}" equals 2
+  assert "${lines[1]}" same_as "gcv='git commit -v'"
+  assert "${lines[2]}" same_as "gcvs='git commit -v -S'"
+}
+
+@test 'find aliases including expensive (longer) than input' {
+  set_git_aliases
+  alias expensiveCommands="git commit"
+
+  run alias-finder "git commit -v"
+
+  assert "${#lines[@]}" equals 4
+  assert "${lines[1]}" same_as "gcv='git commit -v'"
+  assert "${lines[2]}" same_as "expensiveCommands='git commit'"
+  assert "${lines[3]}" same_as "gc='git commit'"
+  assert "${lines[4]}" same_as "g=git"
+}
+
+@test 'find aliases excluding expensive (longer) than input when --cheap option is set' {
+  set_git_aliases
+  alias expensiveCommands="git commit"
+
+  run alias-finder -c "git commit -v"
+
+  assert "${#lines[@]}" equals 3
+  assert "${lines[1]}" same_as "gcv='git commit -v'"
+  assert "${lines[2]}" same_as "gc='git commit'"
+  assert "${lines[3]}" same_as "g=git"
+}