Esempio n. 1
0
def server(request):
    t = Server()
    t.socket_name = 'tmuxp_test%s' % next(namer)

    def fin():
        t.kill_server()
    request.addfinalizer(fin)

    return t
Esempio n. 2
0
def server(request, socket_name):
    t = Server()
    t.socket_name = socket_name

    def fin():
        t.kill_server()

    request.addfinalizer(fin)

    return t
Esempio n. 3
0
def server(request):
    t = Server()
    t.socket_name = 'tmuxp_test%s' % next(namer)

    def fin():
        t.kill_server()

    request.addfinalizer(fin)

    return t
Esempio n. 4
0
def server(request, monkeypatch):

    t = Server()
    t.socket_name = "tmuxp_test%s" % next(namer)

    def fin():
        t.kill_server()

    request.addfinalizer(fin)

    return t
Esempio n. 5
0
    def __init__(self):

        self.server = Server()
        self.miner_session = None
        self.miner_layout = ''

        # get the miner session if exists.
        # we don't use exact match
        # the session name is like 'multiminer-zen'
        if self.server.has_session(SESSION_NAME, exact=False):
            for sess in self.server.list_sessions():
                if sess['session_name'].startswith(SESSION_NAME):
                    self.miner_session = sess
                    self.miner_layout = sess['session_name'][len(SESSION_NAME)+1:]
                    break
Esempio n. 6
0
def command_freeze(session_name, socket_name, socket_path):
    """Import teamocil config to tmuxp format."""

    t = Server(
        socket_name=socket_name,
        socket_path=socket_path,
    )

    try:
        session = t.find_where({
            'session_name': session_name
        })

        if not session:
            raise exc.TmuxpException('Session not found.')
    except exc.TmuxpException as e:
        print(e)
        return

    sconf = freeze(session)
    configparser = kaptan.Kaptan()
    newconfig = config.inline(sconf)
    configparser.import_config(newconfig)
    config_format = "yaml"
    newconfig = configparser.export(
            'yaml', indent=2, default_flow_style=False, safe=True
    )

    save_to = os.path.abspath(
        os.path.join(
            get_config_dir(),
            '%s.%s' % (sconf.get('session_name'), config_format)
        )
    )
    dest_prompt = save_to
    dest = dest_prompt
    dest = os.path.abspath(os.path.relpath(os.path.expanduser(dest)))
    destdir = os.path.dirname(dest)
    if not os.path.isdir(destdir):
        os.makedirs(destdir)
    buf = open(dest, 'w')
    buf.write(newconfig)
    buf.close()

    print('Saved to %s.' % dest)
Esempio n. 7
0
def command_shell(
    session_name,
    window_name,
    socket_name,
    socket_path,
    command,
    shell,
    use_pythonrc,
    use_vi_mode,
):
    """Launch python shell for tmux server, session, window and pane.

    Priority given to loaded session/wndow/pane objects:
    - session_name and window_name arguments
    - current shell: environmental variable of TMUX_PANE (which gives us window and
      session)
    - ``server.attached_session``, ``session.attached_window``, ``window.attached_pane``
    """
    server = Server(socket_name=socket_name, socket_path=socket_path)

    util.raise_if_tmux_not_running(server=server)

    current_pane = util.get_current_pane(server=server)

    session = util.get_session(server=server,
                               session_name=session_name,
                               current_pane=current_pane)

    window = util.get_window(session=session,
                             window_name=window_name,
                             current_pane=current_pane)

    pane = util.get_pane(window=window,
                         current_pane=current_pane)  # NOQA: F841

    if command is not None:
        exec(command)
    else:
        if shell == 'pdb' or (os.getenv('PYTHONBREAKPOINT') and PY3
                              and PYMINOR >= 7):
            from ._compat import breakpoint as tmuxp_breakpoint

            tmuxp_breakpoint()
            return
        else:
            from .shell import launch

            launch(
                shell=shell,
                use_pythonrc=use_pythonrc,  # shell: code
                use_vi_mode=use_vi_mode,  # shell: ptpython, ptipython
                # tmux environment / libtmux variables
                server=server,
                session=session,
                window=window,
                pane=pane,
            )
Esempio n. 8
0
def main():
    """Main CLI application."""

    parser = get_parser()

    argcomplete.autocomplete(parser, always_complete_options=False)

    args = parser.parse_args()

    log_level = 'INFO'
    if 'log_level' in args and isinstance(args.log_level, string_types):
        log_level = args.log_level.upper()

    setup_logger(level=log_level)

    try:
        has_required_tmux_version()
    except exc.TmuxpException as e:
        logger.error(e)
        sys.exit()

    util.oh_my_zsh_auto_title()

    t = Server(  # noqa
        socket_name=args.socket_name,
        socket_path=args.socket_path,
        colors=args.colors)

    try:
        if not hasattr(args, 'callback'):
            parser.print_help()
        elif 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_freeze:
            command_freeze(args)
        elif args.callback is command_attach_session:
            command_attach_session(args)
        elif args.callback is command_kill_session:
            command_kill_session(args)
    except KeyboardInterrupt:
        pass
Esempio n. 9
0
def SessionCompleter(prefix, parsed_args, **kwargs):
    """Return list of session names for argcomplete completer."""

    t = Server(socket_name=parsed_args.socket_name,
               socket_path=parsed_args.socket_path)

    sessions_available = [
        s.get('session_name') for s in t._sessions
        if s.get('session_name').startswith(' '.join(prefix))
    ]

    if parsed_args.session_name and sessions_available:
        return []

    return [
        s.get('session_name') for s in t._sessions
        if s.get('session_name').startswith(prefix)
    ]
Esempio n. 10
0
def command_kill_session(args):
    """Command to kill a tmux session."""
    ctext = ' '.join(args.session_name)

    t = Server(socket_name=args.socket_name or None,
               socket_path=args.socket_path or None)

    try:
        session = next(
            (s for s in t.sessions if s.get('session_name') == ctext), None)
        if not session:
            raise exc.TmuxpException('Session not found.')
    except exc.TmuxpException as e:
        print(e)
        return

    try:
        session.kill_session()
        print("Killed session %s." % ctext)
    except exc.TmuxpException as e:
        logger.error(e)
Esempio n. 11
0
def command_attach_session(args):
    """Command to attach / switch client to a tmux session."""
    ctext = ' '.join(args.session_name)

    t = Server(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('session_name') == ctext), None)
        if not session:
            raise exc.TmuxpException('Session not found.')
    except exc.TmuxpException as e:
        print(e)
        return

    if 'TMUX' in os.environ:
        del os.environ['TMUX']
        session.switch_client()
        print('Inside tmux client, switching client.')
    else:
        session.attach_session()
        print('Attaching client.')
