pcb-rnd knowledge pool
Resource files converted to lihata
res_file by Tibor 'Igor2' Palinkas on 2016-04-19 | Tags: insight, history, historical, resource, file, menu, config, menufile |
Abstract: Notes on how the custom format "resource" files got converted to lihata documents (for menu layout config and vendor drill). May help for advanced users with transition from gEDA/PCB to pcb-rnd.
PCB used to have an own file format for describing resources (menu structure and hotkey bindings, vendor drill mapping). The resource format was generic enough to describe these things, but the syntax was somewhat weird: mixed positional and named fields. More precisely, composite nodes could contain named and anonymous subnodes, and the meaning of anonymous subnodes depended on their position in the anon-subnode-list.
The code that dealt with the in-memory representation of the resource tree was weird and big chunks duplicated in the HIDs and vendor drill module. It was also hard to parse a resource file with external tools.
Since version 1.0.10, pcb-rnd replaces resource files with lihata . Lihata is a small, generic purpose container format that can describe arbitrary trees. Just like resource file syntax, lihata is optimized for hand-editing: no need to use excess quoting or long boilerplate blocks.
Liblihata also provides a lot of helper functions that made the code dealing with the menus and vendor drill resources much simpler and less redundant. Since the parser is small and external, and since there are external converter tools available, it is also easier to deal with the files outside of the pcb executable.
menu files
There are pcb-menu-gtk.lht and pcb-menu-lesstif.lht. They are in trunk/src in the source tree and are installed in the SHAREDIR. Currently each GUI HID (lesstif, gtk) loads the corresponding menu file.menu resource lihata structure
The root of a menu resource file should be a ha: with the following children:- li:mouse for mouse button bindings
- li:main_menu for describing the main menu
- li:popups for describing the popup menus
ha:{ li:mouse { ... } li:main_menu { ... } li:popups { ... } }
li:mouse
The mouse subtree may contain a li: for each mouse button action; the children of the list are further li: nodes for key modifiers, whose children are text nodes: actions executed in order.Buttons supported are: left, right, middle, up, down - the last two are for the scroll wheel. Modifier name should start with "press" or "release" optionally followed by modifier key suffixes separated with dashes, e.g. "press-alt-shift" means the given button is pressed while alt and shift were also pressed.
Example structure:
li:mouse { li:left { li:press = { Mode(Notify) } li:press-ctrl = { Mode(Save); Mode(None); } } }
li:main_menu
The main menu is a list of menubar items that may host submenu items recursively. Each normal item is a hash with the following children:- li:submenu an ordered list of submenu nodes (should not have accel key or action)
- tip tooltip text
- action text or list of actions to execute when menu is selected
- a a key description for an accelerator key (hotkey)
- li:a a list of key descriptions for an accelerator keys (hotkeys); all keys will be bound to the menu and the first key is shown in the menu
- starting with @, are dynamic, auto-generated items (e.g. layers; might be HID-dependent)
- a single dash: separator
A key description is a text in the form of:
- the name of the node is the visible name of the menu item
- <key>keyname, e.g. "<key>k" for key K, or "<key>F10" for F10
- modifier<key>keyname, e.g. "Alt-<key>K" for Alt+K
- modifier-modifier<key>keyname, e.g. "Shift-Alt-<key>K" for Shift+Alt+K; modifiers are Alt, Shift and Ctrl; order does not matter, all three can be used together.
- multikey sequence: multiple of the above, separated by semicolons (protected with {} for lihata, as the text contains semicolon); e.g. "{<key>f;<key>o}" means the user presses "f" then "o". Sequences can be a dozen stroke long and any segment may use modifiers
ha:example menu item { li:submenu { ha:menu item { action=Save(ElementConnections) tip=example menu } - ha:another menu item { a={Shift-Alt<key>r} action={Action1(); Action2();} } } }