164 lines
5.8 KiB
Python
Executable File
164 lines
5.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# This script reads the keybinds configuration file ("$HOME/.config/openbox/rc.xml")
|
|
# and writes them to a text file ("$HOME/.config/openbox/kbinds.txt").
|
|
# The script is used by mb-kb-pipemenu to pipe the output to the Openbox menu,
|
|
# or to display keybinds in a separate window.
|
|
#
|
|
# Based on a script by wlourf 07/03/2010
|
|
# http://u-scripts.blogspot.com/2010/03/how-to-display-openboxs-shortcuts.html
|
|
#
|
|
# Written by damo <damo@bunsenlabs.org> for BunsenLabs Linux, April 2015
|
|
# Ported to Manjaro by napcok <napcok@gmail.com> March 2016
|
|
# Fix (multi-action keybinds): prefer Execute over first action — musqz
|
|
|
|
import sys
|
|
import os
|
|
import datetime
|
|
|
|
try:
|
|
from lxml import etree
|
|
except ImportError:
|
|
import xml.etree.ElementTree as etree
|
|
|
|
rc_fpath = os.environ["HOME"] + "/.config/openbox/rc.xml"
|
|
kb_fpath = os.environ["HOME"] + "/.config/openbox/kbinds.txt"
|
|
arrShortcut = []
|
|
gui = False
|
|
|
|
|
|
def cmdargs():
|
|
if len(sys.argv) > 1:
|
|
if sys.argv[1] == "--gui":
|
|
return True
|
|
else:
|
|
msg = "\n\n\tUSAGE: to display keybinds in a text window use 'mb-kb --gui &>/dev/null'\n\n"
|
|
msg += "\tRunning the script without args will send output to the terminal\n\n"
|
|
print(msg)
|
|
sys.exit()
|
|
return False
|
|
|
|
|
|
def keyboard():
|
|
strRoot = "{http://openbox.org/3.4/rc}"
|
|
tree = etree.parse(rc_fpath)
|
|
root = tree.getroot()
|
|
|
|
for k in root.findall(strRoot + "keyboard/" + strRoot + "keybind"):
|
|
key = k.get("key")
|
|
|
|
# Collect ALL actions for this keybind (fixes multi-action entries like
|
|
# Unmaximize + Execute where the old k.find() only saw the first one).
|
|
actions = k.findall(strRoot + "action")
|
|
if not actions:
|
|
continue
|
|
|
|
# Priority: Execute > MoveResizeTo > first action
|
|
# This ensures tiling keybinds (Unmaximize + MoveResizeTo) show geometry
|
|
# instead of the preceding window-state action.
|
|
action_element = next(
|
|
(a for a in actions if a.get("name") == "Execute"),
|
|
next(
|
|
(a for a in actions if a.get("name") == "MoveResizeTo"),
|
|
actions[0]
|
|
)
|
|
)
|
|
|
|
strTxt = ""
|
|
strType = "o "
|
|
arrShortcut.append((key, "", ""))
|
|
|
|
if action_element.get("name") == "Execute":
|
|
name_element = action_element.find(strRoot + "name")
|
|
command_element = action_element.find(strRoot + "command")
|
|
exec_element = action_element.find(strRoot + "execute")
|
|
strType = "x "
|
|
if name_element is not None:
|
|
strTxt = name_element.text
|
|
elif command_element is not None:
|
|
strTxt = command_element.text
|
|
elif exec_element is not None:
|
|
strTxt = exec_element.text
|
|
elif action_element.get("name") == "MoveResizeTo":
|
|
parts = []
|
|
for tag in ("x", "y", "width", "height"):
|
|
el = action_element.find(strRoot + tag)
|
|
if el is None:
|
|
el = action_element.find(tag) # fallback: no namespace
|
|
if el is not None and el.text:
|
|
parts.append(tag + ":" + el.text.strip())
|
|
strTxt = "MoveResizeTo " + " ".join(parts) if parts else "MoveResizeTo"
|
|
elif action_element.get("name") == "ShowMenu":
|
|
menu_element = action_element.find(strRoot + "menu")
|
|
if menu_element is not None:
|
|
strTxt = menu_element.text
|
|
else:
|
|
action_name = action_element.get("name")
|
|
if action_name is not None:
|
|
strTxt = action_name
|
|
|
|
arrShortcut[len(arrShortcut) - 1] = (strType, key, strTxt)
|
|
|
|
|
|
def output_keybinds(arrShortcut, gui):
|
|
for i in range(len(arrShortcut)):
|
|
exe = str(arrShortcut[i][0])
|
|
keybinding = str(arrShortcut[i][1])
|
|
execute = str(arrShortcut[i][2])
|
|
if gui:
|
|
if len(execute) > 80:
|
|
execute = execute[:75] + "....."
|
|
line = "{:2}".format(i) + "\t" + "{:<16}".format(keybinding) \
|
|
+ "\t" + execute
|
|
else:
|
|
line = exe + "{:<16}".format(keybinding) + "\t" + execute
|
|
print(line)
|
|
write_file(line)
|
|
|
|
|
|
def check_rcfile(fpath, mode):
|
|
try:
|
|
open(fpath, mode).close()
|
|
except IOError:
|
|
return False
|
|
return True
|
|
|
|
|
|
def write_file(line):
|
|
with open(kb_fpath, 'a') as f:
|
|
f.write(line + "\n")
|
|
|
|
|
|
def check_txtfile(kb_fpath):
|
|
try:
|
|
open(kb_fpath, 'w').close()
|
|
except IOError:
|
|
return False
|
|
return True
|
|
|
|
|
|
if __name__ == "__main__":
|
|
gui = cmdargs()
|
|
check_txtfile(kb_fpath)
|
|
|
|
if gui:
|
|
write_file(str(datetime.date.today()) + "\trc.xml KEYBINDS")
|
|
write_file("-------------------------------\n")
|
|
|
|
if check_rcfile(rc_fpath, "r"):
|
|
keyboard()
|
|
output_keybinds(arrShortcut, gui)
|
|
else:
|
|
print("\nCan't open rc.xml for parsing\n\tCheck the filepath: " + rc_fpath + "\n")
|
|
sys.exit(1)
|
|
|
|
if gui:
|
|
dlg = "yad --text-info --title='Mabox Openbox Keybinds' "
|
|
dlg += "--window-icon=distributor-logo-mabox --image=/usr/share/icons/mabox_trans_64.png "
|
|
dlg += "--text '\n<b>Key bindings</b> are confugured in your <i>~/.config/openbox/rc.xml</i> file. <a href=\"http://openbox.org/help/Bindings\">docs</a>\n\t\t\t\t<b>S</b> - Shift key\n\t\t\t\t<b>C</b> - Control key\n\t\t\t\t<b>A</b> - Alt key\n\t\t\t\t<b>W</b> - Super key (usually bound to the Windows key)' "
|
|
dlg += "--filename=$HOME/.config/openbox/kbinds.txt "
|
|
dlg += "--width=640 --height=560 --fontname=Monospace "
|
|
dlg += "--button='Edit rc.xml:geany " + rc_fpath + "' --button='Reload Openbox configuration:openbox --reconfigure' --button=Close"
|
|
os.system(dlg)
|