Esempio n. 12
0
class MultiMiner(object):
    """ multi miner class 
    
    use session name suffix as the identifier for runner plan

    Command List
        start [planname]        run the corresponding plan, or the default if planname not given
        stop                    stop the miner tmux session

    TMUX commands you might use
        C-b d          detach the current session
        C-b left       go to the next pane on the left
        C-b right      (or one of these other directions)
        C-b up
        C-b down
    """
    
    def __init__(self):

        self.server = Server()
        self.miner_session = None
        self.miner_layout = ''

        # get the miner session if exists.
        # we don't use exact match
        # the session name is like 'multiminer-zen'
        if self.server.has_session(SESSION_NAME, exact=False):
            for sess in self.server.list_sessions():
                if sess['session_name'].startswith(SESSION_NAME):
                    self.miner_session = sess
                    self.miner_layout = sess['session_name'][len(SESSION_NAME)+1:]
                    break

    def _miner_exist(func):
        def _decorator(self, *args, **kwargs):
            if self.miner_session is None:
                print("NO MINER SESSION RUNNING")
                return
            return func(self, *args, **kwargs)
        return _decorator

    @_miner_exist
    def miners(self):
        pass
        
    @_miner_exist
    def stop(self):
        try:
            self.server.kill_session(SESSION_NAME)
            print("MINER STOPPED")
        except:
            # LibTmuxException
            pass

    def start(self, target="default"):
        # load config file
        with open("./config.yaml", 'r') as stream:
            try:
                config = yaml.load(stream)

                # kill all miner sessions
                if self.server.has_session(SESSION_NAME, exact=False):
                    self.server.kill_session(target_session=SESSION_NAME)
                    print("Killing the running miners ...")
                
                # run new session
                self.miner_session = self.server.new_session(
                    session_name=SESSION_NAME + '-' + target,
                    kill_session=True,
                    )

                self._build_layout(target, config)

            except yaml.YAMLError as e:
                print(e)
            except:
                pass
        pass

    def _build_layout(self, target, config):
        
        runner_config = config['runners'][target]

        # we use only one window, the default window
        default_window = self.miner_session.attached_window

        p = None 
        for miner_conf in runner_config:
            device_config = miner_conf['devices']
            if device_config is None or len(device_config) == 0:
                # skip if no or 0 device configed
                continue

            if p is None:
                p = default_window.attached_pane
            else:
                # split the current window for more panes
                p = default_window.split_window(
                    target=p.id,
                    attach=True,
                    start_directory= None,
                    vertical=False
                )
            
            default_window.select_layout('even-horizontal') # default layout
            default_window.server._update_panes()

            wallet_config = config['wallets'][miner_conf['wallet']]
            miner_config = config['miners'][miner_conf['miner']]

            # build cmd
            cmd = self._build_miner_cmd(miner_conf, wallet_config, miner_config, device_config)
            print(cmd)
            p.send_keys(cmd, suppress_history=True)

        self.server.attach_session(SESSION_NAME)
            
    
    def _build_miner_cmd(self, miner_conf, wallet, miner, device):
        cmd = ''
        miner_name = miner_conf['miner']

        if miner_name == 'zm':
            # zm --server servername.com --port 1234 --user username -- dev 0 1 2 --time --color
            # TODO: support temperature adaptation
            protocol = ''
            if wallet['ssl'] is True:
                protocol = 'ssl://'
            cmd = '%s --server %s%s --port %d --user %s --pass %s --dev %s --time --color' % (miner['location'], protocol, wallet['server'], wallet['port'], wallet['address'], wallet['pass'], " ".join(map(str, device)))

        if miner_name == 'bminer':
            # ./bminer -uri $SCHEME://$USERNAME@$POOL -api 127.0.0.1:1880
            protocol = 'stratum://'
            if wallet['ssl'] is True:
                protocol = 'stratum+ssl://'
            cmd = '%s -uri %s%s:%s@%s:%s -devices %s' % (miner['location'], protocol, wallet['address'], wallet['pass'], wallet['server'], wallet['port'], ",".join(map(str, device)))

        if miner_name == 'ethminer':
            # ./ethminer -P stratum+ssl://0x2f112f0f47fda00fb52493a990d49a75faed69e3.miner1@us1.ethermine.org:5555 -U
            protocol = 'stratum+tcp://'
            if wallet['ssl'] is True:
                protocol = 'stratum+ssl://'
            cmd = '%s -P %s%s:%s@%s:%s -U --cuda-devices %s' % (miner['location'], protocol, wallet['address'], wallet['pass'], wallet['server'], wallet['port'], " ".join(map(str, device)))
	if miner_name == 'ccminer':
	    protocol = 'stratum+tcp://'
            alg = miner_conf['wallet'].split('-')[-1]
            if wallet['ssl'] is True:
                print("ccminer not support ssl")
                return "exit"
            cmd = '%s -a %s -o %s%s:%s -u %s -p %s -d %s' % (miner['location'], alg, protocol, wallet['server'], wallet['port'], wallet['address'], wallet['pass'],  ",".join(map(str, device)))
        return cmd
Esempio n. 13
0
def command_freeze(args):
    """Import teamocil config to tmuxp format."""

    ctext = ' '.join(args.session_name)

    t = Server(socket_name=args.socket_name,
               socket_path=args.socket_path,
               colors=args.colors)

    try:
        session = t.findWhere({'session_name': ctext})

        if not session:
            raise exc.TmuxpException('Session not found.')
    except exc.TmuxpException as e:
        print(e)
        return

    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 args.answer_yes or prompt_yes_no(
            'The new config *WILL* require adjusting afterwards. Save config?'
    ):
        dest = None
        while not dest:
            save_to = os.path.abspath(
                os.path.join(
                    config_dir,
                    '%s.%s' % (sconf.get('session_name'), config_format)))
            dest_prompt = prompt('Save to: ', save_to)
            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(os.path.expanduser(dest)))
        if args.answer_yes or prompt_yes_no('Save to %s?' % dest):
            destdir = os.path.dirname(dest)
            if not os.path.isdir(destdir):
                os.makedirs(destdir)
            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 '
              '<http://tmuxp.readthedocs.org/en/latest/examples.html>\n'
              'View tmuxp docs at <http://tmuxp.readthedocs.org/>.')
        sys.exit()
