mirror of
				https://github.com/ohmyzsh/ohmyzsh.git
				synced 2025-11-04 05:01:17 +08:00 
			
		
		
		
	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
This commit is contained in:
		
							parent
							
								
									8c5f64cc2f
								
							
						
					
					
						commit
						b0561d28b5
					
				
							
								
								
									
										14
									
								
								lib/cli.zsh
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								lib/cli.zsh
									
									
									
									
									
								
							@ -241,10 +241,18 @@ function _omz::plugin::disable {
 | 
			
		||||
 | 
			
		||||
  # Remove plugins substitution awk script
 | 
			
		||||
  local awk_subst_plugins="\
 | 
			
		||||
  gsub(/[ \t]+(${(j:|:)dis_plugins})/, \"\") # with spaces before
 | 
			
		||||
  gsub(/(${(j:|:)dis_plugins})[ \t]+/, \"\") # with spaces after
 | 
			
		||||
  gsub(/\((${(j:|:)dis_plugins})\)/, \"\") # without spaces (only plugin)
 | 
			
		||||
  gsub(/[ \t]+(${(j:|:)dis_plugins})[ \t]+/, \" \") # with spaces before or after
 | 
			
		||||
  gsub(/[ \t]+(${(j:|:)dis_plugins})$/, \"\")       # with spaces before and EOL
 | 
			
		||||
  gsub(/^(${(j:|:)dis_plugins})[ \t]+/, \"\")       # with BOL and spaces after
 | 
			
		||||
 | 
			
		||||
  gsub(/\((${(j:|:)dis_plugins})[ \t]+/, \"(\")     # with parenthesis before and spaces after
 | 
			
		||||
  gsub(/[ \t]+(${(j:|:)dis_plugins})\)/, \")\")     # with spaces before or parenthesis after
 | 
			
		||||
  gsub(/\((${(j:|:)dis_plugins})\)/, \"()\")        # with only parentheses
 | 
			
		||||
 | 
			
		||||
  gsub(/^(${(j:|:)dis_plugins})\)/, \")\")          # with BOL and closing parenthesis
 | 
			
		||||
  gsub(/\((${(j:|:)dis_plugins})$/, \"(\")          # with opening parenthesis and EOL
 | 
			
		||||
"
 | 
			
		||||
 | 
			
		||||
  # Disable plugins awk script
 | 
			
		||||
  local awk_script="
 | 
			
		||||
# if plugins=() is in oneline form, substitute disabled plugins and go to next line
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										169
									
								
								lib/tests/cli.test.zsh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								lib/tests/cli.test.zsh
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,169 @@
 | 
			
		||||
#!/usr/bin/zsh -df
 | 
			
		||||
 | 
			
		||||
run_awk() {
 | 
			
		||||
  local -a dis_plugins=(${=1})
 | 
			
		||||
  local input_text="$2"
 | 
			
		||||
 | 
			
		||||
  (( ! DEBUG )) || set -xv
 | 
			
		||||
 | 
			
		||||
  local awk_subst_plugins="\
 | 
			
		||||
    gsub(/[ \t]+(${(j:|:)dis_plugins})[ \t]+/, \" \") # with spaces before or after
 | 
			
		||||
    gsub(/[ \t]+(${(j:|:)dis_plugins})$/, \"\")       # with spaces before and EOL
 | 
			
		||||
    gsub(/^(${(j:|:)dis_plugins})[ \t]+/, \"\")       # with BOL and spaces after
 | 
			
		||||
 | 
			
		||||
    gsub(/\((${(j:|:)dis_plugins})[ \t]+/, \"(\")     # with parenthesis before and spaces after
 | 
			
		||||
    gsub(/[ \t]+(${(j:|:)dis_plugins})\)/, \")\")     # with spaces before or parenthesis after
 | 
			
		||||
    gsub(/\((${(j:|:)dis_plugins})\)/, \"()\")        # with only parentheses
 | 
			
		||||
 | 
			
		||||
    gsub(/^(${(j:|:)dis_plugins})\)/, \")\")          # with BOL and closing parenthesis
 | 
			
		||||
    gsub(/\((${(j:|:)dis_plugins})$/, \"(\")          # with opening parenthesis and EOL
 | 
			
		||||
  "
 | 
			
		||||
    # Disable plugins awk script
 | 
			
		||||
    local awk_script="
 | 
			
		||||
  # if plugins=() is in oneline form, substitute disabled plugins and go to next line
 | 
			
		||||
  /^[ \t]*plugins=\([^#]+\).*\$/ {
 | 
			
		||||
    $awk_subst_plugins
 | 
			
		||||
    print \$0
 | 
			
		||||
    next
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  # if plugins=() is in multiline form, enable multi flag and disable plugins if they're there
 | 
			
		||||
  /^[ \t]*plugins=\(/ {
 | 
			
		||||
    multi=1
 | 
			
		||||
    $awk_subst_plugins
 | 
			
		||||
    print \$0
 | 
			
		||||
    next
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  # if multi flag is enabled and we find a valid closing parenthesis, remove plugins and disable multi flag
 | 
			
		||||
  multi == 1 && /^[^#]*\)/ {
 | 
			
		||||
    multi=0
 | 
			
		||||
    $awk_subst_plugins
 | 
			
		||||
    print \$0
 | 
			
		||||
    next
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  multi == 1 && length(\$0) > 0 {
 | 
			
		||||
    $awk_subst_plugins
 | 
			
		||||
    if (length(\$0) > 0) print \$0
 | 
			
		||||
    next
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  { print \$0 }
 | 
			
		||||
  "
 | 
			
		||||
 | 
			
		||||
  command awk "$awk_script" <<< "$input_text"
 | 
			
		||||
 | 
			
		||||
  (( ! DEBUG )) || set +xv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# runs awk against stdin, checks if the resulting file is not empty and then checks if the file has valid zsh syntax
 | 
			
		||||
run_awk_and_test() {
 | 
			
		||||
  local description="$1"
 | 
			
		||||
  local plugins_to_disable="$2"
 | 
			
		||||
  local input_text="$3"
 | 
			
		||||
  local expected_output="$4"
 | 
			
		||||
 | 
			
		||||
  local tmpfile==(:)
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    print -u2 "Test: $description"
 | 
			
		||||
    DEBUG=0 run_awk "$plugins_to_disable" "$input_text" >| $tmpfile
 | 
			
		||||
 | 
			
		||||
    if [[ ! -s "$tmpfile" ]]; then
 | 
			
		||||
      print -u2 "\e[31mError\e[0m: output file empty"
 | 
			
		||||
      return 1
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    if ! zsh -n $tmpfile; then
 | 
			
		||||
      print -u2 "\e[31mError\e[0m: zsh syntax error"
 | 
			
		||||
      diff -u $tmpfile <(echo "$expected_output")
 | 
			
		||||
      return 1
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    if ! diff -u --color=always $tmpfile <(echo "$expected_output"); then
 | 
			
		||||
      if (( DEBUG )); then
 | 
			
		||||
        print -u2 ""
 | 
			
		||||
        DEBUG=1 run_awk "$plugins_to_disable" "$input_text"
 | 
			
		||||
        print -u2 ""
 | 
			
		||||
      fi
 | 
			
		||||
      print -u2 "\e[31mError\e[0m: output file does not match expected output"
 | 
			
		||||
      return 1
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    print -u2 "\e[32mSuccess\e[0m"
 | 
			
		||||
  } always {
 | 
			
		||||
    print -u2 ""
 | 
			
		||||
    command rm -f "$tmpfile"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# These tests are for the `omz plugin disable` command
 | 
			
		||||
run_awk_and_test \
 | 
			
		||||
  "it should delete a single plugin in oneline format" \
 | 
			
		||||
  "git" \
 | 
			
		||||
  "plugins=(git)" \
 | 
			
		||||
  "plugins=()"
 | 
			
		||||
 | 
			
		||||
run_awk_and_test \
 | 
			
		||||
  "it should delete a single plugin in multiline format" \
 | 
			
		||||
  "github" \
 | 
			
		||||
"plugins=(
 | 
			
		||||
  github
 | 
			
		||||
)" \
 | 
			
		||||
"plugins=(
 | 
			
		||||
)"
 | 
			
		||||
 | 
			
		||||
run_awk_and_test \
 | 
			
		||||
  "it should delete multiple plugins in oneline format" \
 | 
			
		||||
  "github git z" \
 | 
			
		||||
  "plugins=(github git z)" \
 | 
			
		||||
  "plugins=()"
 | 
			
		||||
 | 
			
		||||
run_awk_and_test \
 | 
			
		||||
  "it should delete multiple plugins in multiline format" \
 | 
			
		||||
  "github git z" \
 | 
			
		||||
"plugins=(
 | 
			
		||||
  github
 | 
			
		||||
  git
 | 
			
		||||
  z
 | 
			
		||||
)" \
 | 
			
		||||
"plugins=(
 | 
			
		||||
)"
 | 
			
		||||
 | 
			
		||||
run_awk_and_test \
 | 
			
		||||
  "it should delete a single plugin among multiple in oneline format" \
 | 
			
		||||
  "git" \
 | 
			
		||||
  "plugins=(github git z)" \
 | 
			
		||||
  "plugins=(github z)"
 | 
			
		||||
 | 
			
		||||
run_awk_and_test \
 | 
			
		||||
  "it should delete a single plugin among multiple in multiline format" \
 | 
			
		||||
  "git" \
 | 
			
		||||
"plugins=(
 | 
			
		||||
  github
 | 
			
		||||
  git
 | 
			
		||||
  z
 | 
			
		||||
)" \
 | 
			
		||||
"plugins=(
 | 
			
		||||
  github
 | 
			
		||||
  z
 | 
			
		||||
)"
 | 
			
		||||
 | 
			
		||||
run_awk_and_test \
 | 
			
		||||
  "it should delete multiple plugins in mixed format" \
 | 
			
		||||
  "git z" \
 | 
			
		||||
"plugins=(github
 | 
			
		||||
git z)" \
 | 
			
		||||
"plugins=(github
 | 
			
		||||
)"
 | 
			
		||||
 | 
			
		||||
run_awk_and_test \
 | 
			
		||||
  "it should delete multiple plugins in mixed format 2" \
 | 
			
		||||
  "github z" \
 | 
			
		||||
"plugins=(github
 | 
			
		||||
  git
 | 
			
		||||
z)" \
 | 
			
		||||
"plugins=(
 | 
			
		||||
  git
 | 
			
		||||
)"
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user