Skip to content

Commit 8644fa5

Browse files
committed
Add tmuxp shell_plus (credits to django-extensions, license MIT)
1 parent 9187c30 commit 8644fa5

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

tmuxp/cli.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,147 @@ def command_shell(session_name, window_name, socket_name, socket_path, command):
749749
tmuxp_breakpoint()
750750

751751

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

0 commit comments

Comments
 (0)