Esempio n. 14
0
class AppController(Controller):
    """Main application class."""

    def __init__(self, common: Common, args):
        super().__init__(common, type(self).__name__)

        self._scriptdir = os.path.dirname(os.path.abspath(__file__))
        self._common = common
        self.is_exit = False

        self.workdir = os.getcwd()
        self.file = ''
        self.debug_bin = "t1"

        self.tmux_server = None
        self.tmux_session = None
        self.tmux_pwin_idx = ''
        self.tmux_window_vim = None
        self.tmux_curr_pan_id = ''
        self.tmux_pan_vim = None
        self.tmux_pan_gdb = None
        self.tmux_pan_gdbserver = None
        self.tmux_sesname = ""
        self.tmux_sesid = ""
        self.tmux_win_def_width = 800
        self.tmux_win_def_height = 600

        self.layout_conf = {}
        self.workSpace = None
        self.workLayouts = {}
        self.helper = {}
        self.helper['worklayouts_loaded'] = False

        self.ctx_gdb = None
        self.ctx_gdbserver = None

        self.cmd_gdb = ""
        self.cmd_gdbserver = ''
        self.curr_layout = ''

        # self.breakpoint = Breakpoint(common)
        # self.cursor = Cursor(common)
        # self.win = Win(common, self.cursor)


    def _wrap_async(self, func):
        """
        Wraps `func` so that invocation of `func(args, kwargs)` happens
        from the main thread. This is a requirement of pynvim API when
        function call happens from other threads.
        Related issue: https://github.com/numirias/semshi/issues/25
        """

        def wrapper(*args, **kwargs):
            return self.vim.async_call(func, *args, **kwargs)

        return wrapper


    def create_gdb_local(self, args):
        modelGdb = Gdb(self._common,
                self,
                self.tmux_window_vim,
                self.workSpace.get_pane(self.curr_layout, Common.tmux_pane_builtin_gdb),
                self.debug_bin, self.gdb_output)
        if not modelGdb:
            return
        self.models_coll[modelGdb._name] = modelGdb

        # self.vim.command('let g:vimgdb_gdb = ' + modelGdb._name)
        self.vim.vars['vimgdb_gdb'] = modelGdb._name

        self.tmux_server._update_windows()
        self.tmux_server._update_panes()


    def create_gdb_remote(self, args):
        modelGdbserver = GdbServer(self._common, self,
                self.tmux_window_vim,
                self.workSpace.get_pane(self.curr_layout, Common.tmux_pane_builtin_gdbserver),
                self.debug_bin, self.gdbserver_output)
        if not modelGdbserver:
            return
        self.models_coll[modelGdbserver._name] = modelGdbserver
        # self.vim.command('let g:vimgdb_gdbserver = ' + modelGdbserver._name)
        self.vim.vars['vimgdb_gdbserver'] = modelGdbserver._name

        self.tmux_server._update_windows()
        self.tmux_server._update_panes()


    def _define_vimsigns(self):
        # Define the sign for current line the debugged program is executing.
        self.vim.call('sign_define', 'GdbCurrentLine',
                {'text': self.vim.vars['vimgdb_sign_currentline'],
                 'texthl': self.vim.vars['vimgdb_sign_currentline_color']})

        # Define signs for the breakpoints.
        breaks = self.vim.vars['vimgdb_sign_breakpoints']
        for i, brk in enumerate(breaks):
            #sign define GdbBreakpointEn  text=● texthl=Search
            #sign define GdbBreakpointDis text=● texthl=Function
            #sign define GdbBreakpointDel text=● texthl=Comment

            self.vim.call('sign_define', f'GdbBreakpointEn{i+1}',
                    {'text': brk,
                     'texthl': self.vim.vars['vimgdb_sign_breakp_color_en']})
            self.vim.call('sign_define', f'GdbBreakpointDis{i+1}',
                    {'text': brk,
                     'texthl': self.vim.vars['vimgdb_sign_breakp_color_dis']})
            Common.vimsign_break_max += 1


    def list_layout(self):
        names = ''
        for layoutname in self.workLayouts.keys():
            names += layoutname + ', '
        self.vim.command(f'echomsg "VimGdb layout: `{names}`"')


    def load_layout_conf(self):
        self.conf = self._scriptdir + "/../config/default.json"
        if os.path.isfile(Common.vimgdb_conffile):
            self.conf = Common.vimgdb_conffile
        #self.logger.info(f"connect config={self.conf}")
        with open(self.conf, 'r') as f:
            content = f.read()
            #decoded_data=content.encode().decode('utf-8-sig')
            self.layout_conf = json.loads(content)

    def build_workspace(self):
        self.load_layout_conf()

        tmux_builtin_panes = {}
        self.helper[Common.tmux_builtin_panes] = tmux_builtin_panes
        tmux_builtin_panes[Common.tmux_pane_builtin_main] = ''
        tmux_builtin_panes[Common.tmux_pane_builtin_gdb] = Gdb.get_cmdstr(self._scriptdir, self.debug_bin)

        # Avoid gdbserver start too ealier, waiting gdb done.
        #tmux_builtin_panes[Common.tmux_pane_builtin_gdbserver] = GdbServer.get_cmdstr(self._scriptdir, self.debug_bin)
        tmux_builtin_panes[Common.tmux_pane_builtin_gdbserver] = ''

        self.workSpace = Workspace(self._common,
                self.layout_conf,
                self.helper[Common.tmux_builtin_panes],
                self.workdir,
                self.tmux_server, self.tmux_win_def_width, self.tmux_win_def_height)

        self.build_set_current()
        if self.gdbMode == GdbMode.LOCAL:
            self.curr_layout = Common.tmux_layout_local
        elif self.gdbMode == GdbMode.REMOTE:
            self.curr_layout = Common.tmux_layout_remote

        self.build_all_layout_codes()
        self.build_layout(self.curr_layout)


    def build_all_layout_codes(self):
        if self.workLayouts and self.helper['worklayouts_loaded']:
            self.logger.info(f"connect Existed and don't need create layout={self.workLayouts}")
            return

        self.helper['worklayouts_loaded'] = True
        self.workLayouts.update(self.workSpace.build_all_layout_codes(Common.tmux_vimgdb_session_name))
        self.logger.info(f"connect layout={self.workLayouts}")


    def build_set_current(self):
        # Tmux: reuse current tmux-window, but close all other panes in current window
        #   for only current vim is the controled vim instance.
        # self.tmux_window_vim = self.tmux_session.new_window(
        #        attach=True,           # do not move to the new window
        #        window_name="VimGdb",
        #        start_directory=self.workdir,
        #        window_index='', #
        #        window_shell='', #"vim " + self.file,
        #        )
        self.tmux_window_vim = self.tmux_session.attached_window;
        assert isinstance(self.tmux_window_vim, Window)
        self.tmux_window_vim['window_name'] = self.curr_layout

        self.tmux_pane_vim = self.tmux_window_vim.attached_pane
        assert isinstance(self.tmux_pane_vim, Pane)
        self.tmux_pane_vim['pane_name'] = Common.tmux_pane_builtin_main


    def build_layout(self, layout: str):
        self.logger.info(f"connect rebuild layout '{layout}'")
        self.workSpace.build_one_layout(layout,
                self.tmux_session,
                self.tmux_window_vim,
                self.tmux_pane_vim,
                Common.tmux_pane_builtin_main)


    def layout_select(self, layout: str):
        if layout not in self.workLayouts:
            self.vim.command(f'echomsg "VimGdb layout `{layout}` not exist, check VimGdbLayoutList()"')
            return

        # But can't create new pane
        #self.tmux_window_vim.select_layout(self.workLayouts[layout]['layout'])

        self.workSpace.build_one_layout(layout,
                self.tmux_session,
                self.tmux_window_vim,
                self.tmux_pane_vim,
                Common.tmux_pane_builtin_main)


    def run(self, args):
        os.system(f'touch {Common.vimgdb_debugfile}; truncate -s 0 {Common.vimgdb_debugfile}')

        self.logger.info("==============================================")
        self.logger.info("==============================================")
        self.logger.info("==============================================")
        self.logger.info("==============================================")
        self.logger.info("             *** Gdb instance ***")
        self.logger.info("")
        self.logger.info("args=%s", args)
        arg_n = len(args)
        if arg_n < 2:
            self.vim.command('echomsg "Gdb start fail, should: call VimGdb(\'local\', \'<bin-file>\')"')
            return

        os.system(f'touch {Common.gdb_output}; truncate -s 0 {Common.gdb_output}')
        os.system(f'touch {Common.gdbserver_output}; truncate -s 0 {Common.gdbserver_output}')
        os.system(f'touch {Common.vimqf_backtrace}; truncate -s 0 {Common.vimqf_backtrace}')
        os.system(f'touch {Common.vimqf_breakpoint}; truncate -s 0 {Common.vimqf_breakpoint}')
        os.system(f'touch {Common.gdb_tmp_break}; truncate -s 0 {Common.gdb_tmp_break}')
        os.system(f'touch {Common.gdb_file_infolocal}; truncate -s 0 {Common.gdb_file_infolocal}')

        self.gdbMode = args[0]
        self.gdbArgs = args[1]    # 't1 dut:8888 -u admin -p "" -t "gdb:trace"'
        chunks = re.split(' +', self.gdbArgs)
        if chunks:
            self.debug_bin = chunks[0]
            self.logger.info(f"Gdb starting '{self.debug_bin}' with {chunks[1:]} ...")
        else:
            self.debug_bin = self.gdbArgs
            self.logger.info(f"Gdb starting '{self.debug_bin}' ...")

        # let s:dir = expand('<sfile>:p:h')
        self.vim.command('let g:vimgdb_file = expand("%:p")')
        self.file = self.vim.eval('g:vimgdb_file')
        if len(self.file) < 1:
            self.vim.command('echomsg "Gdb start fail, no current file"')
            return

        tmux_info = subprocess.check_output(
            ['tmux', 'display-message', '-p', '#S;#{session_id};#{window_width};#{window_height};#{window_index};#{pane_id}'])
        tmux_info = tmux_info.decode()
        [self.tmux_sesname, self.tmux_sesid, self.tmux_win_def_width, self.tmux_win_def_height, self.tmux_pwin_idx, self.tmux_curr_pan_id] = tmux_info.strip().split(';')

        # option controller: kill other pane of current tmux window
        subprocess.check_output(['tmux', 'kill-pane', '-a', '-t', self.tmux_curr_pan_id])

        self.logger.info(f"Tmux: #{self.tmux_sesid} '{self.tmux_sesname}' {self.tmux_win_def_width}x{self.tmux_win_def_height} cwd='{self.workdir}'")
        self.tmux_server = Server()
        self.tmux_session = self.tmux_server.get_by_id(self.tmux_sesid)

        self.build_workspace()

        self.vim.funcs.VimGdbInit()
        self._define_vimsigns()

        # Create model Cursor:
        _model = Cursor(self._common, self)
        if not _model:
            return
        self.models_coll[_model._name] = _model

        # Create model Breakpoint:
        _model = Breakpoint(self._common, self)
        if not _model:
            return
        self.models_coll[_model._name] = _model

        # Create view MainVimWin:
        _view = Win(self._common, self)
        if not _view:
            return
        self.views_coll[_view._name] = _view

        self.logger.info(f"VimGdb mode={self.gdbMode}", )
        if self.gdbMode == GdbMode.LOCAL or self.gdbMode == GdbMode.REMOTE:
            self.create_gdb_local(args)
        if self.gdbMode == GdbMode.REMOTE:
            self.create_gdb_remote(args)

        ##self.tmux_window_vim.select_layout('main-horizontal')
        #self.tmux_window_vim.select_layout('main-vertical')

        # focus backto vim
        self.tmux_pane_vim.select_pane()

        # monitor all outfile
        if Common.tailModeSubprocess:
            self.logger.info("Start subprocess(tail -f) ...")
            t1 = threading.Thread(target=self.tail_files)
            #t1.setDaemon(True)
            t1.start()

        return
