b0561d28b5a3efbbcca4700626fa32e62c23959b

Author
Marc Cornellà <marc@mcornella.com>
Committer
GitHub <noreply@github.com>
Date

Message

fix(cli): fix edge cases in `omz plugin disable` command (#12401)

Also introduces tests, which will be refactored into the proper
place when a test system is finally designed.

Fixes #12400

Diff

This diff is truncated to protect this page.

  1diff --git a/lib/cli.zsh b/lib/cli.zsh
  2index 4a8d4d12785a647c48081702816675716758c772..383b0cfb04c33edee171b6eeafb65158ebf193d3 100644
  3--- a/lib/cli.zsh
  4+++ b/lib/cli.zsh
  5@@ -241,10 +241,18 @@ function _omz::plugin::disable {
  6 
  7   # Remove plugins substitution awk script
  8   local awk_subst_plugins="\
  9-  gsub(/[ \t]+(${(j:|:)dis_plugins})/, \"\") # with spaces before
 10-  gsub(/(${(j:|:)dis_plugins})[ \t]+/, \"\") # with spaces after
 11-  gsub(/\((${(j:|:)dis_plugins})\)/, \"\") # without spaces (only plugin)
 12+  gsub(/[ \t]+(${(j:|:)dis_plugins})[ \t]+/, \" \") # with spaces before or after
 13+  gsub(/[ \t]+(${(j:|:)dis_plugins})$/, \"\")       # with spaces before and EOL
 14+  gsub(/^(${(j:|:)dis_plugins})[ \t]+/, \"\")       # with BOL and spaces after
 15+
 16+  gsub(/\((${(j:|:)dis_plugins})[ \t]+/, \"(\")     # with parenthesis before and spaces after
 17+  gsub(/[ \t]+(${(j:|:)dis_plugins})\)/, \")\")     # with spaces before or parenthesis after
 18+  gsub(/\((${(j:|:)dis_plugins})\)/, \"()\")        # with only parentheses
 19+
 20+  gsub(/^(${(j:|:)dis_plugins})\)/, \")\")          # with BOL and closing parenthesis
 21+  gsub(/\((${(j:|:)dis_plugins})$/, \"(\")          # with opening parenthesis and EOL
 22 "
 23+
 24   # Disable plugins awk script
 25   local awk_script="
 26 # if plugins=() is in oneline form, substitute disabled plugins and go to next line
 27diff --git a/lib/tests/cli.test.zsh b/lib/tests/cli.test.zsh
 28new file mode 100644
 29index 0000000000000000000000000000000000000000..9ee5cd219f7be9e0d6a07b9fe985b8d6ff1d21ee
 30--- /dev/null
 31+++ b/lib/tests/cli.test.zsh
 32@@ -0,0 +1,169 @@
 33+#!/usr/bin/zsh -df
 34+
 35+run_awk() {
 36+  local -a dis_plugins=(${=1})
 37+  local input_text="$2"
 38+
 39+  (( ! DEBUG )) || set -xv
 40+
 41+  local awk_subst_plugins="\
 42+    gsub(/[ \t]+(${(j:|:)dis_plugins})[ \t]+/, \" \") # with spaces before or after
 43+    gsub(/[ \t]+(${(j:|:)dis_plugins})$/, \"\")       # with spaces before and EOL
 44+    gsub(/^(${(j:|:)dis_plugins})[ \t]+/, \"\")       # with BOL and spaces after
 45+
 46+    gsub(/\((${(j:|:)dis_plugins})[ \t]+/, \"(\")     # with parenthesis before and spaces after
 47+    gsub(/[ \t]+(${(j:|:)dis_plugins})\)/, \")\")     # with spaces before or parenthesis after
 48+    gsub(/\((${(j:|:)dis_plugins})\)/, \"()\")        # with only parentheses
 49+
 50+    gsub(/^(${(j:|:)dis_plugins})\)/, \")\")          # with BOL and closing parenthesis
 51+    gsub(/\((${(j:|:)dis_plugins})$/, \"(\")          # with opening parenthesis and EOL
 52+  "
 53+    # Disable plugins awk script
 54+    local awk_script="
 55+  # if plugins=() is in oneline form, substitute disabled plugins and go to next line
 56+  /^[ \t]*plugins=\([^#]+\).*\$/ {
 57+    $awk_subst_plugins
 58+    print \$0
 59+    next
 60+  }
 61+
 62+  # if plugins=() is in multiline form, enable multi flag and disable plugins if they're there
 63+  /^[ \t]*plugins=\(/ {
 64+    multi=1
 65+    $awk_subst_plugins
 66+    print \$0
 67+    next
 68+  }
 69+
 70+  # if multi flag is enabled and we find a valid closing parenthesis, remove plugins and disable multi flag
 71+  multi == 1 && /^[^#]*\)/ {
 72+    multi=0
 73+    $awk_subst_plugins
 74+    print \$0
 75+    next
 76+  }
 77+
 78+  multi == 1 && length(\$0) > 0 {
 79+    $awk_subst_plugins
 80+    if (length(\$0) > 0) print \$0
 81+    next
 82+  }
 83+
 84+  { print \$0 }
 85+  "
 86+
 87+  command awk "$awk_script" <<< "$input_text"
 88+
 89+  (( ! DEBUG )) || set +xv
 90+}
 91+
 92+# runs awk against stdin, checks if the resulting file is not empty and then checks if the file has valid zsh syntax
 93+run_awk_and_test() {
 94+  local description="$1"
 95+  local plugins_to_disable="$2"
 96+  local input_text="$3"
 97+  local expected_output="$4"
 98+
 99+  local tmpfile==(:)
100+
101+  {
102+    print -u2 "Test: $description"
103+    DEBUG=0 run_awk "$plugins_to_disable" "$input_text" >| $tmpfile
104+
105+    if [[ ! -s "$tmpfile" ]]; then
106+      print -u2 "\e[31mError\e[0m: output file empty"
107+      return 1
108+    fi
109+
110+    if ! zsh -n $tmpfile; then
111+      print -u2 "\e[31mError\e[0m: zsh syntax error"
112+      diff -u $tmpfile <(echo "$expected_output")
113+      return 1
114+    fi
115+
116+    if ! diff -u --color=always $tmpfile <(echo "$expected_output"); then
117+      if (( DEBUG )); then
118+        print -u2 ""
119+        DEBUG=1 run_awk "$plugins_to_disable" "$input_text"
120+        print -u2 ""
121+      fi
122+      print -u2 "\e[31mError\e[0m: output file does not match expected output"
123+      return 1
124+    fi
125+
126+    print -u2 "\e[32mSuccess\e[0m"
127+  } always {
128+    print -u2 ""
129+    command rm -f "$tmpfile"
130+  }
131+}