sed and fluxbox menu conversion

I've been working on a sawfish window manager.dsl, and I made a .sawfish file that makes a few of the menu items, but I thought it would be nice to have a fluxbox menu converter (or at least an outline that others could use as well. I played around in sed and I got something that works so I thought I'd share the code, the results, and the sorrows.

The sawfish menu entries, like ion's, are in a different order than fluxbox's. The submenus must be fully defined before they are called by their owner. I looked at bash and C, but for whatever reason, I could see the answer in sed.

My basic strategy was to clean up the file a bit, then use the two buffers in sed to my advantage. Since sed is good at pattern matching, I thought I could use the next read [end] statement to tell me that the last [submenu] in the hold buffer was ready for writing. Then I would write that submenu out and replace everything in the hold buffer past that point with the call to the newly created submenu. Then when the next [end] comes around, you have everything set up. [exec] entries get reformatted and appended to the hold buffer.

I had two problems. The first was that I keep getting double double quote in one spot. It turns out it was supposed to be like that! The second was that some of the entries were formed differently (ie, no trailing {}). The second problem took lots of fiddling with different replacements. I also had a problem with the sed that comes out of the box in dsl, but gnu-utils.dsl took care of that.

I also had problems with general "is this really the right format? why does the final menu need a setq when the others use a defvar?"

The format I needed to a submenu was:

(defvar mymenu-symbol
'(("Some Sub-Menu" . somesubmenu-menu)
("Some wiz bang application" (system "/path/to wiz/bang"))))

I didn't include the output because it's so long. It also took a bit of time to run, perhaps there's a way to clean it up a bit. There's a whole lotta buffer swapping going on.

here is the sed script I wrote. It looks long here but in beaver it's no that bad.I ran it with:

sed -nf flux2saw .fluxbox/menu | tee .sawfishrc

# clacker's fluxbox -> sawfish sed script
# flux2saw
# written 05-26-05
#
#####################################################################
# first, clean up the .fluxbox/menu file
# remove extra space, control chars, blank lines and such
#
s/.*\(\[.*\]\).*\((.*)\).*\(\{.*\}\).*/\1\2\3/
s/.*\(\[.*\]\).*\((.*)\)[^\{]*/\1\2/
s/.*\(\[.*\]\)[^(\{]*/\1/
/^[[:space:]]*$/d
s/[[:space:]]*$//g
s/[[:cntrl:]]//g
/^$/d
/^[^\[].*/d
s/\r//g
#
# backslash # chars
s/\#/\\\#/g
# backslash double quote marks
s/\"/\\\"/g
s/""/"/g
#######################################################################
# remove special fluxbox menu items like restart
# could replace them with sawfish equivalents but I'm Lazy
#
/\[include/d
/\[nop/d
/\[workspaces/d
/\[stylesdir/d
/\[config/d
/\[reconfigure/d
/\[restart/d
/\[exit/d
#######################################################################
# change the begin line into a submenu called "sawcoreapps-menu"
# this is a dummy because the main menu sawfish wants to
# see is called apps-menu. This dummy gets replaced later
#
/\[begin].*/{
s/^\(.*\)$/[submenu](sawcoreapps){}/
h
}
########################################################################
# put the submenus at the end of the hold space
/\[submenu]/{
s/.*\(\[.*)\)/\1/
s/\[submenu](\(.*\)[^{]/[submenu](\1){}/
H
}
#########################################################################
# append modified exec statement into the hold buffer
/\[exec\]/{
s/\[exec\].*(\(.*\)).*{\(.*\)}/\t("\1" (system "\2 \&"))/
H
G
s/\(.*\)[\n\r]\(\[exec.*\)/\1\2/
h
}
#########################################################################
# When we hit an [end] we want to write out the last submenu and replace it
# with a correct menu call
/\[end]/{
### print the menu start
g
s/\(.*\)\[submenu](\([^)]*\)).*/\2/
s|/||g
s/{.*}//g
s/ //g
s|\\\/||g
s/\(.*\)/(defvar dsl-\1-menu \'(/
s/defvar dsl-sawcoreapps-menu/setq apps-menu/g
y/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/[abcdefghijklmnopqrstuvwxyz]/
s/^\(.*\)$/\1/p
### print the menu guts
g
s/\(.*\)\[submenu][^}]*}\(.*\)/\2/p
### make a menu entry, swap pattern & hold
g
s/\(.*\)\[submenu](\([^)]*\)).*/\2/
s|/||g
s/{.*}//g
s/ //g
s|\\\/||g
s/\(.*\)/\t("\1" . dsl-\1-menu)/
y/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/[abcdefghijklmnopqrstuvwxyz]/
x
### remove the last submenu and append entry from hold
s/\(.*\)\(\n\[submenu.*\)/\1/
G
h
### print the menu end
c ))\

}
##########################################################################