Esempio n. 15
0
def load_workspace(
    config_file,
    socket_name=None,
    socket_path=None,
    tmux_config_file=None,
    new_session_name=None,
    colors=None,
    detached=False,
    answer_yes=False,
    append=False,
):
    """
    Load a tmux "workspace" session via tmuxp file.

    Parameters
    ----------
    config_file : str
        absolute path to config file
    socket_name : str, optional
        ``tmux -L <socket-name>``
    socket_path: str, optional
        ``tmux -S <socket-path>``
    new_session_name: str, options
        ``tmux new -s <new_session_name>``
    colors : str, optional
        '-2'
            Force tmux to support 256 colors
    detached : bool
        Force detached state. default False.
    answer_yes : bool
        Assume yes when given prompt to attach in new session.
        Default False.
    append : bool
       Assume current when given prompt to append windows in same session.
       Default False.

    Notes
    -----

    tmuxp will check and load a configuration file. The file will use kaptan
    to load a JSON/YAML into a :py:obj:`dict`. Then :func:`config.expand` and
    :func:`config.trickle` will be used to expand any shorthands, template
    variables, or file paths relative to where the config/script is executed
    from.

    :func:`config.expand` accepts the directory of the config file, so the
    user's configuration can resolve absolute paths relative to where the
    config file is. In otherwords, if a config file at */var/moo/hi.yaml*
    has *./* in its configs, we want to be sure any file path with *./* is
    relative to */var/moo*, not the user's PWD.

    A :class:`libtmux.Server` object is created. No tmux server is started yet,
    just the object.

    The prepared configuration and the server object is passed into an instance
    of :class:`~tmuxp.workspacebuilder.WorkspaceBuilder`.

    A sanity check against :meth:`libtmux.common.which` is ran. It will raise
    an exception if tmux isn't found.

    If a tmux session under the same name as ``session_name`` in the tmuxp
    configuration exists, tmuxp offers to attach the session. Currently, tmuxp
    does not allow appending a workspace / incremental building on top of a
    current session (pull requests are welcome!).

    :meth:`~tmuxp.workspacebuilder.WorkspaceBuilder.build` will build the session in
    the background via using tmux's detached state (``-d``).

    After the session (workspace) is built, unless the user decided to load
    the session in the background via ``tmuxp -d`` (which is in the spirit
    of tmux's ``-d``), we need to prompt the user to attach the session.

    If the user is already inside a tmux client, which we detect via the
    ``TMUX`` environment variable bring present, we will prompt the user to
    switch their current client to it.

    If they're outside of tmux client - in a plain-old PTY - we will
    automatically ``attach``.

    If an exception is raised during the building of the workspace, tmuxp will
    prompt to cleanup (``$ tmux kill-session``) the session on the user's
    behalf. An exception raised during this process means it's not easy to
    predict how broken the session is.

    .. versionchanged:: tmux 2.6+

        In tmux 2.6, the way layout and proportion's work when interfacing
        with tmux in a detached state (outside of a client) changed. Since
        tmuxp builds workspaces in a detached state, the WorkspaceBuilder isn't
        able to rely on functionality requiring awarness of session geometry,
        e.g. ``set-layout``.

        Thankfully, tmux is able to defer commands to run after the user
        performs certain actions, such as loading a client via
        ``attach-session`` or ``switch-client``.

        Upon client switch, ``client-session-changed`` is triggered [1]_.

    References
    ----------
    .. [1] cmd-switch-client.c hook. GitHub repo for tmux.

       https://github.com/tmux/tmux/blob/2.6/cmd-switch-client.c#L132.
       Accessed April 8th, 2018.
    """
    # get the canonical path, eliminating any symlinks
    config_file = os.path.realpath(config_file)

    tmuxp_echo(
        click.style("[Loading] ", fg="green") +
        click.style(config_file, fg="blue", bold=True))

    # kaptan allows us to open a yaml or json file as a dict
    sconfig = kaptan.Kaptan()
    sconfig = sconfig.import_config(config_file).get()
    # shapes configurations relative to config / profile file location
    sconfig = config.expand(sconfig, os.path.dirname(config_file))
    # Overwrite session name
    if new_session_name:
        sconfig["session_name"] = new_session_name
    # propagate config inheritance (e.g. session -> window, window -> pane)
    sconfig = config.trickle(sconfig)

    t = Server(  # create tmux server object
        socket_name=socket_name,
        socket_path=socket_path,
        config_file=tmux_config_file,
        colors=colors,
    )

    which("tmux")  # raise exception if tmux not found

    try:  # load WorkspaceBuilder object for tmuxp config / tmux server
        builder = WorkspaceBuilder(sconf=sconfig,
                                   plugins=load_plugins(sconfig),
                                   server=t)
    except exc.EmptyConfigException:
        tmuxp_echo("%s is empty or parsed no config data" % config_file,
                   err=True)
        return

    session_name = sconfig["session_name"]

    # if the session already exists, prompt the user to attach
    if builder.session_exists(session_name) and not append:
        if not detached and (answer_yes or click.confirm(
                "%s is already running. Attach?" %
                click.style(session_name, fg="green"),
                default=True,
        )):
            _reattach(builder)
        return

    try:
        if detached:
            _load_detached(builder)
            return _setup_plugins(builder)

        if append:
            if "TMUX" in os.environ:  # tmuxp ran from inside tmux
                _load_append_windows_to_current_session(builder)
            else:
                _load_attached(builder, detached)

            return _setup_plugins(builder)

        # append and answer_yes have no meaning if specified together
        elif answer_yes:
            _load_attached(builder, detached)
            return _setup_plugins(builder)

        if "TMUX" in os.environ:  # tmuxp ran from inside tmux
            msg = (
                "Already inside TMUX, switch to session? yes/no\n"
                "Or (a)ppend windows in the current active session?\n[y/n/a]")
            options = ["y", "n", "a"]
            choice = click.prompt(msg, value_proc=_validate_choices(options))

            if choice == "y":
                _load_attached(builder, detached)
            elif choice == "a":
                _load_append_windows_to_current_session(builder)
            else:
                _load_detached(builder)
        else:
            _load_attached(builder, detached)

    except exc.TmuxpException as e:
        import traceback

        tmuxp_echo(traceback.format_exc(), err=True)
        tmuxp_echo(e, err=True)

        choice = click.prompt(
            "Error loading workspace. (k)ill, (a)ttach, (d)etach?",
            value_proc=_validate_choices(["k", "a", "d"]),
            default="k",
        )

        if choice == "k":
            builder.session.kill_session()
            tmuxp_echo("Session killed.")
        elif choice == "a":
            _reattach(builder)
        else:
            sys.exit()

    return _setup_plugins(builder)
