From 525212ee74520fc06a6a797f5d6da2256a5b81a9 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 10:29:15 +0800 Subject: [PATCH 0001/3283] cleaning, docs --- tmuxp/cli.py | 108 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 45 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 3751588ac3d..ba42a8d9c8d 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -115,7 +115,9 @@ def prompt_choices(name, choices, default=None, resolve=ascii_lowercase, return rv -class ConfigCompleter(argcomplete.completers.FilesCompleter): +class ConfigFileCompleter(argcomplete.completers.FilesCompleter): + + """ argcomplete completer for tmuxp files. """ def __call__(self, prefix, **kwargs): completion = argcomplete.completers.FilesCompleter.__call__( @@ -130,6 +132,8 @@ def __call__(self, prefix, **kwargs): class TmuxinatorCompleter(argcomplete.completers.FilesCompleter): + """ argcomplete completer for Tmuxinator files. """ + def __call__(self, prefix, **kwargs): completion = argcomplete.completers.FilesCompleter.__call__( self, prefix, **kwargs @@ -145,6 +149,8 @@ def __call__(self, prefix, **kwargs): class TeamocilCompleter(argcomplete.completers.FilesCompleter): + """ argcomplete completer for Teamocil files. """ + def __call__(self, prefix, **kwargs): completion = argcomplete.completers.FilesCompleter.__call__( self, prefix, **kwargs @@ -158,16 +164,19 @@ def __call__(self, prefix, **kwargs): def SessionCompleter(prefix, **kwargs): + """ Return list of session names for argcomplete completer. """ t = Server() - return [s.get('session_name') for s in t._sessions if s.get('session_name').startswith(prefix)] + return [s.get('session_name') for s in t._sessions + if s.get('session_name').startswith(prefix)] def setupLogger(logger=None, level='INFO'): - '''setup logging for CLI use. + """Setup logging for CLI use. :param logger: instance of logger :type logger: :py:class:`Logger` - ''' + + """ if not logger: logger = logging.getLogger() if not logger.handlers: @@ -178,22 +187,24 @@ def setupLogger(logger=None, level='INFO'): def startup(config_dir): - ''' Initialize CLI. + """Initialize CLI. :param config_dir: Config directory to search :type config_dir: string - ''' + + """ if not os.path.exists(config_dir): os.makedirs(config_dir) -def build_workspace(config_file, args): - ''' build config workspace. +def load_workspace(config_file, args): + """ Build config workspace. :param config_file: full path to config file :param type: string - ''' + + """ logger.info('building %s.' % config_file) sconfig = kaptan.Kaptan() @@ -239,7 +250,8 @@ def build_workspace(config_file, args): return -def subcommand_load(args): +def command_load(args): + """ Load a session from a tmuxp session file. """ if args.list: startup(config_dir) configs_in_user = config.in_dir(config_dir) @@ -272,14 +284,16 @@ def subcommand_load(args): file_user = os.path.join(config_dir, configfile) file_cwd = os.path.join(cwd_dir, configfile) if os.path.exists(file_cwd) and os.path.isfile(file_cwd): - build_workspace(file_cwd, args) + load_workspace(file_cwd, args) elif os.path.exists(file_user) and os.path.isfile(file_user): - build_workspace(file_user, args) + load_workspace(file_user, args) else: logger.error('%s not found.' % configfile) -def subcommand_import_teamocil(args): +def command_import_teamocil(args): + """ Import teamocil config to tmuxp format. """ + if args.list: try: configs_in_user = config.in_dir( @@ -306,8 +320,7 @@ def subcommand_import_teamocil(args): ) print(output) - - if args.config: + elif args.config: configfile = os.path.relpath(args.config) configparser = kaptan.Kaptan(handler='yaml') configparser.import_config(configfile) @@ -322,7 +335,8 @@ def subcommand_import_teamocil(args): print(newconfig) -def subcommand_import_tmuxinator(args): +def command_import_tmuxinator(args): + """ Import tmuxinator config to tmuxp format. """ if args.list: try: configs_in_user = config.in_dir( @@ -365,7 +379,8 @@ def subcommand_import_tmuxinator(args): print(newconfig) -def subcommand_convert(args): +def command_convert(args): + """ Convert tmuxp config to and from JSON and YAML. """ try: configfile = args.config @@ -412,7 +427,8 @@ def subcommand_convert(args): print('written new config to <%s>.' % (newfile)) -def subcommand_attach_session(args): +def command_attach_session(args): + """ Command to attach / switch client to a tmux session.""" commands = [] ctext = args.session_name @@ -438,7 +454,8 @@ def subcommand_attach_session(args): print('Attaching client.') -def subcommand_kill_session(args): +def command_kill_session(args): + """ Command to kill a tmux session.""" commands = [] ctext = args.session_name @@ -462,7 +479,8 @@ def subcommand_kill_session(args): logger.error(e) -def cli_parser(): +def get_parser(): + """ Return :py:class:`argparse.ArgumentParser` instance for CLI. """ parser = argparse.ArgumentParser( description='''\ @@ -470,12 +488,12 @@ def cli_parser(): ''', ) - subparsers = parser.add_subparsers(title='subcommands', - description='valid subcommands', + subparsers = parser.add_subparsers(title='commands', + description='valid commands', help='additional help') kill_session = subparsers.add_parser('kill-session') - kill_session.set_defaults(callback=subcommand_kill_session) + kill_session.set_defaults(callback=command_kill_session) kill_session.add_argument( dest='session_name', @@ -484,7 +502,7 @@ def cli_parser(): ).completer = SessionCompleter attach_session = subparsers.add_parser('attach-session') - attach_session.set_defaults(callback=subcommand_attach_session) + attach_session.set_defaults(callback=command_attach_session) attach_session.add_argument( dest='session_name', @@ -513,8 +531,8 @@ def cli_parser(): will check launch a ~/.pullv.yaml / ~/.pullv.json from the cwd. will also check for any ./*.yaml and ./*.json. ''' % (cwd_dir + '/', config_dir), - ).completer = ConfigCompleter(allowednames=('.yaml', '.json'), directories=False) - load.set_defaults(callback=subcommand_load) + ).completer = ConfigFileCompleter(allowednames=('.yaml', '.json'), directories=False) + load.set_defaults(callback=command_load) convert = subparsers.add_parser('convert') @@ -530,13 +548,13 @@ def cli_parser(): will check launch a ~/.pullv.yaml / ~/.pullv.json from the cwd. will also check for any ./*.yaml and ./*.json. ''' % (cwd_dir + '/', config_dir) - ).completer = ConfigCompleter(allowednames=('.yaml', '.json'), directories=False) + ).completer = ConfigFileCompleter(allowednames=('.yaml', '.json'), directories=False) - convert.set_defaults(callback=subcommand_convert) + convert.set_defaults(callback=command_convert) importparser = subparsers.add_parser('import') - importsubparser = importparser.add_subparsers(title='subcommands', - description='valid subcommands', + importsubparser = importparser.add_subparsers(title='commands', + description='valid commands', help='additional help') import_teamocil = importsubparser.add_parser('teamocil') @@ -556,7 +574,7 @@ def cli_parser(): Checks current ~/.teamocil and current directory for yaml files. ''' ).completer = TeamocilCompleter(allowednames=('.yml'), directories=False) - import_teamocil.set_defaults(callback=subcommand_import_teamocil) + import_teamocil.set_defaults(callback=command_import_teamocil) import_tmuxinator = importsubparser.add_parser('tmuxinator') @@ -576,7 +594,7 @@ def cli_parser(): ''' ).completer = TmuxinatorCompleter(allowednames=('.yml'), directories=False) - import_tmuxinator.set_defaults(callback=subcommand_import_tmuxinator) + import_tmuxinator.set_defaults(callback=command_import_tmuxinator) parser.add_argument('--log-level', dest='log_level', default='INFO', metavar='log-level', @@ -599,7 +617,7 @@ def cli_parser(): def main(): - parser = cli_parser() + parser = get_parser() argcomplete.autocomplete(parser, always_complete_options=False) @@ -615,17 +633,17 @@ def main(): util.oh_my_zsh_auto_title() - if args.callback is subcommand_load: - subcommand_load(args) - elif args.callback is subcommand_convert: - subcommand_convert(args) - elif args.callback is subcommand_import_teamocil: - subcommand_import_teamocil(args) - elif args.callback is subcommand_import_tmuxinator: - subcommand_import_tmuxinator(args) - elif args.callback is subcommand_attach_session: - subcommand_attach_session(args) - elif args.callback is subcommand_kill_session: - subcommand_kill_session(args) + if args.callback is command_load: + command_load(args) + elif args.callback is command_convert: + command_convert(args) + elif args.callback is command_import_teamocil: + command_import_teamocil(args) + elif args.callback is command_import_tmuxinator: + command_import_tmuxinator(args) + elif args.callback is command_attach_session: + command_attach_session(args) + elif args.callback is command_kill_session: + command_kill_session(args) else: parser.print_help() From 32ff66e838f6693381196a6d246439b0f586ce4a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 11:54:02 +0800 Subject: [PATCH 0002/3283] update apidocs, changes. Pane.set_height, Pane.set_width --- CHANGES | 2 ++ doc/api.rst | 6 ++++-- tmuxp/pane.py | 32 +++++++++++++++++++++----------- tmuxp/session.py | 6 ++---- tmuxp/testsuite/test_pane.py | 27 +++++++++++++++++++++++++-- tmuxp/window.py | 2 ++ 6 files changed, 56 insertions(+), 19 deletions(-) diff --git a/CHANGES b/CHANGES index 3a81180017a..06ff090608e 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,8 @@ Here you can find the recent changes to tmuxp. - [cli] fix ``tmuxp load .`` fixed - [cli] fix ``tmuxp convert `` fixed. - [internal] `pep257` fixes. +- [internal] [tests] - :class:`Pane` now has :meth:`Pane.set_width` and + :meth:`Pane.set_height`. 2013-10-27 ---------- diff --git a/doc/api.rst b/doc/api.rst index f6cc21ad640..709a8e2472d 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -81,9 +81,11 @@ Command Line .. automethod:: tmuxp.cli.startup -.. automethod:: tmuxp.cli.query_yes_no +.. automethod:: tmuxp.cli.prompt +.. automethod:: tmuxp.cli.prompt_bool +.. automethod:: tmuxp.cli.prompt_choices -.. automethod:: tmuxp.cli.setupLogger +.. automethod:: tmuxp.cli.get_logger Configuration ------------- diff --git a/tmuxp/pane.py b/tmuxp/pane.py index 43540edf906..c9f23133315 100644 --- a/tmuxp/pane.py +++ b/tmuxp/pane.py @@ -78,11 +78,27 @@ def send_keys(self, cmd, enter=True): :param enter: bool. send enter after sending the key. ''' - self.tmux('send-keys', '-t%s' % self.target, cmd) + self.tmux('send-keys', '-t%s' % self.get('pane_id'), cmd) if enter: self.enter() + def set_width(self, width): + """Set width of pane. + + :param width: pane width, in cells. + :type width: int + """ + self.resize_pane(width=width) + + def set_height(self, height): + """Set height of pane. + + :param height: pane height, in cells. + :type height: int + """ + self.resize_pane(height=height) + def resize_pane(self, *args, **kwargs): ''' ``$ tmux resize-pane`` @@ -98,12 +114,12 @@ def resize_pane(self, *args, **kwargs): # logger.error('resize-pane', '-t%s' % self.target) if 'height' in kwargs: proc = self.tmux('resize-pane', '-t%s' % - self.target, '-y%s' % int(kwargs['height'])) + self.get('pane_id'), '-y%s' % int(kwargs['height'])) elif 'width' in kwargs: proc = self.tmux('resize-pane', '-t%s' % - self.target, '-x%s' % int(kwargs['width'])) + self.get('pane_id'), '-x%s' % int(kwargs['width'])) else: - proc = self.tmux('resize-pane', '-t%s' % self.target, args[0]) + proc = self.tmux('resize-pane', '-t%s' % self.get('pane_id'), args[0]) if proc.stderr: raise Exception(proc.stderr) @@ -115,13 +131,7 @@ def enter(self): ''' ``$ tmux send-keys`` send Enter to the pane. ''' - self.tmux('send-keys', '-t%s' % self.target, 'Enter') - - @property - def target(self): - # return "%s:%s.%s" % (self.session.get('session_id'), - # self.get('window_id'), self.get('pane_index')) - return self.get('pane_id') + self.tmux('send-keys', '-t%s' % self.get('pane_id'), 'Enter') def __repr__(self): return "%s(%s %s)" % (self.__class__.__name__, self.get('pane_id'), self.window) diff --git a/tmuxp/session.py b/tmuxp/session.py index 8af651adf0e..42b49ff43d8 100644 --- a/tmuxp/session.py +++ b/tmuxp/session.py @@ -246,17 +246,15 @@ def attached_window(self): else: continue - if len(active_windows) == 1: + if len(active_windows) == int(1): return active_windows[0] else: raise Exception( 'multiple active windows found. %s' % active_windows) - if len(self._windows) == 0: + if len(self._windows) == int(0): raise Exception('No Windows') - return False - def select_window(self, target_window): ''' ``$ tmux select-window`` diff --git a/tmuxp/testsuite/test_pane.py b/tmuxp/testsuite/test_pane.py index bd76e2e2f1a..a3d986c3b8a 100644 --- a/tmuxp/testsuite/test_pane.py +++ b/tmuxp/testsuite/test_pane.py @@ -13,10 +13,11 @@ class ResizeTest(TmuxTestCase): - def test_window_pane(self): - '''Pane.resize_pane()''' + def test_resize_pane(self): + """ Test Pane.resize_pane(). """ window = self.session.attached_window() + window.rename_window('test_resize_pane') pane1 = window.attached_pane() pane1_id = pane1['pane_id'] @@ -29,3 +30,25 @@ def test_window_pane(self): pane1.resize_pane(height=10) self.assertEqual(int(pane1['pane_height']), 10) + + def test_set_height(self): + window = self.session.new_window(window_name='test_set_height') + pane2 = window.split_window() + pane1 = window.attached_pane() + pane1_height = pane1['pane_height'] + + pane1.set_height(20) + self.assertNotEqual(pane1['pane_height'], pane1_height) + self.assertEqual(int(pane1['pane_height']), 20) + + def test_set_width(self): + window = self.session.new_window(window_name='test_set_width') + pane2 = window.split_window() + + window.select_layout('main-vertical') + pane1 = window.attached_pane() + pane1_width = pane1['pane_width'] + + pane1.set_width(25) + self.assertNotEqual(pane1['pane_width'], pane1_width) + self.assertEqual(int(pane1['pane_width']), 25) diff --git a/tmuxp/window.py b/tmuxp/window.py index 2c0149c1d5c..e90a6549742 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -324,6 +324,8 @@ def attached_pane(self): else: continue + return [] + def _list_panes(self): panes = self.server._update_panes()._panes From 726cf0e2298645c389df22954bf1ce946731f8cd Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 11:56:32 +0800 Subject: [PATCH 0003/3283] remove Session.is_clean --- tmuxp/session.py | 30 ------------------------------ tmuxp/testsuite/test_session.py | 14 -------------- 2 files changed, 44 deletions(-) diff --git a/tmuxp/session.py b/tmuxp/session.py index 42b49ff43d8..de5d42b3ff5 100644 --- a/tmuxp/session.py +++ b/tmuxp/session.py @@ -267,12 +267,6 @@ def select_window(self, target_window): Todo: assure ``-l``, ``-n``, ``-p`` work. ''' - # if isinstance(target_window, int): - # target = '-t%s:%s' % (self.get('session_name'), target_window) - # elif isinstance(target_window, basestring): - # target = '-t%s:%s' % (self.get('session_name'), target_window) - # else: - # target = '-t%s' % target_window target = '-t%s' % target_window @@ -289,30 +283,6 @@ def attached_pane(self): ''' return self.attached_window().attached_pane() - def is_clean(self): - ''' check if current session is pure, untouched: - - - 1 window - - 1 pane, no history. - - returns True or False. - ''' - if (len(self._windows) > 1): - logger.debug('%s not clean, multiple windows', self) - return False - - if (len(self.attached_window()._panes) > 1): - logger.debug('%s not clean, multiple panes (%s)' % ( - self, len(self.attached_window()._panes))) - return False - - if (int(self.attached_window().attached_pane().get('history_size')) > 0): - logger.debug('%s history_size (%s), greater than 0' % ( - self, self.attached_window().attached_pane().get('history_size'))) - return False - - return True - def set_option(self, option, value): ''' wrapper for ``tmux(1)``:: diff --git a/tmuxp/testsuite/test_session.py b/tmuxp/testsuite/test_session.py index e5ee1f21817..79cb83ed375 100644 --- a/tmuxp/testsuite/test_session.py +++ b/tmuxp/testsuite/test_session.py @@ -89,20 +89,6 @@ def test_session_rename(self): ) -class SessionCleanTest(TmuxTestCase): - - def test_is_session_clean(self): - '''Session.is_clean() returns False for sessions with previous commands''' - - self.assertEqual(self.session.is_clean(), True) - self.session.attached_window().attached_pane().send_keys('top') - sleep(.4) - self.session.attached_window().list_panes() - self.session.attached_window().attached_pane().send_keys( - 'C-c', enter=False) - self.assertEqual(self.session.is_clean(), False) - - class SessionNewTest(TmuxTestCase): def test_new_session(self): From 714fdc70234e61f15999a1d579a4e2d4d284faea Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 12:02:42 +0800 Subject: [PATCH 0004/3283] Add PEP257 link in CHANGES --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 06ff090608e..a81151aa9f2 100644 --- a/CHANGES +++ b/CHANGES @@ -8,7 +8,7 @@ Here you can find the recent changes to tmuxp. - [cli] fix ``tmuxp load .`` fixed - [cli] fix ``tmuxp convert `` fixed. -- [internal] `pep257` fixes. +- [internal] `pep257`_ fixes. - [internal] [tests] - :class:`Pane` now has :meth:`Pane.set_width` and :meth:`Pane.set_height`. From e5d29990356664fda4a694d70e428159a1ac42b8 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 12:14:55 +0800 Subject: [PATCH 0005/3283] rewrite Pane.tmux to send -t Pane.get('pane_id') --- tmuxp/pane.py | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/tmuxp/pane.py b/tmuxp/pane.py index c9f23133315..1b2b987e3e7 100644 --- a/tmuxp/pane.py +++ b/tmuxp/pane.py @@ -17,19 +17,11 @@ class Pane(util.TmuxMappingObject, util.TmuxRelationalObject): - ''' - ``tmux(1)`` pane. + """:term:`tmux(1)` :ref:`pane`. - pane holds a psuedoterm and linked to tmux windows. + :param window: :class:`Window` - Retrieve a tmux pane from server. Returns :class:`Pane`. - - Iterates ``$ tmux list-panes``, ``-F`` for return formatting. - - :param session: :class:`Session` object. - :param window: :class:`Window` object. - - ''' + """ def __init__(self, window=None, **kwargs): if not window: @@ -64,13 +56,11 @@ def by(val, *args): return list(filter(by, self.server._panes))[0] - # def __getitem__(self, key): - # return + def tmux(self, cmd, *args, **kwargs): + if not len([arg for arg in args if '-t' in arg]): + args = ('-t', self.get('pane_id')) + args - def tmux(self, *args, **kwargs): - # if '-t' not in kwargs: - # kwargs['-t'] = self.get['session_id'] - return self.server.tmux(*args, **kwargs) + return self.server.tmux(cmd, *args, **kwargs) def send_keys(self, cmd, enter=True): ''' @@ -78,7 +68,7 @@ def send_keys(self, cmd, enter=True): :param enter: bool. send enter after sending the key. ''' - self.tmux('send-keys', '-t%s' % self.get('pane_id'), cmd) + self.tmux('send-keys', cmd) if enter: self.enter() @@ -111,15 +101,12 @@ def resize_pane(self, *args, **kwargs): # if isinstance(target_pane, basestring) and not ':' not in target_pane or isinstance(target_pane, int): # target_pane = "%s.%s" % (self.target, target_pane) - # logger.error('resize-pane', '-t%s' % self.target) if 'height' in kwargs: - proc = self.tmux('resize-pane', '-t%s' % - self.get('pane_id'), '-y%s' % int(kwargs['height'])) + proc = self.tmux('resize-pane', '-y%s' % int(kwargs['height'])) elif 'width' in kwargs: - proc = self.tmux('resize-pane', '-t%s' % - self.get('pane_id'), '-x%s' % int(kwargs['width'])) + proc = self.tmux('resize-pane', '-x%s' % int(kwargs['width'])) else: - proc = self.tmux('resize-pane', '-t%s' % self.get('pane_id'), args[0]) + proc = self.tmux('resize-pane', args[0]) if proc.stderr: raise Exception(proc.stderr) @@ -131,7 +118,7 @@ def enter(self): ''' ``$ tmux send-keys`` send Enter to the pane. ''' - self.tmux('send-keys', '-t%s' % self.get('pane_id'), 'Enter') + self.tmux('send-keys', 'Enter') def __repr__(self): return "%s(%s %s)" % (self.__class__.__name__, self.get('pane_id'), self.window) From 827dc5743ea40eaa2f39b6de95cd1675b64799e8 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 14:12:24 +0800 Subject: [PATCH 0006/3283] Add todo --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index 52f60211164..d4a33327901 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,7 @@ Roadmap Immediate """"""""" +- make prompt_bool Y/n by default - shorts for load ========================= ====================================================== From b0b6dd746468545399932eff3bd8426ecceb362d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 14:26:51 +0800 Subject: [PATCH 0007/3283] Update .tmuxp.json and .tmuxp.yaml to reset before opening vim --- .tmuxp.json | 5 ++++- .tmuxp.yaml | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.tmuxp.json b/.tmuxp.json index 5711628474a..1cf06c82eed 100644 --- a/.tmuxp.json +++ b/.tmuxp.json @@ -4,6 +4,7 @@ "panes": [ { "shell_command": [ + "reset", "vim", ":Ex" ], @@ -37,7 +38,9 @@ "panes": [ { "shell_command": [ - "vim" + "reset", + "vim", + ":Ex" ], "focus": true }, diff --git a/.tmuxp.yaml b/.tmuxp.yaml index f573fe28c2b..b6f51c3e1c5 100644 --- a/.tmuxp.yaml +++ b/.tmuxp.yaml @@ -10,6 +10,7 @@ windows: - '[ ! -d .env/build ] || rm -rf .env/build' panes: - shell_command: + - reset - vim - :Ex focus: true @@ -31,7 +32,9 @@ windows: - cd ./doc panes: - shell_command: + - reset - vim + - :Ex focus: true - pwd - echo 'docs built to '; python -m SimpleHTTPServer From d7db400b2ca125b23043ba4e9abf81262ff8ac9d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 14:52:29 +0800 Subject: [PATCH 0008/3283] ./run_tests.py automatically add tmuxp.testsuite to testmodule names --- CHANGES | 2 ++ doc/developing.rst | 31 +++++++++++++++++++++++-------- run_tests.py | 22 +++++++++++++++++----- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index a81151aa9f2..532f0db55ba 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,8 @@ Here you can find the recent changes to tmuxp. - [internal] `pep257`_ fixes. - [internal] [tests] - :class:`Pane` now has :meth:`Pane.set_width` and :meth:`Pane.set_height`. +- [tests] ``./run_tests.py --tests`` now automatically prepends + ``tmuxp.testsuite`` to names. 2013-10-27 ---------- diff --git a/doc/developing.rst b/doc/developing.rst index b7e28bfc0a3..a0639eb0906 100644 --- a/doc/developing.rst +++ b/doc/developing.rst @@ -74,7 +74,22 @@ If you found a problem or are trying to write a test, you can file an Choose tests to run """"""""""""""""""" -Testing specific testsuites, testcase and tests +.. note:: + + As of v0.0.20, ``--tests`` automatically assume the namespace of + ``tmuxp.testsuite``. + + .. code-block:: bash + + $ ./run_tests.py --tests test_config.ImportExportTest + + Is now equivalent to: + + .. code-block:: bash + + $ ./run_tests.py --tests tmuxp.testsuite.test_config.ImportExportTest + +Testing specific TestSuites, TestCase and tests .. code-block:: bash @@ -87,26 +102,26 @@ By :py:class:`unittest.TestSuite` / module: .. code-block:: bash - $ ./run_tests.py tmuxp.testsuite.test_config + $ ./run_tests.py test_config by :py:class:`unittest.TestCase`: .. code-block:: bash - $ ./run_tests.py --tests tmuxp.testsuite.test_config.ImportExportTest + $ ./run_tests.py --tests test_config.ImportExportTest individual tests: .. code-block:: bash - $ ./run_tests.py --tests tmuxp.testsuite.test_config.ImportExportTest.test_export_json + $ ./run_tests.py --tests test_config.ImportExportTest.test_export_json Multiple can be separated by spaces: .. code-block:: bash - $ ./run_tests.py --tests tmuxp.testsuite.test_config.ImportExportTest.test_export_json \ - testsuite.test_config.ImportExportTest.test_window + $ ./run_tests.py --tests ImportExportTest.test_export_json \ + ImportExportTest.test_window .. _test_builder_visually: @@ -237,9 +252,9 @@ In this, I will also begin documenting the API. the use of: Session -Session.new_window() - returns a new Window object bound to the session, +:meth:`Session.new_window()` - returns a new Window object bound to the session, also uses ``tmux new-window``. -Session.new_session() - class method - returns a new Session object. +:meth:`Session.new_session()` - class method - returns a new Session object. Differences from tmux --------------------- diff --git a/run_tests.py b/run_tests.py index 46cdebb969c..f9a309368a6 100755 --- a/run_tests.py +++ b/run_tests.py @@ -131,16 +131,24 @@ def output(line): Test individual, TestCase or TestSuites, or multiple. Example for test_config TestSuite: by TestSuite (module): - $ ./run_tests.py tmuxp.testsuite.test_config + $ ./run_tests.py test_config by TestCase: - $ ./run_tests.py tmuxp.testsuite.test_config.ImportExportTest + $ ./run_tests.py test_config.ImportExportTest individual tests: - $ ./run_tests.py tmuxp.testsuite.test_config.ImportExportTest.test_export_json + $ ./run_tests.py test_config.ImportExportTest.test_export_json Multiple can be separated by spaces: - $ ./run_tests.py tmuxp.testsuite.test_config.ImportExportTest.test_export_json \\ - testsuite.test_config.ImportExportTest.test_window + $ ./run_tests.py test_config.ImportExportTest.test_export_json \\ + test_config.ImportExportTest.test_window + + ./run_tests will automatically assume the package namespace ``tmuxp.testsuite``. + + $ ./run_tests.py test_config.ImportExportTest + + is the same as: + + $ ./run_tests.py tmuxp.testsuite.test_config.ImportExportTest ''' ) parser.add_argument('-l', '--log-level', dest='log_level', default='INFO', @@ -171,6 +179,10 @@ def output(line): else: sys.exit(1) if args.tests and len(args.tests) > int(0): + for arg in args.tests: + if not arg.startswith('tmuxp.testsuite'): + loc = args.tests.index(arg) + args.tests[loc] = 'tmuxp.testsuite.%s' % arg suites = unittest.TestLoader().loadTestsFromNames(args.tests) result = unittest.TextTestRunner(verbosity=verbosity, failfast=args.failfast).run(suites) else: From 84e601e39f319ffb3f7c5da207d7081f6db28d3a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 14:53:47 +0800 Subject: [PATCH 0009/3283] add some util methods to api docs --- doc/api.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/api.rst b/doc/api.rst index 709a8e2472d..097e04beabc 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -74,6 +74,10 @@ Internals .. autoclass:: tmuxp.util.tmux +.. automethod:: tmuxp.util.version + +.. automethod:: tmuxp.util.oh_my_zsh_autotitle + .. automethod:: tmuxp.util.which Command Line From 21413ae07ec8777bebc09b001333d1708a322b54 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 14:54:24 +0800 Subject: [PATCH 0010/3283] Window.tmux adds tmux target --- CHANGES | 2 ++ tmuxp/window.py | 12 +++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index 532f0db55ba..d914db9cb4a 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,8 @@ Here you can find the recent changes to tmuxp. :meth:`Pane.set_height`. - [tests] ``./run_tests.py --tests`` now automatically prepends ``tmuxp.testsuite`` to names. +- [internal] :meth:`Window.tmux` and :meth:`Pane.tmux` will automatically add + their ``{window/pane}_id`` if one isn't specific. 2013-10-27 ---------- diff --git a/tmuxp/window.py b/tmuxp/window.py index e90a6549742..ab5f583ebee 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -70,10 +70,11 @@ def by(val, *args): return list(filter(by, self.server._windows))[0] - def tmux(self, *args, **kwargs): - # if '-t' not in kwargs: - # kwargs['-t'] = self.get['session_id'] - return self.server.tmux(*args, **kwargs) + def tmux(self, cmd, *args, **kwargs): + if not len([arg for arg in args if '-t' in str(arg)]): + args = ('-t', self.get('window_id')) + args + + return self.server.tmux(cmd, *args, **kwargs) def select_layout(self, layout=None): ''' @@ -105,7 +106,6 @@ def select_layout(self, layout=None): ''' self.tmux( 'select-layout', - '-t%s' % self.target, # target (name of session) layout ) @@ -132,7 +132,6 @@ def set_window_option(self, option, value): process = self.tmux( 'set-window-option', - '-t%s' % self['window_id'], option, value ) @@ -216,7 +215,6 @@ def rename_window(self, new_name): try: self.tmux( 'rename-window', - '-t%s' % self.target, new_name ) self['window_name'] = new_name From 8b9bc7de946e765a7cc624640fe70285c97b953b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 15:00:00 +0800 Subject: [PATCH 0011/3283] Pane now has Pane.clear() and Pane.reset(), Pane.tmux docs --- tmuxp/pane.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tmuxp/pane.py b/tmuxp/pane.py index 1b2b987e3e7..143f5de9a59 100644 --- a/tmuxp/pane.py +++ b/tmuxp/pane.py @@ -35,7 +35,6 @@ def __init__(self, window=None, **kwargs): self._pane_id = kwargs['pane_id'] self.server._update_panes() - # self.update(**kwargs) @property def _TMUX(self, *args): @@ -57,6 +56,12 @@ def by(val, *args): return list(filter(by, self.server._panes))[0] def tmux(self, cmd, *args, **kwargs): + """Send command to tmux with :attr:`pane_id` as ``target-pane``. + + Specifying ``('-t', 'custom-target')`` or ``('-tcustom_target')`` in + ``args`` will override using the object's ``pane_id`` as target. + + """ if not len([arg for arg in args if '-t' in arg]): args = ('-t', self.get('pane_id')) + args @@ -73,6 +78,15 @@ def send_keys(self, cmd, enter=True): if enter: self.enter() + def clear(self): + """Clear pane.""" + self.send_keys('reset') + + def reset(self): + """Reset and clear pane history. """ + + self.tmux('send-keys', '-R \; clear-history') + def set_width(self, width): """Set width of pane. From 48d90a25bd072a0fd288c5754359a50c80957884 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 15:00:09 +0800 Subject: [PATCH 0012/3283] Window.tmux docs --- tmuxp/window.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tmuxp/window.py b/tmuxp/window.py index ab5f583ebee..cba37b151d5 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -71,6 +71,12 @@ def by(val, *args): return list(filter(by, self.server._windows))[0] def tmux(self, cmd, *args, **kwargs): + """Send command to tmux with :attr:`window_id` as ``target-window``. + + Specifying ``('-t', 'custom-target')`` or ``('-tcustom_target')`` in + ``args`` will override using the object's ``window_id`` as target. + + """ if not len([arg for arg in args if '-t' in str(arg)]): args = ('-t', self.get('window_id')) + args From 98f557b1b399f46dbabd8eaf7d2e9a8634971477 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 15:00:46 +0800 Subject: [PATCH 0013/3283] add Pane.reset() to test_pane testsuite for giggles --- tmuxp/testsuite/test_pane.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tmuxp/testsuite/test_pane.py b/tmuxp/testsuite/test_pane.py index a3d986c3b8a..abdf64000af 100644 --- a/tmuxp/testsuite/test_pane.py +++ b/tmuxp/testsuite/test_pane.py @@ -52,3 +52,5 @@ def test_set_width(self): pane1.set_width(25) self.assertNotEqual(pane1['pane_width'], pane1_width) self.assertEqual(int(pane1['pane_width']), 25) + + pane1.reset() From 39afc21f86018e0df1ddfaa2e4dc81c556a58a5f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 15:11:23 +0800 Subject: [PATCH 0014/3283] cli.prompt_yes_no --- tmuxp/cli.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index ba42a8d9c8d..44a02e178f3 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -79,6 +79,13 @@ def prompt_bool(name, default=False, yes_choices=None, no_choices=None): return False +def prompt_yes_no(name, default=True): + return prompt_bool(name, + default=default, + yes_choices=['Y', 'y'], + no_choices=['n'] + ) + def prompt_choices(name, choices, default=None, resolve=ascii_lowercase, no_choice=('none',)): """ @@ -229,7 +236,7 @@ def load_workspace(config_file, args): builder.build() if 'TMUX' in os.environ: - if prompt_bool('Already inside TMUX, load session?'): + if prompt_yes_no('Already inside TMUX, load session?', default='Y'): del os.environ['TMUX'] os.execl(tmux_bin, 'tmux', 'switch-client', '-t', sconfig[ 'session_name']) @@ -237,7 +244,7 @@ def load_workspace(config_file, args): os.execl(tmux_bin, 'tmux', 'attach-session', '-t', sconfig[ 'session_name']) except exc.TmuxSessionExists as e: - attach_session = prompt_bool(e.message + ' Attach?') + attach_session = prompt_yes_no(e.message + ' Attach?', default='Y') if 'TMUX' in os.environ: del os.environ['TMUX'] @@ -401,26 +408,26 @@ def command_convert(args): return if 'json' in ext: - if prompt_bool('convert to <%s> to yaml?' % (fullfile)): + if prompt_yes_no('convert to <%s> to yaml?' % (fullfile), default='Y'): configparser = kaptan.Kaptan() configparser.import_config(configfile) newfile = fullfile.replace(ext, '.yaml') newconfig = configparser.export( 'yaml', indent=2, default_flow_style=False ) - if prompt_bool('write config to %s?' % (newfile)): + if prompt_yes_no('write config to %s?' % (newfile), default='Y'): buf = open(newfile, 'w') buf.write(newconfig) buf.close() print('written new config to %s' % (newfile)) elif 'yaml' in ext: - if prompt_bool('convert to <%s> to json?' % (fullfile)): + if prompt_yes_no('convert to <%s> to json?' % (fullfile), default='Y'): configparser = kaptan.Kaptan() configparser.import_config(configfile) newfile = fullfile.replace(ext, '.json') newconfig = configparser.export('json', indent=2) print(newconfig) - if prompt_bool('write config to <%s>?' % (newfile)): + if prompt_yes_no('write config to <%s>?' % (newfile), default='Y'): buf = open(newfile, 'w') buf.write(newconfig) buf.close() From b49bdb2472d2d02b5444a05f9c33dc2f4a6f51ad Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 15:34:59 +0800 Subject: [PATCH 0015/3283] prompt_bool return choice of y/n, Y/n or y/N --- tmuxp/cli.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 44a02e178f3..92ff343ee3d 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -69,8 +69,18 @@ def prompt_bool(name, default=False, yes_choices=None, no_choices=None): yes_choices = yes_choices or ('y', 'yes', '1', 'on', 'true', 't') no_choices = no_choices or ('n', 'no', '0', 'off', 'false', 'f') + if default is None: + prompt_choice = 'y/n' + elif default is True: + prompt_choice = 'Y/n' + else: + prompt_choice = 'y/N' + + prompt = name + ' [%s]' % prompt_choice + prompt += name.endswith('?') and ' ' or ': ' + while True: - rv = prompt(name, default and yes_choices[0] or no_choices[0]) + rv = input(prompt) if not rv: return default if rv.lower() in yes_choices: @@ -80,11 +90,7 @@ def prompt_bool(name, default=False, yes_choices=None, no_choices=None): def prompt_yes_no(name, default=True): - return prompt_bool(name, - default=default, - yes_choices=['Y', 'y'], - no_choices=['n'] - ) + return prompt_bool(name, default=default) def prompt_choices(name, choices, default=None, resolve=ascii_lowercase, no_choice=('none',)): @@ -236,7 +242,7 @@ def load_workspace(config_file, args): builder.build() if 'TMUX' in os.environ: - if prompt_yes_no('Already inside TMUX, load session?', default='Y'): + if prompt_yes_no('Already inside TMUX, load session?'): del os.environ['TMUX'] os.execl(tmux_bin, 'tmux', 'switch-client', '-t', sconfig[ 'session_name']) @@ -244,7 +250,7 @@ def load_workspace(config_file, args): os.execl(tmux_bin, 'tmux', 'attach-session', '-t', sconfig[ 'session_name']) except exc.TmuxSessionExists as e: - attach_session = prompt_yes_no(e.message + ' Attach?', default='Y') + attach_session = prompt_yes_no(e.message + ' Attach?') if 'TMUX' in os.environ: del os.environ['TMUX'] @@ -408,26 +414,26 @@ def command_convert(args): return if 'json' in ext: - if prompt_yes_no('convert to <%s> to yaml?' % (fullfile), default='Y'): + if prompt_yes_no('convert to <%s> to yaml?' % (fullfile)): configparser = kaptan.Kaptan() configparser.import_config(configfile) newfile = fullfile.replace(ext, '.yaml') newconfig = configparser.export( 'yaml', indent=2, default_flow_style=False ) - if prompt_yes_no('write config to %s?' % (newfile), default='Y'): + if prompt_yes_no('write config to %s?' % (newfile)): buf = open(newfile, 'w') buf.write(newconfig) buf.close() print('written new config to %s' % (newfile)) elif 'yaml' in ext: - if prompt_yes_no('convert to <%s> to json?' % (fullfile), default='Y'): + if prompt_yes_no('convert to <%s> to json?' % (fullfile)): configparser = kaptan.Kaptan() configparser.import_config(configfile) newfile = fullfile.replace(ext, '.json') newconfig = configparser.export('json', indent=2) print(newconfig) - if prompt_yes_no('write config to <%s>?' % (newfile), default='Y'): + if prompt_yes_no('write config to <%s>?' % (newfile)): buf = open(newfile, 'w') buf.write(newconfig) buf.close() From c91b9625e10079a15915ed81a02a88751b15a7b4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 15:38:00 +0800 Subject: [PATCH 0016/3283] v0.0.20 --- tmuxp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index c21f557403b..44edcb2c69c 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -20,4 +20,4 @@ import logging -__version__ = '0.0.19' +__version__ = '0.0.20' From b6f399cfe0bb1a77c2f5500cd5102b7ff2fb2ddf Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 21:20:42 +0800 Subject: [PATCH 0017/3283] doc updates --- doc/api.rst | 3 ++- tmuxp/cli.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index 097e04beabc..17bf374f9ce 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -89,7 +89,8 @@ Command Line .. automethod:: tmuxp.cli.prompt_bool .. automethod:: tmuxp.cli.prompt_choices -.. automethod:: tmuxp.cli.get_logger +.. automethod:: tmuxp.cli.setup_logger +.. automethod:: tmuxp.cli.get_parser Configuration ------------- diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 92ff343ee3d..e8ecce617db 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -183,7 +183,7 @@ def SessionCompleter(prefix, **kwargs): if s.get('session_name').startswith(prefix)] -def setupLogger(logger=None, level='INFO'): +def setup_logger(logger=None, level='INFO'): """Setup logging for CLI use. :param logger: instance of logger @@ -636,7 +636,7 @@ def main(): args = parser.parse_args() - setupLogger(level=args.log_level.upper()) + setup_logger(level=args.log_level.upper()) try: util.version() From 03f979ca6aa6f4548990c8f3e62850b3af557748 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 28 Oct 2013 21:33:44 +0800 Subject: [PATCH 0018/3283] api --- doc/api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api.rst b/doc/api.rst index 17bf374f9ce..b043b67aa72 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -76,7 +76,7 @@ Internals .. automethod:: tmuxp.util.version -.. automethod:: tmuxp.util.oh_my_zsh_autotitle +.. automethod:: tmuxp.util.oh_my_zsh_auto_title .. automethod:: tmuxp.util.which From 5360ca52ae6e447428af0925627e9443ed0737b6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 07:04:27 +0800 Subject: [PATCH 0019/3283] Add todo items --- TODO | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TODO b/TODO index d4a33327901..34b15b9c3de 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,11 @@ Roadmap Immediate """"""""" +- auto-rename +- prompt filepath/filename choice before save +- confirm and loop +- fix import of blank panes teamocil tmuxinator + - make prompt_bool Y/n by default - shorts for load From 923cdf9b070479fa2622ee58801ae7c6f589ccb3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 08:29:09 +0800 Subject: [PATCH 0020/3283] todo item, give imported configs session name --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index 34b15b9c3de..bdbc320f8d9 100644 --- a/TODO +++ b/TODO @@ -8,6 +8,7 @@ Immediate - prompt filepath/filename choice before save - confirm and loop - fix import of blank panes teamocil tmuxinator +- give a real session name if none exists - make prompt_bool Y/n by default - shorts for load From 66a655bfa87aa8b5f286e5a8154dd63594e06acc Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 08:30:07 +0800 Subject: [PATCH 0021/3283] or support without a session name --- TODO | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index bdbc320f8d9..c3faba1c0e9 100644 --- a/TODO +++ b/TODO @@ -8,7 +8,8 @@ Immediate - prompt filepath/filename choice before save - confirm and loop - fix import of blank panes teamocil tmuxinator -- give a real session name if none exists +- give a real session name if none exists or support building without + a session name - make prompt_bool Y/n by default - shorts for load From 59bf78358f3bbae8caaecfe97787b93054fa5c38 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 08:37:36 +0800 Subject: [PATCH 0022/3283] Workflow for importing config files from tmuxinator and teamocil --- tmuxp/cli.py | 118 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 16 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index e8ecce617db..394498510c7 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -92,6 +92,7 @@ def prompt_bool(name, default=False, yes_choices=None, no_choices=None): def prompt_yes_no(name, default=True): return prompt_bool(name, default=default) + def prompt_choices(name, choices, default=None, resolve=ascii_lowercase, no_choice=('none',)): """ @@ -254,12 +255,13 @@ def load_workspace(config_file, args): if 'TMUX' in os.environ: del os.environ['TMUX'] - os.execl(tmux_bin, 'tmux', 'switch-client', '-t', sconfig[ - 'session_name']) + os.execl(tmux_bin, 'tmux', 'switch-client', '-t', + sconfig['session_name']) if attach_session: - os.execl(tmux_bin, 'tmux', 'attach-session', '-t', sconfig[ - 'session_name']) + print(sconfig['sesson_name']) + os.execl(tmux_bin, 'tmux', 'attach-session', '-t', + sconfig['session_name']) return @@ -334,18 +336,60 @@ def command_import_teamocil(args): print(output) elif args.config: - configfile = os.path.relpath(args.config) + configfile = os.path.abspath(os.path.relpath(args.config)) configparser = kaptan.Kaptan(handler='yaml') - configparser.import_config(configfile) + + if os.path.exists(configfile): + print(configfile) + configparser.import_config(configfile) + else: + sys.exit('File not found: %s' % configfile) newconfig = config.import_teamocil(configparser.get()) - newconfig = configparser.import_config(newconfig) - newconfig = configparser.export( - 'yaml', indent=2, default_flow_style=False - ) + config_format = prompt_choices('Convert to', choices=[ + 'yaml', 'json'], default='yaml') + + if config_format == 'yaml': + newconfig = configparser.export( + 'yaml', indent=2, default_flow_style=False + ) + elif config_format == 'json': + newconfig = configparser.export('json', indent=2) + else: + sys.exit('Unknown config format.') print(newconfig) + print( + '---------------------------------------------------------------') + print( + 'Configuration import does its best to convert teamocil files.\n') + if prompt_yes_no( + 'The new config *WILL* require adjusting afterwards. Save config?' + ): + dest = None + while not dest: + dest_prompt = prompt('Save to: ', os.path.abspath( + os.path.join(config_dir, 'myimport.%s' % config_format))) + if os.path.exists(dest_prompt): + print('%s exists. Pick a new filename.' % dest_prompt) + continue + + dest = dest_prompt + + dest = os.path.abspath(os.path.relpath(dest)) + if prompt_yes_no('Write to %s?' % dest): + buf = open(dest, 'w') + buf.write(newconfig) + buf.close() + + print('Saved to %s.' % dest) + else: + print( + 'tmuxp has examples in JSON and YAML format at \n' + 'View tmuxp docs at ' + ) + sys.exit() def command_import_tmuxinator(args): @@ -378,18 +422,60 @@ def command_import_tmuxinator(args): print(output) if args.config: - configfile = os.path.relpath(args.config) + configfile = os.path.abspath(os.path.relpath(args.config)) configparser = kaptan.Kaptan(handler='yaml') - configparser.import_config(configfile) + + if os.path.exists(configfile): + print(configfile) + configparser.import_config(configfile) + else: + sys.exit('File not found: %s' % configfile) newconfig = config.import_tmuxinator(configparser.get()) - newconfig = configparser.import_config(newconfig) - newconfig = configparser.export( - 'yaml', indent=2, default_flow_style=False - ) + config_format = prompt_choices('Convert to', choices=[ + 'yaml', 'json'], default='yaml') + + if config_format == 'yaml': + newconfig = configparser.export( + 'yaml', indent=2, default_flow_style=False + ) + elif config_format == 'json': + newconfig = configparser.export('json', indent=2) + else: + sys.exit('Unknown config format.') print(newconfig) + print( + '---------------------------------------------------------------') + print( + 'Configuration import does its best to convert teamocil files.\n') + if prompt_yes_no( + 'The new config *WILL* require adjusting afterwards. Save config?' + ): + dest = None + while not dest: + dest_prompt = prompt('Save to: ', os.path.abspath( + os.path.join(config_dir, 'myimport.%s' % config_format))) + if os.path.exists(dest_prompt): + print('%s exists. Pick a new filename.' % dest_prompt) + continue + + dest = dest_prompt + + dest = os.path.abspath(os.path.relpath(dest)) + if prompt_yes_no('Write to %s?' % dest): + buf = open(dest, 'w') + buf.write(newconfig) + buf.close() + + print('Saved to %s.' % dest) + else: + print( + 'tmuxp has examples in JSON and YAML format at \n' + 'View tmuxp docs at ' + ) + sys.exit() def command_convert(args): From 1dd136824167699baf61bb9deca9f8649effb352 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 08:39:14 +0800 Subject: [PATCH 0023/3283] 0.0.21 --- CHANGES | 7 +++++++ tmuxp/__init__.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index d914db9cb4a..09f0714ea62 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,13 @@ tmuxp Changelog Here you can find the recent changes to tmuxp. +2013-10-29 +---------- + +- [cli] enhancements to prompts +- [cli] ``tmuxp import`` for teamocil and tmuxinator now has a wizard and offers + to save in JSON or YAML format. + 2013-10-28 ---------- diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index 44edcb2c69c..997f0eb8016 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -20,4 +20,4 @@ import logging -__version__ = '0.0.20' +__version__ = '0.0.21' From 423a478c78bdd3dd769bb8064ec0ca7ba5c924ca Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 09:57:54 +0800 Subject: [PATCH 0024/3283] let's try autorename test. update select_pane to correctly use -l -U -D -L -R or custom target_pane input --- tmuxp/testsuite/test_workspacebuilder.py | 84 ++++++++++++++++++++---- tmuxp/window.py | 11 ++-- 2 files changed, 79 insertions(+), 16 deletions(-) diff --git a/tmuxp/testsuite/test_workspacebuilder.py b/tmuxp/testsuite/test_workspacebuilder.py index b2706e6bd64..7b672a763a6 100644 --- a/tmuxp/testsuite/test_workspacebuilder.py +++ b/tmuxp/testsuite/test_workspacebuilder.py @@ -4,6 +4,7 @@ import os import unittest import logging +import time import kaptan from .. import Window, config, exc from ..workspacebuilder import WorkspaceBuilder @@ -24,7 +25,7 @@ class TwoPaneTest(TmuxTestCase): - vim start_directory: '~' - shell_command: - - cowsay "hey" + - echo "hey" window_name: editor - panes: - shell_command: @@ -70,9 +71,9 @@ class ThreePaneTest(TmuxTestCase): - vim start_directory: '~' - shell_command: - - cowsay "hey" + - echo "hey" - shell_command: - - cowsay "moo" + - echo "moo" ''' def test_split_windows(self): @@ -112,9 +113,9 @@ class FocusAndPaneIndexTest(TmuxTestCase): - vim start_directory: '~' - shell_command: - - cowsay "hey" + - echo "hey" - shell_command: - - cowsay "moo" + - echo "moo" - top focus: true - window_name: window 2 @@ -124,9 +125,9 @@ class FocusAndPaneIndexTest(TmuxTestCase): start_directory: '~' focus: true - shell_command: - - cowsay "hey" + - echo "hey" - shell_command: - - cowsay "moo" + - echo "moo" ''' @@ -165,8 +166,6 @@ def test_split_windows(self): class WindowOptions(TmuxTestCase): - '''sample config with no session name''' - yaml_config = ''' session_name: test window options start_directory: '~' @@ -179,9 +178,9 @@ class WindowOptions(TmuxTestCase): - vim start_directory: '~' - shell_command: - - cowsay "hey" + - echo "hey" - shell_command: - - cowsay "moo" + - echo "moo" window_name: editor ''' @@ -208,6 +207,69 @@ def test_window_options(self): w.select_layout(wconf['layout']) +class WindowAutomaticRename(TmuxTestCase): + + yaml_config = ''' + session_name: test window options + start_directory: '~' + windows: + - layout: main-horizontal + options: + automatic-rename: on + panes: + - shell_command: + - nano + start_directory: '~' + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" + ''' + + def test_automatic_rename_option(self): + """ with option automatic-rename: on. """ + s = self.session + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(self.yaml_config).get() + + builder = WorkspaceBuilder(sconf=sconfig) + + window_count = len(self.session._windows) # current window count + self.assertEqual(len(s._windows), window_count) + for w, wconf in builder.iter_create_windows(s): + + window_pane_count = len(w._panes) + for p in builder.iter_create_panes(w, wconf): + p = p + self.assertEqual(len(s._windows), window_count) + self.assertIsInstance(w, Window) + self.assertEqual(w.show_window_option('automatic-rename'), 'on') + + self.assertEqual(len(s._windows), window_count) + + window_count += 1 + w.select_layout(wconf['layout']) + + w = s.attached_window() + + for i in range(5): + w = s.attached_window() + if w['window_name'] == 'nano': + break + time.sleep(.1) + + self.assertEqual(w.get('window_name'), 'nano') + + w.select_pane('-D') + for i in range(5): + w = s.attached_window() + if w['window_name'] != 'nano': + break + time.sleep(.1) + + self.assertNotEqual(w.get('window_name'), 'nano') + + class TestsToDo(object): def test_uses_first_window_if_exists(self): diff --git a/tmuxp/window.py b/tmuxp/window.py index cba37b151d5..4a48283484a 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -235,16 +235,17 @@ def select_pane(self, target_pane): ''' ``$ tmux select-pane`` - :param target_pane: ``target_pane``, or ``-U``,``-D``, ``-L``, ``-R``. + :param target_pane: ``target_pane``, or ``-U``,``-D``, ``-L``, ``-R`` + or ``-l``. :type target_pane: string :rtype: :class:`Pane` - Todo: make 'up', 'down', 'left', 'right' acceptable ``target_pane``. ''' - # if isinstance(target_pane, basestring) and not ':' not in target_pane or isinstance(target_pane, int): - # target_pane = "%s.%s" % (self.target, target_pane) - proc = self.tmux('select-pane', '-t%s' % target_pane) + if target_pane in ['-l', '-U', '-D', '-L', '-R']: + proc = self.tmux('select-pane', '-t%s' % self.get('window_id'), target_pane) + else: + proc = self.tmux('select-pane', '-t%s' % target_pane) if proc.stderr: raise Exception(proc.stderr) From 9c738489f11b58dce8b3326bb4e07b50db87dade Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 10:04:30 +0800 Subject: [PATCH 0025/3283] automatic_rename test: "man echo" instead of nano --- tmuxp/testsuite/test_workspacebuilder.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tmuxp/testsuite/test_workspacebuilder.py b/tmuxp/testsuite/test_workspacebuilder.py index 7b672a763a6..8dfe4f46359 100644 --- a/tmuxp/testsuite/test_workspacebuilder.py +++ b/tmuxp/testsuite/test_workspacebuilder.py @@ -218,7 +218,7 @@ class WindowAutomaticRename(TmuxTestCase): automatic-rename: on panes: - shell_command: - - nano + - man echo start_directory: '~' - shell_command: - echo "hey" @@ -254,20 +254,20 @@ def test_automatic_rename_option(self): for i in range(5): w = s.attached_window() - if w['window_name'] == 'nano': + if w['window_name'] == 'man': break time.sleep(.1) - self.assertEqual(w.get('window_name'), 'nano') + self.assertEqual(w.get('window_name'), 'man') w.select_pane('-D') for i in range(5): w = s.attached_window() - if w['window_name'] != 'nano': + if w['window_name'] != 'man': break time.sleep(.1) - self.assertNotEqual(w.get('window_name'), 'nano') + self.assertNotEqual(w.get('window_name'), 'man') class TestsToDo(object): From 3c42a1533cac5e22956cf47f6ac4652f080f6a57 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 10:08:55 +0800 Subject: [PATCH 0026/3283] adjust range(30) time.sleep(.01) for test --- tmuxp/testsuite/test_workspacebuilder.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tmuxp/testsuite/test_workspacebuilder.py b/tmuxp/testsuite/test_workspacebuilder.py index 8dfe4f46359..7045049cbca 100644 --- a/tmuxp/testsuite/test_workspacebuilder.py +++ b/tmuxp/testsuite/test_workspacebuilder.py @@ -252,20 +252,20 @@ def test_automatic_rename_option(self): w = s.attached_window() - for i in range(5): + for i in range(30): w = s.attached_window() if w['window_name'] == 'man': break - time.sleep(.1) + time.sleep(.01) self.assertEqual(w.get('window_name'), 'man') w.select_pane('-D') - for i in range(5): + for i in range(30): w = s.attached_window() if w['window_name'] != 'man': break - time.sleep(.1) + time.sleep(.01) self.assertNotEqual(w.get('window_name'), 'man') From 6ec00bc58afa478a516af4e47150ed3729578930 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 10:16:03 +0800 Subject: [PATCH 0027/3283] 2 new examples, automatic renaming, main-pane-height --- doc/examples.rst | 30 ++++++++++++++++++++++++++++++ examples/automatic-rename.json | 30 ++++++++++++++++++++++++++++++ examples/automatic-rename.yaml | 14 ++++++++++++++ examples/main-pane-height.json | 31 +++++++++++++++++++++++++++++++ examples/main-pane-height.yaml | 15 +++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 examples/automatic-rename.json create mode 100644 examples/automatic-rename.yaml create mode 100644 examples/main-pane-height.json create mode 100644 examples/main-pane-height.yaml diff --git a/doc/examples.rst b/doc/examples.rst index 6cc567a85e6..6ee9f8526c0 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -104,6 +104,36 @@ JSON :language: json +Automatic Rename +---------------- + +YAML +"""" + +.. literalinclude:: ../examples/automatic-rename.yaml + :language: yaml + +JSON +"""" + +.. literalinclude:: ../examples/automatic-rename.json + :language: json + +Main pane height +---------------- + +YAML +"""" + +.. literalinclude:: ../examples/main-pane-height.yaml + :language: yaml + +JSON +"""" + +.. literalinclude:: ../examples/main-pane-height.json + :language: json + Super-advanced dev environment ------------------------------ diff --git a/examples/automatic-rename.json b/examples/automatic-rename.json new file mode 100644 index 00000000000..87c9d09ca08 --- /dev/null +++ b/examples/automatic-rename.json @@ -0,0 +1,30 @@ +{ + "windows": [ + { + "panes": [ + { + "shell_command": [ + "man echo" + ], + "start_directory": "~" + }, + { + "shell_command": [ + "echo \"hey\"" + ] + }, + { + "shell_command": [ + "echo \"moo\"" + ] + } + ], + "layout": "main-horizontal", + "options": { + "automatic-rename": true + } + } + ], + "session_name": "test window options", + "start_directory": "~" +} \ No newline at end of file diff --git a/examples/automatic-rename.yaml b/examples/automatic-rename.yaml new file mode 100644 index 00000000000..fbbe8f08e4f --- /dev/null +++ b/examples/automatic-rename.yaml @@ -0,0 +1,14 @@ +session_name: test window options +start_directory: '~' +windows: +- layout: main-horizontal + options: + automatic-rename: on + panes: + - shell_command: + - man echo + start_directory: '~' + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" diff --git a/examples/main-pane-height.json b/examples/main-pane-height.json new file mode 100644 index 00000000000..280d7ca3342 --- /dev/null +++ b/examples/main-pane-height.json @@ -0,0 +1,31 @@ +{ + "windows": [ + { + "panes": [ + { + "shell_command": [ + "vim" + ], + "start_directory": "~" + }, + { + "shell_command": [ + "echo \"hey\"" + ] + }, + { + "shell_command": [ + "echo \"moo\"" + ] + } + ], + "layout": "main-horizontal", + "options": { + "main-pane-height": 30 + }, + "window_name": "editor" + } + ], + "session_name": "main pane height", + "start_directory": "~" +} \ No newline at end of file diff --git a/examples/main-pane-height.yaml b/examples/main-pane-height.yaml new file mode 100644 index 00000000000..3dbcc479f90 --- /dev/null +++ b/examples/main-pane-height.yaml @@ -0,0 +1,15 @@ +session_name: main-pane-height +start_directory: '~' +windows: +- layout: main-horizontal + options: + main-pane-height: 30 + panes: + - shell_command: + - top + start_directory: '~' + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" + window_name: my window name From e92441707ea2ec39bc65095b34a4ed993474c3f6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 10:16:34 +0800 Subject: [PATCH 0028/3283] TODO: use ./examples for test_workspacebuilder tests --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index c3faba1c0e9..1535d189fa5 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,7 @@ Roadmap Immediate """"""""" +- have test_workspace_builder use tests from ./examples! - auto-rename - prompt filepath/filename choice before save - confirm and loop From 0b8e77b4a013d20ea29104ea6615ab23b33176a4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 10:18:33 +0800 Subject: [PATCH 0029/3283] fix main-pane-height.json example --- examples/main-pane-height.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/main-pane-height.json b/examples/main-pane-height.json index 280d7ca3342..8d90ee30225 100644 --- a/examples/main-pane-height.json +++ b/examples/main-pane-height.json @@ -4,7 +4,7 @@ "panes": [ { "shell_command": [ - "vim" + "top" ], "start_directory": "~" }, @@ -28,4 +28,4 @@ ], "session_name": "main pane height", "start_directory": "~" -} \ No newline at end of file +} From 62caebcac4fc6dd5ce1dcfa3e4aa1ab0608e695b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 10:22:00 +0800 Subject: [PATCH 0030/3283] Update CHANGES --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 09f0714ea62..fc953e8c70f 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,10 @@ Here you can find the recent changes to tmuxp. 2013-10-29 ---------- +- [internal] :meth:`Window.select_pane` now accepts ``-l``, ``-U``, ``-D``, + ``-L``, ``-R``. +- [internal] [tests] support for ``automatic-rename`` option. +- [docs] 2 new :ref:`examples`, 'main-pane-height' and 'automatic-rename'. - [cli] enhancements to prompts - [cli] ``tmuxp import`` for teamocil and tmuxinator now has a wizard and offers to save in JSON or YAML format. From 1f8bc797bddf685bdb74c00beaec2d7e976e39ae Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 10:23:03 +0800 Subject: [PATCH 0031/3283] 0.0.22 --- tmuxp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index 997f0eb8016..715e47cf062 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -20,4 +20,4 @@ import logging -__version__ = '0.0.21' +__version__ = '0.0.22' From bbe44b1e353456186aa607e199638fe79b7b2636 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 10:33:04 +0800 Subject: [PATCH 0032/3283] hotfix for cli.py --- tmuxp/cli.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 394498510c7..c974156fc24 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -259,7 +259,6 @@ def load_workspace(config_file, args): sconfig['session_name']) if attach_session: - print(sconfig['sesson_name']) os.execl(tmux_bin, 'tmux', 'attach-session', '-t', sconfig['session_name']) return From b6c2e84d7b151acd77d189a02e703db0fc0a2d65 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 11:45:22 +0800 Subject: [PATCH 0033/3283] Fix bug where tmuxp load w/ session already loaded would switch/attach even if no was entered --- tmuxp/cli.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index c974156fc24..69954e21c23 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -251,16 +251,17 @@ def load_workspace(config_file, args): os.execl(tmux_bin, 'tmux', 'attach-session', '-t', sconfig[ 'session_name']) except exc.TmuxSessionExists as e: - attach_session = prompt_yes_no(e.message + ' Attach?') + if prompt_yes_no(e.message + ' Attach?'): - if 'TMUX' in os.environ: - del os.environ['TMUX'] - os.execl(tmux_bin, 'tmux', 'switch-client', '-t', - sconfig['session_name']) + if 'TMUX' in os.environ: + del os.environ['TMUX'] + os.execl(tmux_bin, 'tmux', 'switch-client', '-t', + sconfig['session_name']) - if attach_session: - os.execl(tmux_bin, 'tmux', 'attach-session', '-t', - sconfig['session_name']) + if attach_session: + os.execl(tmux_bin, 'tmux', 'attach-session', '-t', + sconfig['session_name']) + return return From e2a5608fd3d5b1f659583bd6d5e29e5807275b04 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 11:46:09 +0800 Subject: [PATCH 0034/3283] update CHANGELOG for bugfix --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index fc953e8c70f..8f62c4f7a7b 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,8 @@ Here you can find the recent changes to tmuxp. - [cli] enhancements to prompts - [cli] ``tmuxp import`` for teamocil and tmuxinator now has a wizard and offers to save in JSON or YAML format. +- [cli] [bug] [b6c2e84] Fix bug where tmuxp load w/ session already loaded would + switch/attach even if no was entered 2013-10-28 ---------- From f69d2bf81ef105138a8fc3a1c4e8533f95b544fb Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 11:47:54 +0800 Subject: [PATCH 0035/3283] More bugfix for attach session if already exists --- tmuxp/cli.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 69954e21c23..b739be04add 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -257,11 +257,9 @@ def load_workspace(config_file, args): del os.environ['TMUX'] os.execl(tmux_bin, 'tmux', 'switch-client', '-t', sconfig['session_name']) - - if attach_session: + else: os.execl(tmux_bin, 'tmux', 'attach-session', '-t', sconfig['session_name']) - return return From f56521d4b1c6ccf2cd9c6faa6d8b5e124e01a4b3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 11:49:34 +0800 Subject: [PATCH 0036/3283] TODO Note for shlex.escape session names in completion for cli --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index 1535d189fa5..6cbef31ace1 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,7 @@ Roadmap Immediate """"""""" +- tmuxp kill-session escape / quote names with spaces - have test_workspace_builder use tests from ./examples! - auto-rename - prompt filepath/filename choice before save From f1744596f9adcb6c07078e636c0f59f56859254f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 11:53:48 +0800 Subject: [PATCH 0037/3283] Server.kill_session needs no target --- tmuxp/session.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tmuxp/session.py b/tmuxp/session.py index de5d42b3ff5..77d43516182 100644 --- a/tmuxp/session.py +++ b/tmuxp/session.py @@ -78,12 +78,10 @@ def attach_session(self, target_session=None): if proc.stderr: raise Exception(proc.stderr) - def kill_session(self, target_session=None): + def kill_session(self): ''' ``$ tmux kill-session`` - :param: target_session: str. note this accepts fnmatch(3). 'asdf' will - kill asdfasd ''' proc = self.tmux('kill-session', '-t%s' % self.get('session_id')) From d42aeccf661d6c99274dbac0ff99b9f613b36702 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 11:57:08 +0800 Subject: [PATCH 0038/3283] todo: update prompt*() to have verbose choices (via dict?) --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index 6cbef31ace1..a1a90eeb69a 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,7 @@ Roadmap Immediate """"""""" +- update prompt() to have verbose choices - tmuxp kill-session escape / quote names with spaces - have test_workspace_builder use tests from ./examples! - auto-rename From 0657ab2178deb5e958a69e3d03315d11a535ba2f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 12:13:09 +0800 Subject: [PATCH 0039/3283] [cli] optimize workspace builder error handling. give option to kill, attach or detach session --- CHANGES | 2 ++ tmuxp/cli.py | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 8f62c4f7a7b..9e793d1dd8f 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,8 @@ Here you can find the recent changes to tmuxp. to save in JSON or YAML format. - [cli] [bug] [b6c2e84] Fix bug where tmuxp load w/ session already loaded would switch/attach even if no was entered +- [cli] when workspace loader crashes, give option to kill session, attach it or + detach it. 2013-10-28 ---------- diff --git a/tmuxp/cli.py b/tmuxp/cli.py index b739be04add..66082f80b3c 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -252,15 +252,32 @@ def load_workspace(config_file, args): 'session_name']) except exc.TmuxSessionExists as e: if prompt_yes_no(e.message + ' Attach?'): - + # TODO, do we need os.execl for this? if 'TMUX' in os.environ: - del os.environ['TMUX'] os.execl(tmux_bin, 'tmux', 'switch-client', '-t', sconfig['session_name']) else: os.execl(tmux_bin, 'tmux', 'attach-session', '-t', sconfig['session_name']) return + except Exception as e: + logger.error(e) + choice = prompt_choices( + 'Error loading workspace. (k)ill, (a)ttach, (d)etach?', + choices=['k', 'a', 'd'], + default='k' + ) + + if choice == 'k': + builder.session.kill_session() + print('Session killed.') + elif choice == 'a': + if 'TMUX' in os.environ: + builder.session.switch_session() + else: + builder.session.attach_session() + else: + sys.exit() def command_load(args): From 9d9cd89f930f9c4b570a0bd4f9b64cb734bc1c05 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 12:26:22 +0800 Subject: [PATCH 0040/3283] wierd fix for set-window-option on tmux 1.8 --- CHANGES | 2 ++ tmuxp/window.py | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 9e793d1dd8f..cb0db040d9f 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,8 @@ Here you can find the recent changes to tmuxp. switch/attach even if no was entered - [cli] when workspace loader crashes, give option to kill session, attach it or detach it. +- [cli] tmux 1.8 ``set-option`` / ``set-window-options`` command + ``target-window`` fix. 2013-10-28 ---------- diff --git a/tmuxp/window.py b/tmuxp/window.py index 4a48283484a..a7da2d0ea77 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -138,14 +138,19 @@ def set_window_option(self, option, value): process = self.tmux( 'set-window-option', + '-t%s:%s' % (self.get('session_id'), self.get('window_index')), option, value ) + # tmuxp set-window-option version 1.8 has a quirk where + # -t@2 window id won't work as ``target-pane``. + if process.stderr: if isinstance(process.stderr, list) and len(process.stderr) == int(1): process.stderr = process.stderr[0] raise ValueError( - 'tmux set-window-option stderr: %s' % process.stderr) + 'tmux set-window-option -t%s %s %s\n' % (self.get('window_id'), option, value) + + process.stderr) def show_window_options(self, option=None): ''' From 01a65506403303f38210d8893a2db57fed580337 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 12:28:04 +0800 Subject: [PATCH 0041/3283] make session attribute/instance accessible via WorkspaceBuilder class --- CHANGES | 2 ++ tmuxp/workspacebuilder.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index cb0db040d9f..1ae2387b39b 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,8 @@ Here you can find the recent changes to tmuxp. detach it. - [cli] tmux 1.8 ``set-option`` / ``set-window-options`` command ``target-window`` fix. +- [internal] :class:`WorkspaceBuilder` now has ``.session`` attribute accessible + publicly. 2013-10-28 ---------- diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index 05f5a00ecba..7316b329213 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -122,6 +122,8 @@ def build(self, session=None): assert(self.sconf['session_name'] == session.get('session_name')) + self.session = session + assert(isinstance(session, Session)) if 'options' in self.sconf and isinstance(self.sconf['options'], dict): for key, val in self.sconf['options'].items(): From 19c76be5e408241561454757955578f72330b128 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 12:29:31 +0800 Subject: [PATCH 0042/3283] 0.0.23 --- tmuxp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index 715e47cf062..54594b35c42 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -20,4 +20,4 @@ import logging -__version__ = '0.0.22' +__version__ = '0.0.23' From 935e53fd0865608eb9e22c9e8069c8fb30747fe5 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 13:25:27 +0800 Subject: [PATCH 0043/3283] CLI no longer uses OS.execl to switch and attach built sessions --- CHANGES | 2 ++ tmuxp/cli.py | 23 ++++++++++++----------- tmuxp/workspacebuilder.py | 12 +++++++++--- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 1ae2387b39b..e91d011a288 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,8 @@ Here you can find the recent changes to tmuxp. ``target-window`` fix. - [internal] :class:`WorkspaceBuilder` now has ``.session`` attribute accessible publicly. +- [cli] tmux will now use :meth:`Session.switch_client` and + :meth:`Session.attach_session` to open new sessions instead of ``os.exec``. 2013-10-28 ---------- diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 66082f80b3c..7016a33e2b5 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -243,22 +243,23 @@ def load_workspace(config_file, args): builder.build() if 'TMUX' in os.environ: - if prompt_yes_no('Already inside TMUX, load session?'): - del os.environ['TMUX'] - os.execl(tmux_bin, 'tmux', 'switch-client', '-t', sconfig[ - 'session_name']) + if prompt_yes_no('Already inside TMUX, switch to session?'): + tmux_env = os.environ.pop('TMUX') + builder.session.switch_client() - os.execl(tmux_bin, 'tmux', 'attach-session', '-t', sconfig[ - 'session_name']) + os.environ['TMUX'] = tmux_env + return + else: + sys.exit('Session created in detached state.') + + builder.session.attach_session() except exc.TmuxSessionExists as e: if prompt_yes_no(e.message + ' Attach?'): - # TODO, do we need os.execl for this? if 'TMUX' in os.environ: - os.execl(tmux_bin, 'tmux', 'switch-client', '-t', - sconfig['session_name']) + builder.session.switch_client() + else: - os.execl(tmux_bin, 'tmux', 'attach-session', '-t', - sconfig['session_name']) + builder.session.attach_session() return except Exception as e: logger.error(e) diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index 7316b329213..4b2fbae5c12 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -112,13 +112,19 @@ def build(self, session=None): ) if self.server.has_session(self.sconf['session_name']): + self.session = self.server.findWhere( + { + 'session_name': self.sconf['session_name'] + } + ) raise exc.TmuxSessionExists( - 'Session name %s is already running.' % self.sconf[ - 'session_name'] + 'Session name %s is already running.' % + self.sconf['session_name'] ) else: session = self.server.new_session( - session_name=self.sconf['session_name']) + session_name=self.sconf['session_name'] + ) assert(self.sconf['session_name'] == session.get('session_name')) From 67d94af26a3a04ee50011a69edd0c1d21e55ca46 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 13:26:36 +0800 Subject: [PATCH 0044/3283] docs: developing.rst use tmuxp module autodoc ref --- doc/developing.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/developing.rst b/doc/developing.rst index a0639eb0906..43692257ebb 100644 --- a/doc/developing.rst +++ b/doc/developing.rst @@ -1,3 +1,5 @@ +.. module:: tmuxp + .. _developing: ====================== From 03cee2afb977bd2cc6143b64063f23f8c98cc284 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 14:11:27 +0800 Subject: [PATCH 0045/3283] 0.0.24 speed up session building and attachment --- tmuxp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index 54594b35c42..408c27d55a9 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -20,4 +20,4 @@ import logging -__version__ = '0.0.23' +__version__ = '0.0.24' From 6a89d2dc446130df759cb86820e911fcda44b4bd Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 14:49:49 +0800 Subject: [PATCH 0046/3283] start to document commands, try sphinx-argparse --- doc/about.rst | 9 +++++++++ doc/conf.py | 1 + doc/quickstart.rst | 5 +++++ doc/requirements.pip | 1 + tmuxp/cli.py | 2 ++ 5 files changed, 18 insertions(+) diff --git a/doc/about.rst b/doc/about.rst index b8906a5af2f..19d230c5e1c 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -18,6 +18,15 @@ Interested in some kung-fu or joining the effort? :ref:`api` and License is `BSD-licensed`_. Code can be found at github at http://github.com/tony/tmuxp. +How is tmuxp different from teamocil and tmuxinator +--------------------------------------------------- + +teamocil and tmuxinator both build tmux workspaces from yaml. tmuxp +also handles building workspaces. + +teamocil and tmuxinator do this by turning YAML directly into tmux +commands. + .. _attempt at 1.7 test: https://travis-ci.org/tony/tmuxp/jobs/12348263 .. _kaptan: https://github.com/emre/kaptan .. _unittest: http://docs.python.org/2/library/unittest.html diff --git a/doc/conf.py b/doc/conf.py index c34e6a43900..4fc47a571c1 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -33,6 +33,7 @@ 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinxcontrib.aafig', + 'sphinxarg.ext', ] # Add any paths that contain templates here, relative to this directory. diff --git a/doc/quickstart.rst b/doc/quickstart.rst index 3f9b35bef3b..d71ea2cb9d8 100644 --- a/doc/quickstart.rst +++ b/doc/quickstart.rst @@ -7,6 +7,11 @@ Quickstart Tmux Session Manager -------------------- +.. argparse:: + :module: tmuxp.cli + :func: get_parser + :prog: tmuxp + tmuxp launches sessions from a configuration file. Configuration files can be stored in ``$HOME/.tmuxp`` or in project diff --git a/doc/requirements.pip b/doc/requirements.pip index 418f231be68..7c1f70aef4c 100644 --- a/doc/requirements.pip +++ b/doc/requirements.pip @@ -3,3 +3,4 @@ docutils==0.11 sphinx==dev sphinxcontrib-aafig reportlab +sphinx-argparse diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 7016a33e2b5..23a508baf9b 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -716,9 +716,11 @@ def get_parser(): help='Log level e.g. INFO, DEBUG, ERROR') parser.add_argument('-L', dest='socket_name', default=None, + help='socket name of tmux server. Same as tmux.', metavar='socket-name') parser.add_argument('-S', dest='socket_path', default=None, + help='socket path of tmux server. Same as tmux.', metavar='socket-path') # http://stackoverflow.com/questions/8521612/argparse-optional-subparser From 6baf949b05c4729241daf68a52bd96aec87b12fd Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 15:17:23 +0800 Subject: [PATCH 0047/3283] New shorthand example. Allow shorter pane commands --- README.rst | 8 ++++++++ doc/examples.rst | 29 +++++++++++++++++++++++++++++ examples/shorthands.json | 20 ++++++++++++++++++++ examples/shorthands.yaml | 9 +++++++++ tmuxp/config.py | 13 ++++++++++--- 5 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 examples/shorthands.json create mode 100644 examples/shorthands.yaml diff --git a/README.rst b/README.rst index 486c9fc8636..31a4909b5ec 100644 --- a/README.rst +++ b/README.rst @@ -35,6 +35,14 @@ See: `Quickstart`_ CLI Commands """""""""""" +========================== + + ``tmuxp attach-session`` + ``tmuxp kill-session`` + ``tmuxp convert`` + ``tmuxp import`` + ``tmuxp import`` + tmuxp uses ``switch-client`` for you if already in a TMUX client. .. code-block:: bash diff --git a/doc/examples.rst b/doc/examples.rst index 6ee9f8526c0..6a1426c003b 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -4,6 +4,35 @@ Examples ======== +Short hand / inline +------------------- + +.. sidebar:: short hand + + .. aafig:: + + +-----------------+ + | $ | + | | + +-----------------+ + | $ | + | | + +-----------------+ + | $ | + +-----------------+ + +YAML +"""" + +.. literalinclude:: ../examples/shorthands.yaml + :language: yaml + +JSON +"""" + +.. literalinclude:: ../examples/shorthands.json + :language: json + 2 split panes ------------- diff --git a/examples/shorthands.json b/examples/shorthands.json new file mode 100644 index 00000000000..977592cf298 --- /dev/null +++ b/examples/shorthands.json @@ -0,0 +1,20 @@ +{ + "windows": [ + { + "panes": [ + { + "shell_command": [ + "echo 'did you know'", + "echo 'you can inline'" + ] + }, + { + "shell_command": "echo 'single commands'" + }, + "echo 'for panes'" + ], + "window_name": "long form" + } + ], + "session_name": "shorthands" +} \ No newline at end of file diff --git a/examples/shorthands.yaml b/examples/shorthands.yaml new file mode 100644 index 00000000000..5fb88100fb8 --- /dev/null +++ b/examples/shorthands.yaml @@ -0,0 +1,9 @@ +session_name: shorthands +windows: + - window_name: long form + panes: + - shell_command: + - echo 'did you know' + - echo 'you can inline' + - shell_command: echo 'single commands' + - echo 'for panes' diff --git a/tmuxp/config.py b/tmuxp/config.py index e5cbef3f934..b22a6b2793a 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -155,9 +155,16 @@ def expand(config): # recurse into window and pane config items if 'windows' in config: - config['windows'] = [expand(window) - for window in config['windows']] - if 'panes' in config: + config['windows'] = [ + expand(window) for window in config['windows'] + ] + elif 'panes' in config: + for p in config['panes']: + if isinstance(p, basestring): + p_index = config['panes'].index(p) + config['panes'][p_index] = { + 'shell_command': [p] + } config['panes'] = [expand(pane) for pane in config['panes']] return config From 867f56b7bc510ff2533979dda911c6fd0d381260 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 15:19:02 +0800 Subject: [PATCH 0048/3283] aafig fix --- doc/examples.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/examples.rst b/doc/examples.rst index 6a1426c003b..ef8bc377b56 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -19,6 +19,7 @@ Short hand / inline | | +-----------------+ | $ | + | | +-----------------+ YAML From 7f088b92dd814bd263276bf1eebc3ae788f4090d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 15:20:18 +0800 Subject: [PATCH 0049/3283] Update aafig for short hand again --- doc/examples.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/examples.rst b/doc/examples.rst index ef8bc377b56..cd791eb6304 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -12,13 +12,13 @@ Short hand / inline .. aafig:: +-----------------+ - | $ | - | | + | did you know | + | you can inline | +-----------------+ - | $ | + | single commands | | | +-----------------+ - | $ | + | for panes | | | +-----------------+ From 92486aa83431175650d5d0a8222c70829c48fe6e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 15:24:07 +0800 Subject: [PATCH 0050/3283] aafig textual for short hand --- doc/examples.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/examples.rst b/doc/examples.rst index cd791eb6304..35ec2eea2bc 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -10,15 +10,16 @@ Short hand / inline .. sidebar:: short hand .. aafig:: + :textual: +-----------------+ - | did you know | - | you can inline | + |'did you know' | + |'you can inline' | +-----------------+ - | single commands | + |'single commands'| | | +-----------------+ - | for panes | + |'for panes' | | | +-----------------+ From 698585507690acfa99903f500e3d8ff6409bef80 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 15:25:57 +0800 Subject: [PATCH 0051/3283] fix symbols in aafig --- doc/examples.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/examples.rst b/doc/examples.rst index 35ec2eea2bc..bcb3b200518 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -12,16 +12,16 @@ Short hand / inline .. aafig:: :textual: - +-----------------+ - |'did you know' | - |'you can inline' | - +-----------------+ - |'single commands'| - | | - +-----------------+ - |'for panes' | - | | - +-----------------+ + +-------------------+ + | 'did you know' | + | 'you can inline' | + +-------------------+ + | 'single commands' | + | | + +-------------------+ + | 'for panes' | + | | + +-------------------+ YAML """" From 332ea21c8455529667f96e11609c44f4cf85715a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 15:33:37 +0800 Subject: [PATCH 0052/3283] update CHANGELOG --- CHANGES | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index e91d011a288..a15e98ade95 100644 --- a/CHANGES +++ b/CHANGES @@ -9,7 +9,8 @@ Here you can find the recent changes to tmuxp. - [internal] :meth:`Window.select_pane` now accepts ``-l``, ``-U``, ``-D``, ``-L``, ``-R``. - [internal] [tests] support for ``automatic-rename`` option. -- [docs] 2 new :ref:`examples`, 'main-pane-height' and 'automatic-rename'. +- [docs] 3 new :ref:`examples`, 'main-pane-height', 'automatic-rename', and + 'shorthands'. - [cli] enhancements to prompts - [cli] ``tmuxp import`` for teamocil and tmuxinator now has a wizard and offers to save in JSON or YAML format. @@ -23,6 +24,8 @@ Here you can find the recent changes to tmuxp. publicly. - [cli] tmux will now use :meth:`Session.switch_client` and :meth:`Session.attach_session` to open new sessions instead of ``os.exec``. +- [config] tmuxp now allows a new shorter form for panes. Panes can just be a + string. See the shorthand form in the :ref:`examples` section. 2013-10-28 ---------- From 987c6e0681babf2ae6d50912b10743fc21b2be8f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 15:42:22 +0800 Subject: [PATCH 0053/3283] README update, 0.0.25 --- README.rst | 54 ++++++++++++++++++++++------------------------- tmuxp/__init__.py | 2 +- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/README.rst b/README.rst index 31a4909b5ec..006a7c5a37e 100644 --- a/README.rst +++ b/README.rst @@ -35,50 +35,46 @@ See: `Quickstart`_ CLI Commands """""""""""" -========================== - - ``tmuxp attach-session`` - ``tmuxp kill-session`` - ``tmuxp convert`` - ``tmuxp import`` - ``tmuxp import`` - -tmuxp uses ``switch-client`` for you if already in a TMUX client. - -.. code-block:: bash - - $ tmuxp attach-session # current sessions - -Kill session +========================== ============================================== + ``tmuxp attach-session`` ```` + tmuxp uses ``switch-client`` if already inside + tmux client. + ``tmuxp kill-session`` ````. + ``tmuxp load`` ````. Load a workspace yaml / json file. + If session already made, will offer to attach. + ``tmuxp convert`` ````. Convert session yaml / json. + ``tmuxp import`` ``[teamocil | tmuxinator]`` ```` import + a `teamocil`_ or `tmuxinator`_ config. +========================== ============================================== + +Bash completion +""""""""""""""" + +For bash, ``.bashrc``: .. code-block:: bash - $ tmuxp kill-session # current sessions + $ source tmuxp.bash -Load a session configuration from a YAML or JSON file. +For tcsh, ``.tcshrc``: .. code-block:: bash - $ tmuxp load # configs in config dir, current directory + $ complete tmuxp 'p/*/`tmuxp.tcsh`/' -Convert a session config JSON <=> YAML: +For zsh, ``.zshrc``: .. code-block:: bash - $ tmuxp convert # configs in config dir, current directory - -Experimental: Import configuration from `teamocil`_ or `tmuxinator`_: - -.. code-block:: bash - - $ tmuxp import teamocil # configs in ~/.teamocil dir - $ tmuxp import tmuxinator # configs in ~/.tmuxinator dir + $ source tmuxp.zsh See `installing bash completion`_ to get bash, zsh and tcsh completion working on your machine. -load tmux sessions from yaml and json -""""""""""""""""""""""""""""""""""""" +Mini Quickstart +""""""""""""""" + +See the full `Quickstart`_ in the documentation. Load from ``~/.tmuxp.yaml`` or ``~/.tmuxp.json`` in current directory. diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index 408c27d55a9..aab98dc8608 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -20,4 +20,4 @@ import logging -__version__ = '0.0.24' +__version__ = '0.0.25' From a2751570f04099f37e33a30b8657d47c94bcbe03 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 15:59:43 +0800 Subject: [PATCH 0054/3283] README update --- README.rst | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 006a7c5a37e..63d3e9d9a2d 100644 --- a/README.rst +++ b/README.rst @@ -35,17 +35,19 @@ See: `Quickstart`_ CLI Commands """""""""""" -========================== ============================================== +========================== =============================================== ``tmuxp attach-session`` ```` tmuxp uses ``switch-client`` if already inside tmux client. - ``tmuxp kill-session`` ````. - ``tmuxp load`` ````. Load a workspace yaml / json file. + ``tmuxp kill-session`` ```` + ``tmuxp load`` ```` + Load a workspace yaml / json file. If session already made, will offer to attach. - ``tmuxp convert`` ````. Convert session yaml / json. - ``tmuxp import`` ``[teamocil | tmuxinator]`` ```` import - a `teamocil`_ or `tmuxinator`_ config. -========================== ============================================== + ``tmuxp convert`` ```` + Convert session yaml / json. + ``tmuxp import`` ``[teamocil | tmuxinator]`` ```` + Import a `teamocil`_ or `tmuxinator`_ config. +========================== =============================================== Bash completion """"""""""""""" From d0fe6d32071873f478fb36e7a6c7d2ee4861c1be Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 17:43:18 +0800 Subject: [PATCH 0055/3283] Clean up run_tests.py --- run_tests.py | 89 +++++++--------------------------------------------- 1 file changed, 12 insertions(+), 77 deletions(-) diff --git a/run_tests.py b/run_tests.py index f9a309368a6..f0b1fdf246b 100755 --- a/run_tests.py +++ b/run_tests.py @@ -17,83 +17,14 @@ if tmux_path not in sys.path: sys.path.insert(0, tmux_path) -from time import sleep -import itertools - def main(verbosity=2, failfast=False): - # from tmuxp import log - # import logging - - # logger = logging.getLogger() - # channel = logging.StreamHandler() - # channel.setFormatter(log.LogFormatter()) - # logger.setLevel('INFO') - # logger.addHandler(channel) - - def has_virtualenv(): - if os.environ.get('VIRTUAL_ENV'): - return os.environ.get('VIRTUAL_ENV') - else: - False - - def in_tmux(): - if os.environ.get('TMUX'): - return True - else: - return False - - tmuxclient = None - - def la(): - if not in_tmux(): - shell_commands = [] - if has_virtualenv(): - shell_commands.append( - 'source %s/bin/activate' % has_virtualenv()) - shell_commands.append('echo wat lol %s' % has_virtualenv()) - session_name = 'tmuxp' - t.tmux('new-session', '-d', '-s', session_name) - for shell_command in shell_commands: - t.tmux('send-keys', '-t', session_name, shell_command, '^M') - - t.tmux('send-keys', '-R', '-t', session_name, - 'python run_tests.py --pypid=%s' % os.getpid(), '^M') - - os.environ['pypid'] = str(os.getpid()) - - # os.execl('/usr/local/bin/tmux', 'tmux', 'attach-session', '-t', session_name) - # t.hotswap(session_name=session_name) - def output(line): - pass - # tmuxclient = t.tmux('-C') - # tmuxclient = subprocess.Popen(['tmux', '-C', '-Lhi', 'attach'], - # stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - else: - print(has_virtualenv()) - print(in_tmux()) - print(os.environ.get('pypid')) - args = vars(parser.parse_args()) - if 'pypid' in args: - print(args['pypid']) - - # todo create a hook to run after suite / loader to detach - # and killall tmuxp + tmuxp_-prefixed sessions. - # tmux('detach') - # os.kill(args['pypid'], 9) - # t.kill_server() - suites = unittest.TestLoader().discover( - 'tmuxp.testsuite', pattern="*.py") - result = unittest.TextTestRunner(verbosity=verbosity).run(suites) - if result.wasSuccessful(): - sys.exit(0) - else: - sys.exit(1) session_name = 'tmuxp' t.tmux('new-session', '-d', '-s', session_name) suites = unittest.TestLoader().discover('tmuxp.testsuite', pattern="*.py") - result = unittest.TextTestRunner(verbosity=verbosity, failfast=failfast).run(suites) + result = unittest.TextTestRunner( + verbosity=verbosity, failfast=failfast).run(suites) if result.wasSuccessful(): sys.exit(0) else: @@ -153,11 +84,13 @@ def output(line): ) parser.add_argument('-l', '--log-level', dest='log_level', default='INFO', help='Log level') - parser.add_argument('-v', '--verbosity', dest='verbosity', type=int, default=2, - help='unittest verbosity level') - parser.add_argument('-F', '--failfast', dest='failfast', action='store_true', + parser.add_argument( + '-v', '--verbosity', dest='verbosity', type=int, default=2, + help='unittest verbosity level') + parser.add_argument( + '-F', '--failfast', dest='failfast', action='store_true', - help='Stop on first test failure. failfast=True') + help='Stop on first test failure. failfast=True') args = parser.parse_args() verbosity = args.verbosity @@ -172,7 +105,8 @@ def output(line): # to the new session with os.exec and attach the session. loader = unittest.TestLoader() suites = loader.loadTestsFromName('tmuxp.testsuite.test_builder') - result = unittest.TextTestRunner(verbosity=verbosity, failfast=args.failfast).run(suites) + result = unittest.TextTestRunner( + verbosity=verbosity, failfast=args.failfast).run(suites) if result.wasSuccessful(): sys.exit(0) @@ -184,6 +118,7 @@ def output(line): loc = args.tests.index(arg) args.tests[loc] = 'tmuxp.testsuite.%s' % arg suites = unittest.TestLoader().loadTestsFromNames(args.tests) - result = unittest.TextTestRunner(verbosity=verbosity, failfast=args.failfast).run(suites) + result = unittest.TextTestRunner( + verbosity=verbosity, failfast=args.failfast).run(suites) else: main(verbosity=verbosity, failfast=args.failfast) From e8710120319c65d6efa5b6da75020790880fd698 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 20:15:26 +0800 Subject: [PATCH 0056/3283] tmuxp/__init__ doc pep257 --- tmuxp/__init__.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index aab98dc8608..ee45f0caecd 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -1,10 +1,12 @@ # -*- coding: utf8 - *- """ - tmuxp - ~~~~~ +Manage tmux workspaces from JSON and YAML, pythonic API, shell completion. - :copyright: Copyright 2013 Tony Narlock. - :license: BSD, see LICENSE for details +tmuxp +~~~~~ + +:copyright: Copyright 2013 Tony Narlock. +:license: BSD, see LICENSE for details """ From 0ba9f5a2df9daa2aad2ad2bd25a2e81972211313 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 20:16:45 +0800 Subject: [PATCH 0057/3283] v0.0.26 - support loading .yml files --- requirements.pip | 2 +- tmuxp/__init__.py | 2 +- tmuxp/config.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.pip b/requirements.pip index 6b5fed8757d..a08de2695d2 100644 --- a/requirements.pip +++ b/requirements.pip @@ -1,3 +1,3 @@ -kaptan +-e git://github.com/tony/kaptan.git@yml#egg=kaptan colorama argcomplete diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index ee45f0caecd..bbdf039bb29 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -22,4 +22,4 @@ import logging -__version__ = '0.0.25' +__version__ = '0.0.26' diff --git a/tmuxp/config.py b/tmuxp/config.py index b22a6b2793a..b129e8d3439 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -42,7 +42,7 @@ def check_consistency(sconf): return True -def is_config_file(filename, extensions=['.yaml', '.json', '.ini']): +def is_config_file(filename, extensions=['.yml', '.yaml', '.json', '.ini']): '''Is config compatible extension. :param filename: filename to check (e.g. ``mysession.json``). @@ -56,7 +56,7 @@ def is_config_file(filename, extensions=['.yaml', '.json', '.ini']): return any(filename.endswith(e) for e in extensions) -def in_dir(config_dir=os.path.expanduser('~/.tmuxp'), extensions=['.yaml', '.json', '.ini']): +def in_dir(config_dir=os.path.expanduser('~/.tmuxp'), extensions=['.yml', '.yaml', '.json', '.ini']): '''Find configs in config_dir and current dir :param config_dir: directory to search From 85e5f9dda93edd22129047389d124504ddf69681 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 20:19:35 +0800 Subject: [PATCH 0058/3283] Update CHANGES --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index a15e98ade95..1ceb5c14e5e 100644 --- a/CHANGES +++ b/CHANGES @@ -26,6 +26,7 @@ Here you can find the recent changes to tmuxp. :meth:`Session.attach_session` to open new sessions instead of ``os.exec``. - [config] tmuxp now allows a new shorter form for panes. Panes can just be a string. See the shorthand form in the :ref:`examples` section. +- [cli] [config] support loading ``.yml``. 2013-10-28 ---------- From 7fab5ecdfde24888d1fe4e0d040ed1b1367bf850 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 21:27:39 +0800 Subject: [PATCH 0059/3283] kaptan >= 0.5.6 --- requirements.pip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.pip b/requirements.pip index a08de2695d2..f3b0f92e0ed 100644 --- a/requirements.pip +++ b/requirements.pip @@ -1,3 +1,3 @@ --e git://github.com/tony/kaptan.git@yml#egg=kaptan +kaptan>=0.5.6 colorama argcomplete From e8c52e3c02780ff721409f4d75198370f1ec080d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 29 Oct 2013 21:28:08 +0800 Subject: [PATCH 0060/3283] v0.0.27 --- tmuxp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index bbdf039bb29..7fe8b46404a 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -22,4 +22,4 @@ import logging -__version__ = '0.0.26' +__version__ = '0.0.27' From 4d2c39b1e1c46d9da4d8d0a9cc1c7c1949819d35 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 06:32:51 +0800 Subject: [PATCH 0061/3283] test_pane tests : Use smaller heights to avoid size issues --- tmuxp/testsuite/test_pane.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tmuxp/testsuite/test_pane.py b/tmuxp/testsuite/test_pane.py index abdf64000af..92a3c3d66fa 100644 --- a/tmuxp/testsuite/test_pane.py +++ b/tmuxp/testsuite/test_pane.py @@ -24,12 +24,12 @@ def test_resize_pane(self): pane1_height = pane1['pane_height'] pane2 = window.split_window() - pane1.resize_pane(height=17) + pane1.resize_pane(height=7) self.assertNotEqual(pane1['pane_height'], pane1_height) - self.assertEqual(int(pane1['pane_height']), 17) + self.assertEqual(int(pane1['pane_height']), 7) - pane1.resize_pane(height=10) - self.assertEqual(int(pane1['pane_height']), 10) + pane1.resize_pane(height=9) + self.assertEqual(int(pane1['pane_height']), 9) def test_set_height(self): window = self.session.new_window(window_name='test_set_height') @@ -37,9 +37,9 @@ def test_set_height(self): pane1 = window.attached_pane() pane1_height = pane1['pane_height'] - pane1.set_height(20) + pane1.set_height(12) self.assertNotEqual(pane1['pane_height'], pane1_height) - self.assertEqual(int(pane1['pane_height']), 20) + self.assertEqual(int(pane1['pane_height']), 12) def test_set_width(self): window = self.session.new_window(window_name='test_set_width') From dba54294667e423b653c0f38df19b84239288c52 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 06:35:09 +0800 Subject: [PATCH 0062/3283] Give workspace_builder automatic-rename test more time --- tmuxp/testsuite/test_workspacebuilder.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tmuxp/testsuite/test_workspacebuilder.py b/tmuxp/testsuite/test_workspacebuilder.py index 7045049cbca..ea041fcddc7 100644 --- a/tmuxp/testsuite/test_workspacebuilder.py +++ b/tmuxp/testsuite/test_workspacebuilder.py @@ -12,6 +12,11 @@ logger = logging.getLogger(__name__) +current_dir = os.path.abspath(os.path.dirname(__file__)) +example_dir = os.path.join('../../', current_dir) + +print(example_dir) +logger.error(example_dir) class TwoPaneTest(TmuxTestCase): @@ -256,7 +261,7 @@ def test_automatic_rename_option(self): w = s.attached_window() if w['window_name'] == 'man': break - time.sleep(.01) + time.sleep(.1) self.assertEqual(w.get('window_name'), 'man') @@ -265,7 +270,7 @@ def test_automatic_rename_option(self): w = s.attached_window() if w['window_name'] != 'man': break - time.sleep(.01) + time.sleep(.1) self.assertNotEqual(w.get('window_name'), 'man') From 88e740c956854d343dbe71c740b8466b2da4c3bc Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 06:38:27 +0800 Subject: [PATCH 0063/3283] Adjust unit tests to give more time, set height less for set_height on panes --- tmuxp/testsuite/test_pane.py | 4 ++-- tmuxp/testsuite/test_workspacebuilder.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tmuxp/testsuite/test_pane.py b/tmuxp/testsuite/test_pane.py index 92a3c3d66fa..b5b7c880504 100644 --- a/tmuxp/testsuite/test_pane.py +++ b/tmuxp/testsuite/test_pane.py @@ -37,9 +37,9 @@ def test_set_height(self): pane1 = window.attached_pane() pane1_height = pane1['pane_height'] - pane1.set_height(12) + pane1.set_height(6) self.assertNotEqual(pane1['pane_height'], pane1_height) - self.assertEqual(int(pane1['pane_height']), 12) + self.assertEqual(int(pane1['pane_height']), 6) def test_set_width(self): window = self.session.new_window(window_name='test_set_width') diff --git a/tmuxp/testsuite/test_workspacebuilder.py b/tmuxp/testsuite/test_workspacebuilder.py index ea041fcddc7..6b8ffb5689b 100644 --- a/tmuxp/testsuite/test_workspacebuilder.py +++ b/tmuxp/testsuite/test_workspacebuilder.py @@ -261,7 +261,7 @@ def test_automatic_rename_option(self): w = s.attached_window() if w['window_name'] == 'man': break - time.sleep(.1) + time.sleep(.2) self.assertEqual(w.get('window_name'), 'man') @@ -270,7 +270,7 @@ def test_automatic_rename_option(self): w = s.attached_window() if w['window_name'] != 'man': break - time.sleep(.1) + time.sleep(.2) self.assertNotEqual(w.get('window_name'), 'man') From 7acc16df2cf1d4c6720e6c97471f6bfea2946dbb Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 06:44:38 +0800 Subject: [PATCH 0064/3283] clean up workspace builder, unused code. Add examples_dir --- tmuxp/testsuite/test_workspacebuilder.py | 44 +----------------------- 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/tmuxp/testsuite/test_workspacebuilder.py b/tmuxp/testsuite/test_workspacebuilder.py index 6b8ffb5689b..c22db99591f 100644 --- a/tmuxp/testsuite/test_workspacebuilder.py +++ b/tmuxp/testsuite/test_workspacebuilder.py @@ -13,10 +13,8 @@ logger = logging.getLogger(__name__) current_dir = os.path.abspath(os.path.dirname(__file__)) -example_dir = os.path.join('../../', current_dir) +example_dir = os.path.abspath(os.path.join(current_dir, '..', '..')) -print(example_dir) -logger.error(example_dir) class TwoPaneTest(TmuxTestCase): @@ -275,45 +273,5 @@ def test_automatic_rename_option(self): self.assertNotEqual(w.get('window_name'), 'man') -class TestsToDo(object): - - def test_uses_first_window_if_exists(self): - ''' - if the session is already on the first window, use that. - - this is useful if the user is already inside of a tmux session - ''' - - def test_same_session_already_exists_unclean(self): - ''' - raise exception if session_name already exists and has multiple - windows the user could potentially be offered to add a cli argument to - override the session_name in config. Perhaps `-n` could be used to load - a config from file with overridden session_name. - ''' - - def test_inside_tmux_same_session_already_exists(self): - ''' same as above, but when the config file and the current $TMUX - session are the same ''' - - def test_inside_tmux_no_session_name_exists(self): - ''' - if the session_name doesn't currently exist and the user is in tmux - rename the current session by the config / -n and build there. - ''' - - def testPaneProportions(self): - """ - todo. checking the proportions of a pane on a grid allows - us to verify a window has been build correctly without - needing to see the tmux session itself. - - we expect panes in a list to be ordered and show up to - their corresponding pane_index. - """ - pass - - if __name__ == '__main__': - # t.socket_name = 'tmuxp_test' unittest.main() From 070cc2fb7d7689629cfbc610ece132ab59981e18 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 07:00:56 +0800 Subject: [PATCH 0065/3283] test_config: test for panes: ['onecommand'] --- tmuxp/testsuite/test_config.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/tmuxp/testsuite/test_config.py b/tmuxp/testsuite/test_config.py index 9908750488b..2557088fe14 100644 --- a/tmuxp/testsuite/test_config.py +++ b/tmuxp/testsuite/test_config.py @@ -163,6 +163,11 @@ class ExpandTest(unittest.TestCase): {'shell_command': 'htop'}, 'vim', ] + }, + { + 'panes': [ + 'top' + ] }] } @@ -195,6 +200,11 @@ class ExpandTest(unittest.TestCase): {'shell_command': ['htop']}, {'shell_command': ['vim']} ] + }, + { + 'panes': [ + {'shell_command': ['top']} + ] } ] } @@ -444,6 +454,9 @@ class ShellCommandBeforeTest(unittest.TestCase): 'panes': [ {'shell_command': ['htop']} ] + }, + { + 'panes': ['top'] } ] } @@ -488,7 +501,12 @@ class ShellCommandBeforeTest(unittest.TestCase): 'panes': [ {'shell_command': ['htop']} ] - } + }, + { + 'panes': [{ + 'shell_command': ['top'] + }] + }, ] } @@ -537,11 +555,17 @@ class ShellCommandBeforeTest(unittest.TestCase): 'panes': [ {'shell_command': ['htop']} ] + }, + { + 'panes': [ + {'shell_command': ['top']} + ] } ] } def test_shell_command_before(self): + self.maxDiff = None test_config = self.config_unexpanded test_config = config.expand(test_config) From 7a5b978385611f3abfe65437b35768da5ef01403 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 10:10:48 +0800 Subject: [PATCH 0066/3283] Beginning of tmuxp freeze --- requirements.pip | 2 +- tmuxp/testsuite/test_workspacefreezer.py | 110 +++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 tmuxp/testsuite/test_workspacefreezer.py diff --git a/requirements.pip b/requirements.pip index f3b0f92e0ed..7caa1e76b9c 100644 --- a/requirements.pip +++ b/requirements.pip @@ -1,3 +1,3 @@ -kaptan>=0.5.6 +kaptan>=0.5.7 colorama argcomplete diff --git a/tmuxp/testsuite/test_workspacefreezer.py b/tmuxp/testsuite/test_workspacefreezer.py new file mode 100644 index 00000000000..7299e908299 --- /dev/null +++ b/tmuxp/testsuite/test_workspacefreezer.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, with_statement + +import os +import unittest +import logging +import time +import kaptan +from .. import Window, config, exc +from ..workspacebuilder import WorkspaceBuilder +from .helpers import TmuxTestCase + +logger = logging.getLogger(__name__) + +current_dir = os.path.abspath(os.path.dirname(__file__)) +example_dir = os.path.abspath(os.path.join(current_dir, '..', '..')) + + +def freeza(session): + sconf = {} + + sconf['session_name'] = session['session_name'] + + sconf['windows'] = [] + for w in session.windows: + wconf = {} + wconf['options'] = w.show_window_options() + wconf['window_name'] = w.get('window_name') + wconf['panes'] = [] + logger.error(w) + logger.error(dict(w)) + + for p in w.panes: + pconf = {} + pconf['shell_command'] = [] + pconf['shell_command'].append('cd ' + p.get('pane_current_path')) + pconf['shell_command'].append(p.get('pane_current_command')) + wconf['panes'].append(pconf) + logger.error(p) + logger.error(dict(p)) + + + sconf['windows'].append(wconf) + + logger.error(sconf) + + return sconf + + + + + + +class FreezeTest(TmuxTestCase): + + yaml_config = ''' + session_name: sampleconfig + start_directory: '~' + windows: + - layout: main-vertical + panes: + - shell_command: + - vim + start_directory: '~' + - shell_command: + - echo "hey" + - cd ../ + window_name: editor + - panes: + - shell_command: + - tail -F /var/log/syslog + start_directory: /var/log + window_name: logging + - window_name: test + panes: + - shell_command: + - htop + ''' + + def test_split_windows(self): + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(self.yaml_config).get() + + builder = WorkspaceBuilder(sconf=sconfig) + builder.build(session=self.session) + assert(self.session == builder.session) + + import time + time.sleep(1) + + session = self.session + sconf = freeza(session) + + config.check_consistency(sconf) + + sconf = config.inline(sconf) + + kaptanconf = kaptan.Kaptan() + kaptanconf = kaptanconf.import_config(sconf) + json = kaptanconf.export('json', indent=2) + json = kaptanconf.export('json', indent=2) + yaml = kaptanconf.export( + 'yaml', indent=2, default_flow_style=False, safe=True) + + + logger.error(json) + logger.error(yaml) + +if __name__ == '__main__': + unittest.main() From 2f3d9d0993f58dac3954df0efba85533bf67431c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 12:02:17 +0800 Subject: [PATCH 0067/3283] tmuxp freeze --- tmuxp/cli.py | 86 ++++++++++++++++++++++-- tmuxp/testsuite/test_workspacefreezer.py | 47 +++---------- tmuxp/workspacebuilder.py | 34 ++++++++++ 3 files changed, 124 insertions(+), 43 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 23a508baf9b..ee301e55a38 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -18,12 +18,13 @@ import argparse import argcomplete import logging +import pkg_resources import kaptan -from . import config -from distutils.util import strtobool -from . import log, util, exc, WorkspaceBuilder, Server +from . import log, util, exc, WorkspaceBuilder, Server, config from .util import ascii_lowercase, input -import pkg_resources +from .workspacebuilder import freeze +from distutils.util import strtobool + __version__ = pkg_resources.require("tmuxp")[0].version @@ -281,6 +282,70 @@ def load_workspace(config_file, args): sys.exit() +def command_freeze(args): + """ Import teamocil config to tmuxp format. """ + + t = Server( + socket_name=args.socket_name, + socket_path=args.socket_path + ) + + logger.error(args) + session = t.findWhere({ + 'session_name': args.session_name + }) + + sconf = freeze(session) + configparser = kaptan.Kaptan() + newconfig = config.inline(sconf) + configparser.import_config(newconfig) + config_format = prompt_choices('Convert to', choices=[ + 'yaml', 'json'], default='yaml') + + if config_format == 'yaml': + newconfig = configparser.export( + 'yaml', indent=2, default_flow_style=False, safe=True + ) + elif config_format == 'json': + newconfig = configparser.export('json', indent=2) + else: + sys.exit('Unknown config format.') + + print(newconfig) + print( + '---------------------------------------------------------------') + print( + 'Configuration import does its best to convert teamocil files.\n') + if prompt_yes_no( + 'The new config *WILL* require adjusting afterwards. Save config?' + ): + dest = None + while not dest: + dest_prompt = prompt('Save to: ', os.path.abspath( + os.path.join(config_dir, 'myimport.%s' % config_format))) + if os.path.exists(dest_prompt): + print('%s exists. Pick a new filename.' % dest_prompt) + continue + + dest = dest_prompt + + dest = os.path.abspath(os.path.relpath(dest)) + if prompt_yes_no('Write to %s?' % dest): + buf = open(dest, 'w') + buf.write(newconfig) + buf.close() + + print('Saved to %s.' % dest) + else: + print( + 'tmuxp has examples in JSON and YAML format at \n' + 'View tmuxp docs at ' + ) + sys.exit() + + + + def command_load(args): """ Load a session from a tmuxp session file. """ if args.list: @@ -542,6 +607,9 @@ def command_convert(args): print('written new config to <%s>.' % (newfile)) + + + def command_attach_session(args): """ Command to attach / switch client to a tmux session.""" commands = [] @@ -624,6 +692,14 @@ def get_parser(): type=str, ).completer = SessionCompleter + freeze = subparsers.add_parser('freeze') + freeze.set_defaults(callback=command_freeze) + + freeze.add_argument( + dest='session_name', + type=str, + ).completer = SessionCompleter + load = subparsers.add_parser('load') loadgroup = load.add_mutually_exclusive_group(required=True) @@ -758,6 +834,8 @@ def main(): command_import_teamocil(args) elif args.callback is command_import_tmuxinator: command_import_tmuxinator(args) + elif args.callback is command_freeze: + command_freeze(args) elif args.callback is command_attach_session: command_attach_session(args) elif args.callback is command_kill_session: diff --git a/tmuxp/testsuite/test_workspacefreezer.py b/tmuxp/testsuite/test_workspacefreezer.py index 7299e908299..92f8e4b7b0d 100644 --- a/tmuxp/testsuite/test_workspacefreezer.py +++ b/tmuxp/testsuite/test_workspacefreezer.py @@ -2,12 +2,13 @@ from __future__ import absolute_import, division, print_function, with_statement import os +import sys import unittest import logging import time import kaptan from .. import Window, config, exc -from ..workspacebuilder import WorkspaceBuilder +from ..workspacebuilder import WorkspaceBuilder, freeze from .helpers import TmuxTestCase logger = logging.getLogger(__name__) @@ -16,41 +17,6 @@ example_dir = os.path.abspath(os.path.join(current_dir, '..', '..')) -def freeza(session): - sconf = {} - - sconf['session_name'] = session['session_name'] - - sconf['windows'] = [] - for w in session.windows: - wconf = {} - wconf['options'] = w.show_window_options() - wconf['window_name'] = w.get('window_name') - wconf['panes'] = [] - logger.error(w) - logger.error(dict(w)) - - for p in w.panes: - pconf = {} - pconf['shell_command'] = [] - pconf['shell_command'].append('cd ' + p.get('pane_current_path')) - pconf['shell_command'].append(p.get('pane_current_command')) - wconf['panes'].append(pconf) - logger.error(p) - logger.error(dict(p)) - - - sconf['windows'].append(wconf) - - logger.error(sconf) - - return sconf - - - - - - class FreezeTest(TmuxTestCase): yaml_config = ''' @@ -77,7 +43,11 @@ class FreezeTest(TmuxTestCase): - htop ''' - def test_split_windows(self): + def test_focus(self): + # assure the built yaml config has focus + pass + + def test_freeze_config(self): sconfig = kaptan.Kaptan(handler='yaml') sconfig = sconfig.import_config(self.yaml_config).get() @@ -89,7 +59,7 @@ def test_split_windows(self): time.sleep(1) session = self.session - sconf = freeza(session) + sconf = freeze(session) config.check_consistency(sconf) @@ -102,7 +72,6 @@ def test_split_windows(self): yaml = kaptanconf.export( 'yaml', indent=2, default_flow_style=False, safe=True) - logger.error(json) logger.error(yaml) diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index 4b2fbae5c12..90632df23e7 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -215,3 +215,37 @@ def iter_create_panes(self, w, wconf): w.server._update_panes() yield p + + +def freeze(session): + sconf = {} + + sconf['session_name'] = session['session_name'] + + sconf['windows'] = [] + for w in session.windows: + wconf = {} + wconf['options'] = w.show_window_options() + wconf['window_name'] = w.get('window_name') + wconf['panes'] = [] + logger.error(w) + logger.error(dict(w)) + + if all(w.panes[0].get('pane_current_path') == p.get('pane_current_path') for p in w.panes): + wconf['shell_command_before'] = w.panes[0].get('pane_current_path') + + for p in w.panes: + pconf = {} + pconf['shell_command'] = [] + if 'shell_command_before' not in wconf: + pconf['shell_command'].append('cd ' + p.get('pane_current_path')) + pconf['shell_command'].append(p.get('pane_current_command')) + wconf['panes'].append(pconf) + logger.error(p) + logger.error(dict(p)) + + + sconf['windows'].append(wconf) + + return sconf + From 6dbf9ed824ea03d5bd62be1b285a87dc79043081 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 12:02:47 +0800 Subject: [PATCH 0068/3283] tmuxp freeze --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 63d3e9d9a2d..8388dbc7704 100644 --- a/README.rst +++ b/README.rst @@ -40,6 +40,7 @@ CLI Commands tmuxp uses ``switch-client`` if already inside tmux client. ``tmuxp kill-session`` ```` + ``tmuxp freeze`` ```` ``tmuxp load`` ```` Load a workspace yaml / json file. If session already made, will offer to attach. From e8b550b16548e51af99ef7b19ae8c121a1c627f5 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 12:12:14 +0800 Subject: [PATCH 0069/3283] fix bug where if inside tmux, loading a workspace via switch_client wouldn't work. --- CHANGES | 6 ++++++ tmuxp/cli.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 1ceb5c14e5e..b00edfef121 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,12 @@ tmuxp Changelog Here you can find the recent changes to tmuxp. +2013-10-30 +---------- + +- [cli] fix bug where if inside tmux, loading a workspace via switch_client + wouldn't work. + 2013-10-29 ---------- diff --git a/tmuxp/cli.py b/tmuxp/cli.py index ee301e55a38..a988b8998ed 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -275,7 +275,7 @@ def load_workspace(config_file, args): print('Session killed.') elif choice == 'a': if 'TMUX' in os.environ: - builder.session.switch_session() + builder.session.switch_client() else: builder.session.attach_session() else: From 4ffe555d50aab48f9bf77d47313e6ed029d514c7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 12:31:53 +0800 Subject: [PATCH 0070/3283] Fix Window.select_layout. Freeze 'layout' of windows --- tmuxp/cli.py | 8 +++++++- tmuxp/window.py | 8 +++++++- tmuxp/workspacebuilder.py | 10 ++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index a988b8998ed..ef81329637d 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -196,7 +196,9 @@ def setup_logger(logger=None, level='INFO'): logger = logging.getLogger() if not logger.handlers: channel = logging.StreamHandler() - channel.setFormatter(log.LogFormatter()) + channel.setFormatter(log.DebugLogFormatter()) + + #channel.setFormatter(log.LogFormatter()) logger.setLevel(level) logger.addHandler(channel) @@ -263,7 +265,11 @@ def load_workspace(config_file, args): builder.session.attach_session() return except Exception as e: + import traceback + + print(traceback.format_exc()) logger.error(e) + choice = prompt_choices( 'Error loading workspace. (k)ill, (a)ttach, (d)etach?', choices=['k', 'a', 'd'], diff --git a/tmuxp/window.py b/tmuxp/window.py index a7da2d0ea77..f64e8c7936b 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -110,11 +110,17 @@ def select_layout(self, layout=None): :param layout: string of the layout, 'even-horizontal', 'tiled', etc. :type layout: string ''' - self.tmux( + + + proc = self.tmux( 'select-layout', + '-t%s:%s' % (self.get('session_id'), self.get('window_index')), layout ) + if proc.stderr: + raise Exception(proc.stderr) + @property def target(self): return "%s:%s" % (self.session.get('session_id'), self.get('window_id')) diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index 90632df23e7..c3d18a8b4e0 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -141,8 +141,9 @@ def build(self, session=None): assert(isinstance(p, Pane)) p = p - if 'layout' in wconf: - w.select_layout(wconf['layout']) + if 'layout' in wconf: + logger.error(wconf['layout']) + w.select_layout(wconf['layout']) def iter_create_windows(self, s): ''' generator that creates tmux windows, yields :class:`Window` object @@ -206,6 +207,10 @@ def iter_create_panes(self, w, wconf): p = w.attached_pane() assert(isinstance(p, Pane)) + if 'layout' in wconf: + logger.error(wconf['layout']) + w.select_layout(wconf['layout']) + for cmd in pconf['shell_command']: p.send_keys(cmd) @@ -227,6 +232,7 @@ def freeze(session): wconf = {} wconf['options'] = w.show_window_options() wconf['window_name'] = w.get('window_name') + wconf['layout'] = w.get('window_layout') wconf['panes'] = [] logger.error(w) logger.error(dict(w)) From 402238e7e271acf5f66b59b4335c9c1b398a4e1a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 12:34:21 +0800 Subject: [PATCH 0071/3283] fix bad test with blank select_layout calls --- tmuxp/testsuite/test_window.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tmuxp/testsuite/test_window.py b/tmuxp/testsuite/test_window.py index c3f81fc9357..8b06113ad06 100644 --- a/tmuxp/testsuite/test_window.py +++ b/tmuxp/testsuite/test_window.py @@ -91,17 +91,13 @@ def test_newest_pane_data(self): window = self.session.new_window(window_name='test', attach=True) self.assertIsInstance(window, Window) self.assertEqual(1, len(window.panes)) - window.select_layout() window.split_window(attach=True) - window.select_layout() self.assertEqual(2, len(window.panes)) # note: the below used to accept -h, removing because split_window now # has attach as its only argument now - window.select_layout() window.split_window(attach=True) self.assertEqual(3, len(window.panes)) - window.select_layout() class NewTest3(TmuxTestCase): From c723816e916a34f77412091568810e3935583f1b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 13:09:04 +0800 Subject: [PATCH 0072/3283] doc updates --- doc/about.rst | 61 +++++++++++++++++++++++++++++++++++++++++----- doc/developing.rst | 2 ++ doc/index.rst | 7 ++++-- doc/quickstart.rst | 2 ++ 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/doc/about.rst b/doc/about.rst index 19d230c5e1c..0098be321c5 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -1,3 +1,5 @@ +.. module:: tmuxp + .. _about: ===== @@ -18,14 +20,59 @@ Interested in some kung-fu or joining the effort? :ref:`api` and License is `BSD-licensed`_. Code can be found at github at http://github.com/tony/tmuxp. -How is tmuxp different from teamocil and tmuxinator ---------------------------------------------------- +Differences from tmuxinator / teamocil +-------------------------------------- + +.. note:: + + If you use teamocli / tmuxinator and can clarify or add differences, + please free to `edit this page`_ on github. + +Similarities +"""""""""""" + +**Load sessions** Loads tmux sessions from config + +**YAML** Supports YAML format + +**Inlining / shorthand configuration** All three support short-hand and +simplified markup for panes that have one command. + +Missing +""""""" + +**Stability** tmuxinator and teamocil are far more stable and +well-developed than tmuxp. + +**ERB / Template support** teamocil supports `ERB`_ markup. + +**Version support** tmuxp only supports ``tmux >= 1.8``. Teamocil and +tmuxinator may have support for earlier versions. + +Differences +""""""""""" + +**Programming Language** python. teamocil and tmuxinator uses ruby. + +**Internals** teamocil and tmuxinator pipe configurations into +commands. tmuxp turns configuration into a live :class:`Session` object +with access to all window and pane data. See :ref:`ORM_AL`. + +**CLI** tmuxp's CLI can attach and kill sessions. + +Additional Features +""""""""""""""""""" + +**Unit tests** Tests against live tmux version to test statefulness of +tmux sessions, windows and panes. See :ref:`travis`. + +**Import config** import configs from Teamocil / Tmuxinator + +**JSON config** JSON config support -teamocil and tmuxinator both build tmux workspaces from yaml. tmuxp -also handles building workspaces. +**Conversion** -teamocil and tmuxinator do this by turning YAML directly into tmux -commands. +**Session freezing** Supports session freezing into YAML and JSON format. .. _attempt at 1.7 test: https://travis-ci.org/tony/tmuxp/jobs/12348263 .. _kaptan: https://github.com/emre/kaptan @@ -33,3 +80,5 @@ commands. .. _BSD-licensed: http://opensource.org/licenses/BSD-2-Clause .. _tmuxinator: https://github.com/aziz/tmuxinator .. _teamocil: https://github.com/remiprev/teamocil +.. _ERB: http://ruby-doc.org/stdlib-2.0.0/libdoc/erb/rdoc/ERB.html +.. _edit this page: https://github.com/tony/tmuxp/edit/master/doc/about.rst diff --git a/doc/developing.rst b/doc/developing.rst index 43692257ebb..631fdf5c971 100644 --- a/doc/developing.rst +++ b/doc/developing.rst @@ -224,6 +224,8 @@ this will load the ``.tmuxp.yaml`` in the root of the project. .. literalinclude:: ../.tmuxp.yaml :language: yaml +.. _travis: + Travis CI """"""""" diff --git a/doc/index.rst b/doc/index.rst index f42cde082ff..1db8871e359 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -10,14 +10,17 @@ tmuxp, a novel approach to managing `tmux(1)`_ workspaces through python objects. Features: - Load + switch to new session from inside tmux. -- bash / zsh / tcsh completion +- :ref:`bash / zsh / tcsh completion `. - JSON, YAML and `python dict`_ configuration. - Support for pre-commands with ``shell_command_before`` to load virtualenv / rvm / any other commands. - Session resuming from config file if already running. -- Per-project tmux sessions +- Per-project tmux sessions, load directly from config file. + `` $ tmuxp load /full/file/path.json `` - uses tmux 1.8's ``pane_id``, ``window_id`` and ``session_id`` to build create python objects to build workspaces with the freshest data. +- (experimental) Import configs from `teamocil`_ and `tmuxinator`_. +- (experimental) Freezing sessions. tmuxp works in 3 ways: diff --git a/doc/quickstart.rst b/doc/quickstart.rst index d71ea2cb9d8..dcb6dad7589 100644 --- a/doc/quickstart.rst +++ b/doc/quickstart.rst @@ -45,6 +45,8 @@ This creates your tmuxp session. .. seealso:: :ref:`examples` +.. _bash_completion: + Bash completion """"""""""""""" From be1869889a8081f4fd903803a19dcbd055409cd3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 13:14:48 +0800 Subject: [PATCH 0073/3283] more doc updates --- doc/about.rst | 15 ++++++++++++--- doc/conf.py | 1 - 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/about.rst b/doc/about.rst index 0098be321c5..9b7122eec22 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -66,13 +66,22 @@ Additional Features **Unit tests** Tests against live tmux version to test statefulness of tmux sessions, windows and panes. See :ref:`travis`. -**Import config** import configs from Teamocil / Tmuxinator +**Import config** import configs from Teamocil / Tmuxinator ***** + +**Session freezing** Supports session freezing into YAML and JSON +format *****. **JSON config** JSON config support -**Conversion** +**Conversion** ``$ tmuxp convert `` can convert files to and +from JSON and YAML. + +Footnotes +""""""""" -**Session freezing** Supports session freezing into YAML and JSON format. +* Tmuxp session configurations can be very complicated, importing and + freezing sessions may save a lot of time, but tweaking will probably be + required. There is no substitute for a config made with love. .. _attempt at 1.7 test: https://travis-ci.org/tony/tmuxp/jobs/12348263 .. _kaptan: https://github.com/emre/kaptan diff --git a/doc/conf.py b/doc/conf.py index 4fc47a571c1..7cab6bf4962 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -113,7 +113,6 @@ if on_rtd: html_theme = 'default' else: - html_theme = 'bootstrap' html_theme = 'rtd' # Theme options are theme-specific and customize the look and feel of a theme From 5b7aae508e952f34133b4bd55b7b02c08f841689 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 13:20:05 +0800 Subject: [PATCH 0074/3283] suppress debug logs --- tmuxp/workspacebuilder.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index c3d18a8b4e0..36c94d8ab79 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -142,7 +142,6 @@ def build(self, session=None): p = p if 'layout' in wconf: - logger.error(wconf['layout']) w.select_layout(wconf['layout']) def iter_create_windows(self, s): @@ -208,7 +207,6 @@ def iter_create_panes(self, w, wconf): assert(isinstance(p, Pane)) if 'layout' in wconf: - logger.error(wconf['layout']) w.select_layout(wconf['layout']) for cmd in pconf['shell_command']: @@ -234,8 +232,6 @@ def freeze(session): wconf['window_name'] = w.get('window_name') wconf['layout'] = w.get('window_layout') wconf['panes'] = [] - logger.error(w) - logger.error(dict(w)) if all(w.panes[0].get('pane_current_path') == p.get('pane_current_path') for p in w.panes): wconf['shell_command_before'] = w.panes[0].get('pane_current_path') @@ -244,14 +240,13 @@ def freeze(session): pconf = {} pconf['shell_command'] = [] if 'shell_command_before' not in wconf: - pconf['shell_command'].append('cd ' + p.get('pane_current_path')) + pconf['shell_command'].append( + 'cd ' + p.get('pane_current_path')) pconf['shell_command'].append(p.get('pane_current_command')) wconf['panes'].append(pconf) - logger.error(p) - logger.error(dict(p)) - + # logger.error(p) + # logger.error(dict(p)) sconf['windows'].append(wconf) return sconf - From 5ceba30a94b62f4cb5545d9f52871e9a7c7eb959 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 13:20:36 +0800 Subject: [PATCH 0075/3283] fix bug where 'tmuxp load .' would return an error instead of a notice --- tmuxp/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index ef81329637d..1c0705ac705 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -380,7 +380,7 @@ def command_load(args): if config.in_cwd(): configfile = config.in_cwd()[0] else: - print('No tmuxp configs found in current directory.') + sys.exit('No tmuxp configs found in current directory.') else: configfile = args.config file_user = os.path.join(config_dir, configfile) From 93435f075bcd94321d0160be4385951fa401f83d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 13:23:05 +0800 Subject: [PATCH 0076/3283] v0.0.28 --- CHANGES | 5 +++++ tmuxp/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index b00edfef121..8f7600f86d7 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,11 @@ Here you can find the recent changes to tmuxp. - [cli] fix bug where if inside tmux, loading a workspace via switch_client wouldn't work. +- [cli] fix bug where ``tmuxp load .`` would return an error instead of a + notice. +- [cli] ``tmuxp freeze `` experimental +- [freeze] [tests] tmuxp now has experimental support for freezing live + sessions. 2013-10-29 ---------- diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index 7fe8b46404a..db6f86d8b16 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -22,4 +22,4 @@ import logging -__version__ = '0.0.27' +__version__ = '0.0.28' From 2baa17004113a6a03fa5061c91b49981eba140ae Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 18:17:33 +0800 Subject: [PATCH 0077/3283] CHANGES --- CHANGES | 1 + tmuxp/testsuite/test_window.py | 11 +++++++++++ tmuxp/window.py | 23 ++++++++++++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 8f7600f86d7..500f214c769 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,7 @@ Here you can find the recent changes to tmuxp. - [cli] ``tmuxp freeze `` experimental - [freeze] [tests] tmuxp now has experimental support for freezing live sessions. +- [internals] :meth:`Window.kill_window()` 2013-10-29 ---------- diff --git a/tmuxp/testsuite/test_window.py b/tmuxp/testsuite/test_window.py index 8b06113ad06..3fd2ae0caa1 100644 --- a/tmuxp/testsuite/test_window.py +++ b/tmuxp/testsuite/test_window.py @@ -149,6 +149,17 @@ class RenameSpacesTest(RenameTest): window_name_after = 'hello \\ wazzup 0' +class KillWindow(TmuxTestCase): + + def test_kill_window(self): + w = self.session.attached_window() + w.get('window_id') + + w.kill_window() + with self.assertRaises(IndexError): + w.get('window_id') + + class Options(TmuxTestCase): def test_show_window_options(self): diff --git a/tmuxp/window.py b/tmuxp/window.py index f64e8c7936b..18976f21f5b 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -137,6 +137,8 @@ def set_window_option(self, option, value): :type value: string or bool ''' + self.server._update_windows() + if isinstance(value, bool) and value: value = 'on' elif isinstance(value, bool) and not value: @@ -145,6 +147,7 @@ def set_window_option(self, option, value): process = self.tmux( 'set-window-option', '-t%s:%s' % (self.get('session_id'), self.get('window_index')), + #'-t%s' % self.get('window_id'), option, value ) @@ -155,7 +158,7 @@ def set_window_option(self, option, value): if isinstance(process.stderr, list) and len(process.stderr) == int(1): process.stderr = process.stderr[0] raise ValueError( - 'tmux set-window-option -t%s %s %s\n' % (self.get('window_id'), option, value) + + 'tmux set-window-option -t%s:%s %s %s\n' % (self.get('session_id'), self.get('window_index'), option, value) + process.stderr) def show_window_options(self, option=None): @@ -242,6 +245,24 @@ def rename_window(self, new_name): return self + def kill_window(self): + ''' + ``$ tmux kill-window`` + + Kill the current :class:`Window` object. + + :param target_window: the ``target window``. + :type target_window: string + ''' + + proc = self.tmux('kill-window', '-t%s' % self.get('window_id')) + + if proc.stderr: + raise Exception(proc.stderr) + + self.server._update_windows() + + def select_pane(self, target_pane): ''' ``$ tmux select-pane`` From 74f1be45bf16b99ac951d106aada4cab93fea159 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 18:55:38 +0800 Subject: [PATCH 0078/3283] make new of an expand bug with start_directory --- TODO | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/TODO b/TODO index a1a90eeb69a..42fc6720940 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,27 @@ Roadmap Immediate """"""""" +bug: + +'pane_start_path': u'/home/tony/workspace/tmuxp/ /var/log', + +.. code-block:: yaml + + yaml_config = ''' + session_name: sampleconfig + start_directory: '~' + windows: + - window_name: test + start_directory: /var/log + layout: main-horizontal + panes: + - shell_command: + - vim + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" + - update prompt() to have verbose choices - tmuxp kill-session escape / quote names with spaces - have test_workspace_builder use tests from ./examples! From 55e0d5b8985724362ca39a7c99d6d720cc08691f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 30 Oct 2013 20:54:39 +0800 Subject: [PATCH 0079/3283] midway commit: pane_start_path / start_directory support --- CHANGES | 3 +- tmuxp/session.py | 22 +++++++++---- tmuxp/testsuite/test_config.py | 2 ++ tmuxp/testsuite/test_workspacebuilder.py | 42 ++++++++++++++++++++---- tmuxp/util.py | 3 ++ tmuxp/workspacebuilder.py | 21 ++++++------ 6 files changed, 70 insertions(+), 23 deletions(-) diff --git a/CHANGES b/CHANGES index 500f214c769..444252ea9e7 100644 --- a/CHANGES +++ b/CHANGES @@ -13,7 +13,8 @@ Here you can find the recent changes to tmuxp. - [cli] ``tmuxp freeze `` experimental - [freeze] [tests] tmuxp now has experimental support for freezing live sessions. -- [internals] :meth:`Window.kill_window()` +- [internal] :meth:`Window.kill_window()` +- [internal] support for ``start_directory`` (work in progress) 2013-10-29 ---------- diff --git a/tmuxp/session.py b/tmuxp/session.py index 77d43516182..cab4355f4ab 100644 --- a/tmuxp/session.py +++ b/tmuxp/session.py @@ -100,7 +100,6 @@ def switch_client(self, target_session=None): if proc.stderr: raise Exception(proc.stderr) - def rename_session(self, new_name): '''rename session and return new :class:`Session` object @@ -121,6 +120,7 @@ def rename_session(self, new_name): def new_window(self, window_name=None, + start_directory=None, attach=True): ''' ``$ tmux new-window`` @@ -134,10 +134,12 @@ def new_window(self, .. code-block:: bash - $ tmux new-window -n + $ tmux new-window -n -c :type window_name: string - + :param start_directory: specifies the working directory in which the + new created. + :type start_directory: string :param attach: make new window the current window after creating it, default True. :param type: bool @@ -149,14 +151,22 @@ def new_window(self, window_args = ( '-t%s' % self.get('session_id'), '-P', - '-F%s' % '\t'.join(tmux_formats), # output ) + if not attach: + window_args += ('-d',) + + if start_directory: + # start_directory = pipes.quote(start_directory) + logger.error(start_directory) + window_args += ('-c %s' % start_directory,) + if window_name: window_args += ('-n%s' % window_name,) - if not attach: - window_args += ('-d',) + window_args += ( + '-F%s' % '\t'.join(tmux_formats), # output + ) proc = self.tmux('new-window', *window_args) diff --git a/tmuxp/testsuite/test_config.py b/tmuxp/testsuite/test_config.py index 2557088fe14..fe9c6729844 100644 --- a/tmuxp/testsuite/test_config.py +++ b/tmuxp/testsuite/test_config.py @@ -158,6 +158,7 @@ class ExpandTest(unittest.TestCase): ] }, { + 'start_directory': '/var/log', 'options': {'automatic_rename': True, }, 'panes': [ {'shell_command': 'htop'}, @@ -195,6 +196,7 @@ class ExpandTest(unittest.TestCase): ] }, { + 'start_directory': '/var/log', 'options': {'automatic_rename': True}, 'panes': [ {'shell_command': ['htop']}, diff --git a/tmuxp/testsuite/test_workspacebuilder.py b/tmuxp/testsuite/test_workspacebuilder.py index c22db99591f..4f058021b12 100644 --- a/tmuxp/testsuite/test_workspacebuilder.py +++ b/tmuxp/testsuite/test_workspacebuilder.py @@ -26,14 +26,12 @@ class TwoPaneTest(TmuxTestCase): panes: - shell_command: - vim - start_directory: '~' - shell_command: - echo "hey" window_name: editor - panes: - shell_command: - tail -F /var/log/syslog - start_directory: /var/log window_name: logging - window_name: test panes: @@ -72,7 +70,6 @@ class ThreePaneTest(TmuxTestCase): panes: - shell_command: - vim - start_directory: '~' - shell_command: - echo "hey" - shell_command: @@ -114,7 +111,6 @@ class FocusAndPaneIndexTest(TmuxTestCase): panes: - shell_command: - vim - start_directory: '~' - shell_command: - echo "hey" - shell_command: @@ -125,8 +121,7 @@ class FocusAndPaneIndexTest(TmuxTestCase): panes: - shell_command: - vim - start_directory: '~' - focus: true + rocus: true - shell_command: - echo "hey" - shell_command: @@ -273,5 +268,40 @@ def test_automatic_rename_option(self): self.assertNotEqual(w.get('window_name'), 'man') +class StartDirectoryTest(TmuxTestCase): + + yaml_config = ''' + session_name: sampleconfig + start_directory: '~' + windows: + - window_name: test + start_directory: /var/log + layout: main-horizontal + panes: + - shell_command: + - vim + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" + ''' + + def test_start_directory(self): + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(self.yaml_config).get() + #sconfig = config.expand(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + builder.build(session=self.session) + + assert(self.session == builder.session) + logger.error(self.session) + self.assertEqual(1, len(self.session.windows)) + for window in self.session.windows: + for p in window.panes: + logger.error(dict(p)) + logger.error(p.get('pane_start_path')) + self.assertEqual('/var/log', p.get('pane_start_path')) + if __name__ == '__main__': unittest.main() diff --git a/tmuxp/util.py b/tmuxp/util.py index e85078b9ea8..a984017b499 100644 --- a/tmuxp/util.py +++ b/tmuxp/util.py @@ -69,6 +69,9 @@ def __init__(self, *args, **kwargs): self.stderr = stderr.decode().split('\n') self.stderr = list(filter(None, self.stderr)) # filter empty values + if 'new-window' in cmd: + logger.error(' '.join(cmd)) + if 'has-session' in cmd and len(self.stderr): if not self.stdout: self.stdout = self.stderr[0] diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index 36c94d8ab79..862ab9af541 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -161,18 +161,19 @@ def iter_create_windows(self, s): else: window_name = wconf['window_name'] + w1 = None if i == int(1): # if first window, use window 1 - # w = s.select_window(1) - w = s.attached_window() - w = w.rename_window(window_name) - else: - w = s.new_window( - window_name=window_name, - attach=False # do not move to the new window - ) - + w1 = s.attached_window() + w = s.new_window( + window_name=window_name, + start_directory=wconf['start_directory'] if 'start_directory' in wconf else None, + attach=False # do not move to the new window + ) + + if i == int(1) and w1: # if first window, use window 1 + w1.kill_window() assert(isinstance(w, Window)) - + s.server._update_windows() if 'options' in wconf and isinstance(wconf['options'], dict): for key, val in wconf['options'].items(): w.set_window_option(key, val) From 801a2826f9a6d1f221417cebf8ca66e92615dbd1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 09:52:48 +0800 Subject: [PATCH 0080/3283] Try set-option default-path before creation if -c entered. Add util.check_version. Expecting 1.9 to fail on this. wip --- tmuxp/server.py | 12 +----------- tmuxp/session.py | 22 +++++++++++++++------- tmuxp/testsuite/test_workspacebuilder.py | 22 ++++++++++++++++------ tmuxp/util.py | 21 +++++++++++++++++++-- tmuxp/workspacebuilder.py | 5 +++-- 5 files changed, 54 insertions(+), 28 deletions(-) diff --git a/tmuxp/server.py b/tmuxp/server.py index 0af159cbdf9..c71f12675ab 100644 --- a/tmuxp/server.py +++ b/tmuxp/server.py @@ -85,17 +85,7 @@ def __list_sessions(self): ) if proc.stderr: - if 'unknown option -- F' in proc.stderr[0]: - proc = self.tmux( - 'list-sessions', - ) - - if proc.stderr: - raise Exception(proc.stderr) - else: - return 'hi' - else: - raise Exception(proc.stderr) + raise Exception(proc.stderr) else: session_info = proc.stdout[0] diff --git a/tmuxp/session.py b/tmuxp/session.py index cab4355f4ab..fd227feff4c 100644 --- a/tmuxp/session.py +++ b/tmuxp/session.py @@ -148,24 +148,32 @@ def new_window(self, wformats = ['session_name', 'session_id'] + formats.WINDOW_FORMATS tmux_formats = ['#{%s}' % f for f in wformats] - window_args = ( - '-t%s' % self.get('session_id'), - '-P', - ) + window_args = tuple() + if not attach: window_args += ('-d',) + window_args += ( + '-P', + ) + if start_directory: - # start_directory = pipes.quote(start_directory) + self.tmux('set-option', 'default-path', start_directory) + self.server.tmux('set-option', 'default-path', start_directory) + #start_directory = pipes.quote(start_directory) logger.error(start_directory) - window_args += ('-c %s' % start_directory,) + #window_args += ('-c%s' % start_directory,) + + window_args += ( + '-F"%s"' % '\t'.join(tmux_formats), # output + ) if window_name: window_args += ('-n%s' % window_name,) window_args += ( - '-F%s' % '\t'.join(tmux_formats), # output + '-t%s' % self.get('session_id'), ) proc = self.tmux('new-window', *window_args) diff --git a/tmuxp/testsuite/test_workspacebuilder.py b/tmuxp/testsuite/test_workspacebuilder.py index 4f058021b12..b779e61e732 100644 --- a/tmuxp/testsuite/test_workspacebuilder.py +++ b/tmuxp/testsuite/test_workspacebuilder.py @@ -269,17 +269,26 @@ def test_automatic_rename_option(self): class StartDirectoryTest(TmuxTestCase): - yaml_config = ''' session_name: sampleconfig - start_directory: '~' + #start_directory: '/home/tony' windows: - window_name: test - start_directory: /var/log + start_directory: '/var/log' layout: main-horizontal + options: + main-pane-height: 50 panes: - shell_command: - - vim + - echo "hey" + - shell_command: + - echo "moo" + - window_name: testsa + start_directory: '/dev' + layout: main-horizontal + panes: + - shell_command: + - pwd - shell_command: - echo "hey" - shell_command: @@ -287,6 +296,7 @@ class StartDirectoryTest(TmuxTestCase): ''' def test_start_directory(self): + sconfig = kaptan.Kaptan(handler='yaml') sconfig = sconfig.import_config(self.yaml_config).get() #sconfig = config.expand(sconfig) @@ -296,12 +306,12 @@ def test_start_directory(self): assert(self.session == builder.session) logger.error(self.session) - self.assertEqual(1, len(self.session.windows)) + #self.assertEqual(1, len(self.session.windows)) for window in self.session.windows: for p in window.panes: logger.error(dict(p)) logger.error(p.get('pane_start_path')) - self.assertEqual('/var/log', p.get('pane_start_path')) + self.assertTrue(any(p.get('pane_start_path', ['/var/log', '/dev/']))) if __name__ == '__main__': unittest.main() diff --git a/tmuxp/util.py b/tmuxp/util.py index a984017b499..f25238ba740 100644 --- a/tmuxp/util.py +++ b/tmuxp/util.py @@ -53,14 +53,14 @@ def __init__(self, *args, **kwargs): self.process = subprocess.Popen( cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE + stderr=subprocess.PIPE, ) self.process.wait() stdout = self.process.stdout.read() stderr = self.process.stderr.read() except Exception as e: logger.error('Exception for %s: \n%s' % ( - cmd, + subprocess.list2cmdline(cmd), e.message) ) self.stdout = stdout.decode().split('\n') @@ -221,8 +221,25 @@ def which(exe=None): logger.error('No executable was passed to be searched by which') return None +def get_version(version): + """ Return True if tmux version installed. + + :param version: version, '1.8' + :param type: string + """ + proc = tmux('-V') + + if proc.stderr: + raise Exception(proc.stderr) + + installed_version = proc.stdout[0].split('tmux ')[1] + + return StrictVersion(installed_version) == StrictVersion(version) def version(): + """ + check to see if tmux is version >1.8 or above + """ proc = tmux('-V') if proc.stderr: diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index 862ab9af541..9287615c0ff 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -164,6 +164,7 @@ def iter_create_windows(self, s): w1 = None if i == int(1): # if first window, use window 1 w1 = s.attached_window() + w1.attached_pane().send_keys('la') w = s.new_window( window_name=window_name, start_directory=wconf['start_directory'] if 'start_directory' in wconf else None, @@ -241,8 +242,8 @@ def freeze(session): pconf = {} pconf['shell_command'] = [] if 'shell_command_before' not in wconf: - pconf['shell_command'].append( - 'cd ' + p.get('pane_current_path')) + pconf['shell_command'].append( + 'cd ' + p.get('pane_current_path')) pconf['shell_command'].append(p.get('pane_current_command')) wconf['panes'].append(pconf) # logger.error(p) From 6c070063f1a3f7870d111812d5fec9dab273336e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 10:07:08 +0800 Subject: [PATCH 0081/3283] Clean up --- tmuxp/session.py | 7 ++----- tmuxp/testsuite/test_workspacebuilder.py | 5 ----- tmuxp/testsuite/test_workspacefreezer.py | 4 ++-- tmuxp/util.py | 3 --- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/tmuxp/session.py b/tmuxp/session.py index fd227feff4c..e517d8033b3 100644 --- a/tmuxp/session.py +++ b/tmuxp/session.py @@ -150,7 +150,6 @@ def new_window(self, window_args = tuple() - if not attach: window_args += ('-d',) @@ -161,10 +160,8 @@ def new_window(self, if start_directory: self.tmux('set-option', 'default-path', start_directory) self.server.tmux('set-option', 'default-path', start_directory) - #start_directory = pipes.quote(start_directory) - logger.error(start_directory) - #window_args += ('-c%s' % start_directory,) - + # start_directory = pipes.quote(start_directory) + # window_args += ('-c%s' % start_directory,) window_args += ( '-F"%s"' % '\t'.join(tmux_formats), # output diff --git a/tmuxp/testsuite/test_workspacebuilder.py b/tmuxp/testsuite/test_workspacebuilder.py index b779e61e732..aa7a0120cd7 100644 --- a/tmuxp/testsuite/test_workspacebuilder.py +++ b/tmuxp/testsuite/test_workspacebuilder.py @@ -299,18 +299,13 @@ def test_start_directory(self): sconfig = kaptan.Kaptan(handler='yaml') sconfig = sconfig.import_config(self.yaml_config).get() - #sconfig = config.expand(sconfig) builder = WorkspaceBuilder(sconf=sconfig) builder.build(session=self.session) assert(self.session == builder.session) - logger.error(self.session) - #self.assertEqual(1, len(self.session.windows)) for window in self.session.windows: for p in window.panes: - logger.error(dict(p)) - logger.error(p.get('pane_start_path')) self.assertTrue(any(p.get('pane_start_path', ['/var/log', '/dev/']))) if __name__ == '__main__': diff --git a/tmuxp/testsuite/test_workspacefreezer.py b/tmuxp/testsuite/test_workspacefreezer.py index 92f8e4b7b0d..4676bb6836a 100644 --- a/tmuxp/testsuite/test_workspacefreezer.py +++ b/tmuxp/testsuite/test_workspacefreezer.py @@ -72,8 +72,8 @@ def test_freeze_config(self): yaml = kaptanconf.export( 'yaml', indent=2, default_flow_style=False, safe=True) - logger.error(json) - logger.error(yaml) + #logger.error(json) + #logger.error(yaml) if __name__ == '__main__': unittest.main() diff --git a/tmuxp/util.py b/tmuxp/util.py index f25238ba740..6efd5511a78 100644 --- a/tmuxp/util.py +++ b/tmuxp/util.py @@ -69,9 +69,6 @@ def __init__(self, *args, **kwargs): self.stderr = stderr.decode().split('\n') self.stderr = list(filter(None, self.stderr)) # filter empty values - if 'new-window' in cmd: - logger.error(' '.join(cmd)) - if 'has-session' in cmd and len(self.stderr): if not self.stdout: self.stdout = self.stderr[0] From 5d66126342a8bb9d00eb7d14fa0b47def9ee3b78 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 10:23:56 +0800 Subject: [PATCH 0082/3283] Fix config.trickle to pass down start_directory properly. Assure that StartDirectory works correctly. --- tmuxp/config.py | 4 +++ tmuxp/testsuite/test_config.py | 39 +++++++++++++----------- tmuxp/testsuite/test_workspacebuilder.py | 15 +++++++-- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/tmuxp/config.py b/tmuxp/config.py index b129e8d3439..845fea66614 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -190,7 +190,11 @@ def trickle(config): ``shell_command_before``. ''' + session_start_directory = config['start_directory'] if 'start_directory' in config else None + for windowconfig in config['windows']: + if not 'start_directory' in windowconfig and session_start_directory: + windowconfig['start_directory'] = session_start_directory for paneconfig in windowconfig['panes']: commands_before = config[ 'shell_command_before'] if 'shell_command_before' in config else [] diff --git a/tmuxp/testsuite/test_config.py b/tmuxp/testsuite/test_config.py index fe9c6729844..648f2636ffc 100644 --- a/tmuxp/testsuite/test_config.py +++ b/tmuxp/testsuite/test_config.py @@ -144,8 +144,9 @@ class ExpandTest(unittest.TestCase): 'window_name': 'editor', 'panes': [ { - 'start_directory': '~', 'shell_command': ['vim'], - }, { + 'shell_command': ['vim'], + }, + { 'shell_command': 'cowsay "hey"' }, ], @@ -154,7 +155,7 @@ class ExpandTest(unittest.TestCase): 'window_name': 'logging', 'panes': [ {'shell_command': ['tail -F /var/log/syslog'], - 'start_directory':'/var/log'} + } ] }, { @@ -181,7 +182,7 @@ class ExpandTest(unittest.TestCase): 'window_name': 'editor', 'panes': [ { - 'start_directory': '~', 'shell_command': ['vim'], + 'shell_command': ['vim'], }, { 'shell_command': ['cowsay "hey"'] }, @@ -192,7 +193,7 @@ class ExpandTest(unittest.TestCase): 'window_name': 'logging', 'panes': [ {'shell_command': ['tail -F /var/log/syslog'], - 'start_directory':'/var/log'} + } ] }, { @@ -215,6 +216,7 @@ def test_config(self): ''' expands shell commands from string to list ''' + self.maxDiff = None test_config = config.expand(self.before_config) self.assertDictEqual(test_config, self.after_config) @@ -426,7 +428,7 @@ class ShellCommandBeforeTest(unittest.TestCase): 'shell_command_before': 'source .env/bin/activate', 'panes': [ { - 'start_directory': '~', 'shell_command': ['vim'], + 'shell_command': ['vim'], }, { 'shell_command_before': ['rbenv local 2.0.0-p0'], 'shell_command': ['cowsay "hey"'] }, @@ -438,9 +440,9 @@ class ShellCommandBeforeTest(unittest.TestCase): 'window_name': 'logging', 'panes': [ {'shell_command': ['tail -F /var/log/syslog'], - 'start_directory':'/var/log'}, + }, { - 'start_directory': '/var/log'} + } ] }, { @@ -448,7 +450,7 @@ class ShellCommandBeforeTest(unittest.TestCase): 'panes': [ { 'shell_command_before': ['rbenv local 2.0.0-p0'], - 'shell_command': ['htop'], 'start_directory': '/etc/'} + 'shell_command': ['htop'], } ] }, { @@ -473,7 +475,7 @@ class ShellCommandBeforeTest(unittest.TestCase): 'shell_command_before': ['source .env/bin/activate'], 'panes': [ { - 'start_directory': '~', 'shell_command': ['vim'], + 'shell_command': ['vim'], }, { 'shell_command_before': ['rbenv local 2.0.0-p0'], 'shell_command': ['cowsay "hey"'] }, @@ -485,9 +487,9 @@ class ShellCommandBeforeTest(unittest.TestCase): 'window_name': 'logging', 'panes': [ {'shell_command': ['tail -F /var/log/syslog'], - 'start_directory':'/var/log'}, + }, { - 'start_directory': '/var/log'} + } ] }, { @@ -495,7 +497,7 @@ class ShellCommandBeforeTest(unittest.TestCase): 'panes': [ { 'shell_command_before': ['rbenv local 2.0.0-p0'], - 'shell_command': ['htop'], 'start_directory': '/etc/'} + 'shell_command': ['htop'],} ] }, { @@ -522,7 +524,6 @@ class ShellCommandBeforeTest(unittest.TestCase): 'shell_command_before': ['source .env/bin/activate'], 'panes': [ { - 'start_directory': '~', 'shell_command': ['source .env/bin/activate', 'vim'], }, { 'shell_command_before': ['rbenv local 2.0.0-p0'], @@ -536,29 +537,33 @@ class ShellCommandBeforeTest(unittest.TestCase): }, { 'shell_command_before': ['rbenv local 2.0.0-p0'], + 'start_directory': '/', 'window_name': 'logging', 'panes': [ {'shell_command': ['rbenv local 2.0.0-p0', 'tail -F /var/log/syslog'], - 'start_directory':'/var/log'}, + }, { - 'start_directory': '/var/log', 'shell_command': ['rbenv local 2.0.0-p0']} + 'shell_command': ['rbenv local 2.0.0-p0']} ] }, { + 'start_directory': '/', 'window_name': 'shufu', 'panes': [ { 'shell_command_before': ['rbenv local 2.0.0-p0'], - 'shell_command': ['rbenv local 2.0.0-p0', 'htop'], 'start_directory': '/etc/'} + 'shell_command': ['rbenv local 2.0.0-p0', 'htop'],} ] }, { + 'start_directory': '/', 'options': {'automatic_rename': True, }, 'panes': [ {'shell_command': ['htop']} ] }, { + 'start_directory': '/', 'panes': [ {'shell_command': ['top']} ] diff --git a/tmuxp/testsuite/test_workspacebuilder.py b/tmuxp/testsuite/test_workspacebuilder.py index aa7a0120cd7..af30bf7c4ce 100644 --- a/tmuxp/testsuite/test_workspacebuilder.py +++ b/tmuxp/testsuite/test_workspacebuilder.py @@ -271,7 +271,7 @@ def test_automatic_rename_option(self): class StartDirectoryTest(TmuxTestCase): yaml_config = ''' session_name: sampleconfig - #start_directory: '/home/tony' + start_directory: '/var' windows: - window_name: test start_directory: '/var/log' @@ -293,12 +293,23 @@ class StartDirectoryTest(TmuxTestCase): - echo "hey" - shell_command: - echo "moo" + - window_name: testsa3 + layout: main-horizontal + panes: + - shell_command: + - pwd + - shell_command: + - echo "hey" + - shell_command: + - echo "moo3" ''' def test_start_directory(self): 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) @@ -306,7 +317,7 @@ def test_start_directory(self): assert(self.session == builder.session) for window in self.session.windows: for p in window.panes: - self.assertTrue(any(p.get('pane_start_path', ['/var/log', '/dev/']))) + self.assertTrue(any(p.get('pane_start_path', ['/var/log', '/dev/', '/var/']))) if __name__ == '__main__': unittest.main() From a6646655b78df5fb8ad6fdd1caf7dfc3819c93ea Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 10:33:00 +0800 Subject: [PATCH 0083/3283] CHANGELOG, util.get_version rename to util.is_version, test_window.KillWindow create second window to avoid dumping test client out of client --- CHANGES | 7 +++++++ tmuxp/testsuite/test_window.py | 5 +++++ tmuxp/util.py | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 444252ea9e7..8a2ba0adfe2 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,13 @@ tmuxp Changelog Here you can find the recent changes to tmuxp. +2013-10-31 +---------- + +- [internal] :meth:`util.is_version()` +- [config] [tests]: correctly :meth:`config.trickle()` the ``start_directory``. +- [config] [tests]: get ``start_directory`` working for configs + 2013-10-30 ---------- diff --git a/tmuxp/testsuite/test_window.py b/tmuxp/testsuite/test_window.py index 3fd2ae0caa1..dab04eab094 100644 --- a/tmuxp/testsuite/test_window.py +++ b/tmuxp/testsuite/test_window.py @@ -152,7 +152,12 @@ class RenameSpacesTest(RenameTest): class KillWindow(TmuxTestCase): def test_kill_window(self): + self.session.new_window() + # create a second window to not kick out the client. + # there is another way to do this via options too. + w = self.session.attached_window() + w.get('window_id') w.kill_window() diff --git a/tmuxp/util.py b/tmuxp/util.py index 6efd5511a78..29cb13adb20 100644 --- a/tmuxp/util.py +++ b/tmuxp/util.py @@ -218,7 +218,7 @@ def which(exe=None): logger.error('No executable was passed to be searched by which') return None -def get_version(version): +def is_version(version): """ Return True if tmux version installed. :param version: version, '1.8' From 7a479cb13a655a894781f4d376d3a523a01717e7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 10:42:43 +0800 Subject: [PATCH 0084/3283] start_directory example for docs. adjust target on Window.kill_window() to session_id:window_index for compatibility --- CHANGES | 3 +++ doc/examples.rst | 19 +++++++++++++++++++ examples/start_directory.json | 21 +++++++++++++++++++++ examples/start_directory.yaml | 12 ++++++++++++ tmuxp/window.py | 6 +++++- 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 examples/start_directory.json create mode 100644 examples/start_directory.yaml diff --git a/CHANGES b/CHANGES index 8a2ba0adfe2..1e7a36eef5e 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,9 @@ Here you can find the recent changes to tmuxp. - [internal] :meth:`util.is_version()` - [config] [tests]: correctly :meth:`config.trickle()` the ``start_directory``. - [config] [tests]: get ``start_directory`` working for configs +- [internal]: fix :meth:``Window.kill_window()`` target to + ``session_id:window_index`` for compatibility and pass tests. +- [docs] [examples]: Example for ``start_directory``. 2013-10-30 ---------- diff --git a/doc/examples.rst b/doc/examples.rst index bcb3b200518..949fcf65d40 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -165,6 +165,25 @@ JSON .. literalinclude:: ../examples/main-pane-height.json :language: json +Start Directory +--------------- + +Equivalent to ``tmux new-window -c ``. + +.. sidebar:: short hand + +YAML +"""" + +.. literalinclude:: ../examples/start_directory.yaml + :language: yaml + +JSON +"""" + +.. literalinclude:: ../examples/start_directory.json + :language: json + Super-advanced dev environment ------------------------------ diff --git a/examples/start_directory.json b/examples/start_directory.json new file mode 100644 index 00000000000..c8ab8755728 --- /dev/null +++ b/examples/start_directory.json @@ -0,0 +1,21 @@ +{ + "windows": [ + { + "panes": [ + "pwd", + "echo 'it trickles down from session-level'" + ], + "window_name": "should be /var/log" + }, + { + "panes": [ + "pwd", + "echo 'has precedence'" + ], + "start_directory": "$HOME", + "window_name": "should be $HOME" + } + ], + "session_name": "start directory", + "start_directory": "/var/log" +} \ No newline at end of file diff --git a/examples/start_directory.yaml b/examples/start_directory.yaml new file mode 100644 index 00000000000..e8bef231433 --- /dev/null +++ b/examples/start_directory.yaml @@ -0,0 +1,12 @@ +session_name: start directory +start_directory: /var/log +windows: + - window_name: should be /var/log + panes: + - pwd + - echo 'it trickles down from session-level' + - window_name: should be $HOME + start_directory: $HOME + panes: + - pwd + - echo 'has precedence' diff --git a/tmuxp/window.py b/tmuxp/window.py index 18976f21f5b..1a223ea71bd 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -255,7 +255,11 @@ def kill_window(self): :type target_window: string ''' - proc = self.tmux('kill-window', '-t%s' % self.get('window_id')) + proc = self.tmux( + 'kill-window', + #'-t:%s' % self.get('window_id') + '-t%s:%s' % (self.get('session_id'), self.get('window_index')), + ) if proc.stderr: raise Exception(proc.stderr) From e0e956fdf962ef5d0a061c998f2c5071f76ce864 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 10:43:27 +0800 Subject: [PATCH 0085/3283] v0.0.29 --- tmuxp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index db6f86d8b16..652168471bf 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -22,4 +22,4 @@ import logging -__version__ = '0.0.28' +__version__ = '0.0.29' From b94a396e34635df5c7c452746de6031552f3f492 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 12:07:24 +0800 Subject: [PATCH 0086/3283] Fix bug where windows 1 and 2 load reversed. Add Window.move_window(). Remove superfluous log msg --- CHANGES | 2 ++ tmuxp/__init__.py | 2 +- tmuxp/window.py | 23 +++++++++++++++++++++-- tmuxp/workspacebuilder.py | 2 +- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 1e7a36eef5e..fa37e3be578 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,8 @@ Here you can find the recent changes to tmuxp. - [internal]: fix :meth:``Window.kill_window()`` target to ``session_id:window_index`` for compatibility and pass tests. - [docs] [examples]: Example for ``start_directory``. +- [internal] fix bug where first and second window would load in mixed order +- [internal] :class:`Window.move_window()` for moving window. 2013-10-30 ---------- diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index 652168471bf..e3a93b35ae9 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -22,4 +22,4 @@ import logging -__version__ = '0.0.29' +__version__ = '0.0.30' diff --git a/tmuxp/window.py b/tmuxp/window.py index 1a223ea71bd..d805a4111e9 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -251,8 +251,6 @@ def kill_window(self): Kill the current :class:`Window` object. - :param target_window: the ``target window``. - :type target_window: string ''' proc = self.tmux( @@ -266,6 +264,27 @@ def kill_window(self): self.server._update_windows() + def move_window(self, destination): + ''' + ``$ tmux move-window`` + + move the current :class:`Window` object. + + :param destination: the ``target window`` or index to move the window + to. + :type target_window: string + ''' + + proc = self.tmux( + 'move-window', + '-s%s:%s' % (self.get('session_id'), self.get('window_index')), + '-t%s' % destination, + ) + + if proc.stderr: + raise Exception(proc.stderr) + + self.server._update_windows() def select_pane(self, target_pane): ''' diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index 9287615c0ff..dcaffe0f0c8 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -164,7 +164,7 @@ def iter_create_windows(self, s): w1 = None if i == int(1): # if first window, use window 1 w1 = s.attached_window() - w1.attached_pane().send_keys('la') + w1.move_window(99) w = s.new_window( window_name=window_name, start_directory=wconf['start_directory'] if 'start_directory' in wconf else None, From 9aca2b367babe8406cea936cc92e67717e8cda60 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 17:49:25 +0800 Subject: [PATCH 0087/3283] docs --- doc/about.rst | 8 ++++++++ doc/index.rst | 42 +++++++++++++++++++++--------------------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/doc/about.rst b/doc/about.rst index 9b7122eec22..7f295eeb606 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -76,6 +76,14 @@ format *****. **Conversion** ``$ tmuxp convert `` can convert files to and from JSON and YAML. +Minor tweaks +"""""""""""" + +- Load + switch to new session from inside tmux. +- Resume session if config loaded. +- Pre-commands virtualenv / rvm / any other commands. +- Load config from anywhere `$ tmuxp load /full/file/path.json`. + Footnotes """"""""" diff --git a/doc/index.rst b/doc/index.rst index 1db8871e359..9fd94835a95 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -6,29 +6,29 @@ tmuxp :width: 100% :align: right -tmuxp, a novel approach to managing `tmux(1)`_ workspaces through -python objects. Features: + +tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through +`python objects`_. + +- Basic support for `freezing live sessions`_ +- `importing`_ from `teamocil`_ and `tmuxinator`_. +- JSON or YAML for `simple`_ or `very elaborate`_ configurations. +- `bash, zsh and tcsh`_ completion. +- Unit tested against against live tmux (1.8 and git). See `travis.yml`_ + file and `testing`_ page. +- Documented Examples, Internals. +- and `much, much more`_ + +Ready to begin? See the `Quickstart`_. + +More tweaks: - Load + switch to new session from inside tmux. -- :ref:`bash / zsh / tcsh completion `. -- JSON, YAML and `python dict`_ configuration. -- Support for pre-commands with ``shell_command_before`` to load - virtualenv / rvm / any other commands. -- Session resuming from config file if already running. -- Per-project tmux sessions, load directly from config file. - `` $ tmuxp load /full/file/path.json `` -- uses tmux 1.8's ``pane_id``, ``window_id`` and ``session_id`` to build - create python objects to build workspaces with the freshest data. -- (experimental) Import configs from `teamocil`_ and `tmuxinator`_. -- (experimental) Freezing sessions. - -tmuxp works in 3 ways: - -- a pythonic `abstraction layer`_ on top of tmux' CLI commands -- an `ORM`_ that internally orchestrates relations between servers, - sessions, windows and panes for good and evil purposes. -- CLI tmux session manager, similar to `teamocil`_ and `tmuxinator`_, with - support for loading YAML, JSON and python dicts. +- Resume session if config loaded. +- Pre-commands virtualenv / rvm / any other commands. +- Load config from anywhere `$ tmuxp load /full/file/path.json`. + +.. _bash, zsh, and tcsh: http://tmuxp.readthedocs.org/en/latest/quickstart.html#bash-completion Get started ----------- From de8da30bc4d8d1a71fa7eb3827c5b7b0ebc95fa6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 18:02:59 +0800 Subject: [PATCH 0088/3283] more docs. cli page --- doc/cli.rst | 39 +++++++++++++++++++++++++++++++++++++++ doc/index.rst | 7 +------ doc/quickstart.rst | 33 +++------------------------------ 3 files changed, 43 insertions(+), 36 deletions(-) create mode 100644 doc/cli.rst diff --git a/doc/cli.rst b/doc/cli.rst new file mode 100644 index 00000000000..a2da943d0db --- /dev/null +++ b/doc/cli.rst @@ -0,0 +1,39 @@ +.. _cli: + +====================== +Command Line Interface +====================== + +.. _bash_completion: + +Bash completion +""""""""""""""" + +For bash, ``.bashrc``: + +.. code-block:: bash + + $ source tmuxp.bash + +For tcsh, ``.tcshrc``: + +.. code-block:: bash + + $ complete tmuxp 'p/*/`tmuxp.tcsh`/' + +For zsh, ``.zshrc``: + +.. code-block:: bash + + $ source tmuxp.zsh + + +.. commands:: + +Commands +"""""""" + +.. argparse:: + :module: tmuxp.cli + :func: get_parser + :prog: tmuxp diff --git a/doc/index.rst b/doc/index.rst index 9fd94835a95..bff403c8c13 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -21,12 +21,6 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through Ready to begin? See the `Quickstart`_. -More tweaks: - -- Load + switch to new session from inside tmux. -- Resume session if config loaded. -- Pre-commands virtualenv / rvm / any other commands. -- Load config from anywhere `$ tmuxp load /full/file/path.json`. .. _bash, zsh, and tcsh: http://tmuxp.readthedocs.org/en/latest/quickstart.html#bash-completion @@ -90,6 +84,7 @@ Explore: about about_tmux + cli quickstart examples orm_al diff --git a/doc/quickstart.rst b/doc/quickstart.rst index dcb6dad7589..db58ee55cf4 100644 --- a/doc/quickstart.rst +++ b/doc/quickstart.rst @@ -4,13 +4,10 @@ Quickstart ========== -Tmux Session Manager --------------------- +CLI +--- -.. argparse:: - :module: tmuxp.cli - :func: get_parser - :prog: tmuxp +.. seealso:: :ref:`examples`, :ref:`cli`, :ref:`bash_completion`. tmuxp launches sessions from a configuration file. @@ -43,30 +40,6 @@ It will list configs available in the current directory and This creates your tmuxp session. -.. seealso:: :ref:`examples` - -.. _bash_completion: - -Bash completion -""""""""""""""" - -For bash, ``.bashrc``: - -.. code-block:: bash - - $ source tmuxp.bash - -For tcsh, ``.tcshrc``: - -.. code-block:: bash - - $ complete tmuxp 'p/*/`tmuxp.tcsh`/' - -For zsh, ``.zshrc``: - -.. code-block:: bash - - $ source tmuxp.zsh Python ORM + AL --------------- From cf7c9f1df2f07fd08372a875032784bb152c3f8a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 18:08:31 +0800 Subject: [PATCH 0089/3283] more docs --- doc/about.rst | 17 +++++++--------- doc/index.rst | 51 ---------------------------------------------- doc/quickstart.rst | 2 +- 3 files changed, 8 insertions(+), 62 deletions(-) diff --git a/doc/about.rst b/doc/about.rst index 7f295eeb606..cc2da40a315 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -61,7 +61,7 @@ with access to all window and pane data. See :ref:`ORM_AL`. **CLI** tmuxp's CLI can attach and kill sessions. Additional Features -""""""""""""""""""" +------------------- **Unit tests** Tests against live tmux version to test statefulness of tmux sessions, windows and panes. See :ref:`travis`. @@ -69,28 +69,25 @@ tmux sessions, windows and panes. See :ref:`travis`. **Import config** import configs from Teamocil / Tmuxinator ***** **Session freezing** Supports session freezing into YAML and JSON -format *****. +format [1]_. **JSON config** JSON config support **Conversion** ``$ tmuxp convert `` can convert files to and from JSON and YAML. +.. [1] Freezing sessions may save a lot of time, but tweaking will + probably be required. There is no substitute for a config made with + love. + Minor tweaks -"""""""""""" +------------ - Load + switch to new session from inside tmux. - Resume session if config loaded. - Pre-commands virtualenv / rvm / any other commands. - Load config from anywhere `$ tmuxp load /full/file/path.json`. -Footnotes -""""""""" - -* Tmuxp session configurations can be very complicated, importing and - freezing sessions may save a lot of time, but tweaking will probably be - required. There is no substitute for a config made with love. - .. _attempt at 1.7 test: https://travis-ci.org/tony/tmuxp/jobs/12348263 .. _kaptan: https://github.com/emre/kaptan .. _unittest: http://docs.python.org/2/library/unittest.html diff --git a/doc/index.rst b/doc/index.rst index bff403c8c13..2f62fbe5924 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -21,59 +21,8 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through Ready to begin? See the `Quickstart`_. - .. _bash, zsh, and tcsh: http://tmuxp.readthedocs.org/en/latest/quickstart.html#bash-completion -Get started ------------ - -Get the prerequisites: - -1. installed ``tmux``, at least version **1.8** -2. libyaml is installed for your distribution. - -To install ``tmuxp``: - -.. code-block:: bash - - $ pip install tmuxp - -``$ mkdir ~/.tmuxp`` and make a file ``~/.tmuxp/test.yaml``. - -.. code-block:: yaml - - session_name: 2-pane-vertical - windows: - - window_name: my test window - panes: - - pwd - - pwd - -.. code-block:: bash - - $ tmuxp load test.yaml - -or ``~/.tmuxp/test.json``: - -.. code-block:: json - - { - "windows": [ - { - "panes": [ - "pwd", - "pwd" - ], - "window_name": "my test window" - } - ], - "session_name": "2-pane-vertical" - } - -.. code-block:: bash - - $ tmuxp load test.json - Jump right in: See `Examples`_, `Quickstart`_ and `bash completion`_ support. diff --git a/doc/quickstart.rst b/doc/quickstart.rst index db58ee55cf4..9e406cb619e 100644 --- a/doc/quickstart.rst +++ b/doc/quickstart.rst @@ -14,7 +14,7 @@ tmuxp launches sessions from a configuration file. Configuration files can be stored in ``$HOME/.tmuxp`` or in project directories as ``.tmuxp.py``, ``.tmuxp.json`` or ``.tmuxp.yaml``. -Every configuratio is required to have: +Every configuration is required to have: 1. ``session_name`` 2. list of ``windows`` From 09c4d8b08cfad05eda1bbb3157761d050cd62fe7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 18:13:06 +0800 Subject: [PATCH 0090/3283] docs --- doc/about.rst | 4 ++-- doc/index.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/about.rst b/doc/about.rst index cc2da40a315..7e100bbed63 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -76,8 +76,8 @@ format [1]_. **Conversion** ``$ tmuxp convert `` can convert files to and from JSON and YAML. -.. [1] Freezing sessions may save a lot of time, but tweaking will - probably be required. There is no substitute for a config made with +.. [1] Freezing sessions is a great way to save time, but tweaking will + probably be required - There is no substitute to a config made with love. Minor tweaks diff --git a/doc/index.rst b/doc/index.rst index 2f62fbe5924..49928d80fdb 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -32,15 +32,15 @@ Explore: :maxdepth: 2 about - about_tmux cli quickstart examples orm_al developing api - glossary changes + about_tmux + glossary Indices and tables ================== From 1a88b18ba37d92bb820af07af98b83181aab1857 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 18:22:44 +0800 Subject: [PATCH 0091/3283] latest docs --- doc/cli.rst | 27 +++++++++++++++++++++++++++ doc/index.rst | 6 +++++- doc/quickstart.rst | 8 ++++---- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/doc/cli.rst b/doc/cli.rst index a2da943d0db..4e3d49cec53 100644 --- a/doc/cli.rst +++ b/doc/cli.rst @@ -4,6 +4,33 @@ Command Line Interface ====================== +.. _import_teamocil: + +Freeze sessions +""""""""""""""" + +.. code-block:: bash + + $ tmuxp freeze + +Import from teamocil +"""""""""""""""""""" + +.. _import_teamocil: + +.. code-block:: bash + + $ tmuxp import teamocil + +.. _import_tmuxinator: + +Import from tmuxinator +"""""""""""""""""""""" + +.. code-block:: bash + + $ tmuxp import tmuxinator + .. _bash_completion: Bash completion diff --git a/doc/index.rst b/doc/index.rst index 49928d80fdb..aa1b35be812 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -21,7 +21,11 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through Ready to begin? See the `Quickstart`_. -.. _bash, zsh, and tcsh: http://tmuxp.readthedocs.org/en/latest/quickstart.html#bash-completion +.. _python objects: http://tmuxp.readthedocs.org/en/latest/api.html#api +.. _simple: http://tmuxp.readthedocs.org/en/latest/examples.html#short-hand-inline +.. _very elaborate: http://tmuxp.readthedocs.org/en/latest/examples.html#super-advanced-dev-environment +.. _bash, zsh, and tcsh: http://tmuxp.readthedocs.org/en/latest/cli.html#bash-completion +.. _much, much more: http://tmuxp.readthedocs.org/en/latest/about.html#minor-tweaks Jump right in: See `Examples`_, `Quickstart`_ and `bash completion`_ support. diff --git a/doc/quickstart.rst b/doc/quickstart.rst index 9e406cb619e..8b35a2627a5 100644 --- a/doc/quickstart.rst +++ b/doc/quickstart.rst @@ -41,8 +41,8 @@ It will list configs available in the current directory and This creates your tmuxp session. -Python ORM + AL ---------------- +Pythonics +--------- ORM - `Object Relational Mapper`_ @@ -62,11 +62,11 @@ python abstraction layer ======================================== ================================= :ref:`tmuxp python api ` :term:`tmux(1)` equivalent ======================================== ================================= +:class:`Server.new_session()` ``$ tmux new-session`` :class:`Server.list_sessions()` ``$ tmux list-sessions`` :class:`Session.list_windows()` ``$ tmux list-windows`` -:class:`Window.list_panes()` ``$ tmux list-panes`` -:class:`Server.new_session()` ``$ tmux new-session`` :class:`Session.new_window()` ``$ tmux new-window`` +:class:`Window.list_panes()` ``$ tmux list-panes`` :class:`Window.split_window()` ``$ tmux split-window`` :class:`Pane.send_keys()` ``$ tmux send-keys`` ======================================== ================================= From f2af12928bdf6acdf33a534553e0b1a9c4bc223e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 18:28:52 +0800 Subject: [PATCH 0092/3283] moar --- doc/cli.rst | 11 +++++++---- doc/index.rst | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/cli.rst b/doc/cli.rst index 4e3d49cec53..1771c53f4df 100644 --- a/doc/cli.rst +++ b/doc/cli.rst @@ -13,8 +13,11 @@ Freeze sessions $ tmuxp freeze -Import from teamocil -"""""""""""""""""""" +Import +"""""" + +From teamocil +''''''''''''' .. _import_teamocil: @@ -24,8 +27,8 @@ Import from teamocil .. _import_tmuxinator: -Import from tmuxinator -"""""""""""""""""""""" +From tmuxinator +''''''''''''''' .. code-block:: bash diff --git a/doc/index.rst b/doc/index.rst index aa1b35be812..764710f92e3 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -24,7 +24,7 @@ Ready to begin? See the `Quickstart`_. .. _python objects: http://tmuxp.readthedocs.org/en/latest/api.html#api .. _simple: http://tmuxp.readthedocs.org/en/latest/examples.html#short-hand-inline .. _very elaborate: http://tmuxp.readthedocs.org/en/latest/examples.html#super-advanced-dev-environment -.. _bash, zsh, and tcsh: http://tmuxp.readthedocs.org/en/latest/cli.html#bash-completion +.. _bash, zsh and tcsh: http://tmuxp.readthedocs.org/en/latest/cli.html#bash-completion .. _much, much more: http://tmuxp.readthedocs.org/en/latest/about.html#minor-tweaks Jump right in: See `Examples`_, `Quickstart`_ and `bash completion`_ From af3c7450a25364782780e32b956cf9476739c023 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 18:35:14 +0800 Subject: [PATCH 0093/3283] more --- doc/developing.rst | 73 +++++----------------------------------------- doc/orm_al.rst | 48 ++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 66 deletions(-) diff --git a/doc/developing.rst b/doc/developing.rst index 631fdf5c971..86d9227541d 100644 --- a/doc/developing.rst +++ b/doc/developing.rst @@ -73,7 +73,7 @@ If you found a problem or are trying to write a test, you can file an .. _test_specific_tests: -Choose tests to run +Test runner options """"""""""""""""""" .. note:: @@ -128,9 +128,10 @@ Multiple can be separated by spaces: .. _test_builder_visually: Visual testing -"""""""""""""" +'''''''''''''' -You can watch tmux testsuite build sessions visually also. +You can watch tmux testsuite build sessions visually by keeping a client +open in a separate terminal. Create two terminals: @@ -147,7 +148,7 @@ Terminal 1 should have flickered and built the session before your eyes. tmuxp hides this building from normal users. :) Verbosity and logging -""""""""""""""""""""" +''''''''''''''''''''' ``./run_tests.py`` supports two options, these are *optional* flags that may be added to for :ref:`test_specific_tests` and @@ -174,8 +175,8 @@ may be added to for :ref:`test_specific_tests` and $ ./run_tests.py --verbosity 0 -Watch files and test --------------------- +Run tests on save +----------------- You can re-run tests automatically on file edit. @@ -239,66 +240,6 @@ is tested against 1.8 and latest in addition to python 2.7. The .. literalinclude:: ../.travis.yml :language: yaml -Internals ---------- - -Similarities to Tmux and Pythonics ----------------------------------- - -tmuxp is was built in the spirit of understanding how tmux operates -and how python objects and tools can abstract the API's in a pleasant way. - -tmuxp uses the identify ``FORMATTERS`` used by tmux, you can see -them inside of http://sourceforge.net/p/tmux/tmux-code/ci/master/tree/format.c. - -In this, I will also begin documenting the API. - -the use of: - -Session -:meth:`Session.new_window()` - returns a new Window object bound to the session, -also uses ``tmux new-window``. -:meth:`Session.new_session()` - class method - returns a new Session object. - -Differences from tmux ---------------------- - -Because this is a python abstraction and flags like ``start-directory`` -have dashes (-) replaced with underscores (_). - -interesting observations ------------------------- - -How is tmuxp able to keep references to panes, windows and sessions? - - Tmux has unique ID's for sessions, windows and panes. - - panes use ``%``, such as ``%1234`` - - windows use ``@``, such as ``@2345`` - - sessions use ``$``, for money, such as ``$`` - -How is tmuxp able to handle windows with no names? - - Tmux provides ``window_id`` as a unique identifier. - -What is a {pane,window}_index vs a {pane,window,session}_id? - - Pane index refers to the order of a pane on the screen. - - Window index refers to the # of the pane in the session. - -To assert pane, window and session data, tmuxp will use -:meth:`tmuxp.Server.list_sessions`, :meth:`tmuxp.Session.list_windows`, -:meth:`tmuxp.Window.list_panes` to update objects. - -Reference ---------- - -- tmux docs http://www.openbsd.org/cgi-bin/man.cgi?query=tmux&sektion=1 -- tmux source code http://sourceforge.net/p/tmux/tmux-code/ci/master/tree/ - .. _travis-ci: http://www.travis-ci.org .. _travis build site: http://www.travis-ci.org/tony/tmuxp .. _.travis.yml: https://github.com/tony/tmuxp/blob/master/.travis.yml diff --git a/doc/orm_al.rst b/doc/orm_al.rst index 926b164b5bf..c9f2ec39b0a 100644 --- a/doc/orm_al.rst +++ b/doc/orm_al.rst @@ -41,5 +41,53 @@ Object Prefix Example :class:`Pane` ``%`` ``%5433`` ======================== ======================= ========================= +Similarities to Tmux and Pythonics +---------------------------------- + +tmuxp is was built in the spirit of understanding how tmux operates +and how python objects and tools can abstract the API's in a pleasant way. + +tmuxp uses ``FORMATTERS`` in tmux to give identity attributes to +:class:`Session`, :class:`Window` and :class:`Pane` objects. See +`formatters.c`_. + +.. _formatters.c: http://sourceforge.net/p/tmux/tmux-code/ci/master/tree/format.c + +How is tmuxp able to keep references to panes, windows and sessions? + + Tmux has unique ID's for sessions, windows and panes. + + panes use ``%``, such as ``%1234`` + + windows use ``@``, such as ``@2345`` + + sessions use ``$``, for money, such as ``$`` + +How is tmuxp able to handle windows with no names? + + Tmux provides ``window_id`` as a unique identifier. + +What is a {pane,window}_index vs a {pane,window,session}_id? + + Pane index refers to the order of a pane on the screen. + + Window index refers to the # of the pane in the session. + +To assert pane, window and session data, tmuxp will use +:meth:`Server.list_sessions()`, :meth:`Session.list_windows()`, +:meth:`Window.list_panes()` to update objects. + +Idiosyncrasies +-------------- + +Because this is a python abstraction and commands like ``new-window`` +have dashes (-) replaced with underscores (_). + +Reference +--------- + +- tmux docs http://www.openbsd.org/cgi-bin/man.cgi?query=tmux&sektion=1 +- tmux source code http://sourceforge.net/p/tmux/tmux-code/ci/master/tree/ + .. _abstraction layer: http://en.wikipedia.org/wiki/Abstraction_layer .. _ORM: http://en.wikipedia.org/wiki/Object-relational_mapping From 9723c392ccf83347dfbd11a1b10e211cafde9005 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 18:40:18 +0800 Subject: [PATCH 0094/3283] rst --- doc/cli.rst | 12 ++++++++++++ doc/index.rst | 10 ++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/doc/cli.rst b/doc/cli.rst index 1771c53f4df..2db331bcd9a 100644 --- a/doc/cli.rst +++ b/doc/cli.rst @@ -13,6 +13,8 @@ Freeze sessions $ tmuxp freeze +Tmuxp will offer to convert file to ``.json`` or ``.yaml``. + Import """""" @@ -34,8 +36,18 @@ From tmuxinator $ tmuxp import tmuxinator +.. _convert_config: + +Convert between YAML and JSON +""""""""""""""""""""""""""""" + .. _bash_completion: + $ tmuxp convert + +tmuxp automatically will prompt to convert ``.yaml`` to ``.json`` and +``.json`` to ``.yaml``. + Bash completion """"""""""""""" diff --git a/doc/index.rst b/doc/index.rst index 764710f92e3..1b036fece76 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -16,20 +16,22 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through - `bash, zsh and tcsh`_ completion. - Unit tested against against live tmux (1.8 and git). See `travis.yml`_ file and `testing`_ page. -- Documented Examples, Internals. +- Documented `Examples`_, Internals. - and `much, much more`_ Ready to begin? See the `Quickstart`_. +.. _Examples: http://tmuxp.readthedocs.org/en/latest/examples.html +.. _freezing live sessions: http://tmuxp.readthedocs.org/en/latest/cli.html#freeze-sessions +.. _importing: http://tmuxp.readthedocs.org/en/latest/cli.html#import +.. _travis.yaml: http://tmuxp.readthedocs.org/en/latest/developing.html#travis-ci +.. _testing: http://tmuxp.readthedocs.org/en/latest/developing.html#test-runner .. _python objects: http://tmuxp.readthedocs.org/en/latest/api.html#api .. _simple: http://tmuxp.readthedocs.org/en/latest/examples.html#short-hand-inline .. _very elaborate: http://tmuxp.readthedocs.org/en/latest/examples.html#super-advanced-dev-environment .. _bash, zsh and tcsh: http://tmuxp.readthedocs.org/en/latest/cli.html#bash-completion .. _much, much more: http://tmuxp.readthedocs.org/en/latest/about.html#minor-tweaks -Jump right in: See `Examples`_, `Quickstart`_ and `bash completion`_ -support. - Explore: .. toctree:: From c6b297c9a510a88544471cf77da5db86a090b576 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 18:45:36 +0800 Subject: [PATCH 0095/3283] README, docs --- README.rst | 129 ++++++++++---------------------------------------- doc/index.rst | 17 ++----- 2 files changed, 30 insertions(+), 116 deletions(-) diff --git a/README.rst b/README.rst index 8388dbc7704..46109d586f6 100644 --- a/README.rst +++ b/README.rst @@ -11,26 +11,34 @@ :width: 65% :align: center -Open to testers ---------------- +tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through +`python objects`_. -tmuxp is still **alpha** code and needs a few more weeks until stable. -See the `Issues tracker`_ to see known issues and for any other concerns. +- Basic support for `freezing live sessions`_ +- `importing`_ from `teamocil`_ and `tmuxinator`_. +- JSON or YAML for `simple`_ or `very elaborate`_ configurations. +- `bash, zsh and tcsh`_ completion. +- Unit tested against against live tmux (1.8 and git). See `travis.yml`_ + file and `testing`_ page. +- Documented `Examples`_, Internals. +- and `much, much more`_ -Install -""""""" +Ready to begin? See the `Quickstart`_. -- install ``tmux``, at least version **1.8** -- libyaml is installed for your distribution. - -Install ``tmuxp``: - -.. code-block:: bash - - $ pip install tmuxp - - -See: `Quickstart`_ +.. _tmux(1): http://tmux.sourceforge.net/ +.. _tmuxinator: https://github.com/aziz/tmuxinator +.. _teamocil: https://github.com/remiprev/teamocil +.. _Examples: http://tmuxp.readthedocs.org/en/latest/examples.html +.. _freezing live sessions: http://tmuxp.readthedocs.org/en/latest/cli.html#freeze-sessions +.. _importing: http://tmuxp.readthedocs.org/en/latest/cli.html#import +.. _travis.yml: http://tmuxp.readthedocs.org/en/latest/developing.html#travis-ci +.. _testing: http://tmuxp.readthedocs.org/en/latest/developing.html#test-runner +.. _python objects: http://tmuxp.readthedocs.org/en/latest/api.html#api +.. _simple: http://tmuxp.readthedocs.org/en/latest/examples.html#short-hand-inline +.. _very elaborate: http://tmuxp.readthedocs.org/en/latest/examples.html#super-advanced-dev-environment +.. _bash, zsh and tcsh: http://tmuxp.readthedocs.org/en/latest/cli.html#bash-completion +.. _much, much more: http://tmuxp.readthedocs.org/en/latest/about.html#minor-tweaks +.. _Quickstart: http://tmuxp.readthedocs.org/en/latest/quickstart.html CLI Commands """""""""""" @@ -50,93 +58,6 @@ CLI Commands Import a `teamocil`_ or `tmuxinator`_ config. ========================== =============================================== -Bash completion -""""""""""""""" - -For bash, ``.bashrc``: - -.. code-block:: bash - - $ source tmuxp.bash - -For tcsh, ``.tcshrc``: - -.. code-block:: bash - - $ complete tmuxp 'p/*/`tmuxp.tcsh`/' - -For zsh, ``.zshrc``: - -.. code-block:: bash - - $ source tmuxp.zsh - -See `installing bash completion`_ to get bash, zsh and tcsh completion -working on your machine. - -Mini Quickstart -""""""""""""""" - -See the full `Quickstart`_ in the documentation. - -Load from ``~/.tmuxp.yaml`` or ``~/.tmuxp.json`` in current directory. - -.. code-block:: bash - - $ tmuxp load . - -Load ``myconfig.yaml`` from ``~/.tmuxp`` - -.. code-block:: bash - - $ tmuxp load myconfig.yaml - -Load a relative or full config file (bash complete supports this too) - -.. code-block:: bash - - $ tmuxp load ./myconfig.yaml - $ tmuxp load ../myconfig.yaml - $ tmuxp load /var/www/mywebproject/myconfig.yaml - -``$ mkdir ~/.tmuxp`` and make a file ``~/.tmuxp/test.yaml``. - -.. code-block:: yaml - - session_name: 2-pane-vertical - windows: - - window_name: my test window - panes: - - pwd - - pwd - -.. code-block:: bash - - $ tmuxp load test.yaml - -or ``~/.tmuxp/test.json``: - -.. code-block:: json - - { - "windows": [ - { - "panes": [ - "pwd", - "pwd" - ], - "window_name": "my test window" - } - ], - "session_name": "2-pane-vertical" - } - -.. code-block:: bash - - $ tmuxp load test.json - -See: `Examples`_ - ============== ========================================================== tmux support 1.8, 1.9-dev config support yaml, json, python dict diff --git a/doc/index.rst b/doc/index.rst index 1b036fece76..d59ed55d1a6 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -21,16 +21,20 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through Ready to begin? See the `Quickstart`_. +.. _tmux(1): http://tmux.sourceforge.net/ +.. _tmuxinator: https://github.com/aziz/tmuxinator +.. _teamocil: https://github.com/remiprev/teamocil .. _Examples: http://tmuxp.readthedocs.org/en/latest/examples.html .. _freezing live sessions: http://tmuxp.readthedocs.org/en/latest/cli.html#freeze-sessions .. _importing: http://tmuxp.readthedocs.org/en/latest/cli.html#import -.. _travis.yaml: http://tmuxp.readthedocs.org/en/latest/developing.html#travis-ci +.. _travis.yml: http://tmuxp.readthedocs.org/en/latest/developing.html#travis-ci .. _testing: http://tmuxp.readthedocs.org/en/latest/developing.html#test-runner .. _python objects: http://tmuxp.readthedocs.org/en/latest/api.html#api .. _simple: http://tmuxp.readthedocs.org/en/latest/examples.html#short-hand-inline .. _very elaborate: http://tmuxp.readthedocs.org/en/latest/examples.html#super-advanced-dev-environment .. _bash, zsh and tcsh: http://tmuxp.readthedocs.org/en/latest/cli.html#bash-completion .. _much, much more: http://tmuxp.readthedocs.org/en/latest/about.html#minor-tweaks +.. _Quickstart: http://tmuxp.readthedocs.org/en/latest/quickstart.html Explore: @@ -54,14 +58,3 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` - -.. _tmuxinator: https://github.com/aziz/tmuxinator -.. _teamocil: https://github.com/remiprev/teamocil -.. _abstraction layer: http://en.wikipedia.org/wiki/Abstraction_layer -.. _ORM: http://en.wikipedia.org/wiki/Object-relational_mapping -.. _Examples: http://tmuxp.readthedocs.org/en/latest/examples.html -.. _Quickstart: http://tmuxp.readthedocs.org/en/latest/quickstart.html -.. _bash completion: http://tmuxp.readthedocs.org/en/latest/quickstart.html#bash-completion -.. _tmux(1): http://tmux.sourceforge.net/ -.. _Issues tracker: https://github.com/tony/tmuxp/issues -.. _python dict: http://docs.python.org/2/library/stdtypes.html#dict From 5f531605b254eb3a0c7fbfbc9ea73e81baf5d7ec Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 18:52:38 +0800 Subject: [PATCH 0096/3283] rename orm_al to internals, add links --- README.rst | 10 ++++++---- doc/about.rst | 2 +- doc/index.rst | 12 +++++++----- doc/{orm_al.rst => internals.rst} | 8 ++++---- 4 files changed, 18 insertions(+), 14 deletions(-) rename doc/{orm_al.rst => internals.rst} (97%) diff --git a/README.rst b/README.rst index 46109d586f6..799968dc85b 100644 --- a/README.rst +++ b/README.rst @@ -14,17 +14,18 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through `python objects`_. -- Basic support for `freezing live sessions`_ +- Basic support for `freezing live sessions`_. - `importing`_ from `teamocil`_ and `tmuxinator`_. - JSON or YAML for `simple`_ or `very elaborate`_ configurations. - `bash, zsh and tcsh`_ completion. - Unit tested against against live tmux (1.8 and git). See `travis.yml`_ - file and `testing`_ page. -- Documented `Examples`_, Internals. + file, `tmuxp on Travis CI`_ and `testing`_ page. +- `Documentation`_, `Examples`_, `Internals`_. - and `much, much more`_ Ready to begin? See the `Quickstart`_. - +.. _tmuxp on Travis CI`: http://travis-ci.org/tony/tmuxp +.. _Documentation: http://tmuxp.rtfd.org/ .. _tmux(1): http://tmux.sourceforge.net/ .. _tmuxinator: https://github.com/aziz/tmuxinator .. _teamocil: https://github.com/remiprev/teamocil @@ -39,6 +40,7 @@ Ready to begin? See the `Quickstart`_. .. _bash, zsh and tcsh: http://tmuxp.readthedocs.org/en/latest/cli.html#bash-completion .. _much, much more: http://tmuxp.readthedocs.org/en/latest/about.html#minor-tweaks .. _Quickstart: http://tmuxp.readthedocs.org/en/latest/quickstart.html +.. _Internals: http://tmuxp.readthedocs.org/en/latest/internals.html CLI Commands """""""""""" diff --git a/doc/about.rst b/doc/about.rst index 7e100bbed63..23bf7438db2 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -56,7 +56,7 @@ Differences **Internals** teamocil and tmuxinator pipe configurations into commands. tmuxp turns configuration into a live :class:`Session` object -with access to all window and pane data. See :ref:`ORM_AL`. +with access to all window and pane data. See :ref:`internals`. **CLI** tmuxp's CLI can attach and kill sessions. diff --git a/doc/index.rst b/doc/index.rst index d59ed55d1a6..87550dcd2e7 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -10,17 +10,18 @@ tmuxp tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through `python objects`_. -- Basic support for `freezing live sessions`_ +- Basic support for `freezing live sessions`_. - `importing`_ from `teamocil`_ and `tmuxinator`_. - JSON or YAML for `simple`_ or `very elaborate`_ configurations. - `bash, zsh and tcsh`_ completion. - Unit tested against against live tmux (1.8 and git). See `travis.yml`_ - file and `testing`_ page. -- Documented `Examples`_, Internals. + file, `tmuxp on Travis CI`_ and `testing`_ page. +- `Documentation`_, `Examples`_, Internals. - and `much, much more`_ Ready to begin? See the `Quickstart`_. - +.. _tmuxp on Travis CI`: http://travis-ci.org/tony/tmuxp +.. _Documentation: http://tmuxp.rtfd.org/ .. _tmux(1): http://tmux.sourceforge.net/ .. _tmuxinator: https://github.com/aziz/tmuxinator .. _teamocil: https://github.com/remiprev/teamocil @@ -35,6 +36,7 @@ Ready to begin? See the `Quickstart`_. .. _bash, zsh and tcsh: http://tmuxp.readthedocs.org/en/latest/cli.html#bash-completion .. _much, much more: http://tmuxp.readthedocs.org/en/latest/about.html#minor-tweaks .. _Quickstart: http://tmuxp.readthedocs.org/en/latest/quickstart.html +.. _Internals: http://tmuxp.readthedocs.org/en/latest/internals.html Explore: @@ -45,7 +47,7 @@ Explore: cli quickstart examples - orm_al + internals developing api changes diff --git a/doc/orm_al.rst b/doc/internals.rst similarity index 97% rename from doc/orm_al.rst rename to doc/internals.rst index c9f2ec39b0a..2fa6631e0b5 100644 --- a/doc/orm_al.rst +++ b/doc/internals.rst @@ -1,8 +1,8 @@ -.. _orm_al: +.. _Internals: -========================= -ORM and Abstraction Layer -========================= +========= +Internals +========= .. module:: tmuxp From 6279eb8a01e3f1c4c54861b35863c9e2f503c6de Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 18:54:57 +0800 Subject: [PATCH 0097/3283] power --- README.rst | 37 ++++++++++++++++++------------------- doc/index.rst | 1 + 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/README.rst b/README.rst index 799968dc85b..4cd67696cae 100644 --- a/README.rst +++ b/README.rst @@ -24,23 +24,6 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through - and `much, much more`_ Ready to begin? See the `Quickstart`_. -.. _tmuxp on Travis CI`: http://travis-ci.org/tony/tmuxp -.. _Documentation: http://tmuxp.rtfd.org/ -.. _tmux(1): http://tmux.sourceforge.net/ -.. _tmuxinator: https://github.com/aziz/tmuxinator -.. _teamocil: https://github.com/remiprev/teamocil -.. _Examples: http://tmuxp.readthedocs.org/en/latest/examples.html -.. _freezing live sessions: http://tmuxp.readthedocs.org/en/latest/cli.html#freeze-sessions -.. _importing: http://tmuxp.readthedocs.org/en/latest/cli.html#import -.. _travis.yml: http://tmuxp.readthedocs.org/en/latest/developing.html#travis-ci -.. _testing: http://tmuxp.readthedocs.org/en/latest/developing.html#test-runner -.. _python objects: http://tmuxp.readthedocs.org/en/latest/api.html#api -.. _simple: http://tmuxp.readthedocs.org/en/latest/examples.html#short-hand-inline -.. _very elaborate: http://tmuxp.readthedocs.org/en/latest/examples.html#super-advanced-dev-environment -.. _bash, zsh and tcsh: http://tmuxp.readthedocs.org/en/latest/cli.html#bash-completion -.. _much, much more: http://tmuxp.readthedocs.org/en/latest/about.html#minor-tweaks -.. _Quickstart: http://tmuxp.readthedocs.org/en/latest/quickstart.html -.. _Internals: http://tmuxp.readthedocs.org/en/latest/internals.html CLI Commands """""""""""" @@ -89,6 +72,24 @@ tests .. code-block:: bash $ python ./run_tests.py ============== ========================================================== +.. _tmuxp on Travis CI`: http://travis-ci.org/tony/tmuxp +.. _Documentation: http://tmuxp.rtfd.org/ +.. _tmux(1): http://tmux.sourceforge.net/ +.. _tmuxinator: https://github.com/aziz/tmuxinator +.. _teamocil: https://github.com/remiprev/teamocil +.. _Examples: http://tmuxp.readthedocs.org/en/latest/examples.html +.. _freezing live sessions: http://tmuxp.readthedocs.org/en/latest/cli.html#freeze-sessions +.. _importing: http://tmuxp.readthedocs.org/en/latest/cli.html#import +.. _travis.yml: http://tmuxp.readthedocs.org/en/latest/developing.html#travis-ci +.. _testing: http://tmuxp.readthedocs.org/en/latest/developing.html#test-runner +.. _python objects: http://tmuxp.readthedocs.org/en/latest/api.html#api +.. _simple: http://tmuxp.readthedocs.org/en/latest/examples.html#short-hand-inline +.. _very elaborate: http://tmuxp.readthedocs.org/en/latest/examples.html#super-advanced-dev-environment +.. _bash, zsh and tcsh: http://tmuxp.readthedocs.org/en/latest/cli.html#bash-completion +.. _much, much more: http://tmuxp.readthedocs.org/en/latest/about.html#minor-tweaks +.. _Quickstart: http://tmuxp.readthedocs.org/en/latest/quickstart.html +.. _Internals: http://tmuxp.readthedocs.org/en/latest/internals.html + .. _BSD: http://opensource.org/licenses/BSD-3-Clause .. _developing and testing: http://tmuxp.readthedocs.org/en/latest/developing.html .. _Examples: http://tmuxp.readthedocs.org/en/latest/examples.html @@ -98,7 +99,5 @@ tests .. code-block:: bash .. _tmuxinator: https://github.com/aziz/tmuxinator .. _teamocil: https://github.com/remiprev/teamocil .. _abstraction layer: http://en.wikipedia.org/wiki/Abstraction_layer -.. _ORM: http://tmuxp.readthedocs.org/en/latest/quickstart.html#tmux-orm .. _tmux(1): http://tmux.sourceforge.net/ .. _Issues tracker: https://github.com/tony/tmuxp/issues -.. _python dict: http://docs.python.org/2/library/stdtypes.html#dict diff --git a/doc/index.rst b/doc/index.rst index 87550dcd2e7..e0bf2c52a45 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -20,6 +20,7 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through - and `much, much more`_ Ready to begin? See the `Quickstart`_. + .. _tmuxp on Travis CI`: http://travis-ci.org/tony/tmuxp .. _Documentation: http://tmuxp.rtfd.org/ .. _tmux(1): http://tmux.sourceforge.net/ From b797d4f3baf41b5497d5bdfae7c9daab83b86ec3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 18:56:13 +0800 Subject: [PATCH 0098/3283] make image smaller --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 4cd67696cae..4af3dea10c8 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ .. figure:: https://raw.github.com/tony/tmuxp/master/doc/_static/tmuxp-dev-screenshot.png :scale: 100% - :width: 65% + :width: 50% :align: center tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through From c54c0243538b733e2cf2be8aa17dc73c4b06c83b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 19:00:19 +0800 Subject: [PATCH 0099/3283] fix some bugs README --- README.rst | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 4af3dea10c8..f1e2b199d9e 100644 --- a/README.rst +++ b/README.rst @@ -72,7 +72,7 @@ tests .. code-block:: bash $ python ./run_tests.py ============== ========================================================== -.. _tmuxp on Travis CI`: http://travis-ci.org/tony/tmuxp +.. _tmuxp on Travis CI: http://travis-ci.org/tony/tmuxp .. _Documentation: http://tmuxp.rtfd.org/ .. _tmux(1): http://tmux.sourceforge.net/ .. _tmuxinator: https://github.com/aziz/tmuxinator @@ -92,12 +92,6 @@ tests .. code-block:: bash .. _BSD: http://opensource.org/licenses/BSD-3-Clause .. _developing and testing: http://tmuxp.readthedocs.org/en/latest/developing.html -.. _Examples: http://tmuxp.readthedocs.org/en/latest/examples.html -.. _Quickstart: http://tmuxp.readthedocs.org/en/latest/quickstart.html .. _installing bash completion: http://tmuxp.readthedocs.org/en/latest/quickstart.html#bash-completion .. _Developing and Testing: http://tmuxp.readthedocs.org/en/latest/developing.html -.. _tmuxinator: https://github.com/aziz/tmuxinator -.. _teamocil: https://github.com/remiprev/teamocil -.. _abstraction layer: http://en.wikipedia.org/wiki/Abstraction_layer -.. _tmux(1): http://tmux.sourceforge.net/ .. _Issues tracker: https://github.com/tony/tmuxp/issues From 04be7781336ed94676d9f142dbd7e8b074916239 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 19:01:54 +0800 Subject: [PATCH 0100/3283] Trying floating readme img right --- README.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index f1e2b199d9e..d8644b347eb 100644 --- a/README.rst +++ b/README.rst @@ -6,10 +6,10 @@ .. image:: https://badge.fury.io/py/tmuxp.png :target: http://badge.fury.io/py/tmuxp -.. figure:: https://raw.github.com/tony/tmuxp/master/doc/_static/tmuxp-dev-screenshot.png +.. image:: https://raw.github.com/tony/tmuxp/master/doc/_static/tmuxp-dev-screenshot.png :scale: 100% - :width: 50% - :align: center + :width: 35% + :align: right tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through `python objects`_. From 435d3f90186d38ec3605f2900ffebd84a4cdc9d5 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 19:05:03 +0800 Subject: [PATCH 0101/3283] try float --- README.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index d8644b347eb..23fd5ed141f 100644 --- a/README.rst +++ b/README.rst @@ -6,10 +6,14 @@ .. image:: https://badge.fury.io/py/tmuxp.png :target: http://badge.fury.io/py/tmuxp +
+ .. image:: https://raw.github.com/tony/tmuxp/master/doc/_static/tmuxp-dev-screenshot.png :scale: 100% :width: 35% - :align: right + :align: center + +
tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through `python objects`_. From e30dcc674e82561ff993d14ba36aa4a1b1573fee Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 19:06:14 +0800 Subject: [PATCH 0102/3283] bring picture back to README --- README.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 23fd5ed141f..a924cd2ed03 100644 --- a/README.rst +++ b/README.rst @@ -6,15 +6,11 @@ .. image:: https://badge.fury.io/py/tmuxp.png :target: http://badge.fury.io/py/tmuxp -
- .. image:: https://raw.github.com/tony/tmuxp/master/doc/_static/tmuxp-dev-screenshot.png :scale: 100% - :width: 35% + :width: 45% :align: center -
- tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through `python objects`_. From f762b478218d4c1c2c421d320f98fb40a8be6fa2 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 19:08:22 +0800 Subject: [PATCH 0103/3283] doc updates, v0.0.30a --- CHANGES | 1 + tmuxp/__init__.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index fa37e3be578..b1126d30f20 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,7 @@ Here you can find the recent changes to tmuxp. - [docs] [examples]: Example for ``start_directory``. - [internal] fix bug where first and second window would load in mixed order - [internal] :class:`Window.move_window()` for moving window. +- [docs] major doc overhaul. front page, renamed orm_al.rst to internals.rst. 2013-10-30 ---------- diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index e3a93b35ae9..1096824160e 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -22,4 +22,4 @@ import logging -__version__ = '0.0.30' +__version__ = '0.0.30a' From 255242cfb70d2338e4f874953d73e30d8c01ed1f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 31 Oct 2013 19:14:48 +0800 Subject: [PATCH 0104/3283] fix doc/cli --- doc/cli.rst | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/doc/cli.rst b/doc/cli.rst index 2db331bcd9a..f6f6f9ada4a 100644 --- a/doc/cli.rst +++ b/doc/cli.rst @@ -11,18 +11,37 @@ Freeze sessions .. code-block:: bash - $ tmuxp freeze + $ tmuxp freeze Tmuxp will offer to convert file to ``.json`` or ``.yaml``. +Load session +"""""""""""" + +Keep your configs in ``$HOME/.tmuxp`` for easy access and detection by +:ref:`bash_completion`. + +Files also may be loaded by absolute path. + +.. code-block:: bash + + $ tmuxp load + +Files named ``.tmuxp.yaml`` or ``.tmuxp.json`` in the current working +directory may be loaded with: + +.. code-block:: bash + + $ tmuxp load . + Import """""" +.. _import_teamocil: + From teamocil ''''''''''''' -.. _import_teamocil: - .. code-block:: bash $ tmuxp import teamocil @@ -41,13 +60,15 @@ From tmuxinator Convert between YAML and JSON """"""""""""""""""""""""""""" -.. _bash_completion: +.. code-block:: bash $ tmuxp convert tmuxp automatically will prompt to convert ``.yaml`` to ``.json`` and ``.json`` to ``.yaml``. +.. _bash_completion: + Bash completion """"""""""""""" From bba04abf33ee9e9b419afbf37843d4b309dbb954 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 03:37:06 +0800 Subject: [PATCH 0105/3283] fix doc link --- doc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index e0bf2c52a45..1fdd3d7f5dd 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -21,7 +21,7 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through Ready to begin? See the `Quickstart`_. -.. _tmuxp on Travis CI`: http://travis-ci.org/tony/tmuxp +.. _tmuxp on Travis CI: http://travis-ci.org/tony/tmuxp .. _Documentation: http://tmuxp.rtfd.org/ .. _tmux(1): http://tmux.sourceforge.net/ .. _tmuxinator: https://github.com/aziz/tmuxinator From 50a2f18abda7efcdcbc67d7f134eae005cd13428 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 03:38:36 +0800 Subject: [PATCH 0106/3283] Add another tweak docs --- doc/about.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/about.rst b/doc/about.rst index 23bf7438db2..45580b5859d 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -86,7 +86,9 @@ Minor tweaks - Load + switch to new session from inside tmux. - Resume session if config loaded. - Pre-commands virtualenv / rvm / any other commands. -- Load config from anywhere `$ tmuxp load /full/file/path.json`. +- Load config from anywhere ``$ tmuxp load /full/file/path.json``. +- Load config ``.tmuxp.yaml`` or ``.tmuxp.json`` from current working + directory with ``$ tmuxp load .``. .. _attempt at 1.7 test: https://travis-ci.org/tony/tmuxp/jobs/12348263 .. _kaptan: https://github.com/emre/kaptan From 2ea03a6ae1be1395970c975d22050c7f7186c5bb Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 05:19:40 +0800 Subject: [PATCH 0107/3283] README punctuation --- README.rst | 2 +- doc/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index a924cd2ed03..936a49f3c57 100644 --- a/README.rst +++ b/README.rst @@ -21,7 +21,7 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through - Unit tested against against live tmux (1.8 and git). See `travis.yml`_ file, `tmuxp on Travis CI`_ and `testing`_ page. - `Documentation`_, `Examples`_, `Internals`_. -- and `much, much more`_ +- and `much, much more`_. Ready to begin? See the `Quickstart`_. diff --git a/doc/index.rst b/doc/index.rst index 1fdd3d7f5dd..205f04facb3 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -17,7 +17,7 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through - Unit tested against against live tmux (1.8 and git). See `travis.yml`_ file, `tmuxp on Travis CI`_ and `testing`_ page. - `Documentation`_, `Examples`_, Internals. -- and `much, much more`_ +- and `much, much more`_. Ready to begin? See the `Quickstart`_. From 5dab47ac231045b55215e7aa9189f99bd5d28b19 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 05:19:56 +0800 Subject: [PATCH 0108/3283] tests for Server object config_file, socket_path, socket_name --- tmuxp/testsuite/test_server.py | 41 ++++++++++++++-------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/tmuxp/testsuite/test_server.py b/tmuxp/testsuite/test_server.py index 8ed813b4e68..1b302e772b0 100644 --- a/tmuxp/testsuite/test_server.py +++ b/tmuxp/testsuite/test_server.py @@ -3,7 +3,7 @@ import unittest from random import randint -from .. import Session, Window, Pane +from .. import Server from ..util import tmux from .helpers import TmuxTestCase, TEST_SESSION_PREFIX from . import t @@ -14,42 +14,35 @@ logger = logging.getLogger(__name__) -# class NewServerTest(unittest.TestCase): -class NewServerTest(TmuxTestCase): - - def test_hi(self): - self.assertEqual(2, 2) - sessions = t._sessions - - class ServerTest(TmuxTestCase): def test_has_session(self): self.assertTrue(t.has_session(self.TEST_SESSION_NAME)) self.assertFalse(t.has_session('asdf2314324321')) - logging.debug('wat') - - def test_has_clients(self): - pass - - def test_has_sessions(self): - pass - def test_socket(self): - ''' tmux allows the following configuration options for the server + def test_socket_name(self): + """ ``-L`` socket_name. ``-L`` socket_name file name of socket. which will be stored in env TMUX_TMPDIR or /tmp if unset.) - ``-S`` socket_path (alternative path for server socket) + """ + myserver = Server(socket_name='test') - ''' - pass + self.assertEqual(myserver.socket_name, 'test') + + def test_socket_path(self): + """ ``-S`` socket_path (alternative path for server socket). """ + + myserver = Server(socket_path='test') + + self.assertEqual(myserver.socket_path, 'test') def test_config(self): - ''' test whether passing a ``file`` into Server will alter the tmux - options for server, session and windows ''' - pass + """ ``-f`` file for tmux(1) configuration. """ + + myserver = Server(config_file='test') + self.assertEqual(myserver.config_file, 'test') if __name__ == '__main__': unittest.main() From 2ff7cbd51f543aaca3b87d8eb1a0bd20637fa13d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 05:37:28 +0800 Subject: [PATCH 0109/3283] More tests for Server --- tmuxp/server.py | 27 +++++++++++++++++++++------ tmuxp/testsuite/test_server.py | 7 +++++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/tmuxp/server.py b/tmuxp/server.py index c71f12675ab..c5fbb47ca38 100644 --- a/tmuxp/server.py +++ b/tmuxp/server.py @@ -39,10 +39,17 @@ class Server(TmuxRelationalObject): socket_name = None socket_path = None config_file = None + colors = None childIdAttribute = 'session_id' - def __init__(self, socket_name=None, socket_path=None, config_file=None, - **kwargs): + def __init__( + self, + socket_name=None, + socket_path=None, + config_file=None, + colors=None, + **kwargs + ): self._windows = [] self._panes = [] @@ -55,6 +62,9 @@ def __init__(self, socket_name=None, socket_path=None, config_file=None, if config_file: self.config_file = config_file + if colors: + self.colors = colors + def tmux(self, *args, **kwargs): args = list(args) if self.socket_name: @@ -63,6 +73,13 @@ def tmux(self, *args, **kwargs): args.insert(0, '-S{}'.format(self.socket_path)) if self.config_file: args.insert(0, '-f{}'.format(self.config_file)) + if self.colors: + if self.colors == 256: + args.insert(0, '-2') + elif self.colors == 88: + args.insert(0, '-8') + else: + raise ValueError('Server.colors must equal 88 or 256') return tmux(*args, **kwargs) @@ -437,14 +454,14 @@ def new_session(self, :type kill_session: bool ''' - # ToDo: Update below to work with attach_if_exists if self.has_session(session_name): if kill_session: self.tmux('kill-session', '-t%s' % session_name) logger.info('session %s exists. killed it.' % session_name) else: raise TmuxSessionExists( - 'Session named %s exists' % session_name) + 'Session named %s exists' % session_name + ) logger.debug('creating session %s' % session_name) @@ -485,6 +502,4 @@ def new_session(self, session = Session(server=self, **session) - # self._sessions.append(session) - return session diff --git a/tmuxp/testsuite/test_server.py b/tmuxp/testsuite/test_server.py index 1b302e772b0..9940090ba20 100644 --- a/tmuxp/testsuite/test_server.py +++ b/tmuxp/testsuite/test_server.py @@ -44,5 +44,12 @@ def test_config(self): myserver = Server(config_file='test') self.assertEqual(myserver.config_file, 'test') + def test_256_colors(self): + myserver = Server(colors=256) + self.assertEqual(myserver.colors, 256) + + # try to read the command in util.tmux() + # get util.tmux to have a self.cmd and create tests for it + if __name__ == '__main__': unittest.main() From 95be9163cbc4c7cfe7d3f63a15c8f3d02d313864 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 05:39:10 +0800 Subject: [PATCH 0110/3283] CHANGES --- CHANGES | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES b/CHANGES index b1126d30f20..b3f51fee03d 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,14 @@ tmuxp Changelog Here you can find the recent changes to tmuxp. +2013-11-01 +---------- + +- [internal] New servers for :class:`Server` arguments ``socket_name``, + ``socket_path``, ``config_file``. +- [internal] :class:`Server` support for ``-2`` with ``colors=256`` and + ``colors=8``. + 2013-10-31 ---------- From 8ba1c6c10d8c5633b9ef6a67b9104afd7bf6ec24 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 06:22:07 +0800 Subject: [PATCH 0111/3283] cli -2 and -88 support --- tmuxp/cli.py | 62 ++++++++++++++++++++++++++-------- tmuxp/testsuite/test_server.py | 15 ++++++-- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 1c0705ac705..c8e441f73b2 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -198,7 +198,7 @@ def setup_logger(logger=None, level='INFO'): channel = logging.StreamHandler() channel.setFormatter(log.DebugLogFormatter()) - #channel.setFormatter(log.LogFormatter()) + # channel.setFormatter(log.LogFormatter()) logger.setLevel(level) logger.addHandler(channel) @@ -231,7 +231,8 @@ def load_workspace(config_file, args): t = Server( socket_name=args.socket_name, - socket_path=args.socket_path + socket_path=args.socket_path, + colors=args.colors ) try: @@ -288,14 +289,19 @@ def load_workspace(config_file, args): sys.exit() +def get_server_from_args(args): + """ Return a :class:`Server` object from the argparse response. + + tmuxp allows flags such as -L, -S, -2 and -8. + may delete. sec + + """ + pass + + def command_freeze(args): """ Import teamocil config to tmuxp format. """ - t = Server( - socket_name=args.socket_name, - socket_path=args.socket_path - ) - logger.error(args) session = t.findWhere({ 'session_name': args.session_name @@ -306,7 +312,7 @@ def command_freeze(args): newconfig = config.inline(sconf) configparser.import_config(newconfig) config_format = prompt_choices('Convert to', choices=[ - 'yaml', 'json'], default='yaml') + 'yaml', 'json'], default='yaml') if config_format == 'yaml': newconfig = configparser.export( @@ -350,8 +356,6 @@ def command_freeze(args): sys.exit() - - def command_load(args): """ Load a session from a tmuxp session file. """ if args.list: @@ -613,17 +617,15 @@ def command_convert(args): print('written new config to <%s>.' % (newfile)) - - - def command_attach_session(args): """ Command to attach / switch client to a tmux session.""" commands = [] ctext = args.session_name t = Server( - socket_name=args.socket_name or None, - socket_path=args.socket_path or None + socket_name=args.socket_name, + socket_path=args.socket_path, + colors=args.colors ) try: session = next((s for s in t.sessions if s.get( @@ -805,6 +807,30 @@ def get_parser(): help='socket path of tmux server. Same as tmux.', metavar='socket-path') + colorsgroup = parser.add_mutually_exclusive_group( + required=True + ) + + colorsgroup.add_argument( + '-2', + dest='colors', + # action='store_true', + action='store_const', + const=256, + help='Force tmux to assume the terminal supports 256 colours.', + ) + + colorsgroup.add_argument( + '-8', + dest='colors', + # action='store_true', + action='store_const', + const=88, + help='Like -2, but indicates that the terminal supports 88 colours.', + ) + + parser.set_defaults(colors=None) + # http://stackoverflow.com/questions/8521612/argparse-optional-subparser parser.add_argument( '-v', '--version', action='version', @@ -832,6 +858,12 @@ def main(): util.oh_my_zsh_auto_title() + t = Server( + socket_name=args.socket_name, + socket_path=args.socket_path, + colors=args.colors + ) + if args.callback is command_load: command_load(args) elif args.callback is command_convert: diff --git a/tmuxp/testsuite/test_server.py b/tmuxp/testsuite/test_server.py index 9940090ba20..432851838be 100644 --- a/tmuxp/testsuite/test_server.py +++ b/tmuxp/testsuite/test_server.py @@ -48,8 +48,19 @@ def test_256_colors(self): myserver = Server(colors=256) self.assertEqual(myserver.colors, 256) - # try to read the command in util.tmux() - # get util.tmux to have a self.cmd and create tests for it + proc = myserver.tmux('list-servers') + + self.assertIn('-2', proc.cmd) + self.assertNotIn('-8', proc.cmd) + + def test_88_colors(self): + myserver = Server(colors=88) + self.assertEqual(myserver.colors, 88) + + proc = myserver.tmux('list-servers') + + self.assertIn('-8', proc.cmd) + self.assertNotIn('-2', proc.cmd) if __name__ == '__main__': unittest.main() From 3122430a5dc4a4ab42c74e49fa333f0fcf9e0884 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 06:23:51 +0800 Subject: [PATCH 0112/3283] make -2, -8 optional --- tmuxp/cli.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index c8e441f73b2..3c027385f75 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -807,14 +807,11 @@ def get_parser(): help='socket path of tmux server. Same as tmux.', metavar='socket-path') - colorsgroup = parser.add_mutually_exclusive_group( - required=True - ) + colorsgroup = parser.add_mutually_exclusive_group() colorsgroup.add_argument( '-2', dest='colors', - # action='store_true', action='store_const', const=256, help='Force tmux to assume the terminal supports 256 colours.', @@ -823,7 +820,6 @@ def get_parser(): colorsgroup.add_argument( '-8', dest='colors', - # action='store_true', action='store_const', const=88, help='Like -2, but indicates that the terminal supports 88 colours.', From 8c5feeee63e4a0a96b59578b8f87f09caf36446c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 06:27:16 +0800 Subject: [PATCH 0113/3283] update changelog --- CHANGES | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index b3f51fee03d..d73a57a772f 100644 --- a/CHANGES +++ b/CHANGES @@ -6,10 +6,11 @@ Here you can find the recent changes to tmuxp. 2013-11-01 ---------- -- [internal] New servers for :class:`Server` arguments ``socket_name``, +- [internal] [tests] New servers for :class:`Server` arguments ``socket_name``, ``socket_path``, ``config_file``. - [internal] :class:`Server` support for ``-2`` with ``colors=256`` and ``colors=8``. +- [cli] ``$ tmuxp -2`` for forcing 256 colors and ``tmuxp -8`` for forcing 88. 2013-10-31 ---------- From 89717dfae896345f5307f441cfd3af963e8bb8cc Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 06:27:40 +0800 Subject: [PATCH 0114/3283] ignore Corefiles --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3de12b60cef..cfebb033a52 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ dist *.egg-info doc/_build tmuxp/testsuite/.tmuxp +core.* From 94054bca150fdee900a7cb2539b77cf976620455 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 06:29:16 +0800 Subject: [PATCH 0115/3283] doc update --- doc/about.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/about.rst b/doc/about.rst index 45580b5859d..44dd9030ca7 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -66,7 +66,7 @@ Additional Features **Unit tests** Tests against live tmux version to test statefulness of tmux sessions, windows and panes. See :ref:`travis`. -**Import config** import configs from Teamocil / Tmuxinator ***** +**Import config** import configs from Teamocil / Tmuxinator [1]_. **Session freezing** Supports session freezing into YAML and JSON format [1]_. @@ -76,9 +76,9 @@ format [1]_. **Conversion** ``$ tmuxp convert `` can convert files to and from JSON and YAML. -.. [1] Freezing sessions is a great way to save time, but tweaking will - probably be required - There is no substitute to a config made with - love. +.. [1] While freezing and importing sessions is a great way to save time, + tweaking will probably be required - There is no substitute to a + config made with love. Minor tweaks ------------ From 594799dc6e8e23017f589967b9ef595e80994a6a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 06:30:10 +0800 Subject: [PATCH 0116/3283] v0.0.31 --- tmuxp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index 1096824160e..b275131d969 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -22,4 +22,4 @@ import logging -__version__ = '0.0.30a' +__version__ = '0.0.31' From 88fde2a0cc454da7d9564429c7d13098037c00b2 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 06:34:48 +0800 Subject: [PATCH 0117/3283] doc tweaks --- README.rst | 4 ++-- doc/cli.rst | 4 +++- doc/index.rst | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 936a49f3c57..2d783d27132 100644 --- a/README.rst +++ b/README.rst @@ -15,7 +15,7 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through `python objects`_. - Basic support for `freezing live sessions`_. -- `importing`_ from `teamocil`_ and `tmuxinator`_. +- `Importing`_ from `teamocil`_ and `tmuxinator`_. - JSON or YAML for `simple`_ or `very elaborate`_ configurations. - `bash, zsh and tcsh`_ completion. - Unit tested against against live tmux (1.8 and git). See `travis.yml`_ @@ -79,7 +79,7 @@ tests .. code-block:: bash .. _teamocil: https://github.com/remiprev/teamocil .. _Examples: http://tmuxp.readthedocs.org/en/latest/examples.html .. _freezing live sessions: http://tmuxp.readthedocs.org/en/latest/cli.html#freeze-sessions -.. _importing: http://tmuxp.readthedocs.org/en/latest/cli.html#import +.. _Importing: http://tmuxp.readthedocs.org/en/latest/cli.html#import .. _travis.yml: http://tmuxp.readthedocs.org/en/latest/developing.html#travis-ci .. _testing: http://tmuxp.readthedocs.org/en/latest/developing.html#test-runner .. _python objects: http://tmuxp.readthedocs.org/en/latest/api.html#api diff --git a/doc/cli.rst b/doc/cli.rst index f6f6f9ada4a..3056cd248d3 100644 --- a/doc/cli.rst +++ b/doc/cli.rst @@ -4,7 +4,7 @@ Command Line Interface ====================== -.. _import_teamocil: +.. _cli_freeze: Freeze sessions """"""""""""""" @@ -15,6 +15,8 @@ Freeze sessions Tmuxp will offer to convert file to ``.json`` or ``.yaml``. +.. _cli_load: + Load session """""""""""" diff --git a/doc/index.rst b/doc/index.rst index 205f04facb3..1aa81f2f7e2 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -11,7 +11,7 @@ tmuxp, a novel approach to manage `tmux(1)`_ (>= 1.8) workspaces through `python objects`_. - Basic support for `freezing live sessions`_. -- `importing`_ from `teamocil`_ and `tmuxinator`_. +- `Importing`_ from `teamocil`_ and `tmuxinator`_. - JSON or YAML for `simple`_ or `very elaborate`_ configurations. - `bash, zsh and tcsh`_ completion. - Unit tested against against live tmux (1.8 and git). See `travis.yml`_ @@ -28,7 +28,7 @@ Ready to begin? See the `Quickstart`_. .. _teamocil: https://github.com/remiprev/teamocil .. _Examples: http://tmuxp.readthedocs.org/en/latest/examples.html .. _freezing live sessions: http://tmuxp.readthedocs.org/en/latest/cli.html#freeze-sessions -.. _importing: http://tmuxp.readthedocs.org/en/latest/cli.html#import +.. _Importing: http://tmuxp.readthedocs.org/en/latest/cli.html#import .. _travis.yml: http://tmuxp.readthedocs.org/en/latest/developing.html#travis-ci .. _testing: http://tmuxp.readthedocs.org/en/latest/developing.html#test-runner .. _python objects: http://tmuxp.readthedocs.org/en/latest/api.html#api From bfc6023e5a86778726cf7f16eed2186438748da0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 08:43:25 +0800 Subject: [PATCH 0118/3283] start_directory example showing concatenation. Tests for it. Fix #11. --- CHANGES | 3 ++ examples/start_directory.json | 26 ++++++++++-- examples/start_directory.yaml | 20 +++++++-- tmuxp/cli.py | 4 +- tmuxp/config.py | 38 +++++++++++------ tmuxp/session.py | 1 - tmuxp/testsuite/test_config.py | 74 ++++++++++++++++++++++++++++++++++ tmuxp/window.py | 2 +- tmuxp/workspacebuilder.py | 4 +- 9 files changed, 146 insertions(+), 26 deletions(-) diff --git a/CHANGES b/CHANGES index d73a57a772f..4f0a14ec71e 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,9 @@ Here you can find the recent changes to tmuxp. - [internal] :class:`Server` support for ``-2`` with ``colors=256`` and ``colors=8``. - [cli] ``$ tmuxp -2`` for forcing 256 colors and ``tmuxp -8`` for forcing 88. +- [config] [tests] Concatenation with ``start_directory`` via + :meth:`Config.trickle()` if window ``start_directory`` is alphanumeric / + relative (doesn't start with ``/``). See :ref:`Examples` in *start directory*. 2013-10-31 ---------- diff --git a/examples/start_directory.json b/examples/start_directory.json index c8ab8755728..6816d1ae093 100644 --- a/examples/start_directory.json +++ b/examples/start_directory.json @@ -5,17 +5,35 @@ "pwd", "echo 'it trickles down from session-level'" ], + "window_name": "should be /var/" + }, + { + "panes": [ + "pwd", + "echo 'window start_directory concatenates to session start_directory'", + "echo 'if it is not absolute'" + ], + "start_directory": "log", "window_name": "should be /var/log" }, { "panes": [ "pwd", - "echo 'has precedence'" + "echo 'has precedence'", + "echo 'remember to quote ~ in YAML'" + ], + "start_directory": "~", + "window_name": "should be ~" + }, + { + "panes": [ + "pwd", + "echo 'absolute paths also have precedence'" ], - "start_directory": "$HOME", - "window_name": "should be $HOME" + "start_directory": "/proc", + "window_name": "should be /proc" } ], "session_name": "start directory", - "start_directory": "/var/log" + "start_directory": "/var/" } \ No newline at end of file diff --git a/examples/start_directory.yaml b/examples/start_directory.yaml index e8bef231433..88ffece8ed2 100644 --- a/examples/start_directory.yaml +++ b/examples/start_directory.yaml @@ -1,12 +1,24 @@ session_name: start directory -start_directory: /var/log +start_directory: /var/ windows: - - window_name: should be /var/log + - window_name: should be /var/ panes: - pwd - echo 'it trickles down from session-level' - - window_name: should be $HOME - start_directory: $HOME + - window_name: should be /var/log + start_directory: log + panes: + - pwd + - echo 'window start_directory concatenates to session start_directory' + - echo 'if it is not absolute' + - window_name: should be ~ + start_directory: '~' panes: - pwd - echo 'has precedence' + - echo 'remember to quote ~ in YAML' + - window_name: should be /proc + start_directory: /proc + panes: + - pwd + - echo 'absolute paths also have precedence' diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 3c027385f75..30b19098615 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -232,7 +232,6 @@ def load_workspace(config_file, args): t = Server( socket_name=args.socket_name, socket_path=args.socket_path, - colors=args.colors ) try: @@ -831,7 +830,8 @@ def get_parser(): parser.add_argument( '-v', '--version', action='version', version='tmuxp %s' % __version__, - help='Prints the tmuxp version') + help='Prints the tmuxp version', + ) return parser diff --git a/tmuxp/config.py b/tmuxp/config.py index 845fea66614..d163ed4255d 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -190,24 +190,38 @@ def trickle(config): ``shell_command_before``. ''' - session_start_directory = config['start_directory'] if 'start_directory' in config else None + if 'start_directory' in config: + session_start_directory = config['start_directory'] + else: + session_start_directory = None for windowconfig in config['windows']: - if not 'start_directory' in windowconfig and session_start_directory: - windowconfig['start_directory'] = session_start_directory - for paneconfig in windowconfig['panes']: - commands_before = config[ - 'shell_command_before'] if 'shell_command_before' in config else [] - commands_before.extend(windowconfig[ - 'shell_command_before']) if 'shell_command_before' in windowconfig else None - commands_before.extend(paneconfig[ - 'shell_command_before']) if 'shell_command_before' in paneconfig else None + # Prepend start_directory to relative window commands + if session_start_directory: + + if not 'start_directory' in windowconfig: + windowconfig['start_directory'] = session_start_directory + else: + if not any(windowconfig['start_directory'].startswith(a) for a in ['~', '/']): + windowconfig['start_directory'] = os.path.join(session_start_directory, windowconfig['start_directory']) + + for paneconfig in windowconfig['panes']: + commands_before = [] + + # Prepend shell_command_before to commands + if 'shell_command_before' in config: + commands_before = config['shell_command_before'] + if 'shell_command_before' in windowconfig: + commands_before.extend(windowconfig['shell_command_before']) + if 'shell_command_before' in paneconfig: + commands_before.extend(paneconfig['shell_command_before']) if 'shell_command' not in paneconfig: paneconfig['shell_command'] = list() - commands_before.extend(paneconfig[ - 'shell_command']) if paneconfig['shell_command'] else None + if paneconfig['shell_command']: + commands_before.extend(paneconfig['shell_command']) + paneconfig['shell_command'] = commands_before return config diff --git a/tmuxp/session.py b/tmuxp/session.py index e517d8033b3..604ed289a58 100644 --- a/tmuxp/session.py +++ b/tmuxp/session.py @@ -59,7 +59,6 @@ def by(val, *args): return list(filter(by, self.server._sessions))[0] except IndexError as e: logger.error(e) - logger.error(self._session_name) logger.error(self.server._sessions) def tmux(self, *args, **kwargs): diff --git a/tmuxp/testsuite/test_config.py b/tmuxp/testsuite/test_config.py index 648f2636ffc..d690feb4607 100644 --- a/tmuxp/testsuite/test_config.py +++ b/tmuxp/testsuite/test_config.py @@ -583,6 +583,80 @@ def test_shell_command_before(self): self.assertDictEqual(test_config, self.config_after) + +class TrickleRelativeStartDirectory(unittest.TestCase): + config_expanded = { # shell_command_before is string in some areas + 'session_name': 'sampleconfig', + 'start_directory': '/var', + 'windows': [ + { + 'window_name': 'editor', + 'start_directory': 'log', + 'panes': [ + { + 'shell_command': ['vim'], + }, + { + 'shell_command': ['cowsay "hey"'] + }, + ], + 'layout': 'main-verticle' + }, + { + 'window_name': 'logging', + 'start_directory': '~', + 'panes': [ + { + 'shell_command': ['tail -F /var/log/syslog'], + }, + { + } + ] + }, + ] + } + + config_after = { # shell_command_before is string in some areas + 'session_name': 'sampleconfig', + 'start_directory': '/var', + 'windows': [ + { + 'window_name': 'editor', + 'start_directory': '/var/log', + 'panes': [ + { + 'shell_command': ['vim'], + }, + { + 'shell_command': [ + 'cowsay "hey"' + ] + }, + ], + 'layout': 'main-verticle' + }, + { + 'start_directory': '~', + 'window_name': 'logging', + 'panes': [ + { + 'shell_command': ['tail -F /var/log/syslog'], + }, + { + 'shell_command': [] + } + ] + }, + ] + } + + def test_shell_command_before(self): + self.maxDiff = None + + test_config = config.trickle(self.config_expanded) + self.maxDiff = None + self.assertDictEqual(test_config, self.config_after) + class ConfigConsistency(unittest.TestCase): delete_this = ''' diff --git a/tmuxp/window.py b/tmuxp/window.py index d805a4111e9..a1b81849fd0 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -278,7 +278,7 @@ def move_window(self, destination): proc = self.tmux( 'move-window', '-s%s:%s' % (self.get('session_id'), self.get('window_index')), - '-t%s' % destination, + '-t%s:%s' % (self.get('session_id'), destination), ) if proc.stderr: diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index dcaffe0f0c8..92a586ad796 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -127,6 +127,7 @@ def build(self, session=None): ) assert(self.sconf['session_name'] == session.get('session_name')) + assert(len(self.sconf['session_name']) > 0) self.session = session @@ -165,6 +166,7 @@ def iter_create_windows(self, s): if i == int(1): # if first window, use window 1 w1 = s.attached_window() w1.move_window(99) + pass w = s.new_window( window_name=window_name, start_directory=wconf['start_directory'] if 'start_directory' in wconf else None, @@ -246,8 +248,6 @@ def freeze(session): 'cd ' + p.get('pane_current_path')) pconf['shell_command'].append(p.get('pane_current_command')) wconf['panes'].append(pconf) - # logger.error(p) - # logger.error(dict(p)) sconf['windows'].append(wconf) From 7e150996ada3c26ab0ae5ea92463da09505cb5cc Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 08:47:31 +0800 Subject: [PATCH 0119/3283] v0.0.32 --- tmuxp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index b275131d969..40d4e52a804 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -22,4 +22,4 @@ import logging -__version__ = '0.0.31' +__version__ = '0.0.32' From 90a8f5d52c9c7a8b2439cf0350abd221676c7338 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 08:51:28 +0800 Subject: [PATCH 0120/3283] docs internals --- doc/quickstart.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/quickstart.rst b/doc/quickstart.rst index 8b35a2627a5..d787cd877ae 100644 --- a/doc/quickstart.rst +++ b/doc/quickstart.rst @@ -44,6 +44,11 @@ This creates your tmuxp session. Pythonics --------- +.. seealso:: + :ref:`tmuxp python API documentation ` and :ref:`developing`, + :ref:`internals`. + + ORM - `Object Relational Mapper`_ AL - `Abstraction Layer`_ @@ -56,9 +61,6 @@ python abstraction layer .. module:: tmuxp -.. seealso:: - :ref:`tmuxp python API documentation ` and :ref:`developing`. - ======================================== ================================= :ref:`tmuxp python api ` :term:`tmux(1)` equivalent ======================================== ================================= From 95df9e782c5e6726768ae1cdb308cf2ff6559bce Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 08:54:33 +0800 Subject: [PATCH 0121/3283] Fix bug in cli where tmuxinator import prints teamocil, thanks @stratoukos --- tmuxp/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 30b19098615..67e8e902a05 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -539,7 +539,7 @@ def command_import_tmuxinator(args): print( '---------------------------------------------------------------') print( - 'Configuration import does its best to convert teamocil files.\n') + 'Configuration import does its best to convert tmuxinator files.\n') if prompt_yes_no( 'The new config *WILL* require adjusting afterwards. Save config?' ): From fb2afdcb1b3732e965ff0a936723896dada07ff2 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 08:57:59 +0800 Subject: [PATCH 0122/3283] fix name of config.trickle() in CHANGES --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 4f0a14ec71e..01ec5fa4850 100644 --- a/CHANGES +++ b/CHANGES @@ -12,7 +12,7 @@ Here you can find the recent changes to tmuxp. ``colors=8``. - [cli] ``$ tmuxp -2`` for forcing 256 colors and ``tmuxp -8`` for forcing 88. - [config] [tests] Concatenation with ``start_directory`` via - :meth:`Config.trickle()` if window ``start_directory`` is alphanumeric / + :meth:`config.trickle()` if window ``start_directory`` is alphanumeric / relative (doesn't start with ``/``). See :ref:`Examples` in *start directory*. 2013-10-31 From ae37201219d016f71cde01b956238d369e8ed348 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 09:20:31 +0800 Subject: [PATCH 0123/3283] cli: fix bug where configs would not completely pass through --- tmuxp/cli.py | 8 ++++---- tmuxp/config.py | 21 +++++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 67e8e902a05..c30d7fa4e64 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -432,11 +432,11 @@ def command_import_teamocil(args): if os.path.exists(configfile): print(configfile) configparser.import_config(configfile) + newconfig = config.import_tmuxinator(configparser.get()) + configparser.import_config(newconfig) else: sys.exit('File not found: %s' % configfile) - newconfig = config.import_teamocil(configparser.get()) - config_format = prompt_choices('Convert to', choices=[ 'yaml', 'json'], default='yaml') @@ -518,11 +518,11 @@ def command_import_tmuxinator(args): if os.path.exists(configfile): print(configfile) configparser.import_config(configfile) + newconfig = config.import_tmuxinator(configparser.get()) + configparser.import_config(newconfig) else: sys.exit('File not found: %s' % configfile) - newconfig = config.import_tmuxinator(configparser.get()) - config_format = prompt_choices('Convert to', choices=[ 'yaml', 'json'], default='yaml') diff --git a/tmuxp/config.py b/tmuxp/config.py index d163ed4255d..56b3fe1ceb1 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -240,25 +240,31 @@ def import_tmuxinator(sconf): tmuxp_config = {} + logger.error(sconf) + if 'project_name' in sconf: - tmuxp_config['session_name'] = sconf['project_name'] + tmuxp_config['session_name'] = sconf.pop('project_name') elif 'name' in sconf: - tmuxp_config['session_name'] = sconf['name'] + tmuxp_config['session_name'] = sconf.pop('name') else: tmuxp_config['session_name'] = None + logger.error(tmuxp_config) + if 'cli_args' in sconf: tmuxp_config['config'] = sconf['cli_args'] if '-f' in tmuxp_config['config']: tmuxp_config['config'] = tmuxp_config[ - 'config'].replace('-f', '').strip() + 'config' + ].replace('-f', '').strip() elif 'tmux_options' in sconf: tmuxp_config['config'] = sconf['tmux_options'] if '-f' in tmuxp_config['config']: tmuxp_config['config'] = tmuxp_config[ - 'config'].replace('-f', '').strip() + 'config' + ].replace('-f', '').strip() if 'socket_name' in sconf: tmuxp_config['socket_name'] = sconf['socket_name'] @@ -267,7 +273,7 @@ def import_tmuxinator(sconf): if 'tabs' in sconf: sconf['windows'] = sconf.pop('tabs') - + logger.error(tmuxp_config) if 'pre' in sconf and 'pre_window' in sconf: tmuxp_config['shell_command'] = sconf['pre'] @@ -287,7 +293,7 @@ def import_tmuxinator(sconf): tmuxp_config['shell_command_before'].append( 'rbenv shell %s' % sconf['rbenv'] ) - + logger.error(tmuxp_config) for w in sconf['windows']: for k, v in w.items(): @@ -312,10 +318,9 @@ def import_tmuxinator(sconf): if 'layout' in v: windowdict['layout'] = v['layout'] tmuxp_config['windows'].append(windowdict) - + logger.error(tmuxp_config) return tmuxp_config - def import_teamocil(sconf): '''Import yaml configs from `teamocil`_. From 8d39a3e0e669fde040d2a7069dbe50b44b8aefe1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 09:25:37 +0800 Subject: [PATCH 0124/3283] make sure server in load_workspace uses -2 --- tmuxp/cli.py | 3 +-- tmuxp/config.py | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index c30d7fa4e64..5ae4010ccb5 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -232,6 +232,7 @@ def load_workspace(config_file, args): t = Server( socket_name=args.socket_name, socket_path=args.socket_path, + colors=args.colors ) try: @@ -301,7 +302,6 @@ def get_server_from_args(args): def command_freeze(args): """ Import teamocil config to tmuxp format. """ - logger.error(args) session = t.findWhere({ 'session_name': args.session_name }) @@ -395,7 +395,6 @@ def command_load(args): else: logger.error('%s not found.' % configfile) - def command_import_teamocil(args): """ Import teamocil config to tmuxp format. """ diff --git a/tmuxp/config.py b/tmuxp/config.py index 56b3fe1ceb1..0f275fe9946 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -240,8 +240,6 @@ def import_tmuxinator(sconf): tmuxp_config = {} - logger.error(sconf) - if 'project_name' in sconf: tmuxp_config['session_name'] = sconf.pop('project_name') elif 'name' in sconf: @@ -249,7 +247,8 @@ def import_tmuxinator(sconf): else: tmuxp_config['session_name'] = None - logger.error(tmuxp_config) + if 'project_root' in sconf: + tmuxp_config['start_directory'] = sconf.pop('project_root') if 'cli_args' in sconf: tmuxp_config['config'] = sconf['cli_args'] From 528dd77643706853ea28eb9bb2a980b6138131e2 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 09:41:01 +0800 Subject: [PATCH 0125/3283] remove logger msgs --- tmuxp/config.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tmuxp/config.py b/tmuxp/config.py index 0f275fe9946..fa7786251af 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -272,7 +272,7 @@ def import_tmuxinator(sconf): if 'tabs' in sconf: sconf['windows'] = sconf.pop('tabs') - logger.error(tmuxp_config) + if 'pre' in sconf and 'pre_window' in sconf: tmuxp_config['shell_command'] = sconf['pre'] @@ -292,7 +292,7 @@ def import_tmuxinator(sconf): tmuxp_config['shell_command_before'].append( 'rbenv shell %s' % sconf['rbenv'] ) - logger.error(tmuxp_config) + for w in sconf['windows']: for k, v in w.items(): @@ -317,7 +317,6 @@ def import_tmuxinator(sconf): if 'layout' in v: windowdict['layout'] = v['layout'] tmuxp_config['windows'].append(windowdict) - logger.error(tmuxp_config) return tmuxp_config def import_teamocil(sconf): From 40ece06d420c07cd79beb894b8313f2152f0520a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 09:46:01 +0800 Subject: [PATCH 0126/3283] expanduser ~ in teamocil when saving --- tmuxp/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 5ae4010ccb5..2de42a6074c 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -511,7 +511,7 @@ def command_import_tmuxinator(args): print(output) if args.config: - configfile = os.path.abspath(os.path.relpath(args.config)) + configfile = os.path.abspath(os.path.relpath(os.path.expanduser(args.config))) configparser = kaptan.Kaptan(handler='yaml') if os.path.exists(configfile): @@ -552,7 +552,7 @@ def command_import_tmuxinator(args): dest = dest_prompt - dest = os.path.abspath(os.path.relpath(dest)) + dest = os.path.abspath(os.path.relpath(os.path.expanduser(dest))) if prompt_yes_no('Write to %s?' % dest): buf = open(dest, 'w') buf.write(newconfig) From 10d349671c5712773d1520ad1e52b3b19470b2c8 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 09:48:04 +0800 Subject: [PATCH 0127/3283] Use expanduser for saving and loading files beginning with ~ --- tmuxp/cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 2de42a6074c..47590c70627 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -340,7 +340,7 @@ def command_freeze(args): dest = dest_prompt - dest = os.path.abspath(os.path.relpath(dest)) + dest = os.path.abspath(os.path.relpath(os.path.expanduser(dest))) if prompt_yes_no('Write to %s?' % dest): buf = open(dest, 'w') buf.write(newconfig) @@ -425,7 +425,7 @@ def command_import_teamocil(args): print(output) elif args.config: - configfile = os.path.abspath(os.path.relpath(args.config)) + configfile = os.path.abspath(os.path.relpath(os.path.expanduser(args.config))) configparser = kaptan.Kaptan(handler='yaml') if os.path.exists(configfile): @@ -466,7 +466,7 @@ def command_import_teamocil(args): dest = dest_prompt - dest = os.path.abspath(os.path.relpath(dest)) + dest = os.path.abspath(os.path.relpath(os.path.expanduser(dest))) if prompt_yes_no('Write to %s?' % dest): buf = open(dest, 'w') buf.write(newconfig) From 8a0699bc06b21fa42fcad905bd15637780e6ac13 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 09:49:17 +0800 Subject: [PATCH 0128/3283] Update changes --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 01ec5fa4850..52c4a060b97 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,10 @@ Here you can find the recent changes to tmuxp. - [config] [tests] Concatenation with ``start_directory`` via :meth:`config.trickle()` if window ``start_directory`` is alphanumeric / relative (doesn't start with ``/``). See :ref:`Examples` in *start directory*. +- [import] Fix bug with import teamocil and tmuxinator +- [import] Improve quality of tmuxinator imports. Especially ``session_name`` + and ``start_directory``. +- [cli] Allow saving with ``~`` in file destination. 2013-10-31 ---------- From 760d833aca7bd616315651080e253d8c179fe6dc Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 09:56:36 +0800 Subject: [PATCH 0129/3283] Fix test for test_config_tmuxinator --- tmuxp/testsuite/test_config_tmuxinator.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tmuxp/testsuite/test_config_tmuxinator.py b/tmuxp/testsuite/test_config_tmuxinator.py index ea90f40319e..b443d61fa37 100644 --- a/tmuxp/testsuite/test_config_tmuxinator.py +++ b/tmuxp/testsuite/test_config_tmuxinator.py @@ -15,7 +15,6 @@ TMUXP_DIR = os.path.join(os.path.dirname(__file__), '.tmuxp') - class TmuxinatorTest(unittest.TestCase): tmuxinator_yaml = """\ @@ -181,6 +180,7 @@ class TmuxinatorDeprecationsTest(unittest.TestCase): 'session_name': 'sample', 'socket_name': 'foo', 'config': '~/.tmux.mac.conf', + 'start_directory': '~/test', 'shell_command_before': [ 'sudo /etc/rc.d/mysqld start', 'rbenv shell 2.0.0-p247' @@ -264,8 +264,9 @@ def test_config_to_dict(self): yaml_to_dict = test_config.get() self.assertDictEqual(yaml_to_dict, self.tmuxinator_dict) - self.assertDictEqual(config.import_tmuxinator( - self.tmuxinator_dict), self.tmuxp_dict) + self.assertDictEqual( + config.import_tmuxinator(self.tmuxinator_dict), self.tmuxp_dict + ) class TmuxinatoriSampleTest(unittest.TestCase): From 328b1042f1e58bb73dc99d2a311f59bf8f811e7f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 09:57:05 +0800 Subject: [PATCH 0130/3283] v0.0.33 --- tmuxp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index 40d4e52a804..3816e8546d4 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -22,4 +22,4 @@ import logging -__version__ = '0.0.32' +__version__ = '0.0.33' From b3d6834d39d21d90bcc1f505d2dc80bd9c516bc4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 12:45:09 +0800 Subject: [PATCH 0131/3283] comments, pep8, pep257 --- tmuxp/__init__.py | 1 + tmuxp/__main__.py | 13 ++-- tmuxp/cli.py | 11 ++-- tmuxp/config.py | 152 ++++++++++++++++++++++++---------------------- 4 files changed, 94 insertions(+), 83 deletions(-) diff --git a/tmuxp/__init__.py b/tmuxp/__init__.py index 3816e8546d4..c35b2284f7f 100644 --- a/tmuxp/__init__.py +++ b/tmuxp/__init__.py @@ -7,6 +7,7 @@ :copyright: Copyright 2013 Tony Narlock. :license: BSD, see LICENSE for details + """ diff --git a/tmuxp/__main__.py b/tmuxp/__main__.py index 52e085757d2..801df3b84d2 100755 --- a/tmuxp/__main__.py +++ b/tmuxp/__main__.py @@ -1,10 +1,12 @@ # -*- coding: utf8 - *- -""" - tmuxp - ~~~~~ +"""For accessing tmuxp as a package. + +tmuxp +~~~~~ + +:copyright: Copyright 2013 Tony Narlock. +:license: BSD, see LICENSE for details - :copyright: Copyright 2013 Tony Narlock. - :license: BSD, see LICENSE for details """ import sys @@ -12,6 +14,7 @@ def run(): + """Assure tmuxp is in python path's and available as a package. """ base = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, base) import tmuxp.cli diff --git a/tmuxp/cli.py b/tmuxp/cli.py index 47590c70627..37d451e9546 100644 --- a/tmuxp/cli.py +++ b/tmuxp/cli.py @@ -91,13 +91,13 @@ def prompt_bool(name, default=False, yes_choices=None, no_choices=None): def prompt_yes_no(name, default=True): + """:meth:`prompt_bool()` returning yes by default.""" return prompt_bool(name, default=default) def prompt_choices(name, choices, default=None, resolve=ascii_lowercase, no_choice=('none',)): - """ - Return user input from command line from set of provided choices. + """Return user input from command line from set of provided choices. :param name: prompt text :param choices: list or tuple of available choices. Choices may be @@ -395,6 +395,7 @@ def command_load(args): else: logger.error('%s not found.' % configfile) + def command_import_teamocil(args): """ Import teamocil config to tmuxp format. """ @@ -425,7 +426,8 @@ def command_import_teamocil(args): print(output) elif args.config: - configfile = os.path.abspath(os.path.relpath(os.path.expanduser(args.config))) + configfile = os.path.abspath(os.path.relpath( + os.path.expanduser(args.config))) configparser = kaptan.Kaptan(handler='yaml') if os.path.exists(configfile): @@ -511,7 +513,8 @@ def command_import_tmuxinator(args): print(output) if args.config: - configfile = os.path.abspath(os.path.relpath(os.path.expanduser(args.config))) + configfile = os.path.abspath(os.path.relpath( + os.path.expanduser(args.config))) configparser = kaptan.Kaptan(handler='yaml') if os.path.exists(configfile): diff --git a/tmuxp/config.py b/tmuxp/config.py index fa7786251af..36b8949b5ba 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -22,6 +22,10 @@ def check_consistency(sconf): '''Verify the consistency of the config file. Config files in tmuxp are met to import into :py:mod:`dict`. + + :param sconf: session configuration + :type sconf: dict + ''' # verify session_name @@ -43,28 +47,31 @@ def check_consistency(sconf): def is_config_file(filename, extensions=['.yml', '.yaml', '.json', '.ini']): - '''Is config compatible extension. + """Is config compatible extension. :param filename: filename to check (e.g. ``mysession.json``). :type filename: string :param extensions: filetypes to check (e.g. ``['.yaml', '.json']``). :type extensions: list or string :rtype: bool - ''' - extensions = [extensions] if isinstance(extensions, basestring) else extensions + """ + + extensions = [extensions] if isinstance( + extensions, basestring) else extensions return any(filename.endswith(e) for e in extensions) def in_dir(config_dir=os.path.expanduser('~/.tmuxp'), extensions=['.yml', '.yaml', '.json', '.ini']): - '''Find configs in config_dir and current dir + """Find configs in config_dir and current dir. :param config_dir: directory to search :type config_dir: string :param extensions: filetypes to check (e.g. ``['.yaml', '.json']``). :type extensions: list :rtype: list - ''' + + """ configs = [] for filename in os.listdir(config_dir): @@ -75,13 +82,14 @@ def in_dir(config_dir=os.path.expanduser('~/.tmuxp'), extensions=['.yml', '.yaml def in_cwd(): - '''Return list of configs in current working directory. + """Return list of configs in current working directory. If filename is ``.tmuxp.py``, ``.tmuxp.json``, ``.tmuxp.yaml`` or ``.tmuxp.ini``. :rtype: list - ''' + + """ configs = [] for filename in os.listdir(os.getcwd()): @@ -91,35 +99,36 @@ def in_cwd(): return configs -def inline(config): - '''Opposite of :meth:`config.expand`. Where possible, inline. +def inline(sconf): + """ Return config in inline form, opposite of :meth:`config.expand`. - :param config: unexpanded config file - :type config: dict + :param sconf: unexpanded config file + :type sconf: dict :rtype: dict - ''' - if ('shell_command' in config and isinstance(config['shell_command'], list) and len(config['shell_command']) == 1): - config['shell_command'] = config['shell_command'][0] - if ('shell_command_before' in config and isinstance(config['shell_command_before'], list) and len(config['shell_command_before']) == 1): - config['shell_command_before'] = config['shell_command_before'][0] + """ + + if ('shell_command' in sconf and isinstance(sconf['shell_command'], list) and len(sconf['shell_command']) == 1): + sconf['shell_command'] = sconf['shell_command'][0] + if ('shell_command_before' in sconf and isinstance(sconf['shell_command_before'], list) and len(sconf['shell_command_before']) == 1): + sconf['shell_command_before'] = sconf['shell_command_before'][0] # recurse into window and pane config items - if 'windows' in config: - config['windows'] = [inline(window) - for window in config['windows']] - if 'panes' in config: - config['panes'] = [inline(pane) for pane in config['panes']] + if 'windows' in sconf: + sconf['windows'] = [ + inline(window) for window in sconf['windows'] + ] + if 'panes' in sconf: + sconf['panes'] = [inline(pane) for pane in sconf['panes']] - return config + return sconf -def expand(config): - '''Expand configuration into full form. Enables shorthand forms for tmuxp - config. +def expand(sconf): + """Return config with shorthand and inline properties expanded. - This is necessary to keep the code in the :class:`Builder` clean and also - allow for neat, short-hand configurations. + This is necessary to keep the code in the :class:`WorkspaceBuilder` clean + and also allow for neat, short-hand configurations. As a simple example, internally, tmuxp expects that config options like ``shell_command`` are a list (array):: @@ -131,47 +140,42 @@ def expand(config): 'shell_command': 'htop' Kaptan will load JSON/YAML/INI files into python dicts for you. - :param config: the configuration for the session - :type config: dict + :param sconf: the configuration for the session + :type sconf: dict + :rtype: dict - iterate through session, windows, and panes for ``shell_command``, if - it is a string, turn to list. + """ - :param config: the session configuration - :type config: dict - :rtype: dict - ''' + # Any config section, session, window, pane that can contain the + # 'shell_command' value - '''any config section, session, window, pane that can - contain the 'shell_command' value - ''' - if ('shell_command' in config and isinstance(config['shell_command'], basestring)): - config['shell_command'] = [config['shell_command']] - elif not 'windows' in config and not 'panes' in config and isinstance(config, basestring): - config = {'shell_command': [config]} + if ('shell_command' in sconf and isinstance(sconf['shell_command'], basestring)): + sconf['shell_command'] = [sconf['shell_command']] + elif not 'windows' in sconf and not 'panes' in sconf and isinstance(sconf, basestring): + sconf = {'shell_command': [sconf]} - if ('shell_command_before' in config and isinstance(config['shell_command_before'], basestring)): - config['shell_command_before'] = [config['shell_command_before']] + if ('shell_command_before' in sconf and isinstance(sconf['shell_command_before'], basestring)): + sconf['shell_command_before'] = [sconf['shell_command_before']] # recurse into window and pane config items - if 'windows' in config: - config['windows'] = [ - expand(window) for window in config['windows'] + if 'windows' in sconf: + sconf['windows'] = [ + expand(window) for window in sconf['windows'] ] - elif 'panes' in config: - for p in config['panes']: + elif 'panes' in sconf: + for p in sconf['panes']: if isinstance(p, basestring): - p_index = config['panes'].index(p) - config['panes'][p_index] = { + p_index = sconf['panes'].index(p) + sconf['panes'][p_index] = { 'shell_command': [p] } - config['panes'] = [expand(pane) for pane in config['panes']] + sconf['panes'] = [expand(pane) for pane in sconf['panes']] - return config + return sconf -def trickle(config): - '''Trickle down / inherit config values +def trickle(sconf): + """Return a dict with "trickled down" / inherited config values. This will only work if config has been expanded to full form with :meth:`config.expand`. @@ -180,22 +184,21 @@ def trickle(config): level. shell_command_before trickles down and prepends the ``shell_command`` for the pane. - :param config: the session configuration - :type config: dict + :param sconf: the session configuration + :type sconf: dict :rtype: dict - ''' - ''' - prepends a pane's ``shell_command`` list with the window and sessions' - ``shell_command_before``. - ''' + """ - if 'start_directory' in config: - session_start_directory = config['start_directory'] + # prepends a pane's ``shell_command`` list with the window and sessions' + # ``shell_command_before``. + + if 'start_directory' in sconf: + session_start_directory = sconf['start_directory'] else: session_start_directory = None - for windowconfig in config['windows']: + for windowconfig in sconf['windows']: # Prepend start_directory to relative window commands if session_start_directory: @@ -204,14 +207,15 @@ def trickle(config): windowconfig['start_directory'] = session_start_directory else: if not any(windowconfig['start_directory'].startswith(a) for a in ['~', '/']): - windowconfig['start_directory'] = os.path.join(session_start_directory, windowconfig['start_directory']) + windowconfig['start_directory'] = os.path.join( + session_start_directory, windowconfig['start_directory']) for paneconfig in windowconfig['panes']: commands_before = [] # Prepend shell_command_before to commands - if 'shell_command_before' in config: - commands_before = config['shell_command_before'] + if 'shell_command_before' in sconf: + commands_before = sconf['shell_command_before'] if 'shell_command_before' in windowconfig: commands_before.extend(windowconfig['shell_command_before']) if 'shell_command_before' in paneconfig: @@ -224,19 +228,19 @@ def trickle(config): paneconfig['shell_command'] = commands_before - return config + return sconf def import_tmuxinator(sconf): - '''Import yaml configs from `tmuxinator`_. + """Import yaml configs from `tmuxinator`_. .. _tmuxinator: https://github.com/aziz/tmuxinator - :todo: handle 'root' with a cd shell_command_before - :param sconf: python dict for session configuration :type sconf: dict - ''' + :rtype: dict + + """ tmuxp_config = {} @@ -319,6 +323,7 @@ def import_tmuxinator(sconf): tmuxp_config['windows'].append(windowdict) return tmuxp_config + def import_teamocil(sconf): '''Import yaml configs from `teamocil`_. @@ -379,4 +384,3 @@ def import_teamocil(sconf): tmuxp_config['windows'].append(windowdict) return tmuxp_config - From f35ed0b8817cdee290fe82f4bd643ee731f6b3dd Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 13:10:15 +0800 Subject: [PATCH 0132/3283] pep257 and pep8, docs --- tmuxp/config.py | 7 +++-- tmuxp/exc.py | 23 ++++++++++---- tmuxp/log.py | 82 +++++++++++++++++++++++++++---------------------- 3 files changed, 66 insertions(+), 46 deletions(-) diff --git a/tmuxp/config.py b/tmuxp/config.py index 36b8949b5ba..7f7d2aa301e 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -232,7 +232,7 @@ def trickle(sconf): def import_tmuxinator(sconf): - """Import yaml configs from `tmuxinator`_. + """Return tmuxp config from a `tmuxinator`_ yaml config. .. _tmuxinator: https://github.com/aziz/tmuxinator @@ -325,7 +325,7 @@ def import_tmuxinator(sconf): def import_teamocil(sconf): - '''Import yaml configs from `teamocil`_. + """Return tmuxp config from a `teamocil`_ yaml config. .. _teamocil: https://github.com/remiprev/teamocil @@ -337,7 +337,8 @@ def import_teamocil(sconf): :param sconf: python dict for session configuration :type sconf: dict - ''' + + """ tmuxp_config = {} diff --git a/tmuxp/exc.py b/tmuxp/exc.py index 5aa6e153a9b..113332d8103 100644 --- a/tmuxp/exc.py +++ b/tmuxp/exc.py @@ -1,19 +1,30 @@ # -*- coding: utf8 - *- -""" - tmuxp.exc - ~~~~~~~~~ - :copyright: Copyright 2013 Tony Narlock. - :license: BSD, see LICENSE for details +"""Exceptions for tmuxp. + +tmuxp.exc +~~~~~~~~~ +:copyright: Copyright 2013 Tony Narlock. +:license: BSD, see LICENSE for details + """ class TmuxSessionExists(Exception): + + """Session does not exist in the server.""" + pass class ConfigError(Exception): + + """Error parsing tmuxp configuration dict.""" + pass -class EmptyConfigException(Exception): +class EmptyConfigException(ConfigError): + + """Configuration is empty.""" + pass diff --git a/tmuxp/log.py b/tmuxp/log.py index bf54ca1ef07..d6a28d6892d 100644 --- a/tmuxp/log.py +++ b/tmuxp/log.py @@ -43,10 +43,11 @@ def utf8(value): - """Converts a string argument to a byte string. + """Convert a string argument to a byte string. If the argument is already a byte string or None, it is returned unchanged. Otherwise it must be a unicode string and is encoded as utf8. + """ if isinstance(value, _UTF8_TYPES): return value @@ -56,10 +57,11 @@ def utf8(value): def to_unicode(value): - """Converts a string argument to a unicode string. + """Convert a string argument to a unicode string. If the argument is already a unicode string or None, it is returned unchanged. Otherwise it must be a byte string and is decoded as utf8. + """ if isinstance(value, _TO_UNICODE_TYPES): return value @@ -125,6 +127,24 @@ def safe_unicode(s): } +def default_log_template(self, record): + """ Return the prefix for the log message. Template for Formatter. + + :param: record: :py:class:`logging.LogRecord` object. this is passed in + from inside the :py:meth:`logging.Formatter.format` record. + + """ + + prefix_template = '' + prefix_template += NORMAL + prefix_template += LEVEL_COLORS.get(record.levelname) + Style.BRIGHT + '(%(levelname)s)' + NORMAL + ' ' + prefix_template += '[' + Fore.BLACK + Style.DIM + Style.BRIGHT + '%(asctime)s' + Fore.RESET + Style.RESET_ALL + ']' + prefix_template += ' ' + Fore.WHITE + Style.DIM + Style.BRIGHT + '%(name)s' + Fore.RESET + Style.RESET_ALL + ' ' + prefix_template += NORMAL + + return prefix_template + + class LogFormatter(logging.Formatter): """Log formatter used in Tornado. @@ -138,25 +158,10 @@ class LogFormatter(logging.Formatter): This formatter is enabled automatically by `tornado.options.parse_command_line` (unless ``--logging=none`` is used). - """ - def prefix_template(self, record): - ''' this is available as a definition instead of a class - variable so it can access to instance. it also accepts the record - parameter. - - :param: record: :py:class:`logging.LogRecord` object. this is passed in - from inside the :py:meth:`logging.Formatter.format` record. - ''' - - prefix_template = '' - prefix_template += NORMAL - prefix_template += LEVEL_COLORS.get(record.levelname) + Style.BRIGHT + '(%(levelname)s)' + NORMAL + ' ' - prefix_template += '[' + Fore.BLACK + Style.DIM + Style.BRIGHT + '%(asctime)s' + Fore.RESET + Style.RESET_ALL + ']' - prefix_template += ' ' + Fore.WHITE + Style.DIM + Style.BRIGHT + '%(name)s' + Fore.RESET + Style.RESET_ALL + ' ' - prefix_template += NORMAL + """ - return prefix_template + template = default_log_template def __init__(self, color=True, *args, **kwargs): logging.Formatter.__init__(self, *args, **kwargs) @@ -173,7 +178,7 @@ def format(self, record): date_format = '%H:%m:%S' record.asctime = time.strftime(date_format, self.converter(record.created)) - prefix = self.prefix_template(record) % record.__dict__ + prefix = self.template(record) % record.__dict__ formatted = prefix + " " + safe_unicode(record.message) if record.exc_info: @@ -190,25 +195,28 @@ def format(self, record): return formatted.replace("\n", "\n ") -class DebugLogFormatter(LogFormatter): +def debug_log_template(self, record): + """ Return the prefix for the log message. Template for Formatter. - def prefix_template(self, record): - ''' this is available as a definition instead of a class - variable so it can access to instance. it also accepts the record - argument. + :param: record: :py:class:`logging.LogRecord` object. this is passed in + from inside the :py:meth:`logging.Formatter.format` record. - :param: record: :py:class:`logging.LogRecord` object. this is passed in - from inside the :py:meth:`logging.Formatter.format` record. - ''' + """ - prefix_template = '' - prefix_template += NORMAL - prefix_template += LEVEL_COLORS.get(record.levelname) + Style.BRIGHT + '(%(levelname)1.1s)' + NORMAL + ' ' - prefix_template += '[' + Fore.BLACK + Style.DIM + Style.BRIGHT + '%(asctime)s' + Fore.RESET + Style.RESET_ALL + ']' - prefix_template += ' ' + Fore.WHITE + Style.DIM + Style.BRIGHT + '%(name)s' + Fore.RESET + Style.RESET_ALL + ' ' - prefix_template += Fore.GREEN + Style.BRIGHT + '%(module)s.%(funcName)s()' - prefix_template += Fore.BLACK + Style.DIM + Style.BRIGHT + ':' + NORMAL + Fore.CYAN + '%(lineno)d' - prefix_template += NORMAL + prefix_template = '' + prefix_template += NORMAL + prefix_template += LEVEL_COLORS.get(record.levelname) + Style.BRIGHT + '(%(levelname)1.1s)' + NORMAL + ' ' + prefix_template += '[' + Fore.BLACK + Style.DIM + Style.BRIGHT + '%(asctime)s' + Fore.RESET + Style.RESET_ALL + ']' + prefix_template += ' ' + Fore.WHITE + Style.DIM + Style.BRIGHT + '%(name)s' + Fore.RESET + Style.RESET_ALL + ' ' + prefix_template += Fore.GREEN + Style.BRIGHT + '%(module)s.%(funcName)s()' + prefix_template += Fore.BLACK + Style.DIM + Style.BRIGHT + ':' + NORMAL + Fore.CYAN + '%(lineno)d' + prefix_template += NORMAL + + return prefix_template + + +class DebugLogFormatter(LogFormatter): - return prefix_template + """Provides greater technical details than standard log Formatter.""" + template = debug_log_template From 38161fdc9bd09fb4f9955c0525650a7d02ae28db Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 13:21:08 +0800 Subject: [PATCH 0133/3283] tmuxp/pane pep257, pep8 --- tmuxp/pane.py | 60 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/tmuxp/pane.py b/tmuxp/pane.py index 143f5de9a59..f5629e5cbe5 100644 --- a/tmuxp/pane.py +++ b/tmuxp/pane.py @@ -1,12 +1,14 @@ # -*- coding: utf8 - *- -""" - tmuxp.pane - ~~~~~~~~~~ +"""Pythonization of the :ref:`tmux(1)` pane. + +tmuxp.pane +~~~~~~~~~~ + +tmuxp helps you manage tmux workspaces. - tmuxp helps you manage tmux workspaces. +:copyright: Copyright 2013 Tony Narlock. +:license: BSD, see LICENSE for details - :copyright: Copyright 2013 Tony Narlock. - :license: BSD, see LICENSE for details """ from __future__ import absolute_import, division, print_function, with_statement from . import util, formats @@ -56,7 +58,9 @@ def by(val, *args): return list(filter(by, self.server._panes))[0] def tmux(self, cmd, *args, **kwargs): - """Send command to tmux with :attr:`pane_id` as ``target-pane``. + """Return :meth:`Server.tmux` defaulting to ``target_pane`` as target. + + Send command to tmux with :attr:`pane_id` as ``target-pane``. Specifying ``('-t', 'custom-target')`` or ``('-tcustom_target')`` in ``args`` will override using the object's ``pane_id`` as target. @@ -68,11 +72,14 @@ def tmux(self, cmd, *args, **kwargs): return self.server.tmux(cmd, *args, **kwargs) def send_keys(self, cmd, enter=True): - ''' - ```tmux send-keys``` to the pane + """``$ tmux send-keys`` to the pane. + + :param cmd: Text or input into pane + :type cmd: str + :param enter: Send enter after sending the input. + :type enter: bool - :param enter: bool. send enter after sending the key. - ''' + """ self.tmux('send-keys', cmd) if enter: @@ -90,30 +97,29 @@ def reset(self): def set_width(self, width): """Set width of pane. - :param width: pane width, in cells. - :type width: int + :param width: pane width, in cells. + :type width: int + """ self.resize_pane(width=width) def set_height(self, height): """Set height of pane. - :param height: pane height, in cells. - :type height: int + :param height: pane height, in cells. + :type height: int + """ self.resize_pane(height=height) def resize_pane(self, *args, **kwargs): - ''' - ``$ tmux resize-pane`` + """``$ tmux resize-pane`` of pane and return ``self``. :param target_pane: ``target_pane``, or ``-U``,``-D``, ``-L``, ``-R``. :type target_pane: string :rtype: :class:`Pane` - ''' - # if isinstance(target_pane, basestring) and not ':' not in target_pane or isinstance(target_pane, int): - # target_pane = "%s.%s" % (self.target, target_pane) + """ if 'height' in kwargs: proc = self.tmux('resize-pane', '-y%s' % int(kwargs['height'])) @@ -129,10 +135,16 @@ def resize_pane(self, *args, **kwargs): return self def enter(self): - ''' - ``$ tmux send-keys`` send Enter to the pane. - ''' + """Send carriage return to pane. + + ``$ tmux send-keys`` send Enter to the pane. + + """ self.tmux('send-keys', 'Enter') def __repr__(self): - return "%s(%s %s)" % (self.__class__.__name__, self.get('pane_id'), self.window) + return "%s(%s %s)" % ( + self.__class__.__name__, + self.get('pane_id'), + self.window + ) From 7ff4e3183b922652808c7ee723fa5782c1b8fc8b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 14:03:40 +0800 Subject: [PATCH 0134/3283] code documentation, pep257, remove Server.has_clients, Server.list_clients --- doc/api.rst | 26 +++++--- tmuxp/server.py | 129 +++++++++++--------------------------- tmuxp/session.py | 14 +++-- tmuxp/util.py | 14 +++-- tmuxp/window.py | 14 +++-- tmuxp/workspacebuilder.py | 14 +++-- 6 files changed, 88 insertions(+), 123 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index b043b67aa72..db469c6175c 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -12,11 +12,9 @@ Server Object .. autoclass:: Server :members: :inherited-members: + :private-members: :show-inheritance: - - .. attribute:: _sessions - - A :py:obj:`list` of the server's :class:`Session` objects. + :member-order: bysource Session Object -------------- @@ -26,9 +24,17 @@ Session Object :inherited-members: :show-inheritance: - .. attribute:: _windows + .. attribute:: server + + The :class:`Server` of the window. - A :py:obj:`list` of session's :class:`Window` objects. + .. attribute:: windows + + A :py:obj:`list` of the window's :class:`Window` objects. + + .. attribute:: _window + + A :py:obj:`list` of the session's windows as :py:obj:`dict`. Window Object ------------- @@ -39,14 +45,18 @@ Window Object :private-members: :show-inheritance: - .. attribute:: _session + .. attribute:: session The :class:`Session` of the window. - .. attribute:: _panes + .. attribute:: panes A :py:obj:`list` of the window's :class:`Pane` objects. + .. attribute:: _panes + + A :py:obj:`list` of the window's panes as :py:obj:`dict`. + Pane Object ----------- diff --git a/tmuxp/server.py b/tmuxp/server.py index c5fbb47ca38..304c3dae26b 100644 --- a/tmuxp/server.py +++ b/tmuxp/server.py @@ -1,12 +1,14 @@ # -*- coding: utf8 - *- -""" - tmuxp.server - ~~~~~~~~~~~~ +"""Pythonization of the :ref:`tmux(1)` server. + +tmuxp.server +~~~~~~~~~~~~ + +tmuxp helps you manage tmux workspaces. - tmuxp helps you manage tmux workspaces. +:copyright: Copyright 2013 Tony Narlock. +:license: BSD, see LICENSE for details - :copyright: Copyright 2013 Tony Narlock. - :license: BSD, see LICENSE for details """ from __future__ import absolute_import, division, print_function, with_statement @@ -36,6 +38,7 @@ class Server(TmuxRelationalObject): running tmux server. ''' + #: socket name socket_name = None socket_path = None config_file = None @@ -135,27 +138,40 @@ def _list_sessions(self): @property def _sessions(self): + """Return list of the server's sessions as :py:obj:`dict`. + + :rtype: list + + """ + return self._list_sessions() def list_sessions(self): - ''' - Return a list of :class:`Session` from the ``tmux(1)`` session. + """Return list of :class:`Session` from the ``tmux(1)`` session. :rtype: :py:obj:`list` of :class:`Session` - ''' + + """ return [ Session(server=self, **s) for s in self._sessions ] @property def sessions(self): + """Return a :py:obj:`list` of the server's :class:`Session` objects.""" return self.list_sessions() + #: Alias of :attr:`sessions`. children = sessions def __list_windows(self): - ''' - Return dict of ``tmux(1) list-windows`` values. - ''' + """Return list of ``$ tmux(1) list-windows`` stdout. + + The :py:obj:`list` is derived from :class:`util.tmux` which wraps + :py:meth:`Subprocess.Popen`. + + :rtype: list + + """ wformats = ['session_name', 'session_id'] + formats.WINDOW_FORMATS tmux_formats = ['#{%s}' % format for format in wformats] @@ -172,8 +188,7 @@ def __list_windows(self): return windows.stdout def _list_windows(self): - ''' take the outpout of _list_windows from shell and put it into - a list of dicts''' + """Return list of dicts filtered from :meth:`__list_windows`.""" wformats = ['session_name', 'session_id'] + formats.WINDOW_FORMATS @@ -202,14 +217,19 @@ def _list_windows(self): return self._windows def _update_windows(self): + """Update internal window data and return ``self`` for chainability.""" self._list_windows() return self def __list_panes(self): - '''Return list of :class:`Pane` for the window. + """Return list of ``$ tmux(1) list-panes`` stdout. - :rtype: list of :class:`Pane` - ''' + The :py:obj:`list` is derived from :class:`util.tmux` which wraps + :py:meth:`Subprocess.Popen`. + + :rtype: list + + """ pformats = ['session_name', 'session_id', 'window_index', 'window_id', 'window_name'] + formats.PANE_FORMATS tmux_formats = ['#{%s}\t' % f for f in pformats] @@ -227,8 +247,7 @@ def __list_panes(self): return panes.stdout def _list_panes(self): - ''' take the outpout of _list_panes from shell and put it into - a list of dicts''' + """Return list of dicts filtered from :meth:`__list_panes`.""" pformats = ['session_name', 'session_id', 'window_index', 'window_id', 'window_name'] + formats.PANE_FORMATS @@ -256,78 +275,6 @@ def _update_panes(self): self._list_panes() return self - def list_clients(self): - ''' - Return a list of :class:`client` from tmux server. - - ``$ tmux list-clients`` - ''' - cformats = formats.CLIENT_FORMATS - tmux_formats = ['#{%s}' % format for format in cformats] - # import ipdb - # ipdb.set_trace() - clients = self.tmux( - 'list-clients', - '-F%s' % '\t'.join(tmux_formats), # output - ).stdout - - # combine format keys with values returned from ``tmux list-windows`` - clients = [dict(zip( - cformats, client.split('\t'))) for client in clients] - - # clear up empty dict - new_clients = [ - dict((k, v) for k, v in client.items() if v) for client in clients - ] - - if not self._clients: - for client in new_clients: - logger.debug('adding client_tty %s' % (client['client_tty'])) - self._clients.append(client) - return self._clients - - new = {client['client_tty']: client for client in new_clients} - old = {client.get('client_tty'): client for client in self._clients} - - created = set(new.keys()) - set(old.keys()) - deleted = set(old.keys()) - set(new.keys()) - intersect = set(new.keys()).intersection(set(old.keys())) - - diff = {id: dict(set(new[id].items()) - set(old[id].items())) - for id in intersect} - - logger.debug( - "syncing clients" - "\n\tdiff: %s\n" - "\tcreated: %s\n" - "\tdeleted: %s\n" - "\tintersect: %s" % (diff, created, deleted, intersect) - ) - - for s in self._clients: - # remove client objects if deleted or out of client - if s.get('client_tty') in deleted: - logger.debug("removing %s" % s) - self._clients.remove(s) - - if s.get('client_tty') in intersect: - logger.debug('updating client_tty %s' % (s.get('client_tty'))) - s.update(diff[s.get('client_tty')]) - - # create client objects for non-existant client_tty's - for client in [new[client_tty] for client_tty in created]: - logger.debug('new client %s' % client['client_tty']) - self._clients.append(client) - - return self._clients - - def has_clients(self): - # are any clients connected to tmux - proc = self.tmux('list-clients') - - if proc.stderr: - raise Exception(proc.stderr) - def attached_sessions(self): ''' Returns active :class:`Session` object diff --git a/tmuxp/session.py b/tmuxp/session.py index 604ed289a58..d9fc1b0e8d1 100644 --- a/tmuxp/session.py +++ b/tmuxp/session.py @@ -1,12 +1,14 @@ # -*- coding: utf8 - *- -""" - tmuxp.session - ~~~~~~~~~~~~~ +"""Pythonization of the :ref:`tmux(1)` session. + +tmuxp.session +~~~~~~~~~~~~~ + +tmuxp helps you manage tmux workspaces. - tmuxp helps you manage tmux workspaces. +:copyright: Copyright 2013 Tony Narlock. +:license: BSD, see LICENSE for details - :copyright: Copyright 2013 Tony Narlock. - :license: BSD, see LICENSE for details """ from __future__ import absolute_import, division, print_function, with_statement diff --git a/tmuxp/util.py b/tmuxp/util.py index 29cb13adb20..81bfd7f684c 100644 --- a/tmuxp/util.py +++ b/tmuxp/util.py @@ -1,12 +1,14 @@ # -*- coding: utf8 - *- -""" - tmuxp.util - ~~~~~~~~~~ +"""Utility and helper methods for tmuxp. + +tmuxp.util +~~~~~~~~~~ + +tmuxp helps you manage tmux workspaces. - tmuxp helps you manage tmux workspaces. +:copyright: Copyright 2013 Tony Narlock. +:license: BSD, see LICENSE for details - :copyright: Copyright 2013 Tony Narlock. - :license: BSD, see LICENSE for details """ from __future__ import absolute_import, division, print_function, with_statement from __future__ import unicode_literals diff --git a/tmuxp/window.py b/tmuxp/window.py index a1b81849fd0..83ad3108ef0 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -1,12 +1,14 @@ # -*- coding: utf8 - *- -""" - tmuxp.window - ~~~~~~~~~~~~ +"""Pythonization of the :ref:`tmux(1)` window. + +tmuxp.window +~~~~~~~~~~~~ + +tmuxp helps you manage tmux workspaces. - tmuxp helps you manage tmux workspaces. +:copyright: Copyright 2013 Tony Narlock. +:license: BSD, see LICENSE for details - :copyright: Copyright 2013 Tony Narlock. - :license: BSD, see LICENSE for details """ from __future__ import absolute_import, division, print_function, with_statement diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index 92a586ad796..3d06d5dae00 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -1,12 +1,14 @@ # -*- coding: utf8 -*- -""" - tmuxp.builder - ~~~~~~~~~~~~~ +"""Create a tmux workspace from a configuration :py:obj:`dict`. + +tmuxp.workspacebuilder +~~~~~~~~~~~~~~~~~~~~~~ + +tmuxp helps you manage tmux workspaces. - tmuxp helps you manage tmux workspaces. +:copyright: Copyright 2013 Tony Narlock. +:license: BSD, see LICENSE for details - :copyright: Copyright 2013 Tony Narlock. - :license: BSD, see LICENSE for details """ from __future__ import absolute_import, division, print_function, with_statement From 5fd998b7eeef7994e45f8c2fea67d9ec7af67a6c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 14:15:44 +0800 Subject: [PATCH 0135/3283] pep247. pep8, docs --- tmuxp/pane.py | 2 + tmuxp/server.py | 102 +++++++++++++++++++++++++++++------------------- 2 files changed, 63 insertions(+), 41 deletions(-) diff --git a/tmuxp/pane.py b/tmuxp/pane.py index f5629e5cbe5..5204aa96155 100644 --- a/tmuxp/pane.py +++ b/tmuxp/pane.py @@ -65,6 +65,8 @@ def tmux(self, cmd, *args, **kwargs): Specifying ``('-t', 'custom-target')`` or ``('-tcustom_target')`` in ``args`` will override using the object's ``pane_id`` as target. + :rtype: :class:`util.tmux` + """ if not len([arg for arg in args if '-t' in arg]): args = ('-t', self.get('pane_id')) + args diff --git a/tmuxp/server.py b/tmuxp/server.py index 304c3dae26b..2bcfe48d75b 100644 --- a/tmuxp/server.py +++ b/tmuxp/server.py @@ -15,7 +15,7 @@ import os from .util import tmux, TmuxRelationalObject from .session import Session -from . import formats +from . import formats, exc import logging logger = logging.getLogger(__name__) @@ -23,8 +23,7 @@ class Server(TmuxRelationalObject): - ''' - The :term:`tmux(1)` server. Container for: + """The :term:`tmux(1)` server. - :attr:`Server._sessions` [:class:`Session`, ...] @@ -36,7 +35,8 @@ class Server(TmuxRelationalObject): When instantiated, provides the ``t`` global. stores information on live, running tmux server. - ''' + + """ #: socket name socket_name = None @@ -69,6 +69,12 @@ def __init__( self.colors = colors def tmux(self, *args, **kwargs): + """Send command to tmux with :attr:`pane_id` as ``target-pane``. + + :rtype: :class:`util.tmux` + + """ + args = list(args) if self.socket_name: args.insert(0, '-L{}'.format(self.socket_name)) @@ -87,11 +93,14 @@ def tmux(self, *args, **kwargs): return tmux(*args, **kwargs) def __list_sessions(self): - ''' - compatibility wrapping for ``$ tmux list-sessions``. + """Return list of ``$ tmux(1) list-sessions`` stdout. - :rtype: stdout or stderr of tmux proc - ''' + The :py:obj:`list` is derived from ``stdout`` in :class:`util.tmux` + which wraps :py:meth:`Subprocess.Popen`. + + :rtype: list + + """ sformats = formats.SESSION_FORMATS tmux_formats = ['#{%s}' % f for f in sformats] @@ -166,8 +175,8 @@ def sessions(self): def __list_windows(self): """Return list of ``$ tmux(1) list-windows`` stdout. - The :py:obj:`list` is derived from :class:`util.tmux` which wraps - :py:meth:`Subprocess.Popen`. + The :py:obj:`list` is derived from ``stdout`` in :class:`util.tmux` + which wraps :py:meth:`Subprocess.Popen`. :rtype: list @@ -217,15 +226,20 @@ def _list_windows(self): return self._windows def _update_windows(self): - """Update internal window data and return ``self`` for chainability.""" + """Update internal window data and return ``self`` for chainability. + + :rtype: :class:`Server` + + """ self._list_windows() return self def __list_panes(self): """Return list of ``$ tmux(1) list-panes`` stdout. - The :py:obj:`list` is derived from :class:`util.tmux` which wraps - :py:meth:`Subprocess.Popen`. + The :py:obj:`list` is derived from ``stdout`` in :class:`util.tmux` + which wraps :py:meth:`Subprocess.Popen`. + :rtype: list @@ -272,15 +286,22 @@ def _list_panes(self): return self._panes def _update_panes(self): + """Update internal pane data and return ``self`` for chainability. + + :rtype: :class:`Server` + + """ self._list_panes() return self def attached_sessions(self): - ''' - Returns active :class:`Session` object + """Return active :class:`Session` object. - This will not work where multiple tmux sessions are attached. - ''' + This will not work where multiple tmux sessions are attached. + + :rtype: :class:`Server` + + """ sessions = self._sessions attached_sessions = list() @@ -298,13 +319,12 @@ def attached_sessions(self): return attached_sessions or None def has_session(self, target_session): - ''' - ``$ tmux has-session`` + """Return True if session exists. ``$ tmux has-session``. :param: target_session: str of session name. + :rtype: bool - returns True if session exists. - ''' + """ proc = self.tmux('has-session', '-t%s' % target_session) @@ -316,18 +336,18 @@ def has_session(self, target_session): return True def kill_server(self): - ''' - ``$ tmux kill-server`` - ''' + """``$ tmux kill-server``.""" self.tmux('kill-server') def kill_session(self, target_session=None): - ''' - ``$ tmux kill-session`` + """Kill the tmux session with ``$ tmux kill-session``. - :param: target_session: str. note this accepts fnmatch(3). 'asdf' will - kill asdfasd - ''' + :param: target_session: str. note this accepts ``fnmatch(3)``. 'asdf' + will kill 'asdfasd'. + + :rtype: :class:`Server` + + """ proc = self.tmux('kill-session', '-t%s' % target_session) if proc.stderr: @@ -336,11 +356,12 @@ def kill_session(self, target_session=None): return self def switch_client(self, target_session): - ''' - ``$ tmux switch-client`` + """``$ tmux switch-client``. :param: target_session: str. name of the session. fnmatch(3) works. - ''' + + """ + # tmux('switch-client', '-t', target_session) proc = self.tmux('switch-client', '-t%s' % target_session) @@ -348,11 +369,11 @@ def switch_client(self, target_session): raise Exception(proc.stderr) def attach_session(self, target_session=None): - ''' - ``$ tmux attach-session`` aka alias: ``$ tmux attach`` + """``$ tmux attach-session`` aka alias: ``$ tmux attach``. :param: target_session: str. name of the session. fnmatch(3) works. - ''' + + """ # tmux('switch-client', '-t', target_session) tmux_args = tuple() if target_session: @@ -369,10 +390,7 @@ def new_session(self, attach=False, *args, **kwargs): - ''' - ``$ tmux new-session`` - - Returns :class:`Session` + """Return :class:`Session` from ``$ tmux new-session``. Uses ``-P`` flag to print session info, ``-F`` for return formatting returns new Session object. @@ -399,14 +417,16 @@ def new_session(self, :param kill_session: Kill current session if ``$ tmux has-session`` Useful for testing workspaces. :type kill_session: bool - ''' + :rtype: :class:`Session` + + """ if self.has_session(session_name): if kill_session: self.tmux('kill-session', '-t%s' % session_name) logger.info('session %s exists. killed it.' % session_name) else: - raise TmuxSessionExists( + raise exc.TmuxSessionExists( 'Session named %s exists' % session_name ) From 7e3313ec7abe163fdae72a8d8da829a9e4ec2b63 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 14:16:19 +0800 Subject: [PATCH 0136/3283] examples.rst: remove unnused sidebar from shorthand --- doc/examples.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/examples.rst b/doc/examples.rst index 949fcf65d40..61b5b8dff32 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -170,8 +170,6 @@ Start Directory Equivalent to ``tmux new-window -c ``. -.. sidebar:: short hand - YAML """" From cdeeee71d7278198cad920a18371100892d45b49 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 14:27:24 +0800 Subject: [PATCH 0137/3283] pep257, pep8, docstrings --- tmuxp/pane.py | 2 +- tmuxp/server.py | 3 +-- tmuxp/session.py | 15 ++++++++++----- tmuxp/window.py | 14 +++++++------- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/tmuxp/pane.py b/tmuxp/pane.py index 5204aa96155..39915e12fea 100644 --- a/tmuxp/pane.py +++ b/tmuxp/pane.py @@ -65,7 +65,7 @@ def tmux(self, cmd, *args, **kwargs): Specifying ``('-t', 'custom-target')`` or ``('-tcustom_target')`` in ``args`` will override using the object's ``pane_id`` as target. - :rtype: :class:`util.tmux` + :rtype: :class:`Server.tmux` """ if not len([arg for arg in args if '-t' in arg]): diff --git a/tmuxp/server.py b/tmuxp/server.py index 2bcfe48d75b..338ada142c5 100644 --- a/tmuxp/server.py +++ b/tmuxp/server.py @@ -250,7 +250,6 @@ def __list_panes(self): panes = self.tmux( 'list-panes', - #'-t%s:%s' % (self.get('session_name'), self.get('window_id')), '-a', '-F%s' % ''.join(tmux_formats), # output ) @@ -340,7 +339,7 @@ def kill_server(self): self.tmux('kill-server') def kill_session(self, target_session=None): - """Kill the tmux session with ``$ tmux kill-session``. + """Kill the tmux session with ``$ tmux kill-session``, return ``self``. :param: target_session: str. note this accepts ``fnmatch(3)``. 'asdf' will kill 'asdfasd'. diff --git a/tmuxp/session.py b/tmuxp/session.py index d9fc1b0e8d1..f9e58ce3e73 100644 --- a/tmuxp/session.py +++ b/tmuxp/session.py @@ -64,16 +64,21 @@ def by(val, *args): logger.error(self.server._sessions) def tmux(self, *args, **kwargs): - # if '-t' not in kwargs: - # kwargs['-t'] = self.get['session_id'] + """Return :meth:`Server.tmux`. + + :rtype: :class:`Server.tmux` + + """ + if '-t' not in kwargs: + kwargs['-t'] = self.get('session_id') return self.server.tmux(*args, **kwargs) def attach_session(self, target_session=None): - ''' - ``$ tmux attach-session`` aka alias: ``$ tmux attach`` + """ Return ``$ tmux attach-session`` aka alias: ``$ tmux attach``. :param: target_session: str. name of the session. fnmatch(3) works. - ''' + + """ proc = self.tmux('attach-session', '-t%s' % self.get('session_id')) if proc.stderr: diff --git a/tmuxp/window.py b/tmuxp/window.py index 83ad3108ef0..a0865bb1223 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -23,9 +23,7 @@ class Window(util.TmuxMappingObject, util.TmuxRelationalObject): - ''' - ``tmux(1) window``. - ''' + """:ref:`tmux(1)` window.""" childIdAttribute = 'pane_id' @@ -42,14 +40,12 @@ def __init__(self, session=None, **kwargs): self._window_id = kwargs['window_id'] - #self.server._update_windows() - def __repr__(self): return "%s(%s %s:%s, %s)" % ( self.__class__.__name__, self.get('window_id'), self.get('window_index'), - self.get('window_name'), # @todo, bug when window name blank + self.get('window_name'), self.session ) @@ -73,11 +69,15 @@ def by(val, *args): return list(filter(by, self.server._windows))[0] def tmux(self, cmd, *args, **kwargs): - """Send command to tmux with :attr:`window_id` as ``target-window``. + """Return :meth:`Server.tmux` defaulting ``target_window`` as target. + + Send command to tmux with :attr:`window_id` as ``target-window``. Specifying ``('-t', 'custom-target')`` or ``('-tcustom_target')`` in ``args`` will override using the object's ``window_id`` as target. + :rtype: :class:`Server.tmux` + """ if not len([arg for arg in args if '-t' in str(arg)]): args = ('-t', self.get('window_id')) + args From 92d8e757bcd5f8a667be9a679acfd257ee70f2c6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 14:36:23 +0800 Subject: [PATCH 0138/3283] more docs for internals --- doc/api.rst | 6 +++--- doc/internals.rst | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index db469c6175c..0f40cf65986 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -1,8 +1,8 @@ .. _api: -==================== -Python API Reference -==================== +=================== +tmuxp API Reference +=================== .. module:: tmuxp diff --git a/doc/internals.rst b/doc/internals.rst index 2fa6631e0b5..3ec4e4d79e3 100644 --- a/doc/internals.rst +++ b/doc/internals.rst @@ -4,13 +4,15 @@ Internals ========= +.. seealso:: :ref:`api` + .. module:: tmuxp tmuxp is an `abstraction layer` against tmux' command line arguments. -tmuxp is an `ORM` in the sense bases of :class:`util.TmuxObject`, such as -:class:`Server`, :class:`Session`, :class:`Window` and :class:`Pane` -are stateful objects and related to their parent or child. +:class:`util.TmuxRelationalObject` acts as a container to connect the +relations of :class:`Server`, :class:`Session`, :class:`Window` and +:class:`Pane`. ======================== ======================= ========================= Object Child Parent @@ -29,7 +31,9 @@ A server can have multiple sessions. ``Ctrl-a s`` can be used to switch between sessions running on the server. Sessions, Windows and Panes all have their own unique identifier for -internal purposes. +internal purposes. :class:`util.TmuxMappingObject` will make use of the +unique identifiers (``session_id``, ``window_id``, ``pane_id`` ) to look +up the data stored in the :class:`Server` object. ======================== ======================= ========================= Object Prefix Example From 9f359f09878614a054dad4e6e81e493e2d8a7239 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 14:36:23 +0800 Subject: [PATCH 0139/3283] more docs for internals --- doc/api.rst | 6 +++--- doc/internals.rst | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index db469c6175c..0f40cf65986 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -1,8 +1,8 @@ .. _api: -==================== -Python API Reference -==================== +=================== +tmuxp API Reference +=================== .. module:: tmuxp diff --git a/doc/internals.rst b/doc/internals.rst index 2fa6631e0b5..ad7e7d26830 100644 --- a/doc/internals.rst +++ b/doc/internals.rst @@ -4,13 +4,15 @@ Internals ========= +.. seealso:: :ref:`api` + .. module:: tmuxp -tmuxp is an `abstraction layer` against tmux' command line arguments. +tmuxp is an *abstraction layer* against tmux' command line arguments. -tmuxp is an `ORM` in the sense bases of :class:`util.TmuxObject`, such as -:class:`Server`, :class:`Session`, :class:`Window` and :class:`Pane` -are stateful objects and related to their parent or child. +:class:`util.TmuxRelationalObject` acts as a container to connect the +relations of :class:`Server`, :class:`Session`, :class:`Window` and +:class:`Pane`. ======================== ======================= ========================= Object Child Parent @@ -29,7 +31,9 @@ A server can have multiple sessions. ``Ctrl-a s`` can be used to switch between sessions running on the server. Sessions, Windows and Panes all have their own unique identifier for -internal purposes. +internal purposes. :class:`util.TmuxMappingObject` will make use of the +unique identifiers (``session_id``, ``window_id``, ``pane_id`` ) to look +up the data stored in the :class:`Server` object. ======================== ======================= ========================= Object Prefix Example From 465dba43ae20bc12dcdef47ea07d4d626776dfe3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 14:37:38 +0800 Subject: [PATCH 0140/3283] rename tmuxp API reference to API reference --- doc/api.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index 0f40cf65986..9b7f9be621f 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -1,8 +1,8 @@ .. _api: -=================== -tmuxp API Reference -=================== +============= +API Reference +============= .. module:: tmuxp From e695d2c1af75c1fd8209b213f2e710ba9138a393 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 17:46:56 +0800 Subject: [PATCH 0141/3283] api changes --- doc/api.rst | 37 +++++-------------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index 9b7f9be621f..946f070f7d8 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -22,19 +22,9 @@ Session Object .. autoclass:: Session :members: :inherited-members: + :private-members: :show-inheritance: - - .. attribute:: server - - The :class:`Server` of the window. - - .. attribute:: windows - - A :py:obj:`list` of the window's :class:`Window` objects. - - .. attribute:: _window - - A :py:obj:`list` of the session's windows as :py:obj:`dict`. + :member-order: bysource Window Object ------------- @@ -44,18 +34,7 @@ Window Object :inherited-members: :private-members: :show-inheritance: - - .. attribute:: session - - The :class:`Session` of the window. - - .. attribute:: panes - - A :py:obj:`list` of the window's :class:`Pane` objects. - - .. attribute:: _panes - - A :py:obj:`list` of the window's panes as :py:obj:`dict`. + :member-order: bysource Pane Object ----------- @@ -63,15 +42,9 @@ Pane Object .. autoclass:: Pane :members: :inherited-members: + :private-members: :show-inheritance: - - .. attribute:: _session - - The :class:`Session` of the pane. - - .. attribute:: _window - - The :class:`Window` of the pane. + :member-order: bysource Internals --------- From 65e9bcc20b6d476d26bba56193fb9f8535745387 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 1 Nov 2013 18:39:47 +0800 Subject: [PATCH 0142/3283] doc api updates for Window --- tmuxp/window.py | 92 ++++++++++++++++++++----------------------------- 1 file changed, 37 insertions(+), 55 deletions(-) diff --git a/tmuxp/window.py b/tmuxp/window.py index a0865bb1223..62b16cb5532 100644 --- a/tmuxp/window.py +++ b/tmuxp/window.py @@ -85,12 +85,7 @@ def tmux(self, cmd, *args, **kwargs): return self.server.tmux(cmd, *args, **kwargs) def select_layout(self, layout=None): - ''' - wrapper for ``tmux(1)``. - - .. code-block: bash - - $ tmux select-layout + """Wrapper for ``$ tmux select-layout ``. even-horizontal: Panes are spread out evenly from left to right across the window. @@ -111,8 +106,8 @@ def select_layout(self, layout=None): :param layout: string of the layout, 'even-horizontal', 'tiled', etc. :type layout: string - ''' + """ proc = self.tmux( 'select-layout', @@ -123,21 +118,13 @@ def select_layout(self, layout=None): if proc.stderr: raise Exception(proc.stderr) - @property - def target(self): - return "%s:%s" % (self.session.get('session_id'), self.get('window_id')) - def set_window_option(self, option, value): - ''' - wrapper for ``tmux(1)``. - - .. code-block: bash - - $ tmux set-window-option