Skip to content

Commit e50e73b

Browse files
committed
Add tmuxp shell_plus (credits to django-extensions, license MIT)
1 parent 8af066a commit e50e73b

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

tmuxp/cli.py

+144
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,150 @@ def command_shell(session_name, window_name, socket_name, socket_path, command):
738738
tmuxp_breakpoint()
739739

740740

741+
@cli.command(name='shell_plus')
742+
@click.argument('session_name', nargs=1, required=False)
743+
@click.argument('window_name', nargs=1, required=False)
744+
@click.option('-S', 'socket_path', help='pass-through for tmux -S')
745+
@click.option('-L', 'socket_name', help='pass-through for tmux -L')
746+
@click.option(
747+
'-c',
748+
'command',
749+
help='Instead of opening shell, execute python code in libtmux and exit',
750+
)
751+
@click.option(
752+
'--use-pythonrc/--no-startup',
753+
'use_pythonrc',
754+
help='Load the PYTHONSTARTUP environment variable and ~/.pythonrc.py script.',
755+
default=False,
756+
)
757+
def command_shell_plus(
758+
session_name,
759+
window_name,
760+
socket_name,
761+
socket_path,
762+
command,
763+
use_pythonrc,
764+
):
765+
"""shell w/ tab completion.
766+
767+
Credits: django-extensions shell_plus.py 51fef74 (MIT License)
768+
"""
769+
server = Server(socket_name=socket_name, socket_path=socket_path)
770+
771+
current_pane = None
772+
if os.getenv('TMUX_PANE') is not None:
773+
try:
774+
current_pane = [
775+
p
776+
for p in server._list_panes()
777+
if p.get('pane_id') == os.getenv('TMUX_PANE')
778+
][0]
779+
except IndexError:
780+
pass
781+
782+
try:
783+
if session_name:
784+
session = server.find_where({'session_name': session_name})
785+
elif current_pane is not None:
786+
session = server.find_where({'session_id': current_pane['session_id']})
787+
else:
788+
session = server.list_sessions()[0]
789+
790+
if not session:
791+
raise exc.TmuxpException('Session not found: %s' % session_name)
792+
except exc.TmuxpException as e:
793+
print(e)
794+
return
795+
796+
try:
797+
if window_name:
798+
window = session.find_where({'window_name': window_name})
799+
if not window:
800+
raise exc.TmuxpException('Window not found: %s' % window_name)
801+
elif current_pane is not None:
802+
window = session.find_where({'window_id': current_pane['window_id']})
803+
else:
804+
window = session.list_windows()[0]
805+
806+
except exc.TmuxpException as e:
807+
print(e)
808+
return
809+
810+
try:
811+
if current_pane is not None:
812+
pane = window.find_where({'pane_id': current_pane['pane_id']}) # NOQA: F841
813+
else:
814+
pane = window.attached_pane # NOQA: F841
815+
except exc.TmuxpException as e:
816+
print(e)
817+
return
818+
819+
if command is not None:
820+
exec(command)
821+
else:
822+
# Using normal Python shell
823+
import code
824+
825+
import libtmux
826+
827+
imported_objects = {
828+
'libtmux': libtmux,
829+
'Server': libtmux.Server,
830+
'Session': libtmux.Session,
831+
'Window': libtmux.Window,
832+
'Pane': libtmux.Pane,
833+
'server': server,
834+
'session': session,
835+
'window': window,
836+
'pane': pane,
837+
}
838+
839+
try:
840+
# Try activating rlcompleter, because it's handy.
841+
import readline
842+
except ImportError:
843+
pass
844+
else:
845+
# We don't have to wrap the following import in a 'try', because
846+
# we already know 'readline' was imported successfully.
847+
import rlcompleter
848+
849+
readline.set_completer(rlcompleter.Completer(imported_objects).complete)
850+
# Enable tab completion on systems using libedit (e.g. macOS).
851+
# These lines are copied from Lib/site.py on Python 3.4.
852+
readline_doc = getattr(readline, '__doc__', '')
853+
if readline_doc is not None and 'libedit' in readline_doc:
854+
readline.parse_and_bind("bind ^I rl_complete")
855+
else:
856+
readline.parse_and_bind("tab:complete")
857+
858+
# We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system
859+
# conventions and get $PYTHONSTARTUP first then .pythonrc.py.
860+
if use_pythonrc:
861+
for pythonrc in set(
862+
[os.environ.get("PYTHONSTARTUP"), os.path.expanduser('~/.pythonrc.py')]
863+
):
864+
if not pythonrc:
865+
continue
866+
if not os.path.isfile(pythonrc):
867+
continue
868+
with open(pythonrc) as handle:
869+
pythonrc_code = handle.read()
870+
# Match the behavior of the cpython shell where an error in
871+
# PYTHONSTARTUP prints an exception and continues.
872+
try:
873+
exec(compile(pythonrc_code, pythonrc, 'exec'), imported_objects)
874+
except Exception:
875+
import traceback
876+
877+
traceback.print_exc()
878+
879+
def run_plain():
880+
code.interact(local=imported_objects)
881+
882+
run_plain()
883+
884+
741885
@cli.command(name='freeze')
742886
@click.argument('session_name', nargs=1, required=False)
743887
@click.option('-S', 'socket_path', help='pass-through for tmux -S')

0 commit comments

Comments
 (0)