Skip to content

Commit

Permalink
!experiment shell
Browse files Browse the repository at this point in the history
  • Loading branch information
tony committed Sep 23, 2022
1 parent 853ccb7 commit 16a4c16
Showing 1 changed file with 293 additions and 0 deletions.
293 changes: 293 additions & 0 deletions src/libvcs/shell.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
import logging
import os
import sys

PY3 = sys.version_info[0] == 3
PYMINOR = sys.version_info[1]
PYPATCH = sys.version_info[2]


if PY3 and PYMINOR >= 7:
breakpoint = breakpoint
else:
import pdb

breakpoint = pdb.set_trace # type: ignore


logger = logging.getLogger(__name__)


def has_ipython():
try:
from IPython import start_ipython # NOQA F841
except ImportError:
try:
from IPython.Shell import IPShell # NOQA F841
except ImportError:
return False

return True


def has_ptpython():
try:
from ptpython.repl import embed, run_config # NOQA F841
except ImportError:
try:
from prompt_toolkit.contrib.repl import embed, run_config # NOQA F841
except ImportError:
return False

return True


def has_ptipython():
try:
from ptpython.ipython import embed # NOQA F841
from ptpython.repl import run_config # NOQA F841
except ImportError:
try:
from prompt_toolkit.contrib.ipython import embed # NOQA F841
from prompt_toolkit.contrib.repl import run_config # NOQA F841
except ImportError:
return False

return True


def has_bpython():
try:
from bpython import embed # NOQA F841
except ImportError:
return False
return True


def detect_best_shell():
if has_ptipython():
return "ptipython"
elif has_ptpython():
return "ptpython"
elif has_ipython():
return "ipython"
elif has_bpython():
return "bpython"
return "code"


def get_bpython(options, extra_args=None):
if extra_args is None:
extra_args = {}

from bpython import embed # NOQA F841

def launch_bpython():
imported_objects = get_launch_args(**options)
kwargs = {}
if extra_args:
kwargs["args"] = extra_args
embed(imported_objects, **kwargs)

return launch_bpython


def get_ipython_arguments():
ipython_args = "IPYTHON_ARGUMENTS"
return os.environ.get(ipython_args, "").split()


def get_ipython(options, **extra_args):
try:
from IPython import start_ipython

def launch_ipython():
imported_objects = get_launch_args(**options)
ipython_arguments = extra_args or get_ipython_arguments()
start_ipython(argv=ipython_arguments, user_ns=imported_objects)

return launch_ipython
except ImportError:
# IPython < 0.11
# Explicitly pass an empty list as arguments, because otherwise
# IPython would use sys.argv from this script.
# Notebook not supported for IPython < 0.11.
from IPython.Shell import IPShell

def launch_ipython():
imported_objects = get_launch_args(**options)
shell = IPShell(argv=[], user_ns=imported_objects)
shell.mainloop()

return launch_ipython


def get_ptpython(options, vi_mode=False):
try:
from ptpython.repl import embed, run_config
except ImportError:
from prompt_toolkit.contrib.repl import embed, run_config

def launch_ptpython():
imported_objects = get_launch_args(**options)
history_filename = os.path.expanduser("~/.ptpython_history")
embed(
globals=imported_objects,
history_filename=history_filename,
vi_mode=vi_mode,
configure=run_config,
)

return launch_ptpython


def get_ptipython(options, vi_mode=False):
"""Based on django-extensions
Run renamed to launch, get_imported_objects renamed to get_launch_args
"""
try:
from ptpython.ipython import embed
from ptpython.repl import run_config
except ImportError:
# prompt_toolkit < v0.27
from prompt_toolkit.contrib.ipython import embed
from prompt_toolkit.contrib.repl import run_config

def launch_ptipython():
imported_objects = get_launch_args(**options)
history_filename = os.path.expanduser("~/.ptpython_history")
embed(
user_ns=imported_objects,
history_filename=history_filename,
vi_mode=vi_mode,
configure=run_config,
)

return launch_ptipython


def get_launch_args(**kwargs):
import libtmux

return {
"libtmux": libtmux,
"Server": libtmux.Server,
"Session": libtmux.Session,
"Window": libtmux.Window,
"Pane": libtmux.Pane,
"server": kwargs.get("server"),
"session": kwargs.get("session"),
"window": kwargs.get("window"),
"pane": kwargs.get("pane"),
}


def get_code(use_pythonrc, imported_objects):
import code

try:
# Try activating rlcompleter, because it's handy.
import readline
except ImportError:
pass
else:
# We don't have to wrap the following import in a 'try', because
# we already know 'readline' was imported successfully.
import rlcompleter

readline.set_completer(rlcompleter.Completer(imported_objects).complete)
# Enable tab completion on systems using libedit (e.g. macOS).
# These lines are copied from Lib/site.py on Python 3.4.
readline_doc = getattr(readline, "__doc__", "")
if readline_doc is not None and "libedit" in readline_doc:
readline.parse_and_bind("bind ^I rl_complete")
else:
readline.parse_and_bind("tab:complete")

# We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system
# conventions and get $PYTHONSTARTUP first then .pythonrc.py.
if use_pythonrc:
for pythonrc in {
os.environ.get("PYTHONSTARTUP"),
os.path.expanduser("~/.pythonrc.py"),
}:
if not pythonrc:
continue
if not os.path.isfile(pythonrc):
continue
with open(pythonrc) as handle:
pythonrc_code = handle.read()
# Match the behavior of the cpython shell where an error in
# PYTHONSTARTUP prints an exception and continues.
exec(compile(pythonrc_code, pythonrc, "exec"), imported_objects)

def launch_code():
code.interact(local=imported_objects)

return launch_code


def launch(shell="best", use_pythonrc=False, use_vi_mode=False, **kwargs):
# Also allowing passing shell='code' to force using code.interact
imported_objects = get_launch_args(**kwargs)

if shell == "best":
shell = detect_best_shell()

if shell == "ptipython":
launch = get_ptipython(options=kwargs, vi_mode=use_vi_mode)
elif shell == "ptpython":
launch = get_ptpython(options=kwargs, vi_mode=use_vi_mode)
elif shell == "ipython":
launch = get_ipython(options=kwargs)
elif shell == "bpython":
launch = get_bpython(options=kwargs)
else:
launch = get_code(use_pythonrc=use_pythonrc, imported_objects=imported_objects)

launch()


def command_shell(
session_name,
window_name,
socket_name,
socket_path,
command,
shell,
use_pythonrc,
use_vi_mode,
):
"""Launch python shell for tmux server, session, window and pane.
Priority given to loaded session/window/pane objects:
- session_name and window_name arguments
- current shell: envvar ``TMUX_PANE`` for determining window and session
- :attr:`libtmux.Server.attached_sessions`, :attr:`libtmux.Session.attached_window`,
:attr:`libtmux.Window.attached_pane`
"""
server = Server(socket_name=socket_name, socket_path=socket_path)

if command is not None:
exec(command)
else:
if shell == "pdb" or (os.getenv("PYTHONBREAKPOINT") and PY3 and PYMINOR >= 7):
from tmuxp._compat import breakpoint as tmuxp_breakpoint

tmuxp_breakpoint()
return
else:
from ..shell import launch

launch(
shell=shell,
use_pythonrc=use_pythonrc, # shell: code
use_vi_mode=use_vi_mode, # shell: ptpython, ptipython
# tmux environment / libtmux variables
server=server,
session=session,
window=window,
pane=pane,
)

0 comments on commit 16a4c16

Please sign in to comment.