rafi/.config

i3-focus

pbogut opened this issue · 7 comments

Hi mate,

Sorry for rising issue, but hove no idea how to ask you anywhere else.

I found this issue christoomey/vim-tmux-navigator#45
You mentioned i3-focus script there and I can see it is used in your i3/config file but can't find the script itself. Are you fancy to share it somewhere?

Thanks

I would really appreciate to use this script too.

rafi commented

@pbogut @frdrcv I haven't been using it for more than a year, and it's quite a mess.

#!/usr/bin/python

import sys
import os
import i3
import subprocess
import re
import ast

cmd = str(sys.argv[1])
if len(cmd) == 1:
    if cmd == 'U': cmd = 'up'
    if cmd == 'D': cmd = 'down'
    if cmd == 'L': cmd = 'left'
    if cmd == 'R': cmd = 'right'

source = 'i3'
if len(sys.argv) == 3:
    source = str(sys.argv[2])

current = i3.filter(nodes=[], focused=True)[0]
in_tmux = re.search('tmux\{(.*)\}', current['name'])
move_i3 = True

#mylog = open("/tmp/i3-focus.log", "a")
#mylog.write(current['name'])
#mylog.write(str(source)+' ')

if in_tmux:
    tmux_session = in_tmux.group(1)
    panes = subprocess.check_output([
        'tmux',
        'list-panes',
        '-st',
        tmux_session,
        '-F',
        '[#{window_active},#{pane_active},#{pane_left},#{pane_right},#{pane_top},#{pane_bottom},#{window_width},#{window_height},"#{pane_current_command}"]'
    ])
    # Preparing output for parsing.
    # Note: In zoom mode, other windows will return empty for coordinates.
    panes = panes.decode().replace('\n', ',').replace(',,', '0')
#   mylog.write(', session: '+tmux_session+' '+panes)
    panes = ast.literal_eval(panes)

    for p in panes:
        if p[0] and p[1]:
            pane = p

    move_i3 = False
    # Check tmux borders if Vim called us
    # Or we're not in Vim

#   mylog.write(pane[8]+'%'
#           +' x:'+str(pane[2])+'-'+str(pane[3])+' y:'+str(pane[4])+'-'+str(pane[5])+' ['+str(pane[6])+'w '
#           +str(pane[7])+'h]')

    if source == 'vim' or pane[8] != 'vim':
#       mylog.write(", checking tmux coords")
#       mylog.write(", "+str(pane))
        if cmd == 'up':
            if pane[4] == 0: move_i3 = True
        if cmd == 'down':
            if pane[5] == pane[7]-1: move_i3 = True
        if cmd == 'left':
            if pane[2] == 0: move_i3 = True
        if cmd == 'right':
            if pane[3] == pane[6]-1: move_i3 = True

# ignore vimb, a vim-like gtk browser
if source != 'vim' and re.compile('g?V?im[^b]').match(current['name']):
    move_i3  =  False

if move_i3:
    i3.focus(cmd)

else:
    if in_tmux and source == 'vim':
#       mylog.write(", moving tmux")
        if cmd == 'up':
            subprocess.check_output([ 'tmux', 'select-pane', '-U' ]);
        if cmd == 'down':
            subprocess.check_output([ 'tmux', 'select-pane', '-D' ]);
        if cmd == 'left':
            subprocess.check_output([ 'tmux', 'select-pane', '-L' ]);
        if cmd == 'right':
            subprocess.check_output([ 'tmux', 'select-pane', '-R' ]);
    else:
#   from ctypes import *
#       mylog.write(", moving keyb")
#       libxdo = CDLL('libxdo.so.3')
#       xdo = libxdo.xdo_new(b':0.0')
#       wid = c_int(current['window'])
#       delay = c_int(0)
#       xdo_cmd_dict = {'left':  c_char_p(b"Ctrl+h"),
#                                       'right': c_char_p(b"Ctrl+l"),
#                                       'up':    c_char_p(b"Ctrl+k"),
#                                       'down':  c_char_p(b"Ctrl+j")}

#       libxdo.xdo_keysequence(xdo, wid, xdo_cmd_dict[cmd], delay)
#       libxdo.xdo_free(xdo)

        xdo_cmd_dict = {'left':  'Ctrl+h',
                                        'right': 'Ctrl+l',
                                        'up':    'Ctrl+k',
                                        'down':  'Ctrl+j'}
        subprocess.check_output([ 'xdotool', 'key', xdo_cmd_dict[cmd] ])

#mylog.write(", move i3: "+str(move_i3))
#mylog.write("\n\n")

#  vim: set ts=2 sw=2 tw=80 noet :

It expects a certain title string configured in tmux:

set-option -g set-titles on
set-option -g set-titles-string '#T #W tmux{#S}:#I.#P'

Thanks for sharing, I will try to give it a look soon.

It's working quite well, except that I mustn't type h,j,k or l too fast when using tmux or nothing is happening. May I upload it to a new repository with a reference to you? Or perhaps could you create one so I can fork it? I would like to work on it and make it more public. Thanks!

@frdrcv I've created my own that I'm using, it's not pretty but here it is.
It works with tmux panes and nvim windows inside or outside tmux. It's using nvr (neovim remote) when outside tmux. Session ID is taken from window title so that has to be configured in tmux.conf and/or vimrc (you can check my dotfiles).

Maybe you will find it useful.

rafi commented

@frdrcv sure. go ahead! It's a great way of navigating i3/tmux/vim panes and windows. It worked very well for me, don't remember those issue you mention, however Python isn't really the best tool for this.

@pbogut thanks for sharing.

rafi commented

I also remember nicm, tmux dev, was gracious enough to add the pane_* output variables for this idea to work and be able to detect the "edge" of tmux panes.. tmux/tmux@7160b8c