Esempio n. 16
0
File: cli.py Progetto: aurieh/tmuxp
def load_workspace(
    config_file,
    socket_name=None,
    socket_path=None,
    colors=None,
    detached=False,
    answer_yes=False,
):
    """
    Load a tmux "workspace" session via tmuxp file.

    Parameters
    ----------
    config_file : str
        absolute path to config file
    socket_name : str, optional
        ``tmux -L <socket-name>``
    socket_path: str, optional
        ``tmux -S <socket-path>``
    colors : str, optional
        '-2'
            Force tmux to support 256 colors
    detached : bool
        Force detached state. default False.
    answer_yes : bool
        Assume yes when given prompt. default False.

    Notes
    -----

    tmuxp will check and load a configuration file. The file will use kaptan
    to load a JSON/YAML into a :py:obj:`dict`. Then :func:`config.expand` and
    :func:`config.trickle` will be used to expand any shorthands, template
    variables, or file paths relative to where the config/script is executed
    from.

    :func:`config.expand` accepts the directory of the config file, so the
    user's configuration can resolve absolute paths relative to where the
    config file is. In otherwords, if a config file at */var/moo/hi.yaml*
    has *./* in its configs, we want to be sure any file path with *./* is
    relative to */var/moo*, not the user's PWD.

    A :class:`libtmux.Server` object is created. No tmux server is started yet,
    just the object.

    The prepared configuration and the server object is passed into an instance
    of :class:`~tmuxp.workspacebuilder.WorkspaceBuilder`.

    A sanity check against :meth:`libtmux.common.which` is ran. It will raise
    an exception if tmux isn't found.

    If a tmux session under the same name as ``session_name`` in the tmuxp
    configuration exists, tmuxp offers to attach the session. Currently, tmuxp
    does not allow appending a workspace / incremental building on top of a
    current session (pull requests are welcome!).

    :meth:`~tmuxp.workspacebuilder.WorkspaceBuilder.build` will build the session in
    the background via using tmux's detached state (``-d``).

    After the session (workspace) is built, unless the user decided to load
    the session in the background via ``tmuxp -d`` (which is in the spirit
    of tmux's ``-d``), we need to prompt the user to attach the session.

    If the user is already inside a tmux client, which we detect via the
    ``TMUX`` environment variable bring present, we will prompt the user to
    switch their current client to it.

    If they're outside of tmux client - in a plain-old PTY - we will
    automatically ``attach``.

    If an exception is raised during the building of the workspace, tmuxp will
    prompt to cleanup (``$ tmux kill-session``) the session on the user's
    behalf. An exception raised during this process means it's not easy to
    predict how broken the session is.

    .. versionchanged:: tmux 2.6+

        In tmux 2.6, the way layout and proportion's work when interfacing
        with tmux in a detached state (outside of a client) changed. Since
        tmuxp builds workspaces in a detached state, the WorkspaceBuilder isn't
        able to rely on functionality requiring awarness of session geometry,
        e.g. ``set-layout``.

        Thankfully, tmux is able to defer commands to run after the user
        performs certain actions, such as loading a client via
        ``attach-session`` or ``switch-client``.

        Upon client switch, ``client-session-changed`` is triggered [1]_.

    References
    ----------
    .. [1] cmd-switch-client.c hook. GitHub repo for tmux.
       https://github.com/tmux/tmux/blob/2.6/cmd-switch-client.c#L132.
       Accessed April 8th, 2018.
    """
    # here we ensure COLS and LINES is set for percentage config
    try:
        curses.initscr()
    finally:
        curses.endwin()

    # get the canonical path, eliminating any symlinks
    config_file = os.path.realpath(config_file)

    # kaptan allows us to open a yaml or json file as a dict
    sconfig = kaptan.Kaptan()
    sconfig = sconfig.import_config(config_file).get()
    # shapes configurations relative to config / profile file location
    sconfig = config.expand(sconfig, os.path.dirname(config_file))
    # propagate config inheritance (e.g. session -> window, window -> pane)
    sconfig = config.trickle(sconfig)

    t = Server(  # create tmux server object
        socket_name=socket_name, socket_path=socket_path, colors=colors
    )

    which('tmux')  # raise exception if tmux not found

    try:  # load WorkspaceBuilder object for tmuxp config / tmux server
        builder = WorkspaceBuilder(sconf=sconfig, server=t)
    except exc.EmptyConfigException:
        click.echo('%s is empty or parsed no config data' % config_file, err=True)
        return

    session_name = sconfig['session_name']

    # if the session already exists, prompt the user to attach. tmuxp doesn't
    # support incremental session building or appending (yet, PR's welcome!)
    if builder.session_exists(session_name):
        if not detached and (
            answer_yes
            or click.confirm(
                '%s is already running. Attach?'
                % click.style(session_name, fg='green'),
                default=True,
            )
        ):
            _reattach(builder.session)
        return

    try:
        click.echo(
            click.style('[Loading] ', fg='green')
            + click.style(config_file, fg='blue', bold=True)
        )

        builder.build()  # load tmux session via workspace builder

        if 'TMUX' in os.environ:  # tmuxp ran from inside tmux
            if not detached and (
                answer_yes or click.confirm('Already inside TMUX, switch to session?')
            ):
                # unset TMUX, save it, e.g. '/tmp/tmux-1000/default,30668,0'
                tmux_env = os.environ.pop('TMUX')

                if has_gte_version('2.6'):
                    set_layout_hook(builder.session, 'client-session-changed')

                builder.session.switch_client()  # switch client to new session

                os.environ['TMUX'] = tmux_env  # set TMUX back again
                return builder.session
            else:  # session created in the background, from within tmux
                if has_gte_version('2.6'):  # prepare for both cases
                    set_layout_hook(builder.session, 'client-attached')
                    set_layout_hook(builder.session, 'client-session-changed')

                sys.exit('Session created in detached state.')
        else:  # tmuxp ran from inside tmux
            if has_gte_version('2.6'):
                # if attaching for first time
                set_layout_hook(builder.session, 'client-attached')

                # for cases where user switches client for first time
                set_layout_hook(builder.session, 'client-session-changed')

            if not detached:
                builder.session.attach_session()

    except exc.TmuxpException as e:
        import traceback

        click.echo(traceback.format_exc(), err=True)
        click.echo(e, err=True)

        choice = click.prompt(
            'Error loading workspace. (k)ill, (a)ttach, (d)etach?',
            value_proc=_validate_choices(['k', 'a', 'd']),
            default='k',
        )

        if choice == 'k':
            builder.session.kill_session()
            click.echo('Session killed.')
        elif choice == 'a':
            if 'TMUX' in os.environ:
                builder.session.switch_client()
            else:
                builder.session.attach_session()
        else:
            sys.exit()

    return builder.session
