Skip to content

Commit 16a4c16

Browse files
committed
!experiment shell
1 parent 853ccb7 commit 16a4c16

File tree

1 file changed

+293
-0
lines changed

1 file changed

+293
-0
lines changed

src/libvcs/shell.py

+293
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
import logging
2+
import os
3+
import sys
4+
5+
PY3 = sys.version_info[0] == 3
6+
PYMINOR = sys.version_info[1]
7+
PYPATCH = sys.version_info[2]
8+
9+
10+
if PY3 and PYMINOR >= 7:
11+
breakpoint = breakpoint
12+
else:
13+
import pdb
14+
15+
breakpoint = pdb.set_trace # type: ignore
16+
17+
18+
logger = logging.getLogger(__name__)
19+
20+
21+
def has_ipython():
22+
try:
23+
from IPython import start_ipython # NOQA F841
24+
except ImportError:
25+
try:
26+
from IPython.Shell import IPShell # NOQA F841
27+
except ImportError:
28+
return False
29+
30+
return True
31+
32+
33+
def has_ptpython():
34+
try:
35+
from ptpython.repl import embed, run_config # NOQA F841
36+
except ImportError:
37+
try:
38+
from prompt_toolkit.contrib.repl import embed, run_config # NOQA F841
39+
except ImportError:
40+
return False
41+
42+
return True
43+
44+
45+
def has_ptipython():
46+
try:
47+
from ptpython.ipython import embed # NOQA F841
48+
from ptpython.repl import run_config # NOQA F841
49+
except ImportError:
50+
try:
51+
from prompt_toolkit.contrib.ipython import embed # NOQA F841
52+
from prompt_toolkit.contrib.repl import run_config # NOQA F841
53+
except ImportError:
54+
return False
55+
56+
return True
57+
58+
59+
def has_bpython():
60+
try:
61+
from bpython import embed # NOQA F841
62+
except ImportError:
63+
return False
64+
return True
65+
66+
67+
def detect_best_shell():
68+
if has_ptipython():
69+
return "ptipython"
70+
elif has_ptpython():
71+
return "ptpython"
72+
elif has_ipython():
73+
return "ipython"
74+
elif has_bpython():
75+
return "bpython"
76+
return "code"
77+
78+
79+
def get_bpython(options, extra_args=None):
80+
if extra_args is None:
81+
extra_args = {}
82+
83+
from bpython import embed # NOQA F841
84+
85+
def launch_bpython():
86+
imported_objects = get_launch_args(**options)
87+
kwargs = {}
88+
if extra_args:
89+
kwargs["args"] = extra_args
90+
embed(imported_objects, **kwargs)
91+
92+
return launch_bpython
93+
94+
95+
def get_ipython_arguments():
96+
ipython_args = "IPYTHON_ARGUMENTS"
97+
return os.environ.get(ipython_args, "").split()
98+
99+
100+
def get_ipython(options, **extra_args):
101+
try:
102+
from IPython import start_ipython
103+
104+
def launch_ipython():
105+
imported_objects = get_launch_args(**options)
106+
ipython_arguments = extra_args or get_ipython_arguments()
107+
start_ipython(argv=ipython_arguments, user_ns=imported_objects)
108+
109+
return launch_ipython
110+
except ImportError:
111+
# IPython < 0.11
112+
# Explicitly pass an empty list as arguments, because otherwise
113+
# IPython would use sys.argv from this script.
114+
# Notebook not supported for IPython < 0.11.
115+
from IPython.Shell import IPShell
116+
117+
def launch_ipython():
118+
imported_objects = get_launch_args(**options)
119+
shell = IPShell(argv=[], user_ns=imported_objects)
120+
shell.mainloop()
121+
122+
return launch_ipython
123+
124+
125+
def get_ptpython(options, vi_mode=False):
126+
try:
127+
from ptpython.repl import embed, run_config
128+
except ImportError:
129+
from prompt_toolkit.contrib.repl import embed, run_config
130+
131+
def launch_ptpython():
132+
imported_objects = get_launch_args(**options)
133+
history_filename = os.path.expanduser("~/.ptpython_history")
134+
embed(
135+
globals=imported_objects,
136+
history_filename=history_filename,
137+
vi_mode=vi_mode,
138+
configure=run_config,
139+
)
140+
141+
return launch_ptpython
142+
143+
144+
def get_ptipython(options, vi_mode=False):
145+
"""Based on django-extensions
146+
147+
Run renamed to launch, get_imported_objects renamed to get_launch_args
148+
"""
149+
try:
150+
from ptpython.ipython import embed
151+
from ptpython.repl import run_config
152+
except ImportError:
153+
# prompt_toolkit < v0.27
154+
from prompt_toolkit.contrib.ipython import embed
155+
from prompt_toolkit.contrib.repl import run_config
156+
157+
def launch_ptipython():
158+
imported_objects = get_launch_args(**options)
159+
history_filename = os.path.expanduser("~/.ptpython_history")
160+
embed(
161+
user_ns=imported_objects,
162+
history_filename=history_filename,
163+
vi_mode=vi_mode,
164+
configure=run_config,
165+
)
166+
167+
return launch_ptipython
168+
169+
170+
def get_launch_args(**kwargs):
171+
import libtmux
172+
173+
return {
174+
"libtmux": libtmux,
175+
"Server": libtmux.Server,
176+
"Session": libtmux.Session,
177+
"Window": libtmux.Window,
178+
"Pane": libtmux.Pane,
179+
"server": kwargs.get("server"),
180+
"session": kwargs.get("session"),
181+
"window": kwargs.get("window"),
182+
"pane": kwargs.get("pane"),
183+
}
184+
185+
186+
def get_code(use_pythonrc, imported_objects):
187+
import code
188+
189+
try:
190+
# Try activating rlcompleter, because it's handy.
191+
import readline
192+
except ImportError:
193+
pass
194+
else:
195+
# We don't have to wrap the following import in a 'try', because
196+
# we already know 'readline' was imported successfully.
197+
import rlcompleter
198+
199+
readline.set_completer(rlcompleter.Completer(imported_objects).complete)
200+
# Enable tab completion on systems using libedit (e.g. macOS).
201+
# These lines are copied from Lib/site.py on Python 3.4.
202+
readline_doc = getattr(readline, "__doc__", "")
203+
if readline_doc is not None and "libedit" in readline_doc:
204+
readline.parse_and_bind("bind ^I rl_complete")
205+
else:
206+
readline.parse_and_bind("tab:complete")
207+
208+
# We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system
209+
# conventions and get $PYTHONSTARTUP first then .pythonrc.py.
210+
if use_pythonrc:
211+
for pythonrc in {
212+
os.environ.get("PYTHONSTARTUP"),
213+
os.path.expanduser("~/.pythonrc.py"),
214+
}:
215+
if not pythonrc:
216+
continue
217+
if not os.path.isfile(pythonrc):
218+
continue
219+
with open(pythonrc) as handle:
220+
pythonrc_code = handle.read()
221+
# Match the behavior of the cpython shell where an error in
222+
# PYTHONSTARTUP prints an exception and continues.
223+
exec(compile(pythonrc_code, pythonrc, "exec"), imported_objects)
224+
225+
def launch_code():
226+
code.interact(local=imported_objects)
227+
228+
return launch_code
229+
230+
231+
def launch(shell="best", use_pythonrc=False, use_vi_mode=False, **kwargs):
232+
# Also allowing passing shell='code' to force using code.interact
233+
imported_objects = get_launch_args(**kwargs)
234+
235+
if shell == "best":
236+
shell = detect_best_shell()
237+
238+
if shell == "ptipython":
239+
launch = get_ptipython(options=kwargs, vi_mode=use_vi_mode)
240+
elif shell == "ptpython":
241+
launch = get_ptpython(options=kwargs, vi_mode=use_vi_mode)
242+
elif shell == "ipython":
243+
launch = get_ipython(options=kwargs)
244+
elif shell == "bpython":
245+
launch = get_bpython(options=kwargs)
246+
else:
247+
launch = get_code(use_pythonrc=use_pythonrc, imported_objects=imported_objects)
248+
249+
launch()
250+
251+
252+
def command_shell(
253+
session_name,
254+
window_name,
255+
socket_name,
256+
socket_path,
257+
command,
258+
shell,
259+
use_pythonrc,
260+
use_vi_mode,
261+
):
262+
"""Launch python shell for tmux server, session, window and pane.
263+
264+
Priority given to loaded session/window/pane objects:
265+
266+
- session_name and window_name arguments
267+
- current shell: envvar ``TMUX_PANE`` for determining window and session
268+
- :attr:`libtmux.Server.attached_sessions`, :attr:`libtmux.Session.attached_window`,
269+
:attr:`libtmux.Window.attached_pane`
270+
"""
271+
server = Server(socket_name=socket_name, socket_path=socket_path)
272+
273+
if command is not None:
274+
exec(command)
275+
else:
276+
if shell == "pdb" or (os.getenv("PYTHONBREAKPOINT") and PY3 and PYMINOR >= 7):
277+
from tmuxp._compat import breakpoint as tmuxp_breakpoint
278+
279+
tmuxp_breakpoint()
280+
return
281+
else:
282+
from ..shell import launch
283+
284+
launch(
285+
shell=shell,
286+
use_pythonrc=use_pythonrc, # shell: code
287+
use_vi_mode=use_vi_mode, # shell: ptpython, ptipython
288+
# tmux environment / libtmux variables
289+
server=server,
290+
session=session,
291+
window=window,
292+
pane=pane,
293+
)

0 commit comments

Comments
 (0)