#!/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 for BunsenLabs Linux, April 2015 # Ported to Manjaro by napcok 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 '\nKey bindings are confugured in your ~/.config/openbox/rc.xml file. docs\n\t\t\t\tS - Shift key\n\t\t\t\tC - Control key\n\t\t\t\tA - Alt key\n\t\t\t\tW - 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)