Skip to content

Commit ca89dac

Browse files
Seirdyflashcode
authored andcommitted
buffer_dmenu.py 0.2.1: add support for fzf-tmux, reformat with black
fzf-tmux is a script included with FZF: junegunn/fzf@master/bin/fzf-tmux Included a link to a screenshot to showcase it.
1 parent 8f34f42 commit ca89dac

File tree

1 file changed

+153
-119
lines changed

1 file changed

+153
-119
lines changed

python/buffer_dmenu.py

Lines changed: 153 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717
#
1818

1919

20-
# Select a buffer from dmenu or rofi
20+
# Select a buffer from dmenu, rofi, or fzf-tmux
21+
# Screenshot with fzf-tmux: https://seirdy.one/misc/buffer-dmenu-tmux.png
2122
# To call externally (IE: from i3), enable weechat fifo and run:
2223
# $ echo "core.weechat */buffer_dmenu" >> $(find ~/.weechat -type p)
2324
#
2425
# Optionally requires i3-py [py2] (or i3ipc [py3]) to focus weechat in i3
2526
#
2627
# History:
28+
# 2021-03-19, Seirdy
29+
# version 0.2.1: add support for fzf-tmux
2730
# 2020-06-08, Ferus
2831
# version 0.2: drop support of py2 and fix error when closing
2932
# dmenu/rofi with no choice selected
@@ -39,173 +42,204 @@
3942
# Implement `focus` for other window managers
4043
# if buffer == currentbuffer: switch to previous buffer
4144

42-
#pylint: disable=I0011,W0603,W1401
45+
# pylint: disable=I0011,W0603,W1401
4346

44-
SCRIPT_NAME = "buffer_dmenu"
45-
SCRIPT_AUTHOR = "Ferus <[email protected]>"
46-
SCRIPT_VERSION = "0.2"
47+
SCRIPT_NAME = "buffer_dmenu"
48+
SCRIPT_AUTHOR = "Ferus <[email protected]>"
49+
SCRIPT_VERSION = "0.2.1"
4750
SCRIPT_LICENSE = "GPL3"
48-
SCRIPT_DESC = "List buffers in dmenu (or rofi), changes active window to selected buffer"
51+
SCRIPT_DESC = (
52+
"List buffers in dmenu (or rofi/fzf-tmux), changes active window to selected buffer"
53+
)
4954
SCRIPT_COMMAND = "buffer_dmenu"
5055

5156
import os
5257
import subprocess
5358

5459
try:
55-
import weechat as w
60+
import weechat as w
5661
except ImportError as e:
57-
print("This script must be run under WeeChat.")
58-
exit(1)
62+
print("This script must be run under WeeChat.")
63+
exit(1)
5964

