Browse Source

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

Roeniss Moon 8 months ago
parent
commit
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.
 
+## Usage
+
 To use it, add `alias-finder` to the `plugins` array of your zshrc file:
 ```
 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() {
-  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;;
       -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
   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
+
+  # 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() {
-  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
   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"
+}