From d05feb1f8ef82ec44e1de8cd77a74159a01b9106 Mon Sep 17 00:00:00 2001
From: Frederick Zhang <frederick888@tsundere.moe>
Date: Sat, 21 Sep 2019 16:14:31 +1000
Subject: [PATCH 1/6] do_sudo: new sudo alias to handle alias expansion

---
 plugins/do_sudo/README.md          |  6 ++++++
 plugins/do_sudo/do_sudo.plugin.zsh | 27 +++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 plugins/do_sudo/README.md
 create mode 100644 plugins/do_sudo/do_sudo.plugin.zsh

diff --git a/plugins/do_sudo/README.md b/plugins/do_sudo/README.md
new file mode 100644
index 000000000..1d1b9e7d5
--- /dev/null
+++ b/plugins/do_sudo/README.md
@@ -0,0 +1,6 @@
+# `do_sudo` plugin
+
+This plugin provides a sudo wrapper that handles alias expansion and avoids
+being broken by `nocorrect` `noglob` from other aliases.
+
+Modified from the script by [Wayne Davison](https://www.zsh.org/mla/users/2008/msg01229.html).
diff --git a/plugins/do_sudo/do_sudo.plugin.zsh b/plugins/do_sudo/do_sudo.plugin.zsh
new file mode 100644
index 000000000..b59f3ac6a
--- /dev/null
+++ b/plugins/do_sudo/do_sudo.plugin.zsh
@@ -0,0 +1,27 @@
+if [[ "$ENABLE_CORRECTION" == "true" ]]; then
+    alias sudo='nocorrect noglob _do_sudo '
+else
+    alias sudo='noglob _do_sudo '
+fi
+
+function _do_sudo() {
+    integer glob=1
+    local -a run
+    run=( command sudo )
+    while (($#)); do
+        case "$1" in
+        command|exec|-) shift; break ;;
+        nocorrect) shift ;;
+        noglob) glob=0; shift ;;
+        *) break ;;
+        esac
+    done
+    if ((glob)); then
+        PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" $run $~==*
+    else
+        PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" $run $==*
+    fi
+}
+
+command -v _sudo >/dev/null 2>&1
+[[ $? -eq 0 ]] && compdef _sudo '_do_sudo'

From 7f4d633f464eb8e2d7a8cc6ca8acb0fa05646132 Mon Sep 17 00:00:00 2001
From: Frederick Zhang <frederick888@tsundere.moe>
Date: Sat, 21 Sep 2019 21:05:22 +1000
Subject: [PATCH 2/6] do_sudo: recursive alias expansion

---
 plugins/do_sudo/do_sudo.plugin.zsh | 40 ++++++++++++++++++++++++------
 1 file changed, 32 insertions(+), 8 deletions(-)

