You are not logged in.
Pages: 1
[ Some of this material is taken from Basic Introduction to jgmenu on BL Lithium ]
BL helpfully provides some functions which can be sourced by scripts. These include some shorthand for jgmenu code, and can be utilised by adding this to any script that sends output to jgmenu:
BL_COMMON_LIBDIR="/usr/lib/bunsen/common" # source jgmenu helper functions
if ! . "${BL_COMMON_LIBDIR}/bl-includes" 2> /dev/null; then
echo $"Error: Failed to locate bl-includes in ${BL_COMMON_LIBDIR}" >&2
exit 1
fi
I keep my menu scripts in ~/.config/jgmenu/scripts, but obviously you can put them in your $PATH so they can be run directly.
/usr/lib/bunsen/common/bl-includes has some functions that generate an associative array menu_content.
'root' indexes the root menu, while submenu content is stored under the index of its tag.
jgmenuItem Put an item in the root menu or any submenu.
Usage: jgmenuItem tag label command
Tag 'root' indicates root menu item.
-
jgmenuSeparator Add a separator.
Usage: jgmenuSeparator tag [label]
-
jgmenuSubmenu Put a checkout() for a submenu in the root menu or any submenu.
Usage: jgmenuSubmenu tag(parentmenu) tag(submenu) label
-
jgmenuEnd Print root menu, then submenus.
Usage: jgmenuEnd
A simple menu could be constructed like this:
#!/bin/bash
##
## my-pipemenu
BL_COMMON_LIBDIR="/usr/lib/bunsen/common" # source jgmenu helper functions
if ! . "$BL_COMMON_LIBDIR/bl-includes" 2> /dev/null; then
echo $"Error: Failed to locate bl-includes in $BL_COMMON_LIBDIR" >&2
exit 1
fi
jgmenuSeparator 'root' "Main Menu"
# "jgmenuSubmenu tag(parentmenu) tag(submenu) label"
jgmenuSubmenu 'root' "terminal" "Terminal Emulators"
jgmenuSubmenu 'root' "editor" "Text Editors"
# "jgmenuItem tag label command"
jgmenuItem "terminal" "x-terminal-emulator" "x-terminal-emulator"
jgmenuItem "terminal" "Terminator" "terminator"
jgmenuItem "terminal" "lxterminal" "lxterminal"
jgmenuItem "editor" "Geany" "geany"
jgmenuItem "editor" "Medit" "medit"
jgmenuItem "editor" "Gedit" "gedit"
jgmenuEnd
If my-menu.csv contains:
^sep(Main Menu)
Applications,^pipe(my-pipemenu)
Run it with the commands:
jgmenu --simple --csv-file='~/.config/jgmenu/mymenu.csv'
.
or
.
cat ~/.config/jgmenu/mymenu.csv | jgmenu --simple
#!/bin/bash
##
## xbindkeys-pipemenu
# Initialize vars and arrays
BL_COMMON_LIBDIR="/usr/lib/bunsen/common"
KBINDS="${HOME}/.xbindkeysrc"
declare -a KB_ARR
declare -a CMD_ARR
# source the helper functions
if ! . "${BL_COMMON_LIBDIR}/bl-includes" 2> /dev/null; then
echo $"Error: Failed to locate bl-includes in ${BL_COMMON_LIBDIR}" >&2
exit 1
fi
# add a separator with text to the output
jgmenuSeparator 'run_commands' 'Run commands'
# read and process .xbindkeysrc, and add the keybind names and commands to arrays
while read -r line;do
if [[ -n $line ]];then # skip empty lines
if [[ ${line} = \#* ]];then # skip commented lines
continue
elif [[ ${line} = \"* ]];then # if line starts with double-quote...
CMD=$(echo "${line}" | sed -e 's/"//g') # remove double-quote
CMD_ARR+=("${CMD}") # add command to array
else
# replace "Mod4" with "Super", and remove spaces
KB=$(echo "${line}" | sed -e 's/Mod4/Super/' -e 's/ //g')
KB_ARR+=("${KB}") # add keybinds to array
fi
fi
done < "${KBINDS}"
# read the arrays and populate the output
i=0
for c in "${KB_ARR[@]}";do
# use a tab ('\t') to align second field text
curr_item=$(printf "%s\t %s" "${KB_ARR[$i]}" "${CMD_ARR[$i]}")
# add a menu item to the submenu which has '^tag(run_commands)'
jgmenuItem 'run_commands' "${curr_item}"
i=$((i+1))
done
# Tidy up and close out the menu
jgmenuEnd
exit
Run the script in the terminal to see what the output looks like: that is what jgmenu is using as its csv input.
Let's edit my-pipemenu to show a "Utilities" menu
Terminals
Editors
Screenfetch output
#!/bin/bash
##
## my-pipemenu
BL_COMMON_LIBDIR="/usr/lib/bunsen/common" # source jgmenu helper functions
if ! . "$BL_COMMON_LIBDIR/bl-includes" 2> /dev/null; then
echo $"Error: Failed to locate bl-includes in $BL_COMMON_LIBDIR" >&2
exit 1
fi
jgmenuSubmenu 'root' "terminal" "Terminal Emulators"
jgmenuSubmenu 'root' "editor" "Text Editors"
jgmenuSubmenu 'root' "screenfetch" "Show screenfetch"
jgmenuSeparator "terminal" "Terminals"
jgmenuSeparator "editor" "Text Editors"
jgmenuSeparator "screenfetch" "screenfetch"
# display output from screenfetch command
while read -r line;do
jgmenuItem "screenfetch" "${line}"
done <<< $(screenfetch -nN)
jgmenuItem "terminal" "x-terminal-emulator" "x-terminal-emulator"
jgmenuItem "terminal" "Terminator" "terminator"
jgmenuItem "terminal" "lxterminal" "lxterminal"
jgmenuItem "editor" "Geany" "geany"
jgmenuItem "editor" "Medit" "medit"
jgmenuItem "editor" "Gedit" "gedit"
jgmenuEnd
Note that the order of the jgmenuItem <tag> sections doesn't matter - they will be displayed in the order of their parent jgmenuSubmenu's. The same is also true for the jgmenuSeparator's.
pangoEscape() is used by the jgmenu*() functions, and isn't designed to be used separately. However, with a slight tweak this function could be used in a helper script, to get text into the right format for jgmenu. Trying to redirect unprocessed text to jgmenu may result in:
fatal: item <n> was not correctly terminated with a '\n'
.
or
.
fatal: no closing triple quote
.
or
.
Error on line 1: Entity did not end with a semicolon; most likely you used an ampersand character without intending to start an entity — escape ampersand as &
Strings and lines will also be split on comma characters, so we need to
escape special characters: & < >
wrap lines in triple-quotes in case they contain commas (NB csv = comma separated variable)
ensure printf outputs a newline in the right place
jg-output.sh
#!/bin/bash
##
## jg-output.sh
input="$1"
pangoEscape() {
local string="${1//&/&}"
string="${string//</<}"
string="${string//>/>}"
printf '%s\n' "$string" # note the newline added here
}
input=$(awk '{ print "\"\"\""$0"\"\"\""}' <<< "${input}")
pangoEscape "${input}"
Now you can do something like
jg-output.sh "$(cat input.txt)" | jgmenu --simple
Let's process a command output which has been redirected to a textfile, then display it in my-pipemenu. Save the output from neofetch; process it with pangoEscape() using jg-output.sh; then use the file as the source for a menu item:
neofetch --stdout --disable title underline model term > neofetch.txt
jg-output.sh "$(cat neofetch.txt)" > neofetch.txt
(There are some commas in the output, so the second step is needed here.)
Now add these lines in the order you want them in my-pipemenu
# in the submenu section
jgmenuSubmenu 'root' "neofetch" "Show neofetch"
# anywhere before the jgmenuItems section
jgmenuSeparator "neofetch" "neofetch"
# anywhere after the submenus and separators
# display content of a textfile
while read -r line;do
jgmenuItem "neofetch" "${line}"
done <neofetch.txt
For reference:
Advanced Bash-Scripting Guide: Here Documents
This syntax (here-document) is used to denote the creation of a text file from whatever is between the "EOF"s. ("EOF" signifies "End Of File", but you could use other text if you wanted to: "HERE", "THERE", "EVERYWHERE" etc)
cat >file <<EOF
foo
bar
EOF
The cat command is taking all the text up to "EOF" and redirecting it into "file". This means we could use temporary files to script a menu, and delete them when we are done.
So a single script can do the job, without having to use previously saved rc and csv files, like jgmenurc and prepend.csv.
Making temporary files
CONFIG_FILE=$(mktemp --tmpdir jgcfg.XXX)
MENU_ITEMS=$(mktemp --tmpdir jgmenu.XXX)
Example config file
It could be built like this:
cat > ${CONFIG_FILE} <<EOF
tint2_look = 0
position_mode = center
menu_width = 220
menu_height_min = 0
menu_height_max = 500
menu_margin_x = 10
menu_margin_y = 40
menu_padding_top = 130
menu_padding_right = 10
menu_padding_bottom = 10
menu_padding_left = 10
menu_border = 1
item_height = 20
item_radius = 2
item_border = 1
item_halign = left
item_valign = top
item_margin_x = 10
item_margin_y = 4
sep_halign = right
#sub_padding_left = 10
color_menu_bg = #2B454F 90
color_menu_border = #eeeeee 10
#color_norm_fg = #eeeeee 100
color_sel_bg = #ffffff 10
#color_sel_fg = #eeeeee 100
color_sel_border = #eeeeee 8
color_scroll_ind = #eeeeee 50
icon_theme = Paper
icon_size = 0
arrow_string = ›
arrow_width = 16
EOF
Example csv file
cat <<EOF > ${MENU_ITEMS}
@icon,,10,10,200,,2,left,top,#000000 50,#000000 50,/path/to/image
^sep(Menu)
Terminal Emulators,^checkout(terminal)
Text Editors,^checkout(editors)
^tag(terminal)
Terminal,x-terminal-emulator
lxterminal,lxterminal
terminator,terminator
^tag(editors)
Geany,geany
Medit,medit
Gedit,gedit
EOF
Now you can put the config and csv heredocs in functions, and call them in the script:
mkconfigfile # set up config
mkmenufile # set up menu csv
jgmenu --simple --config-file=${CONFIG_FILE} --csv-file=${MENU_ITEMS} 2>/dev/null
The script now needs to do some tidying up after the menu closes, by removing the temp files. I use an array here, because it makes it easier if you have many variables. For example, a screenshot menu might also have temporary scrot and scrot-thumb image files.
# Clean up temp files
declare -a VARS
VARS=("${CONFIG_FILE}" "${MENU_ITEMS}" )
for v in "${VARS[@]}";do
rm -f "${v}"
done
Full script
#!/bin/bash
##
## heredocs.sh
function mkconfigfile() { # set up jgmenu config
cat > ${CONFIG_FILE} <<EOF
tint2_look = 0
position_mode = pointer
menu_width = 220
menu_height_min = 0
menu_height_max = 500
menu_margin_x = 10
menu_margin_y = 40
menu_padding_top = 130
menu_padding_right = 10
menu_padding_bottom = 10
menu_padding_left = 10
menu_border = 1
item_height = 20
item_radius = 2
item_border = 1
item_halign = left
item_valign = top
item_margin_x = 10
item_margin_y = 4
sep_halign = right
#sub_padding_left = 10
color_menu_bg = #2B454F 90
color_menu_border = #eeeeee 10
#color_norm_fg = #eeeeee 100
color_sel_bg = #ffffff 10
#color_sel_fg = #eeeeee 100
color_sel_border = #eeeeee 8
color_scroll_ind = #eeeeee 50
icon_theme = Paper
icon_size = 0
arrow_string = ›
arrow_width = 16
EOF
}
function mkmenufile() {
cat <<EOF > ${MENU_ITEMS}
@icon,,10,10,200,,2,left,top,#000000 50,#000000 50,/path/to/image
^sep(Menu)
Terminal Emulators,^checkout(terminal)
Text Editors,^checkout(editors)
^tag(terminal)
Terminal,x-terminal-emulator
lxterminal,lxterminal
terminator,terminator
^tag(editors)
Geany,geany
Medit,medit
Gedit,gedit
EOF
}
### END FUNCTIONS ###
CONFIG_FILE=$(mktemp --tmpdir jgcfg.XXX)
MENU_ITEMS=$(mktemp --tmpdir jgmenu.XXX)
mkconfigfile # run function to set up config
mkmenufile # run function to set up menu csv
# run jgmenu
jgmenu --simple --config-file=${CONFIG_FILE} --csv-file=${MENU_ITEMS} 2>/dev/null
# Clean up temp files
declare -a VARS
VARS=("${CONFIG_FILE}" "${MENU_ITEMS}" )
for v in "${VARS[@]}";do
rm -f "${v}" || echo "${v} couldn't be deleted"
done
exit
Last edited by damo (2020-03-05 10:09:39)
Be Excellent to Each Other...
The Bunsenlabs Lithium Desktop » Here
FORUM RULES and posting guidelines «» Help page for forum post formatting
Artwork on DeviantArt «» BunsenLabs on DeviantArt
Offline
Pages: 1