diff --git a/doc/examples.rst b/doc/examples.rst index d4f2aedc5c4..78bb1730031 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -241,6 +241,25 @@ JSON .. literalinclude:: ../examples/focus-window-and-panes.json :language: json +Terminal History +---------------- + +tmuxp allows ``suppress_history: false`` to override the default command / +suppression when building the workspace. +This will add the ``shell_command`` to the bash history in the pane. + +YAML +~~~~ + +.. literalinclude:: ../examples/suppress-history.yaml + :language: yaml + +JSON +~~~~ + +.. literalinclude:: ../examples/suppress-history.json + :language: json + Window Index ------------ diff --git a/examples/suppress-history.json b/examples/suppress-history.json new file mode 100644 index 00000000000..e2ea393b2a5 --- /dev/null +++ b/examples/suppress-history.json @@ -0,0 +1,44 @@ +{ + "windows": [ + { + "panes": [ + "echo 'window in the history!'" + ], + "focus": true, + "suppress_history": false, + "window_name": "appended" + }, + { + "panes": [ + "echo 'window not in the history!'" + ], + "suppress_history": true, + "window_name": "suppressed" + }, + { + "panes": [ + "echo 'session in the history!'" + ], + "window_name": "default" + }, + { + "panes": [ + { + "shell_command": "echo 'command in the history!'", + "suppress_history": false + }, + { + "shell_command": "echo 'command not in the history!'", + "suppress_history": true + }, + { + "shell_command": "echo 'window not in the history!'" + } + ], + "suppress_history": true, + "window_name": "mixed" + } + ], + "suppress_history": false, + "session_name": "suppress" +} diff --git a/examples/suppress-history.yaml b/examples/suppress-history.yaml new file mode 100644 index 00000000000..aa534d5a8a1 --- /dev/null +++ b/examples/suppress-history.yaml @@ -0,0 +1,29 @@ +session_name: suppress +suppress_history: false +windows: +- window_name: appended + focus: true + suppress_history: false + panes: + - echo "window in the history!" + +- window_name: suppressed + suppress_history: true + panes: + - echo "window not in the history!" + +- window_name: default + panes: + - echo "session in the history!" + +- window_name: mixed + suppress_history: false + panes: + - shell_command: + - echo "command in the history!" + suppress_history: false + - shell_command: + - echo "command not in the history!" + suppress_history: true + - shell_command: + - echo "window in the history!" \ No newline at end of file diff --git a/tmuxp/config.py b/tmuxp/config.py index 1c9a33e1a6d..f883ec75c8b 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -309,6 +309,11 @@ def trickle(sconf): else: session_start_directory = None + if 'suppress_history' in sconf: + suppress_history = sconf['suppress_history'] + else: + suppress_history = None + for windowconfig in sconf['windows']: # Prepend start_directory to relative window commands @@ -325,6 +330,11 @@ def trickle(sconf): ) windowconfig['start_directory'] = window_start_path + # We only need to trickle to the window, workspace builder checks wconf + if suppress_history is not None: + if not 'suppress_history' in windowconfig: + windowconfig['suppress_history'] = suppress_history + for paneconfig in windowconfig['panes']: commands_before = [] diff --git a/tmuxp/pane.py b/tmuxp/pane.py index 6190702f3b8..36e9da9b319 100644 --- a/tmuxp/pane.py +++ b/tmuxp/pane.py @@ -75,7 +75,7 @@ def cmd(self, cmd, *args, **kwargs): return self.server.cmd(cmd, *args, **kwargs) - def send_keys(self, cmd, enter=True): + def send_keys(self, cmd, enter=True, suppress_history=True): """``$ tmux send-keys`` to the pane. A leading space character is added to cmd to avoid polluting the @@ -85,9 +85,12 @@ def send_keys(self, cmd, enter=True): :type cmd: str :param enter: Send enter after sending the input. :type enter: bool + :param suppress_history: Don't add these keys to the shell history + :type suppress_history: bool """ - self.cmd('send-keys', ' ' + cmd) + prefix = ' ' if suppress_history else '' + self.cmd('send-keys', prefix + cmd) if enter: self.enter() diff --git a/tmuxp/testsuite/workspacebuilder.py b/tmuxp/testsuite/workspacebuilder.py index 1cfe7d53b1a..79b53299edc 100644 --- a/tmuxp/testsuite/workspacebuilder.py +++ b/tmuxp/testsuite/workspacebuilder.py @@ -14,12 +14,13 @@ import tempfile import time import unittest +import subprocess import kaptan from .helpers import TmuxTestCase from .. import Window, config, exc -from .._compat import text_type +from .._compat import text_type, console_to_str from ..workspacebuilder import WorkspaceBuilder logger = logging.getLogger(__name__) @@ -214,6 +215,63 @@ def test_focus_pane_index(self): self.assertEqual(p.get('pane_current_path'), pane_path) +class SuppressHistoryTest(TmuxTestCase): + yaml_config = """ + session_name: sampleconfig + start_directory: '~' + suppress_history: false + windows: + - window_name: inHistory + panes: + - echo inHistory + - window_name: isMissing + suppress_history: true + panes: + - echo isMissing + """ + def test_suppress_history(self): + s = self.session + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(self.yaml_config).get() + sconfig = config.expand(sconfig) + sconfig = config.trickle(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + builder.build(session=self.session) + time.sleep(0.2) # give .bashrc, etc. time to load + + s.server._update_windows() + for w in s.windows: + w.server._update_panes() + w.select_window() + for p in w.panes: + p.select_pane() + + # Print the last-in-history command in the pane + self.session.cmd('send-keys', ' fc -ln -1') + self.session.cmd('send-keys', 'Enter') + time.sleep(0.01) # give fc time to run + + # Get the contents of the pane + self.session.cmd('capture-pane') + captured_pane = self.session.cmd('show-buffer') + self.session.cmd('delete-buffer') + + # Parse the sent and last-in-history commands + sent_cmd = captured_pane.stdout[0].strip() + history_cmd = captured_pane.stdout[-2].strip() + + # If it was in the history, sent == history + if 'inHistory' in sent_cmd: + self.assertEqual(sent_cmd, history_cmd) + # Otherwise, sent != history + elif 'isMissing' in sent_cmd: + self.assertNotEqual(sent_cmd, history_cmd) + # Something went wrong + else: + self.assertTrue(False) + + class WindowOptions(TmuxTestCase): yaml_config = """ @@ -895,5 +953,6 @@ def suite(): suite.addTest(unittest.makeSuite(WindowAutomaticRename)) suite.addTest(unittest.makeSuite(WindowIndexTest)) suite.addTest(unittest.makeSuite(WindowOptions)) + suite.addTest(unittest.makeSuite(SuppressHistoryTest)) suite.addTest(unittest.makeSuite(EnvironmentVariables)) return suite diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index 1b1f16f5d00..e7072c1c379 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -261,8 +261,15 @@ def get_pane_start_directory(): if 'layout' in wconf: w.select_layout(wconf['layout']) + if 'suppress_history' in pconf: + suppress = pconf['suppress_history'] + elif 'suppress_history' in wconf: + suppress = wconf['suppress_history'] + else: + suppress = True + for cmd in pconf['shell_command']: - p.send_keys(cmd) + p.send_keys(cmd, suppress_history=suppress) if 'focus' in pconf and pconf['focus']: w.select_pane(p['pane_id'])