6065
try:
61-
import i3ipc as i3
62-
have_i3 = True
66+
import i3ipc as i3
67+
68+
have_i3 = True
6369
except ImportError as e:
64-
have_i3 = False
65-
66-
settings = {"launcher": ("dmenu", "launcher to use (supported: dmenu/rofi)")
67-
,"focus" : ("false", "whether to immediately focus the terminal after selecting buffer")
68-
,"focus.wm" : ("i3", "wm focus logic to use (supported: i3)")
69-
,"dmenu.command" : ("dmenu -b -i -l 20", "command used to call dmenu")
70-
,"rofi.command" : ("rofi -p '# ' -dmenu -lines 10 -columns 8 -auto-select -mesg '<big>Pick a <b>buffer</b> to jump to:</big>'", "command used to call rofi")
71-
,"title.regex" : ("WeeChat \d+\.\d+", "regex used to match weechat's title window")
70+
have_i3 = False
71+
72+
settings = {
73+
"launcher": ("dmenu", "launcher to use (supported: dmenu, rofi, fzf_tmux)"),
74+
"focus": (
75+
"false",
76+
"whether to immediately focus the terminal after selecting buffer",
77+
),
78+
"focus.wm": ("i3", "wm focus logic to use (supported: i3)"),
79+
"dmenu.command": ("dmenu -b -i -l 20", "command used to call dmenu"),
80+
"rofi.command": (
81+
"rofi -p '# ' -dmenu -lines 10 -columns 8 -auto-select -mesg '<big>Pick a <b>buffer</b> to jump to:</big>'",
82+
"command used to call rofi",
83+
),
84+
"fzf_tmux.command": (
85+
"sed -e \"s/b'//\" -e s#\\\\n#\\n#g | fzf-tmux -w 40 -h 70%",
86+
"command used to call fzf-tmux",
87+
),
88+
"title.regex": ("WeeChat \d+\.\d+", "regex used to match weechat's title window"),
7289
}
7390

7491

7592
def check_dmenu():
76-
devnull = open(os.devnull)
77-
retcode = subprocess.call(["which", "dmenu"], stdout=devnull, stderr=devnull)
78-
return True if retcode == 0 else False
93+
devnull = open(os.devnull)
94+
retcode = subprocess.call(["which", "dmenu"], stdout=devnull, stderr=devnull)
95+
return True if retcode == 0 else False
7996

8097

8198
def check_rofi():
82-
devnull = open(os.devnull)
83-
retcode = subprocess.call(["which", "rofi"], stdout=devnull, stderr=devnull)
84-
return True if retcode == 0 else False
99+
devnull = open(os.devnull)
100+
retcode = subprocess.call(["which", "rofi"], stdout=devnull, stderr=devnull)
101+
return True if retcode == 0 else False
102+
103+
104+
def check_fzf_tmux():
105+
devnull = open(os.devnull)
106+
retcode = subprocess.call(["which", "fzf-tmux"], stdout=devnull, stderr=devnull)
107+
return True if retcode == 0 else False
85108

86109

87110
def get_launcher():
88-
launcher = w.config_get_plugin("launcher")
89-
command = None
90-
if launcher == "dmenu":
91-
if check_dmenu():
92-
command = w.config_get_plugin("dmenu.command")
93-
elif launcher == "rofi":
94-
if check_rofi():
95-
command = w.config_get_plugin("rofi.command")
96-
return command
111+
launcher = w.config_get_plugin("launcher")
112+
command = None
113+
if launcher == "dmenu":
114+
if check_dmenu():
115+
command = w.config_get_plugin("dmenu.command")
116+
elif launcher == "rofi":
117+
if check_rofi():
118+
command = w.config_get_plugin("rofi.command")
119+
elif launcher == "fzf_tmux":
120+
if check_fzf_tmux():
121+
command = w.config_get_plugin("fzf_tmux.command")
122+
return command
97123

98124

99125
def launch(options):
100-
launcher = get_launcher()
101-
if launcher:
102-
call(launcher, options)
103-
return True
126+
launcher = get_launcher()
127+
if launcher:
128+
call(launcher, options)
129+
return True
104130

105131

106132
def focus():
107-
if w.config_string_to_boolean(w.config_get_plugin("focus")):
108-
if w.config_get_plugin("focus.wm") == "i3":
109-
focus_i3()
133+
if w.config_string_to_boolean(w.config_get_plugin("focus")):
134+
if w.config_get_plugin("focus.wm") == "i3":
135+
focus_i3()
110136

111137

112138
def focus_i3():
113-
if have_i3:
114-
regex = w.config_get_plugin("title.regex")
139+
if have_i3:
140+
regex = w.config_get_plugin("title.regex")
115141

116-
i3conn = i3.Connection()
117-
weechat = i3conn.get_tree().find_named(regex)[0]
118-
weechat.command('focus')
142+
i3conn = i3.Connection()
143+
weechat = i3conn.get_tree().find_named(regex)[0]
144+
weechat.command("focus")
119145

120146

121147
def call(command, options):
122-
options = "\n".join(options)
148+
options = "\n".join(options)
123149

124-
w.hook_process_hashtable("sh"
125-
,{"arg1": "-c","arg2": 'echo "{0}" | {1}'.format(options, command)}
126-
,10 * 1000
127-
,"launch_process_cb"
128-
,""
129-
)
150+
w.hook_process_hashtable(
151+
"sh",
152+
{"arg1": "-c", "arg2": 'echo "{0}" | {1}'.format(options, command)},
153+
10 * 1000,
154+
"launch_process_cb",
155+
"",
156+
)
130157

131158

132159
process_output = ""
160+
161+
133162
def launch_process_cb(data, command, rc, out, err):
134-
global process_output
135-
if out == "" or ":" not in out:
136-
return w.WEECHAT_RC_ERROR
137-
process_output += out
138-
if int(rc) >= 0:
139-
selected = process_output.strip("\n")
140-
number, name = selected.split(":")
141-
process_output = ""
142-
switch_to_buffer(name)
143-
focus()
144-
return w.WEECHAT_RC_OK
163+
global process_output
164+
if out == "" or ":" not in out:
165+
return w.WEECHAT_RC_ERROR
166+
process_output += out
167+
if int(rc) >= 0:
168+
selected = process_output.strip("\n")
169+
_, name = selected.split(":")
170+
process_output = ""
171+
switch_to_buffer(name)
172+
focus()
173+
return w.WEECHAT_RC_OK
145174

146175

147176
def get_open_buffers():
148-
buffers = []
149-
infolist = w.infolist_get("buffer", "", "")
150-
if infolist:
151-
while w.infolist_next(infolist):
152-
name = w.infolist_string(infolist, "name")
153-
number = w.infolist_integer(infolist, "number")
154-
_ = "{0}:{1}".format(number, name)
155-
buffers.append(_)
156-
w.infolist_free(infolist)
157-
return buffers
177+
buffers = []
178+
infolist = w.infolist_get("buffer", "", "")
179+
if infolist:
180+
while w.infolist_next(infolist):
181+
name = w.infolist_string(infolist, "name")
182+
number = w.infolist_integer(infolist, "number")
183+
_ = "{0}:{1}".format(number, name)
184+
buffers.append(_)
185+
w.infolist_free(infolist)
186+
return buffers
158187

159188

160189
def get_hotlist_buffers():
161-
buffers = []
162-
infolist = w.infolist_get("hotlist", "", "")
163-
if infolist:
164-
while w.infolist_next(infolist):
165-
number = w.infolist_integer(infolist, "buffer_number")
166-
buffer = w.infolist_pointer(infolist, "buffer_pointer")
167-
name = w.buffer_get_string(buffer, "name")
168-
_ = "{0}:{1}".format(number, name)
169-
buffers.append(_)
170-
w.infolist_free(infolist)
171-
return buffers
190+
buffers = []
191+
infolist = w.infolist_get("hotlist", "", "")
192+
if infolist:
193+
while w.infolist_next(infolist):
194+
number = w.infolist_integer(infolist, "buffer_number")
195+
buffer = w.infolist_pointer(infolist, "buffer_pointer")
196+
name = w.buffer_get_string(buffer, "name")
197+
_ = "{0}:{1}".format(number, name)
198+
buffers.append(_)
199+
w.infolist_free(infolist)
200+
return buffers
172201

173202

174203
def switch_to_buffer(buffer_name):
175-
w.command("", "/buffer {0}".format(buffer_name))
204+
w.command("", "/buffer {0}".format(buffer_name))
176205

177206

178207
def dmenu_cmd_cb(data, buffer, args):
179-
""" Command /buffers_dmenu """
180-
if args == "hotlist":
181-
buffers = get_hotlist_buffers()
182-
else:
183-
buffers = get_open_buffers()
184-
185-
if not launch(buffers):
186-
return w.WEECHAT_RC_ERROR
187-
return w.WEECHAT_RC_OK
188-
189-
190-
if w.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
191-
version = w.info_get('version_number', '') or 0
192-
for option, value in settings.items():
193-
if not w.config_is_set_plugin(option):
194-
w.config_set_plugin(option, value[0])
195-
if int(version) >= 0x00030500:
196-
w.config_set_desc_plugin(option, '{0} (default: "{1}")'.format(value[1], value[0]))
197-
198-
w.hook_command(SCRIPT_COMMAND
199-
,"Show a list of all buffers in dmenu"
200-
,"[hotlist]"
201-
," hotlist: shows hotlist buffers only\n"
202-
"\n"
203-
"To call externally (IE: from i3), enable weechat fifo and run:\n"
204-
" $ echo 'core.weechat */buffer_dmenu' >> $(find ~/.weechat -type p)\n"
205-
"\n"
206-
"To focus the terminal containing WeeChat for the following WM:\n"
207-
" i3: requires i3ipc from pip3\n"
208-
,""
209-
,"dmenu_cmd_cb"
210-
,""
211-
)
208+
""" Command /buffers_dmenu """
209+
if args == "hotlist":
210+
buffers = get_hotlist_buffers()
211+
else:
212+
buffers = get_open_buffers()
213+
214+
if not launch(buffers):
215+
return w.WEECHAT_RC_ERROR
216+
return w.WEECHAT_RC_OK
217+
218+
219+
if w.register(
220+
SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""
221+
):
222+
version = w.info_get("version_number", "") or 0
223+
for option, value in settings.items():
224+
if not w.config_is_set_plugin(option):
225+
w.config_set_plugin(option, value[0])
226+
if int(version) >= 0x00030500:
227+
w.config_set_desc_plugin(
228+
option, '{0} (default: "{1}")'.format(value[1], value[0])
229+
)
230+
231+
w.hook_command(
232+
SCRIPT_COMMAND,
233+
"Show a list of all buffers in dmenu",
234+
"[hotlist]",
235+
" hotlist: shows hotlist buffers only\n"
236+
"\n"
237+
"To call externally (IE: from i3), enable weechat fifo and run:\n"
238+
" $ echo 'core.weechat */buffer_dmenu' >> $(find ~/.weechat -type p)\n"
239+
"\n"
240+
"To focus the terminal containing WeeChat for the following WM:\n"
241+
" i3: requires i3ipc from pip3\n",
242+
"",
243+
"dmenu_cmd_cb",
244+
"",
245+
)

0 commit comments

Comments
 (0)