Esempio n. 17
0
def load_workspace(config_file,
                   socket_name=None,
                   socket_path=None,
                   colors=None,
                   attached=None,
                   detached=None,
                   answer_yes=False):
    """Build config workspace.

    :param config_file: full path to config file
    :param type: str

    """
    # get the canonical path, eliminating any symlinks
    config_file = os.path.realpath(config_file)

    sconfig = kaptan.Kaptan()
    sconfig = sconfig.import_config(config_file).get()
    # expands configurations relative to config / profile file location
    sconfig = config.expand(sconfig, os.path.dirname(config_file))
    sconfig = config.trickle(sconfig)

    t = Server(socket_name=socket_name, socket_path=socket_path, colors=colors)

    try:
        builder = WorkspaceBuilder(sconf=sconfig, server=t)
    except exc.EmptyConfigException:
        click.echo('%s is empty or parsed no config data' % config_file,
                   err=True)
        return

    which('tmux')

    def reattach(session):
        if 'TMUX' in os.environ:
            session.switch_client()

        else:
            session.attach_session()

    session_name = sconfig['session_name']
    if builder.session_exists(session_name):
        if not detached and (answer_yes or click.confirm(
                '%s is already running. Attach?' %
                click.style(session_name, fg='green'),
                default=True)):
            reattach(builder.session)
        return

    try:
        click.echo(
            click.style('[Loading] ', fg='green') +
            click.style(config_file, fg='blue', bold=True))
        builder.build()

        if 'TMUX' in os.environ:  # tmuxp ran from inside tmux
            if not detached and (
                    answer_yes or
                    click.confirm('Already inside TMUX, switch to session?')):
                tmux_env = os.environ.pop('TMUX')

                if has_gte_version('2.6'):
                    # if using -d from inside tmux session + switching inside
                    # https://github.com/tmux/tmux/blob/2.6/cmd-switch-client.c#L132
                    set_layout_hook(builder.session, 'client-session-changed')

                builder.session.switch_client()

                os.environ['TMUX'] = tmux_env
                return builder.session
            else:  # session created in the background, from within tmux
                if has_gte_version('2.6'):  # prepare for both cases
                    set_layout_hook(builder.session, 'client-attached')
                    set_layout_hook(builder.session, 'client-session-changed')

                sys.exit('Session created in detached state.')

        # below: tmuxp ran outside of tmux

        if has_gte_version('2.6'):
            # if attaching for first time
            set_layout_hook(builder.session, 'client-attached')

            # for cases where user switches client for first time
            set_layout_hook(builder.session, 'client-session-changed')

        if not detached:
            builder.session.attach_session()

    except exc.TmuxpException as e:
        import traceback

        click.echo(traceback.format_exc(), err=True)
        click.echo(e, err=True)

        choice = click.prompt(
            'Error loading workspace. (k)ill, (a)ttach, (d)etach?',
            value_proc=_validate_choices(['k', 'a', 'd']),
            default='k')

        if choice == 'k':
            builder.session.kill_session()
            click.echo('Session killed.')
        elif choice == 'a':
            if 'TMUX' in os.environ:
                builder.session.switch_client()
            else:
                builder.session.attach_session()
        else:
            sys.exit()

    return builder.session
Esempio n. 18
0
def load_workspace(config_file,
                   socket_name=None,
                   socket_path=None,
                   colors=None,
                   attached=None,
                   detached=None,
                   answer_yes=False):
    """Build config workspace.

    :param config_file: full path to config file
    :param type: string

    """

    sconfig = kaptan.Kaptan()
    sconfig = sconfig.import_config(config_file).get()
    # expands configurations relative to config / profile file location
    sconfig = config.expand(sconfig, os.path.dirname(config_file))
    sconfig = config.trickle(sconfig)

    t = Server(socket_name=socket_name, socket_path=socket_path, colors=colors)

    try:
        builder = WorkspaceBuilder(sconf=sconfig, server=t)
    except exc.EmptyConfigException:
        click.echo('%s is empty or parsed no config data' % config_file,
                   err=True)
        return

    which('tmux')

    def reattach(session):
        if 'TMUX' in os.environ:
            session.switch_client()

        else:
            session.attach_session()

    session_name = sconfig['session_name']
    if builder.session_exists(session_name):
        if not detached and (answer_yes or click.confirm(
                '%s is already running. Attach?' %
                click.style(session_name, fg='green'),
                default=True)):
            reattach(builder.session)
        return

    try:
        click.echo(
            click.style('[Loading] ', fg='green') +
            click.style(config_file, fg='blue', bold=True))
        builder.build()

        if 'TMUX' in os.environ:
            if not detached and (
                    answer_yes or
                    click.confirm('Already inside TMUX, switch to session?')):
                tmux_env = os.environ.pop('TMUX')
                builder.session.switch_client()

                os.environ['TMUX'] = tmux_env
                return builder.session
            else:
                sys.exit('Session created in detached state.')

        if not detached:
            builder.session.attach_session()
    except exc.TmuxpException as e:
        import traceback

        click.echo(traceback.format_exc(), err=True)
        click.echo(e, err=True)

        choice = click.prompt(
            'Error loading workspace. (k)ill, (a)ttach, (d)etach?',
            value_proc=_validate_choices(['k', 'a', 'd']),
            default='k')

        if choice == 'k':
            builder.session.kill_session()
            click.echo('Session killed.')
        elif choice == 'a':
            if 'TMUX' in os.environ:
                builder.session.switch_client()
            else:
                builder.session.attach_session()
        else:
            sys.exit()

    return builder.session
