Skip to content

Instantly share code, notes, and snippets.

@EgZvor
Created October 1, 2019 08:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EgZvor/003831589583fd80a54e31ba118eabbf to your computer and use it in GitHub Desktop.
Save EgZvor/003831589583fd80a54e31ba118eabbf to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
"""
The script accepts either an argument or stdin line as a Vim server name
and focuses on i3 window contaning that Vim instance.
Read `:help client-server
<http://vimdoc.sourceforge.net/htmldoc/remote.html#client-server>`_.
Requires ``psutil`` ::
$ pip install psutil
Example usage ::
$ vim --serverlist | rofi -dmenu -p "Choose Vim server" | focus_vim.py
$ focus_vim.py <servername>
"""
import re
import sys
import psutil
import i3ipc
def get_window_id_by_pid(pid):
"""
Find i3 window id by programm's pid.
**Note**: OS specific, could need changing, works in ArchLinux.
:param pid: Process id of the program to find window.
:type pid: int
:return: i3 window id or None.
"""
with open('/proc/{}/environ'.format(pid), 'r') as env:
try:
pid_env = env.read()
except (OSError, IOError):
return None
match = re.search(r'WINDOWID=(\d+)', pid_env)
if match is not None:
wid = int(match.group(1))
return wid
return None
def get_pid(server_name):
"""
Find Vim instance by server name.
:param server_name: Vim server name.
:return: Process id.
"""
for process in psutil.process_iter():
if (
'--servername {}'.format(server_name.lower())
in ' '.join(process.cmdline()).lower()
):
yield process.pid
def get_window_id(server_name):
"""
Find i3 window id of Vim server instance with a `server_name` name
of the Vim instance.
:return: i3 window id.
"""
pid = None
wid = None
while True:
try:
pid = next(get_pid(server_name))
except StopIteration:
break
if pid is None:
continue
else:
break
if pid is not None:
wid = get_window_id_by_pid(pid)
return wid
def get_arg_from_stdin():
"""
Read stdin until EOF or a non-empty line.
:return: A non-empty line or None.
"""
return next((line.strip('\n') for line in sys.stdin.readlines()), None)
def main():
"""
Get a Vim server name either from command line argument or stdin's
first non-empty line and focus on an i3 window containing Vim
instance with that server name.
"""
server_name = None
if sys.argv[1:]:
server_name = sys.argv[1]
else:
server_name = get_arg_from_stdin()
if server_name is not None:
vim_window_id = get_window_id(server_name)
if vim_window_id is not None:
con = i3ipc.Connection()
con.command('[id=%s] focus' % vim_window_id)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment