Diff
1diff --git a/plugins/shell-proxy/README.md b/plugins/shell-proxy/README.md
2new file mode 100644
3index 0000000000000000000000000000000000000000..6f2cd13e0685cb7b8d41009557444aa561fdb9ac
4--- /dev/null
5+++ b/plugins/shell-proxy/README.md
6@@ -0,0 +1,52 @@
7+# Shell Proxy oh-my-zsh plugin
8+
9+This a pure user-space program, shell-proxy setter, written Python3 and Bash.
10+
11+100% only no side-effects, only effect **environment variables** and **aliases**
12+
13+## Key feature
14+
15+- Support Ubuntu, Archlinux, etc (Linux)
16+- Support macOS
17+- Support git via based-`$GIT_SSH`
18+- Support ssh, sftp, scp, slogin and ssh-copy-id via based-`alias`
19+- Built-in Auto-complete
20+
21+## Usage
22+
23+Method 1:
24+
25+`$DEFAULT_PROXY` is the proxy URL you will set
26+
27+Method 2:
28+
29+Write a program to `$HOME/.config/proxy` in the file.
30+
31+Example program:
32+
33+```bash
34+#!/bin/bash
35+# The file path: $HOME/.config/proxy
36+if [[ "$OSTYPE" == "darwin"* ]]; then
37+ echo "http://127.0.0.1:6152" # Surge Mac
38+else
39+ echo "http://127.0.0.1:8123" # polipo
40+fi
41+```
42+
43+Method 3:
44+
45+The working path of **Method 2** can be changed via `$CONFIG_PROXY`
46+
47+## Reference
48+
49+- `$GIT_SSH`: <https://www.git-scm.com/docs/git#Documentation/git.txt-codeGITSSHcode>
50+- OpenSSH manual: <https://man.openbsd.org/ssh>
51+
52+## Maintainer
53+
54+- <https://github.com/septs>
55+
56+## The oh-my-zsh plugin (shell-proxy)
57+
58+Public Domain
59diff --git a/plugins/shell-proxy/proxy.py b/plugins/shell-proxy/proxy.py
60new file mode 100755
61index 0000000000000000000000000000000000000000..2b62f6cb5363a756765e07d92626438163d4d2d5
62--- /dev/null
63+++ b/plugins/shell-proxy/proxy.py
64@@ -0,0 +1,72 @@
65+#!/usr/bin/env python3
66+import os
67+import sys
68+from subprocess import check_output, list2cmdline
69+
70+cwd = os.path.dirname(__file__)
71+ssh_agent = os.path.join(cwd, "ssh-agent.py")
72+user_proxy = os.environ.get("CONFIG_PROXY", os.path.expandvars("$HOME/.config/proxy"))
73+
74+
75+def get_http_proxy():
76+ if "DEFAULT_PROXY" in os.environ:
77+ return os.environ["DEFAULT_PROXY"]
78+ if os.path.isfile(user_proxy):
79+ return check_output(user_proxy).decode("utf-8").strip()
80+ raise Exception("Not found, Proxy configuration")
81+
82+
83+def make_proxies(url: str):
84+ proxies = {"%s_PROXY" % _: url for _ in ("HTTP", "HTTPS", "FTP", "RSYNC", "ALL")}
85+ proxies.update({name.lower(): value for (name, value) in proxies.items()})
86+ proxies["GIT_SSH"] = ssh_agent
87+ return proxies
88+
89+
90+def merge(mapping: dict):
91+ return ("%s=%s" % _ for _ in mapping.items())
92+
93+
94+class CommandSet:
95+ proxies = make_proxies(get_http_proxy())
96+ aliases = {
97+ _: "env NAME=%s %s" % (_, ssh_agent)
98+ for _ in ("ssh", "sftp", "scp", "slogin", "ssh-copy-id")
99+ }
100+
101+ def enable(self):
102+ cmdline("export", *merge(self.proxies))
103+ cmdline("alias", *merge(self.aliases))
104+
105+ def disable(self):
106+ cmdline("unset", *self.proxies.keys())
107+ cmdline("unalias", *self.aliases.keys())
108+
109+ def status(self):
110+ proxies = (
111+ "%11s = %s" % (name, os.environ[name])
112+ for name in self.proxies.keys()
113+ if name in os.environ
114+ )
115+ for _ in proxies:
116+ cmdline("echo", _)
117+
118+ def usage(self):
119+ cmdline("echo", "usage: proxy {enable,disable,status}")
120+ self.status()
121+
122+
123+def cmdline(*items):
124+ print(list2cmdline(items))
125+
126+
127+def main():
128+ command = CommandSet()
129+ if len(sys.argv) == 1:
130+ command.usage()
131+ sys.exit(-1)
132+ getattr(command, sys.argv[1], command.usage)()
133+
134+
135+if __name__ == "__main__":
136+ main()
137diff --git a/plugins/shell-proxy/shell-proxy.plugin.zsh b/plugins/shell-proxy/shell-proxy.plugin.zsh
138new file mode 100644
139index 0000000000000000000000000000000000000000..fd0e2fe79716294dd615292e7cd15c0df1ef1918
140--- /dev/null
141+++ b/plugins/shell-proxy/shell-proxy.plugin.zsh
142@@ -0,0 +1,16 @@
143+#!/usr/bin/bash
144+# shellcheck disable=SC1090
145+
146+__PROXY__="${0:A:h}/proxy.py"
147+
148+proxy() {
149+ source <("$__PROXY__" "$1")
150+}
151+
152+_proxy() {
153+ local -r commands=('enable' 'disable' 'status')
154+ compset -P '*,'
155+ compadd -S '' "${commands[@]}"
156+}
157+
158+compdef '_proxy' 'proxy'
159diff --git a/plugins/shell-proxy/ssh-agent.py b/plugins/shell-proxy/ssh-agent.py
160new file mode 100755
161index 0000000000000000000000000000000000000000..61cf84c0b8bfe67cd9a4465b9d70d23fcb7fa6c8
162--- /dev/null
163+++ b/plugins/shell-proxy/ssh-agent.py
164@@ -0,0 +1,16 @@
165+#!/usr/bin/env python3
166+import os
167+import subprocess
168+import sys
169+
170+ssh_proxy = os.path.join(os.path.dirname(__file__), "ssh-proxy.py")
171+
172+argv = [
173+ os.environ.get("NAME", "ssh"),
174+ "-o",
175+ "ProxyCommand={} %h %p".format(ssh_proxy),
176+ "-o",
177+ "Compression=yes",
178+]
179+
180+subprocess.call(argv + sys.argv[1:], env=os.environ)
181diff --git a/plugins/shell-proxy/ssh-proxy.py b/plugins/shell-proxy/ssh-proxy.py
182new file mode 100755
183index 0000000000000000000000000000000000000000..5efd5fd2184885d67e2f20caf681516bafe0e2f2
184--- /dev/null
185+++ b/plugins/shell-proxy/ssh-proxy.py
186@@ -0,0 +1,18 @@
187+#!/usr/bin/env python3
188+import os
189+import subprocess
190+import sys
191+import urllib.parse
192+
193+proxy = next(os.environ[_] for _ in ("HTTP_PROXY", "HTTPS_PROXY") if _ in os.environ)
194+argv = [
195+ "nc",
196+ "-X",
197+ "connect",
198+ "-x",
199+ urllib.parse.urlparse(proxy).netloc, # proxy-host:proxy-port
200+ sys.argv[1], # host
201+ sys.argv[2], # port
202+]
203+
204+subprocess.call(argv)