Esempio n. 19
0
def command_freeze(session_name, socket_name, socket_path):
    """Snapshot a session into a config.

    If SESSION_NAME is provided, snapshot that session. Otherwise, use the
    current session."""

    t = Server(socket_name=socket_name, socket_path=socket_path)

    try:
        if session_name:
            session = t.find_where({'session_name': session_name})
        else:
            session = t.list_sessions()[0]

        if not session:
            raise exc.TmuxpException('Session not found.')
    except exc.TmuxpException as e:
        print(e)
        return

    sconf = freeze(session)
    configparser = kaptan.Kaptan()
    newconfig = config.inline(sconf)
    configparser.import_config(newconfig)
    config_format = click.prompt(
        'Convert to', value_proc=_validate_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(
        '---------------------------------------------------------------'
        '\n'
        'Freeze does it best to snapshot live tmux sessions.\n'
    )
    if click.confirm(
        'The new config *WILL* require adjusting afterwards. Save config?'
    ):
        dest = None
        while not dest:
            save_to = os.path.abspath(
                os.path.join(
                    get_config_dir(),
                    '%s.%s' % (sconf.get('session_name'), config_format),
                )
            )
            dest_prompt = click.prompt(
                'Save to: %s' % save_to,
                value_proc=get_abs_path,
                default=save_to,
                confirmation_prompt=True,
            )
            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(os.path.expanduser(dest)))
        if click.confirm('Save to %s?' % dest):
            destdir = os.path.dirname(dest)
            if not os.path.isdir(destdir):
                os.makedirs(destdir)
            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 '
            '<http://tmuxp.readthedocs.io/en/latest/examples.html>\n'
            'View tmuxp docs at <http://tmuxp.readthedocs.io/>.'
        )
        sys.exit()
Esempio n. 20
0
def command_freeze(args):
    """Import teamocil config to tmuxp format."""

    ctext = ' '.join(args.session_name)

    t = Server(
        socket_name=args.socket_name,
        socket_path=args.socket_path,
        colors=args.colors
    )

    try:
        session = t.find_where({
            'session_name': ctext
        })

        if not session:
            raise exc.TmuxpException('Session not found.')
    except exc.TmuxpException as e:
        print(e)
        return

    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 args.answer_yes or prompt_yes_no(
        'The new config *WILL* require adjusting afterwards. Save config?'
    ):
        dest = None
        while not dest:
            save_to = os.path.abspath(
                os.path.join(
                    config_dir,
                    '%s.%s' % (sconf.get('session_name'), config_format)
                )
            )
            dest_prompt = prompt('Save to: ', save_to)
            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(os.path.expanduser(dest)))
        if args.answer_yes or prompt_yes_no('Save to %s?' % dest):
            destdir = os.path.dirname(dest)
            if not os.path.isdir(destdir):
                os.makedirs(destdir)
            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 '
            '<http://tmuxp.readthedocs.io/en/latest/examples.html>\n'
            'View tmuxp docs at <http://tmuxp.readthedocs.io/>.'
        )
        sys.exit()
Esempio n. 21
0
def command_freeze(
    session_name, socket_name, config_format, save_to, socket_path, yes, quiet, force
):
    """Snapshot a session into a config.

    If SESSION_NAME is provided, snapshot that session. Otherwise, use the
    current session."""

    t = Server(socket_name=socket_name, socket_path=socket_path)

    try:
        if session_name:
            session = t.find_where({"session_name": session_name})
        else:
            session = util.get_session(t)

        if not session:
            raise exc.TmuxpException("Session not found.")
    except exc.TmuxpException as e:
        print(e)
        return

    sconf = freeze(session)
    configparser = kaptan.Kaptan()
    newconfig = config.inline(sconf)
    configparser.import_config(newconfig)

    if not quiet:
        print(
            "---------------------------------------------------------------"
            "\n"
            "Freeze does its best to snapshot live tmux sessions.\n"
        )
    if not (
        yes
        or click.confirm(
            "The new config *WILL* require adjusting afterwards. Save config?"
        )
    ):
        if not quiet:
            print(
                "tmuxp has examples in JSON and YAML format at "
                "<http://tmuxp.git-pull.com/examples.html>\n"
                "View tmuxp docs at <http://tmuxp.git-pull.com/>."
            )
        sys.exit()

    dest = save_to
    while not dest:
        save_to = os.path.abspath(
            os.path.join(
                get_config_dir(),
                "{}.{}".format(sconf.get("session_name"), config_format or "yaml"),
            )
        )
        dest_prompt = click.prompt(
            "Save to: %s" % save_to, value_proc=get_abs_path, default=save_to
        )
        if not force and 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(os.path.expanduser(dest)))

    if config_format is None:
        valid_config_formats = ["json", "yaml"]
        _, config_format = os.path.splitext(dest)
        config_format = config_format[1:].lower()
        if config_format not in valid_config_formats:
            config_format = click.prompt(
                "Couldn't ascertain one of [%s] from file name. Convert to"
                % ", ".join(valid_config_formats),
                value_proc=_validate_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)

    if yes or click.confirm("Save to %s?" % dest):
        destdir = os.path.dirname(dest)
        if not os.path.isdir(destdir):
            os.makedirs(destdir)
        buf = open(dest, "w")
        buf.write(newconfig)
        buf.close()

        if not quiet:
            print("Saved to %s." % dest)
Esempio n. 22
0
def session_completion(ctx, params, incomplete):
    t = Server()
    choices = [session.name for session in t.list_sessions()]
    return sorted([str(c) for c in choices if str(c).startswith(incomplete)])
Esempio n. 23
0
    def run(self, args):
        os.system(f'touch {Common.vimgdb_debugfile}; truncate -s 0 {Common.vimgdb_debugfile}')

        self.logger.info("==============================================")
        self.logger.info("==============================================")
        self.logger.info("==============================================")
        self.logger.info("==============================================")
        self.logger.info("             *** Gdb instance ***")
        self.logger.info("")
        self.logger.info("args=%s", args)
        arg_n = len(args)
        if arg_n < 2:
            self.vim.command('echomsg "Gdb start fail, should: call VimGdb(\'local\', \'<bin-file>\')"')
            return

        os.system(f'touch {Common.gdb_output}; truncate -s 0 {Common.gdb_output}')
        os.system(f'touch {Common.gdbserver_output}; truncate -s 0 {Common.gdbserver_output}')
        os.system(f'touch {Common.vimqf_backtrace}; truncate -s 0 {Common.vimqf_backtrace}')
        os.system(f'touch {Common.vimqf_breakpoint}; truncate -s 0 {Common.vimqf_breakpoint}')
        os.system(f'touch {Common.gdb_tmp_break}; truncate -s 0 {Common.gdb_tmp_break}')
        os.system(f'touch {Common.gdb_file_infolocal}; truncate -s 0 {Common.gdb_file_infolocal}')

        self.gdbMode = args[0]
        self.gdbArgs = args[1]    # 't1 dut:8888 -u admin -p "" -t "gdb:trace"'
        chunks = re.split(' +', self.gdbArgs)
        if chunks:
            self.debug_bin = chunks[0]
            self.logger.info(f"Gdb starting '{self.debug_bin}' with {chunks[1:]} ...")
        else:
            self.debug_bin = self.gdbArgs
            self.logger.info(f"Gdb starting '{self.debug_bin}' ...")

        # let s:dir = expand('<sfile>:p:h')
        self.vim.command('let g:vimgdb_file = expand("%:p")')
        self.file = self.vim.eval('g:vimgdb_file')
        if len(self.file) < 1:
            self.vim.command('echomsg "Gdb start fail, no current file"')
            return

        tmux_info = subprocess.check_output(
            ['tmux', 'display-message', '-p', '#S;#{session_id};#{window_width};#{window_height};#{window_index};#{pane_id}'])
        tmux_info = tmux_info.decode()
        [self.tmux_sesname, self.tmux_sesid, self.tmux_win_def_width, self.tmux_win_def_height, self.tmux_pwin_idx, self.tmux_curr_pan_id] = tmux_info.strip().split(';')

        # option controller: kill other pane of current tmux window
        subprocess.check_output(['tmux', 'kill-pane', '-a', '-t', self.tmux_curr_pan_id])

        self.logger.info(f"Tmux: #{self.tmux_sesid} '{self.tmux_sesname}' {self.tmux_win_def_width}x{self.tmux_win_def_height} cwd='{self.workdir}'")
        self.tmux_server = Server()
        self.tmux_session = self.tmux_server.get_by_id(self.tmux_sesid)

        self.build_workspace()

        self.vim.funcs.VimGdbInit()
        self._define_vimsigns()

        # Create model Cursor:
        _model = Cursor(self._common, self)
        if not _model:
            return
        self.models_coll[_model._name] = _model

        # Create model Breakpoint:
        _model = Breakpoint(self._common, self)
        if not _model:
            return
        self.models_coll[_model._name] = _model

        # Create view MainVimWin:
        _view = Win(self._common, self)
        if not _view:
            return
        self.views_coll[_view._name] = _view

        self.logger.info(f"VimGdb mode={self.gdbMode}", )
        if self.gdbMode == GdbMode.LOCAL or self.gdbMode == GdbMode.REMOTE:
            self.create_gdb_local(args)
        if self.gdbMode == GdbMode.REMOTE:
            self.create_gdb_remote(args)

        ##self.tmux_window_vim.select_layout('main-horizontal')
        #self.tmux_window_vim.select_layout('main-vertical')

        # focus backto vim
        self.tmux_pane_vim.select_pane()

        # monitor all outfile
        if Common.tailModeSubprocess:
            self.logger.info("Start subprocess(tail -f) ...")
            t1 = threading.Thread(target=self.tail_files)
            #t1.setDaemon(True)
            t1.start()

        return
