You are not logged in.
This script I put together - it took a bit longer than expected, and might not be amazingly useful except perhaps for people making a new Wayland system. Aimed not so much at users as developers.
It will take a jgmenu csv menu file and print out openbox-style xml that should work with labwc. Of course some of it will need editing - like, the "openbox" submenu will need replacing with something for labwc - but people with a long jgmenu menu might enjoy not having to type out all that XML. Just tweak a few places as needed.
A lot of the jgmenu pipemenus in BL are reusing openbox pipemenus, eg this:
Compositor,^pipe(jgmenu_run ob --cmd="bl-compositor" --tag="bl-compositor"),picomoriginally came from the xml pipemenu "bl-compositor", and this converter will migrate it back to:
<menu id="bl-compositor" label="Compositor" icon="picom" execute="bl-compositor" />Anyway, there are short help and debug options, but when you find bugs or improvements, please post!
Just copy/paste from here and either make it executable or call it with bash: 'bash scriptname -c csvfile' -x xmlfile':
#!/bin/bash
#csv2xml
debug() { :; }
HELP="Usage: ${0##*/} [OPTIONS] CSV_FILE
Convert a jgmenu CSV file
(comma‑separated, with optional """...""", ^sep, ^tag, ^checkout, ^pipe)
to a labwc‑compatible xml file.
@ widgets and . includes are ignored.
The converted xml will be printed to STDOUT, or the chosen file.
Options:
-c, --csvfile <file> The csv file to read.
-x, --xmlfile <file> The xml file to write to.
-d, --debug Enable debug output
-h, --help Show this help and exit
"
while [[ -n $1 ]]
do
case "$1" in
-h|--help)
echo "$HELP"
exit 0
;;
-d|--debug)
debug() {
echo -e "$*" >&2
}
shift
;;
-c|--csvfile)
csvfile=$2
shift 2
;;
-x|--xmlfile)
xmlfile=$2
shift 2
;;
*)
echo "${0##*/}: $1: no such option" >&2
exit 1
;;
esac
done
if [[ -n $xmlfile ]]
then
exec >"$xmlfile"
else
debug 'No xml file specified, printing to STDOUT'
fi
parse_jgmenu_line() {
local line="$1"
local pos=0 field="" in_quotes=false
while (( pos < ${#line} )); do
# Check for triple-quote toggle
if [[ "${line:$pos:3}" == '"""' ]]; then
[[ $in_quotes = false ]] && in_quotes=true || in_quotes=false
pos=$((pos+3))
continue
fi
# Comma is a field separator only outside quotes
if [[ "${line:$pos:1}" == ',' ]] && [[ $in_quotes = false ]]; then
fields+=("$field")
field=""
pos=$((pos+1))
continue
fi
# Regular character — add to current field
field+="${line:$pos:1}"
pos=$((pos+1))
done
fields+=("$field") # Don't forget the last field
for i in "${!fields[@]}"
do
fields[i]=$(strip_spaces "${fields[i]}")
done
# three special characters will have been pango escaped in Description (fields[0])
fields[0]=$(pango_unescape "${fields[0]}")
}
strip_spaces(){
local string
string=$1
read -r string <<<"$string"
printf '%s' "$string"
}
pango_unescape(){
local string
string="${1//&/\&}"
string="${string//</<}"
string="${string//>/>}"
printf '%s' "$string"
}
####### functions to generate labwc menu ###########################
# Each helper emits embedded newlines; caller appends with $'\n'.
OBmenuStart() {
printf '%s' '<openbox_menu>'
}
OBmenuEnd() {
printf '%s' '</openbox_menu>'
}
rootmenuStart() {
printf '%s' ' <menu id="root-menu">'
}
# end any toplevel menu except the <openbox_menu>
rootmenuEnd() {
printf '%s' ' </menu>'
}
# args: label command icon (same order as csv fields)
menuItem() {
printf ' <item label="%s" icon="%s" >\n <action name="Execute" command="%s" />\n </item>' \
"$(OBlabelEscape "$1")" "$(XMLescape "$3")" "$(XMLescape "$2")"
}
menuSeparator() {
if [[ ${1-} ]]; then
printf ' <separator label="%s" />' "$(OBlabelEscape "$1")"
else
printf ' <separator />'
fi
}
menuSubmenuStart() {
printf '\n <menu id="%s" label="%s" icon="%s" >\n' \
"$(XMLescape "$1")" "$(OBlabelEscape "$2")" "$(XMLescape "$3")"
}
menuSubmenuEnd() {
printf ' </menu>'
}
menuSubmenuExternal() {
printf ' <menu id="%s" />' "$(XMLescape "$1")"
}
pipemenu() {
printf ' <menu id="%s" label="%s" icon="%s" execute="%s" />' \
"$(XMLescape "$1")" "$(OBlabelEscape "$2")" "$(XMLescape "$3")" "$(XMLescape "$4")"
}
# escape special characters
XMLescape() {
local string="${1//&/\&}"
string="${string//</\<}"
string="${string//>/\>}"
string="${string//\"/\"}"
string="${string//\'/\'}"
printf '%s' "$string"
}
OBlabelEscape() {
local string
string="$(XMLescape "$1")"
printf '%s' "${string//_/__}"
}
########################################################################
generate_xml() {
declare -A menus
declare -A submenulabels
declare -A submenuicons
menus[root]=''
menu=root
debug "currently adding items to menu: $menu"
while read -r line; do
case "$line" in
'')
[[ $menu != root ]] && debug "end of submenu $menu"
menu=root
debug "currently adding items to menu: $menu"
continue
;;
'#'*)
continue
;;
'.'*)
debug "ignoring sourced file: $line"
continue
;;
'@'*)
debug "ignoring widget: $line"
continue
;;
esac
fields=()
parse_jgmenu_line "$line"
case "${fields[0]}" in
^sep\(*\))
title=${fields[0]#*\(}
title=${title%\)*}
menus["$menu"]+=$(menuSeparator "${title}")$'\n'
;;
^tag\(*\))
id=${fields[0]#*\(}
id=${id%\)*}
menu=${id}
debug "currently adding items to menu: $menu"
continue
;;
*)
case "${fields[1]}" in
^back\(\))
continue
;;
^checkout\(*\))
id=${fields[1]#*\(}
id=${id%\)*}
menus["$menu"]+=$(menuSubmenuExternal "$id")$'\n'
submenulabels["$id"]="${fields[0]}"
submenuicons["$id"]="${fields[2]}"
continue
;;
^pipe\(*\)) # pipemenu command needs rewriting if it's an openbox pipemenu, otherwise (csv) leave empty
cmd=${fields[1]#*\(}
cmd=${cmd%\)*}
id=${cmd#*--tag=\"}
id=${id%\"*}
if [[ $cmd = 'jgmenu_run ob'* ]]
then # openbox xml pipemenu
cmd="${cmd#*--cmd=\"}"
cmd="${cmd%%\"*}"
else
debug "Not an xml pipemenu: $cmd"
cmd="<!-- $cmd -->"
fi
label=${fields[0]}
icon=${fields[2]}
menus["$menu"]+=$(pipemenu "$id" "$label" "$icon" "$cmd")$'\n'
continue
esac
menus["$menu"]+=$(menuItem "${fields[@]}")$'\n'
;;
esac
done < "$csvfile"
rootmenu="${menus[root]}"
unset 'menus[root]'
OBmenuStart
echo
printf '%s\n' '<!-- defining submenus -->'
for i in "${!menus[@]}"
do
menuSubmenuStart "$i" "${submenulabels[$i]}" "${submenuicons[$i]}"
printf '%s' "${menus[$i]}"
menuSubmenuEnd
echo
done
printf '\n%s\n\n' '<!-- root menu starts here -->'
rootmenuStart
echo
printf '%s' "$rootmenu"
rootmenuEnd
echo
OBmenuEnd
echo
}
generate_xmlLast edited by johnraff (Today 06:30:53)
...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )
Offline