diff --git a/plugins/do_sudo/do_sudo.plugin.zsh b/plugins/do_sudo/do_sudo.plugin.zsh
index b59f3ac6a..73a17061e 100644
--- a/plugins/do_sudo/do_sudo.plugin.zsh
+++ b/plugins/do_sudo/do_sudo.plugin.zsh
@@ -5,21 +5,45 @@ else
 fi
 
 function _do_sudo() {
-    integer glob=1
-    local -a run
-    run=( command sudo )
+    [[ -z ${__do_sudo_glob+x} ]] && __do_sudo_glob=1
+    [[ -z ${__do_sudo_expanded+x} ]] && declare -A __do_sudo_expanded
+    local -a args
+    local -a cmd_alias_arr
+    local cmd_alias
     while (($#)); do
         case "$1" in
         command|exec|-) shift; break ;;
         nocorrect) shift ;;
-        noglob) glob=0; shift ;;
-        *) break ;;
+        noglob) __do_sudo_glob=0; shift ;;
+        *)
+            cmd_alias="$(command -v 2>/dev/null -- "$1")"
+            if [[ "$?" -eq 0 ]]; then
+                if [[ "$cmd_alias" == 'alias'* ]] && [[ -z "$__do_sudo_expanded["$1"]" ]]; then
+                    __do_sudo_expanded["$1"]=1
+                    IFS=' ' read -A cmd_alias_arr <<< "$(sed -e "s/[^=]*=//" -e "s/^'//" -e "s/'$//" <<< "$cmd_alias")"
+                    args+=( "${cmd_alias_arr[@]}" )
+                else
+                    args+=( "$(sed "s/[^=]*=//" <<< "$(hash -v 2>/dev/null -- "$1")")" )
+                fi
+                shift
+                break
+            else
+                args+=( $1 )
+                shift
+            fi
+            ;;
         esac
     done
-    if ((glob)); then
-        PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" $run $~==*
+    if [[ ${#cmd_alias_arr[@]} -gt 0 ]]; then
+        _do_sudo "${args[@]}" $==*
     else
-        PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" $run $==*
+        if ((__do_sudo_glob)); then
+            PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" command sudo "${args[@]}" $~==*
+        else
+            PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" command sudo "${args[@]}" $==*
+        fi
+        unset __do_sudo_glob
+        unset __do_sudo_expanded
     fi
 }
 

From 557234e352aed58726244fb786619f81b42c0e98 Mon Sep 17 00:00:00 2001
From: Frederick Zhang <frederick888@tsundere.moe>
Date: Fri, 18 Oct 2019 21:41:39 +1100
Subject: [PATCH 3/6] do not resolve command to absolute path

it breaks commands e.g. sudo -u http echo foobar as http is both a
command (httpie) and a user/group (httpd) in my system
---
 plugins/do_sudo/do_sudo.plugin.zsh | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/plugins/do_sudo/do_sudo.plugin.zsh b/plugins/do_sudo/do_sudo.plugin.zsh
index 73a17061e..85ca2d853 100644
--- a/plugins/do_sudo/do_sudo.plugin.zsh
+++ b/plugins/do_sudo/do_sudo.plugin.zsh
@@ -17,14 +17,10 @@ function _do_sudo() {
         noglob) __do_sudo_glob=0; shift ;;
         *)
             cmd_alias="$(command -v 2>/dev/null -- "$1")"
-            if [[ "$?" -eq 0 ]]; then
-                if [[ "$cmd_alias" == 'alias'* ]] && [[ -z "$__do_sudo_expanded["$1"]" ]]; then
-                    __do_sudo_expanded["$1"]=1
-                    IFS=' ' read -A cmd_alias_arr <<< "$(sed -e "s/[^=]*=//" -e "s/^'//" -e "s/'$//" <<< "$cmd_alias")"
-                    args+=( "${cmd_alias_arr[@]}" )
-                else
-                    args+=( "$(sed "s/[^=]*=//" <<< "$(hash -v 2>/dev/null -- "$1")")" )
-                fi
+            if [[ "$?" -eq 0 ]] && [[ "$cmd_alias" == 'alias'* ]] && [[ -z "$__do_sudo_expanded["$1"]" ]]; then
+                __do_sudo_expanded["$1"]=1
+                IFS=' ' read -A cmd_alias_arr <<< "$(sed -e "s/[^=]*=//" -e "s/^'//" -e "s/'$//" <<< "$cmd_alias")"
+                args+=( "${cmd_alias_arr[@]}" )
                 shift
                 break
             else

From 23f1c44ae2ba32b48b4386459058138836c8f98e Mon Sep 17 00:00:00 2001
From: Frederick Zhang <frederick888@tsundere.moe>
Date: Mon, 21 Oct 2019 15:50:44 +1100
Subject: [PATCH 4/6] avoid conflict with 1-9 alises

---
 plugins/do_sudo/do_sudo.plugin.zsh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/plugins/do_sudo/do_sudo.plugin.zsh b/plugins/do_sudo/do_sudo.plugin.zsh
index 85ca2d853..8e28c1953 100644
--- a/plugins/do_sudo/do_sudo.plugin.zsh
+++ b/plugins/do_sudo/do_sudo.plugin.zsh
@@ -15,6 +15,7 @@ function _do_sudo() {
         command|exec|-) shift; break ;;
         nocorrect) shift ;;
         noglob) __do_sudo_glob=0; shift ;;
+        [1-9]) args+=( $1 ); shift ;;
         *)
             cmd_alias="$(command -v 2>/dev/null -- "$1")"
             if [[ "$?" -eq 0 ]] && [[ "$cmd_alias" == 'alias'* ]] && [[ -z "$__do_sudo_expanded["$1"]" ]]; then

From aad3bb04a8c18f997e90f57c9d0eb74414bb52b2 Mon Sep 17 00:00:00 2001
From: Frederick Zhang <frederick888@tsundere.moe>
Date: Wed, 23 Oct 2019 19:53:05 +1100
Subject: [PATCH 5/6] fix globbing

---
 plugins/do_sudo/do_sudo.plugin.zsh | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/plugins/do_sudo/do_sudo.plugin.zsh b/plugins/do_sudo/do_sudo.plugin.zsh
index 8e28c1953..8d1770e94 100644
--- a/plugins/do_sudo/do_sudo.plugin.zsh
+++ b/plugins/do_sudo/do_sudo.plugin.zsh
@@ -25,7 +25,11 @@ function _do_sudo() {
                 shift
                 break
             else
-                args+=( $1 )
+                if ((__do_sudo_glob)); then
+                    args+=( $~==1 )
+                else
+                    args+=( $==1 )
+                fi
                 shift
             fi
             ;;

From 4de06d21e0eb9bd27f090a3863270833d3e64261 Mon Sep 17 00:00:00 2001
From: Frederick Zhang <frederick888@tsundere.moe>
Date: Mon, 2 Mar 2020 18:21:33 +1100
Subject: [PATCH 6/6] preserve exit code

---
 plugins/do_sudo/do_sudo.plugin.zsh | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/plugins/do_sudo/do_sudo.plugin.zsh b/plugins/do_sudo/do_sudo.plugin.zsh
index 8d1770e94..f0bf8440f 100644
--- a/plugins/do_sudo/do_sudo.plugin.zsh
+++ b/plugins/do_sudo/do_sudo.plugin.zsh
@@ -10,6 +10,7 @@ function _do_sudo() {
     local -a args
     local -a cmd_alias_arr
     local cmd_alias
+    local return_value
     while (($#)); do
         case "$1" in
         command|exec|-) shift; break ;;
@@ -43,8 +44,10 @@ function _do_sudo() {
         else
             PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" command sudo "${args[@]}" $==*
         fi
+        return_value=$?
         unset __do_sudo_glob
         unset __do_sudo_expanded
+        return $return_value
     fi
 }