@@ -738,6 +738,150 @@ def command_shell(session_name, window_name, socket_name, socket_path, command):
738
738
tmuxp_breakpoint ()
739
739
740
740
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
+
741
885
@cli .command (name = 'freeze' )
742
886
@click .argument ('session_name' , nargs = 1 , required = False )
743
887
@click .option ('-S' , 'socket_path' , help = 'pass-through for tmux -S' )
0 commit comments