sudo.plugin.zsh 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. # ------------------------------------------------------------------------------
  2. # Description
  3. # -----------
  4. #
  5. # sudo or sudoedit will be inserted before the command
  6. #
  7. # ------------------------------------------------------------------------------
  8. # Authors
  9. # -------
  10. #
  11. # * Dongweiming <ciici123@gmail.com>
  12. # * Subhaditya Nath <github.com/subnut>
  13. # * Marc Cornellà <github.com/mcornella>
  14. #
  15. # ------------------------------------------------------------------------------
  16. __sudo-replace-buffer() {
  17. local old=$1 new=$2 space=${2:+ }
  18. if [[ ${#LBUFFER} -le ${#old} ]]; then
  19. RBUFFER="${space}${BUFFER#$old }"
  20. LBUFFER="${new}"
  21. else
  22. LBUFFER="${new}${space}${LBUFFER#$old }"
  23. fi
  24. }
  25. sudo-command-line() {
  26. # If line is empty, get the last run command from history
  27. [[ -z $BUFFER ]] && LBUFFER="$(fc -ln -1)"
  28. # Save beginning space
  29. local WHITESPACE=""
  30. if [[ ${LBUFFER:0:1} = " " ]]; then
  31. WHITESPACE=" "
  32. LBUFFER="${LBUFFER:1}"
  33. fi
  34. # If $EDITOR is not set, just toggle the sudo prefix on and off
  35. if [[ -z "$EDITOR" ]]; then
  36. case "$BUFFER" in
  37. sudoedit\ *) __sudo-replace-buffer "sudoedit" "" ;;
  38. sudo\ *) __sudo-replace-buffer "sudo" "" ;;
  39. *) LBUFFER="sudo $LBUFFER" ;;
  40. esac
  41. else
  42. # Check if the typed command is really an alias to $EDITOR
  43. # Get the first part of the typed command
  44. local cmd="${${(Az)BUFFER}[1]}"
  45. # Get the first part of the alias of the same name as $cmd, or $cmd if no alias matches
  46. local realcmd="${${(Az)aliases[$cmd]}[1]:-$cmd}"
  47. # Get the first part of the $EDITOR command ($EDITOR may have arguments after it)
  48. local editorcmd="${${(Az)EDITOR}[1]}"
  49. # Note: ${var:c} makes a $PATH search and expands $var to the full path
  50. # The if condition is met when:
  51. # - $realcmd is '$EDITOR'
  52. # - $realcmd is "cmd" and $EDITOR is "cmd"
  53. # - $realcmd is "cmd" and $EDITOR is "cmd --with --arguments"
  54. # - $realcmd is "/path/to/cmd" and $EDITOR is "cmd"
  55. # - $realcmd is "/path/to/cmd" and $EDITOR is "/path/to/cmd"
  56. # or
  57. # - $realcmd is "cmd" and $EDITOR is "cmd"
  58. # - $realcmd is "cmd" and $EDITOR is "/path/to/cmd"
  59. # or
  60. # - $realcmd is "cmd" and $EDITOR is /alternative/path/to/cmd that appears in $PATH
  61. if [[ "$realcmd" = (\$EDITOR|$editorcmd|${editorcmd:c}) \
  62. || "${realcmd:c}" = ($editorcmd|${editorcmd:c}) ]] \
  63. || builtin which -a "$realcmd" | command grep -Fx -q "$editorcmd"; then
  64. editorcmd="$cmd" # replace $editorcmd with the typed command so it matches below
  65. fi
  66. # Check for editor commands in the typed command and replace accordingly
  67. case "$BUFFER" in
  68. $editorcmd\ *) __sudo-replace-buffer "$editorcmd" "sudoedit" ;;
  69. \$EDITOR\ *) __sudo-replace-buffer '$EDITOR' "sudoedit" ;;
  70. sudoedit\ *) __sudo-replace-buffer "sudoedit" "$EDITOR" ;;
  71. sudo\ *) __sudo-replace-buffer "sudo" "" ;;
  72. *) LBUFFER="sudo $LBUFFER" ;;
  73. esac
  74. fi
  75. # Preserve beginning space
  76. LBUFFER="${WHITESPACE}${LBUFFER}"
  77. # Redisplay edit buffer (compatibility with zsh-syntax-highlighting)
  78. zle redisplay
  79. }
  80. zle -N sudo-command-line
  81. # Defined shortcut keys: [Esc] [Esc]
  82. bindkey -M emacs '\e\e' sudo-command-line
  83. bindkey -M vicmd '\e\e' sudo-command-line
  84. bindkey -M viins '\e\e' sudo-command-line