Esempio n. 24
0
def load_workspace(config_file, args):
    """Build config workspace.

    :param config_file: full path to config file
    :param type: string

    """

    sconfig = kaptan.Kaptan()
    sconfig = sconfig.import_config(config_file).get()
    # expands configurations relative to config / profile file location
    sconfig = config.expand(sconfig, os.path.dirname(config_file))
    sconfig = config.trickle(sconfig)

    t = Server(socket_name=args.socket_name,
               socket_path=args.socket_path,
               colors=args.colors)

    try:
        builder = WorkspaceBuilder(sconf=sconfig, server=t)
    except exc.EmptyConfigException:
        logger.error('%s is empty or parsed no config data' % config_file)
        return

    which('tmux')

    try:
        logger.info('Loading %s.' % config_file)
        builder.build()

        if 'TMUX' in os.environ:
            if not args.detached and (
                    args.answer_yes or
                    prompt_yes_no('Already inside TMUX, switch to session?')):
                tmux_env = os.environ.pop('TMUX')
                builder.session.switch_client()

                os.environ['TMUX'] = tmux_env
                return
            else:
                sys.exit('Session created in detached state.')

        if not args.detached:
            builder.session.attach_session()
    except exc.TmuxSessionExists as e:
        if not args.detached and (args.answer_yes
                                  or prompt_yes_no('%s Attach?' % e)):
            if 'TMUX' in os.environ:
                builder.session.switch_client()

            else:
                builder.session.attach_session()
        return
    except exc.TmuxpException 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'],
            default='k')

        if choice == 'k':
            builder.session.kill_session()
            print('Session killed.')
        elif choice == 'a':
            if 'TMUX' in os.environ:
                builder.session.switch_client()
            else:
                builder.session.attach_session()
        else:
            sys.exit()
Esempio n. 25
0
def server():
    t = Server()
    t.socket_name = 'tmuxp_test%s' % next(namer)

    return t
Esempio n. 26
0
def command_shell(session_name, window_name, socket_name, socket_path, command):
    """Launch python shell for tmux server, session, window and pane.

    Priority given to loaded session/wndow/pane objects:
    - session_name and window_name arguments
    - current shell: environmental variable of TMUX_PANE (which gives us window and
      session)
    - ``server.attached_session``, ``session.attached_window``, ``window.attached_pane``
    """
    server = Server(socket_name=socket_name, socket_path=socket_path)

    try:
        server.sessions
    except LibTmuxException as e:
        if 'No such file or directory' in str(e):
            raise LibTmuxException(
                'no tmux session found. Start a tmux session and try again. \n'
                'Original error: ' + str(e)
            )
        else:
            raise e

    current_pane = None
    if os.getenv('TMUX_PANE') is not None:
        try:
            current_pane = [
                p
                for p in server._list_panes()
                if p.get('pane_id') == os.getenv('TMUX_PANE')
            ][0]
        except IndexError:
            pass

    try:
        if session_name:
            session = server.find_where({'session_name': session_name})
        elif current_pane is not None:
            session = server.find_where({'session_id': current_pane['session_id']})
        else:
            session = server.list_sessions()[0]

        if not session:
            raise exc.TmuxpException('Session not found: %s' % session_name)
    except exc.TmuxpException as e:
        print(e)
        return

    try:
        if window_name:
            window = session.find_where({'window_name': window_name})
            if not window:
                raise exc.TmuxpException('Window not found: %s' % window_name)
        elif current_pane is not None:
            window = session.find_where({'window_id': current_pane['window_id']})
        else:
            window = session.list_windows()[0]

    except exc.TmuxpException as e:
        print(e)
        return

    try:
        if current_pane is not None:
            pane = window.find_where({'pane_id': current_pane['pane_id']})  # NOQA: F841
        else:
            pane = window.attached_pane  # NOQA: F841
    except exc.TmuxpException as e:
        print(e)
        return

    if command is not None:
        exec(command)
    else:
        from ._compat import breakpoint as tmuxp_breakpoint

        tmuxp_breakpoint()
Esempio n. 27
0
File: cli.py Progetto: aurieh/tmuxp
def command_freeze(session_name, socket_name, socket_path):
    """Snapshot a session into a config.

    If SESSION_NAME is provided, snapshot that session. Otherwise, use the
    current session."""

    t = Server(socket_name=socket_name, socket_path=socket_path)

    try:
        if session_name:
            session = t.find_where({'session_name': session_name})
        else:
            session = t.list_sessions()[0]

        if not session:
            raise exc.TmuxpException('Session not found.')
    except exc.TmuxpException as e:
        print(e)
        return

    sconf = freeze(session)
    configparser = kaptan.Kaptan()
    newconfig = config.inline(sconf)
    configparser.import_config(newconfig)
    config_format = click.prompt(
        'Convert to', value_proc=_validate_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(
        '---------------------------------------------------------------'
        '\n'
        'Freeze does it best to snapshot live tmux sessions.\n'
    )
    if click.confirm(
        'The new config *WILL* require adjusting afterwards. Save config?'
    ):
        dest = None
        while not dest:
            save_to = os.path.abspath(
                os.path.join(
                    get_config_dir(),
                    '%s.%s' % (sconf.get('session_name'), config_format),
                )
            )
            dest_prompt = click.prompt(
                'Save to: %s' % save_to, value_proc=get_abs_path, default=save_to
            )
            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(os.path.expanduser(dest)))
        if click.confirm('Save to %s?' % dest):
            destdir = os.path.dirname(dest)
            if not os.path.isdir(destdir):
                os.makedirs(destdir)
            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 '
            '<http://tmuxp.readthedocs.io/en/latest/examples.html>\n'
            'View tmuxp docs at <http://tmuxp.readthedocs.io/>.'
        )
        sys.exit()
Esempio n. 28
0
def server():
    t = Server()
    t.socket_name = 'tmuxp_test%s' % next(namer)

    return t