Created
February 17, 2022 19:38
-
-
Save EgZvor/c2ef5857aad61a418c9740dc77746a4d to your computer and use it in GitHub Desktop.
Find Vim window in i3 by its server name
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/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. | |
""" | |
wid = None | |
pids = list(get_pid(server_name)) | |
pid = max(pids) | |
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