# -*- coding: utf-8 -*- # # Copyright (c) 2016 by Ferus Castor # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Select a buffer from dmenu or rofi # To call externally (IE: from i3), enable weechat fifo and run: # $ echo "core.weechat */buffer_dmenu" >> $(find ~/.weechat -type p) # # Optionally requires i3-py [py2] (or i3ipc [py3]) to focus weechat in i3 # # History: # 2017-05-03, Ferus # version 0.1.1: fix argument error for config_set_plugin # 2016-05-01, Ferus # version 0.1: initial release - requires WeeChat ≥ 0.3.7 # TODO: # Option to remove certain buffer types # Implement `focus` for other window managers # if buffer == currentbuffer: switch to previous buffer #pylint: disable=I0011,W0603,W1401 SCRIPT_NAME = "buffer_dmenu" SCRIPT_AUTHOR = "Ferus " SCRIPT_VERSION = "0.1.1" SCRIPT_LICENSE = "GPL3" SCRIPT_DESC = "List buffers in dmenu (or rofi), changes active window to selected buffer" SCRIPT_COMMAND = "buffer_dmenu" import os import sys import subprocess try: import weechat as w except ImportError as e: print("This script must be run under WeeChat.") exit(1) try: if sys.version_info[0] == 3: import i3ipc as i3 else: import i3 have_i3 = True except ImportError as e: have_i3 = False settings = {"launcher": ("dmenu", "launcher to use (supported: dmenu/rofi)") ,"focus" : ("false", "whether to immediately focus the terminal after selecting buffer") ,"focus.wm" : ("i3", "wm focus logic to use (supported: i3)") ,"dmenu.command" : ("dmenu -b -i -l 20", "command used to call dmenu") ,"rofi.command" : ("rofi -p '# ' -dmenu -lines 10 -columns 8 -auto-select -mesg 'Pick a buffer to jump to:'", "command used to call rofi") ,"title.regex" : ("WeeChat \d+\.\d+", "regex used to match weechat's title window") } def check_dmenu(): devnull = open(os.devnull) retcode = subprocess.call(["which", "dmenu"], stdout=devnull, stderr=devnull) return True if retcode == 0 else False def check_rofi(): devnull = open(os.devnull) retcode = subprocess.call(["which", "rofi"], stdout=devnull, stderr=devnull) return True if retcode == 0 else False def get_launcher(): launcher = w.config_get_plugin("launcher") command = None if launcher == "dmenu": if check_dmenu(): command = w.config_get_plugin("dmenu.command") elif launcher == "rofi": if check_rofi(): command = w.config_get_plugin("rofi.command") return command def launch(options): launcher = get_launcher() if launcher: call(launcher, options) return True def focus(): if w.config_string_to_boolean(w.config_get_plugin("focus")): if w.config_get_plugin("focus.wm") == "i3": focus_i3() def focus_i3(): if have_i3: regex = w.config_get_plugin("title.regex") #py3 if sys.version_info[0] == 3: i3conn = i3.Connection() weechat = i3conn.get_tree().find_named(regex)[0] weechat.command('focus') #py2 else: i3.focus(title=regex) def call(command, options): options = "\n".join(options).encode("utf-8") w.hook_process_hashtable("sh" ,{"arg1": "-c","arg2": 'echo "{0}" | {1}'.format(options, command)} ,10 * 1000 ,"launch_process_cb" ,"" ) process_output = "" def launch_process_cb(data, command, rc, out, err): global process_output if out != "": process_output += out if int(rc) >= 0: selected = process_output.decode("utf-8").strip("\n") number, name = selected.split(":") process_output = "" switch_to_buffer(name) focus() return w.WEECHAT_RC_OK def get_open_buffers(): buffers = [] infolist = w.infolist_get("buffer", "", "") if infolist: while w.infolist_next(infolist): name = w.infolist_string(infolist, "name") number = w.infolist_integer(infolist, "number") _ = "{0}:{1}".format(number, name).decode("utf-8") buffers.append(_) w.infolist_free(infolist) return buffers def get_hotlist_buffers(): buffers = [] infolist = w.infolist_get("hotlist", "", "") if infolist: while w.infolist_next(infolist): number = w.infolist_integer(infolist, "buffer_number") buffer = w.infolist_pointer(infolist, "buffer_pointer") name = w.buffer_get_string(buffer, "name") _ = "{0}:{1}".format(number, name).decode("utf-8") buffers.append(_) w.infolist_free(infolist) return buffers def switch_to_buffer(buffer_name): w.command("", "/buffer {0}".format(buffer_name)) def dmenu_cmd_cb(data, buffer, args): """ Command /buffers_dmenu """ if args == "hotlist": buffers = get_hotlist_buffers() else: buffers = get_open_buffers() if not launch(buffers): return w.WEECHAT_RC_ERROR return w.WEECHAT_RC_OK if w.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""): version = w.info_get('version_number', '') or 0 for option, value in settings.items(): if not w.config_is_set_plugin(option): w.config_set_plugin(option, value[0]) if int(version) >= 0x00030500: w.config_set_desc_plugin(option, '{0} (default: "{1}")'.format(value[1], value[0])) w.hook_command(SCRIPT_COMMAND ,"Show a list of all buffers in dmenu" ,"[hotlist]" ," hotlist: shows hotlist buffers only\n" "\n" "To call externally (IE: from i3), enable weechat fifo and run:\n" " $ echo 'core.weechat */buffer_dmenu' >> $(find ~/.weechat -type p)\n" "\n" "To focus the terminal containing WeeChat for the following WM:\n" " i3: requires i3-py [py2] (or i3ipc [py3]) from pip\n" ,"" ,"dmenu_cmd_cb" ,"" )