mikshaw
Group: Members
Posts: 4856
Joined: July 2004 |
|
Posted: Oct. 17 2005,17:23 |
|
I've always had trouble with string parsing....it's one of those things that seems like it would be simple, but i never quite get the syntax right.
I'm building a flua gui for the Fluxbox keys file, and having trouble separating the parts of a line. I've tried various things, and the closer i get to what seems to work, the more unstable the script becomes (getting segmentation faults).
My current parser function (a big mess right now):
Code Sample | function get_line() -- read from the selected keys file line if display.value > 0 then -- all keys keys_string = gsub(display:text(display.value),":.*","") --key_string = keys_string if strfind(strlower(keys_string),"none ") then mod_choice.value = 0 --new_key_string = gsub(keys_string,"NONE ","") --else --new_key_string = keys_string --key_string = gsub(key_string,"NONE ","") end
for modnum = 1,9 do if strfind(keys_string,"Mod"..modnum.." ") then mod_choice.value = modnum --key_string = gsub(key_string,"Mod"..modnum,"") --modnum = modnum+1 end end
if strfind(strlower(keys_string)," shift ") then shift.value = 1 --key_string = gsub(key_string,"Shift","") else shift.value = 0 end if strfind(strlower(keys_string)," control ") then ctrl.value = 1 --key_string = gsub(key_string,"Control","") else ctrl.value = 0 end -- just the key with no modifiers --key_string = gsub(keys_string,"* ","") -- string including just the fluxbox and shell commands com_string = gsub(display:text(display.value),".*:","") if strfind(strlower(com_string),"execcommand ") then sh_command.value = gsub(com_string,"ExecCommand ","") else sh_command.value = "" end --print("com_string="..com_string) end --key_string = strfind(keys_string,".* ",-1) --print("key_string="..key_string) end |
Some of the comments are comments, and some are failed or in-progress tests. I apologize if it's confusing....it's confusing to me too =o)
Essentially, this is what I'm trying... Load a keys file into a hold_browser. When the user clicks a line, the contents of that line are loaded into a series of input fields and pulldown menus. I've had little trouble grabbing Mod#, Shift, Control, and (partially) the command. I haven't figured out yet how to load the flux_command into the chooser menu, but that's a future hurdle. The big problem i'm having is grabbing the key without modifiers...at least in a way that doesn't crash. It would be really nice if i could figure out a way to emulate awk '{print <num>}'
A sample keys file can look something like this:
Mod1 Tab :NextWorkspace mod1 Shift TAB :prevworkspace NONE shift Control f1 :execCommand aterm -e poop none control SHIFT F12 :ExecCommand aterm -e su -c "blah -five"
There is no set number of fields, no defined order of fields, and case is arbitrary. I can deal with the case by using strlower(), and i can break up the string into pieces by breaking it down in stages (cutting key_string multiple times). However, both of these processes seem to break flua after a few clicks. I don't know if flua has difficulty with stopping what it's doing when the user clicks a new line (or if it doesn't stop at all?), or if i'm just a sloppy scripter. Regardless, i've tried to slow down on the clicks and it still crashes, so my guess is that flua just doesn't like to set the same variable several times in a short time, or maybe I'm overlapping variables so nothing works. While typing this I'm forming some ideas, but i'd still llove some input. This is the most complicated task i've had so far (and it seemed so simple at the beginning).
Maybe I need to set initial variables, and return to them as soon as the user clicks anything? Should I use a new variable each time a string is broken into a smaller part?
Thank you for any ideas.
For added clarity (or maybe added confusion), here is the complete script as it is now. Its functionality is limited...it loads a keys file, and has rudimentary line-editing capability. It does not write anything external...that feature will not be added until everything else works. There are various print commands included, which i've been using to debug.
Code Sample | -- DEFAULTS keysfile = getenv("HOME").."/.fluxbox/keys" ww = 420 -- window width wh = 300 -- window height bw = 80 -- button width bh = 20 -- button height bvs = bh+5 -- button vertical spacing bhs = bw+5 -- button horizontal spacing Fl_Widget.initializers = {textfont = 15, labelfont = 15, labelcolor = 0} Fl_Input_.initializers = {when = When.changed} Fl_Button.initializers = {box = Boxtype.thin_up, down_box = Boxtype.thin_down} Fl_Round_Button.initializers = {box = Boxtype.none, down_box=Boxtype.round_down, type = Buttontype.radio, align = Align.bottom} Fl_Window.initializers = {box = Boxtype.thin_down, color = 15}
function set_line() -- modify the keys file line -- a=mod# b=Control c=Shift d=key e=fluxcommand f=shellcommand if display.value > 0 then a = mod_choice.text if ctrl.value == 1 then b = " Control" else b = "" end if shift.value == 1 then c = " Shift" else c = "" end d = " "..key.value e = " :"..fb_command.text if fb_command.text == "ExecCommand" then f = " "..sh_command.value else f = "" end display:set_text(display.value,a..b..c..d..e..f) end end
function get_line() -- read from the selected keys file line if display.value > 0 then -- all keys keys_string = gsub(display:text(display.value),":.*","") --key_string = keys_string if strfind(strlower(keys_string),"none ") then mod_choice.value = 0 --new_key_string = gsub(keys_string,"NONE ","") --else --new_key_string = keys_string --key_string = gsub(key_string,"NONE ","") end
for modnum = 1,9 do if strfind(keys_string,"Mod"..modnum.." ") then mod_choice.value = modnum --key_string = gsub(key_string,"Mod"..modnum,"") --modnum = modnum+1 end end
if strfind(strlower(keys_string)," shift ") then shift.value = 1 --key_string = gsub(key_string,"Shift","") else shift.value = 0 end if strfind(strlower(keys_string)," control ") then ctrl.value = 1 --key_string = gsub(key_string,"Control","") else ctrl.value = 0 end -- just the key with no modifiers --key_string = gsub(keys_string,"* ","") -- string including just the fluxbox and shell commands com_string = gsub(display:text(display.value),".*:","") if strfind(strlower(com_string),"execcommand ") then sh_command.value = gsub(com_string,"ExecCommand ","") else sh_command.value = "" end --print("com_string="..com_string) end --key_string = strfind(keys_string,".* ",-1) --print("key_string="..key_string) end
-- MAIN WINDOW w_main = Window{ww,wh, "fluxkeys.flua"} -- MENU mm = Menu_Bar{0,0,ww,25;textfont=9}
file_open = Menu_Entry{"&File/&Open..."} function file_open:callback() keysfile = fl_file_chooser("Open Keys File","keys*",keysfile) display:load(keysfile) display.value=1 line_num.value=display.value get_line() end
mm:add(file_open)
file_save = Menu_Entry{"&File/&Save"} mm:add(file_save)
help = Menu_Entry{"&File/&Help"} function help:callback() w_help:show() end mm:add(help)
file_quit = Menu_Entry{"&File/&Quit"} function file_quit:callback() exit(0) end mm:add(file_quit)
edit_new = Menu_Entry{"&Edit/&New Key"} function edit_new:callback() display:insert(display.value+1,"Mod1 Shift F12 :Reconfigure") display.value=display.value+1 line_num.value=display.value end mm:add(edit_new)
edit_remove = Menu_Entry{"&Edit/&Remove Key"} function edit_remove:callback() display:remove(display.value) end mm:add(edit_remove) -- MENU END
line_num = Int_Input{360,0,60,25,"line:"} function line_num:callback() if line_num.value > "" then display.value = line_num.value end end
-- The main text field, containing the keys file itself display = Hold_Browser{10,30,ww-20,200} function display:callback() line_num.value = display.value get_line() --debug --print(display:text(display.value)) end
-- CHOOSE MODIFIERS mod_choice = Choice{10,240,64,20} mod_choice:add(Menu_Entry{"NONE"}) mod_choice:add(Menu_Entry{"Mod1"}) mod_choice:add(Menu_Entry{"Mod2"}) mod_choice:add(Menu_Entry{"Mod3"}) mod_choice:add(Menu_Entry{"Mod4"}) mod_choice:add(Menu_Entry{"Mod5"}) mod_choice:add(Menu_Entry{"Mod6"}) mod_choice:add(Menu_Entry{"Mod7"}) mod_choice:add(Menu_Entry{"Mod8"}) mod_choice:add(Menu_Entry{"Mod9"}) mod_choice.value = 0 ctrl = Round_Button{7,260,64,20;type=Buttontype.toggle} ctrl_label = Box{10,260,20,20,"Control";align=Align.right} shift = Round_Button{7,275,64,20;type=Buttontype.toggle} shift_label = Box{10,275,20,20,"Shift";align=Align.right}
-- CHOOSE KEY key = Input{80,240,80,20}
-- CHOOSE FLUXBOX COMMAND fb_command = Choice{170,240,240,20} fb_command:add(Menu_Entry{"ExecCommand"}) fb_command:add(Menu_Entry{"Reconfigure"}) fb_command:add(Menu_Entry{"Workspace1"}) fb_command:add(Menu_Entry{"Workspace2"}) fb_command:add(Menu_Entry{"Workspace3"}) fb_command:add(Menu_Entry{"Workspace4"}) fb_command.value = 0 sh_command = Input{170,265,240,20}
function mod_choice:callback() --print(mod_choice.text) set_line() end function fb_command:callback() if fb_command.text == "ExecCommand" then sh_command:show() else sh_command:hide() end --print(fb_command.text) set_line() end --mod_choice.callback() --fb_command.callback()
w_main:end_layout()
-- HELP WINDOW w_help = Window{ww,wh, "fluxkeys help"} author = Box{0,wh-bh,ww,20, "Lua FLTK script by mikshaw 2005"} w_help:end_layout()
w_main:show()
|
-------------- http://www.tldp.org/LDP/intro-linux/html/index.html
|