User Feedback :: A TWM for Open DSL



I was thinking of it as levels.  Everytime you start a new sebmenu, you open a new string and write to that string.  If you see an end, end that current string.  If you see another submenu, start a new string and write to it.  When you finish a submenu, go back to the string before it.  You know which submenu is terminating because it's the current one you're writing.

Reading my own code, I realize that you would need two array, one containing the menu strings, and another storing a stack for the current and previous submenus.  When you start a submenu, you would put the string in the next menu[] and put the string number into the next position in the menu stack.  When you finish a submenu, you would pop it off the stack by lowering the stack counter.

submenus[30] <= an array of strings holding the submenus
submenucount <= an index of how many sumenus we have already
menustack[10] <= an array of pointers into submenu[]
menustackcount <= an index into menustack to show the current depth

I think I understand what you're saying.  I need to learn more about arrays before I know how to manipulate them...all I've done so far is create an array once and use it once.
how are you parsing the lines into their components?  Are you using awk or sed?  I can't find a good way to do that but I'd like to know because it's useful.

I'm tempted to look into perl, since I believe thats good at pattern matching and parsing strings.  It would take a lot of learning, and it would be nice to be able to do it in bash anyway.

ion uses lua.
why not use lua to convert the fluxbox menu to the ion menu?

Because I'm making progress with Bash, and I don't have much desire to take on a project like this with a lnguage I know nothing about.  Lua isn't going to be any better anyway...it's a text editing project, best suited for tools like sed and awk.

I was making some progress...I got to a point where I had defined one layer of submenus, and it should be fairly downhillish from here.
However, I'm dumping the project for a little while because of something I noticed in Ion3...it sucks with menu items which have dots in them....it completely chokes on the file and reverts to the default menu.  This is unacceptable.  I don't recall Ion2 doing this, so I'm going to go back to that one....but only after I stop grumbling about it.  Ion3 has some big improvements apart from that glitch.

Clacker: I'm using sed mostly.  

This is the bulk of what I have at this point.
The "append_exec_entry" function is what converts fluxbox [exec] lines into Ion format, except that I use awk to remove the '[exec]' part in another section of the script. I overlooked it in the function and just threw it in at the place I was currently working....I'll fix that eventually.   The SUBLEVEL variable really doesn't serve much purpose right now...That's what I'm hoping to use to organize the submenu items in the main menu.

Code Sample

TMP_DIR="/tmp/flux2ion3"
FLUXmenu="$HOME/.fluxbox/menu"
IONmenu="$HOME/.ion3/cfg-menus.lua"

# test if we can write a temp directory
mktmp_failed() {
echo -e "can't write to \033[0;31m${TMP_DIR}\033[0m.
please make sure the 'TMP_DIR' variable in
\033[0;31m$0\033[0m
points to a writeable directory."
exit 1
}

mkdir -p ${TMP_DIR} &>/dev/null || mktmp_failed

# test if we can read fluxbox menu
if [ -r ${FLUXmenu} ]; then
       echo -e "reading from \033[0;31m${FLUXmenu}\033[0m
       "
else
       echo "can't read ${FLUXmenu}, exiting"
       exit 1
fi

# backup ion menu if it already exists
[ -r ${IONmenu} ] && mv -f ${IONmenu} "${IONmenu}.bak"

# function to convert [exec] line to 'menuentry' line
# FLUX: [exec] (menu_title) {command}
# ION:  menuentry("menu_title", "ioncore.exec_on(_, 'command')"),
append_exec_entry() {
sed "s/(/menuentry(\"/
s/)/\",/
s/{/\"ioncore.exec_on(_, \'/
s/}/\')\"),/"
}

# start writing the ion menu
cat << EOF > ${IONmenu}
--
-- Ion menu definitions
--

-- Main menu
defmenu("mainmenu", {
       submenu("Programs", "appmenu"),
--      menuentry("Lock screen", "ioncore.exec_on(_, 'xlock')"),
       menuentry("About Ion", "mod_query.show_about_ion(_)"),
       submenu("Styles", "stylemenu"),
       submenu("Session", "sessionmenu"),
})

-- Application menu
defmenu("appmenu", {
       menuentry("Run...", "mod_query.query_exec(_)"),
EOF

# separate submenus
SUBLEVEL=0
UNIQUE_ID=0 # just so every submenu is guaranteed to have a unique name
cat ${FLUXmenu} |\
while read LINE; do
if echo ${LINE} | grep submenu] &>/dev/null; then
SUBLEVEL=$((${SUBLEVEL}+1))
UNIQUE_ID=$((${UNIQUE_ID}+1))
SUBMENU="`echo ${LINE} | awk -F \) '{print $1}' | awk -F \( '{print $2}'`"
SUBMENUNAME="`echo \"${UNIQUE_ID}-${SUBMENU}_menu\" | sed 's/ /_/g' | sed 's/\//-/g'`"
echo "submenu(\"${SUBMENU}\", \"${SUBMENUNAME}\")," >> "${IONmenu}"
echo -n "."
echo "defmenu(\"${SUBMENUNAME}\", {" > "${TMP_DIR}/${SUBMENUNAME}-${SUBLEVEL}"
fi
if echo ${LINE} | grep end] >/dev/null; then
SUBLEVEL=$((${SUBLEVEL}-1))
fi
if echo ${LINE} | grep exec] >/dev/null; then
if [ "${SUBLEVEL}" != "0" ]; then
echo ${LINE} | awk -F exec] '{print $2}' | append_exec_entry >> "${TMP_DIR}/${SUBMENUNAME}-${SUBLEVEL}"
else
echo ${LINE} | awk -F exec] '{print $2}' | append_exec_entry >> "${IONmenu}"
echo -n "."
fi
fi
done


cat << EOF >> ${IONmenu}
})

-- Session control menu
defmenu("sessionmenu", {
   menuentry("Save",           "ioncore.snapshot()"),
   menuentry("Restart",        "ioncore.restart()"),
   menuentry("Restart Fluxbox", "ioncore.restart_other('fluxbox')"),
--    menuentry("Restart Fluxbox-0.9.11", "ioncore.restart_other('/opt/fluxbox-0.9.11/bin/fluxbox')"),
   menuentry("Exit",           "ioncore.shutdown()"),
})


-- Context menu (frame/client window actions)
   defctxmenu("WFrame", {
   menuentry("Close",          "WRegion.rqclose_propagate(_, _sub)"),
   menuentry("Kill",           "WClientWin.kill(_sub)",
                               "_sub:WClientWin"),
   menuentry("(Un)tag",        "WRegion.toggle_tag(_sub)",
                               "_sub:non-nil"),
   menuentry("Attach tagged",  "WFrame.attach_tagged(_)"),
   menuentry("Clear tags",     "ioncore.clear_tags()"),
   menuentry("Window info",    "mod_query.show_clientwin(_, _sub)",
                               "_sub:WClientWin"),
})

EOF

for file in `ls ${TMP_DIR}/`; do
cat "${TMP_DIR}/${file}" >> ${IONmenu}
echo -E '})' >> ${IONmenu}
echo -n "."
done

echo " done
"
rm -rf ${TMP_DIR}

Next Page...
original here.