Flua string parsing
Forum: Programming and Scripting
Topic: Flua string parsing
started by: mikshaw
Posted by mikshaw on 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()
|
Posted by mikshaw on Oct. 17 2005,19:54
I decided to start rewriting the get_line function from scratch. So far no segfault, although i still have to figure out how to separate "F7" from "Mod1 Shift F7 :*" or None Control Shift F7 :*".
Also put the fb_command lines into a table so i don't have a huge number of redundant "fb_command:add" commands in there.
New get_line function, without the sigle-key detection. "fluxbox_commands" is the comma-separated table of fluxbox commands, "BLANK", "ExecCommand", "Restart", "Workspace1", etc... Eventually i hope to make fluxbox version-specific tables.
Code Sample | function get_line() -- find parts of selected keysfile line
-- find Mod<num> or "None" for modnum = 1,9 do if strfind(strlower(display:text(display.value)),"mod"..modnum.." ") then mod_choice.value = modnum break else mod_choice.value = 0 end end
-- find "Control" if strfind(strlower(display:text(display.value))," control ") then ctrl.value = 1 else ctrl.value = 0 end
-- find "Shift" if strfind(strlower(display:text(display.value))," shift ") then shift.value = 1 else shift.value = 0 end
-- find "ExecCommand" if strfind(strlower(display:text(display.value)),":execcommand ") then fb_command.value = 1 sh_command.value = gsub(display:text(display.value),".*:-ommand ","") sh_command:show() else -- else find other fluxbox commands sh_command:hide() for find_flux = 1,num_fb_commands do if strfind(strlower(display:text(display.value)),":"..strlower(fluxbox_commands[find_flux])) then print(fluxbox_commands[find_flux]) fb_command.value = find_flux break else fb_command.value = 0 end end end --print(display:text(display.value))
end |
Posted by clacker on Oct. 17 2005,20:46
mikshaw, this looks like a great project. I don't have the big answers for you, but here are some of my thoughts:
You want to parse a line to find out what components are there so for each component, you can create a check box (like for shift and mod8), a pull down menu item (like for :prevworkspace or :execcommand), and in input box for things like the execcommand string. What I would do is parse the strings into two parts: before the command and after. Is that OK to do or not? I thought that the keys and modifers came before the :command.
I used the sherlock holmes method to find the key: eleminate everything else, and whatever is left must be the key!
EDIT: modified code to separate out key.
Code Sample | -- test for mikshaw
-- make some test strings
st1 = "Mod1 Tab :NextWorkspace" st2 = "mod1 Shift TAB :prevworkspace" st3 = "NONE shift Control f1 :execCommand aterm -e poop" st4 = 'none control SHIFT F12 :ExecCommand aterm -e su -c "blah -five"'
-- make the parsing function function parseMyLine(mystring) frontstring = strsub( mystring, strfind(mystring, "^[^\:]*")) backstring = strsub( mystring, strfind(mystring, ":.*"))
if strfind( strlower(frontstring), "^%s*none") then cb_none = "true" else cb_none = "false" end if strfind( strlower(frontstring), "control") then cb_control = "true" else cb_control = "false" end if strfind( strlower(frontstring), "shift") then cb_shift = "true" else cb_shift = "false" end
if strfind( strlower(frontstring), "mod%d") then tempModString = strsub( strlower(frontstring), strfind( strlower(frontstring), "mod%d*")) cb_modifier = strsub( tempModString, strfind( tempModString, "%d")) else cb_modifier = "'no value'" end
--strip out everything but the key frontstring = gsub(frontstring,"[nN][oO][Nn][Ee]","") frontstring = gsub(frontstring,"[Cc][Oo][Nn][Tt][Rr][Oo][Ll]","") frontstring = gsub(frontstring,"[Ss][Hh][Ii][Ff][Tt]","") frontstring = gsub(frontstring,"[Mm][Oo][Dd]%d*","") cb_key = gsub(frontstring, "%s%s*","")
list_command = strsub( strlower(backstring), strfind(strlower(backstring), ":[^%s]*")) list_commandargs = gsub(strlower(backstring), ":[^%s]*", "")
print("PARSING: ".. mystring) print("frontstring = " .. frontstring) print("backstring = " .. backstring) print("\tnone was " .. cb_none) print("\tcontrol was " .. cb_control) print("\tshift was " .. cb_shift) print("\tMOD was " .. cb_modifier) print("\tkey was " .. cb_key) print("\tfluxbox command was was " .. list_command) print("\tfluxbox command args were " .. list_commandargs) print() end
parseMyLine(st1) parseMyLine(st2) parseMyLine(st3) parseMyLine(st4) |
Posted by mikshaw on Oct. 17 2005,21:06
I had orignally split the string into the two parts separated by the colon, and ideally i want to put it back in just in case the shell command contains " shift " or " control " (the spaces are useful, by the way...I notice you omitted them in your script). The biggest problem was arising from creating substrings out of substrings i think....i'm guessing that it was inthe middle of parsing wheni tried to get it to start over with a different line? I still don't know for sure. Anyway, my current function seems to do exactly what i need without crashing...EXCEPT for grabbing just the single key without modifiers. I can't see where that is in your script? Thank you for your work...could you please help me to understand it? =o)
I'm beginning to think that a new table for keys might work, in the same way that the fluxbox_commands table is used. Rather than type in the name of the key, the user would select it from a (very) long list. The problem with that, other than the fact that the list would contain over 100 entries, is that different keyboards have different keys, and it also wouldn't allow the user to enter keycodes instead of key names.
Posted by clacker on Oct. 17 2005,21:31
I retro-actively added the part the separates out the string for the key to my previous, just because I'm devious. There are three main string functions I think we are both using: strfind, strsub, and gsub. Strfind looks for a match and return either nil if it finds nothing or a pair of numbers. strsub returns a substring based on the numbers returned by strfind. gsub replaces a matched pattern in a string with another pattern.
I would try matching a pattern, say shift. If that matches, I set some switch. Then i use gsub to remove that string from the test string. Once all of the modifiers have been removed from the test string (and the spaces) whatever is left is the key itself.
What I did is a little harder to explain. It all regular expression stuff. You can look < at the manual > to see more.
frontstring = strsub( mystring, strfind(mystring, "^[^\:]*")) matches from the start of a string ( "^ ) and includes everything from there on except for a : character ( [^:]* )
backstring = strsub( mystring, strfind(mystring, ":.*")) matches from the first : and includes the rest of the string.
Posted by clacker on Oct. 17 2005,23:42
OK, here's what I got. It gets the key (even tab) and it sets the check boxes. You're on your own setting the menu to the correct command.
Code Sample | -- test for mikshaw
-- make some test strings
st1 = "Mod1 Tab :NextWorkspace" st2 = "mod1 Shift TAB :prevworkspace" st3 = "NONE shift Control f12 :execCommand aterm -e poop" st4 = 'none control SHIFT F12 :ExecCommand aterm -e su -c "blah -five"'
-- set up windows and buttons
w = Window{20,100,300,200;label = "Fluxbox Keys Test Window"}
b_none = Check_Button{20,20,60,20;label = "None"} b_shift = Check_Button{20,50,60,20;label = "Shift"} b_control = Check_Button{20,80,60,20;label = "Control"} i_mod = Input{60,110,60,20;label = "Mod"} i_key = Input{140,40,50,20;label = "Key"} o_string = Output{40,170,250,20;label = "string"}
m_command = Choice{20,140,200,20} m_command:add(Menu_Entry{":ExecCommand"}) m_command:add(Menu_Entry{":NextWorkspace"}) m_command:add(Menu_Entry{":PrevWorkspace"})
w:end_layout()
-- make the parsing function function parseMyLine(mystring) o_string.value = mystring frontstring = strsub( mystring, strfind(mystring, "^[^\:]*")) backstring = strsub( mystring, strfind(mystring, ":.*"))
if strfind( strlower(frontstring), "^%s*none") then b_none.value = 1 else b_none.value = 0 end if strfind( strlower(frontstring), "control") then b_control.value = 1 else b_control.value = 0 end if strfind( strlower(frontstring), "shift") then b_shift.value = 1 else b_shift.value = 0 end
if strfind( strlower(frontstring), "mod%d") then tempModString = strsub( strlower(frontstring), strfind( strlower(frontstring), "mod%d*")) i_mod.value = strsub( tempModString, strfind( tempModString, "%d")) else i_mod.value = "" end
--strip out everything but the key frontstring = gsub(frontstring,"[nN][oO][Nn][Ee]","") frontstring = gsub(frontstring,"[Cc][Oo][Nn][Tt][Rr][Oo][Ll]","") frontstring = gsub(frontstring,"[Ss][Hh][Ii][Ff][Tt]","") frontstring = gsub(frontstring,"[Mm][Oo][Dd]%d*","") i_key.value = gsub(frontstring, "%s%s*","")
list_command = strsub( strlower(backstring), strfind(strlower(backstring), ":[^%s]*")) list_commandargs = gsub(strlower(backstring), ":[^%s]*", "")
end
parseMyLine(st1) parseMyLine(st2) --parseMyLine(st3) --parseMyLine(st4)
w:show() |
Posted by mikshaw on Oct. 17 2005,23:47
I got it working the way i was hoping with just a couple of lines: -- cut off the command: the_keystring = gsub(display:text(display.value),"%s:.*","") -- cut off everything but the last field of the string (emulates awk '{print $NF}'): key.value = gsub(the_keystring,".*%s","")
My problem in getting this working before was that i was leaving the space at the end of the keystring, so trying to cut out a string of characters with a space at the end would result in cutting the whole string.
Now all I need to do is add the "save" function and it'll be ready for the first release. I know i pretty much ignored your script entirely, but thanks for trying to help =o)
UPDATE: got a useable script going. It will probably need some debugging, but it does what i need it to do so far. < http://dsl-mirror.vectori.net/tools/mikshaw/ >
Posted by mikshaw on Oct. 18 2005,05:25
crap...couldn't upload it for some reason.....
Code Sample | #!/bin/flua
------------------------------------------------------------------------ -- fluxkeys.flua -- gui frontend to fluxbox keys file -- mikshaw 2005
-- Changelog YYYY-MM-DD -- 2005-10-16 Begin -- 2005-10-17 First release -- 2005-10-18 Fixed recognition of Tab-separated items -- Fixed crash when clicking Edit buttons with no file loaded -- Removed unused Initializers -- Fixed focus issue when using arrows to scroll -- Display line now doesn't change until you press the button -- Fixed "Cancel" bug ------------------------------------------------------------------------
-- DEFAULTS default_keysfile = getenv("HOME").."/.fluxbox/keys" ww = 420 -- window width wh = 300 -- window height Fl_Widget.initializers = {textfont = 15, labelfont = 15, labelcolor = 0} 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} Fl_Input_.initializers = {when = When.changed}
fluxbox_commands = { "BLANK", "ExecCommand", "Reconfigure", "Restart", "Quit", "NextWindow", "PrevWindow", "NextWorkspace", "PrevWorkspace", "Workspace1", "Workspace2", "Workspace3", "Workspace4", "Workspace 1", "Workspace 2", "Workspace 3", "Workspace 4", "SendToNextWorkspace", "SendToPrevWorkspace", "SendToWorkspace 1", "SendToWorkspace 2", "SendToWorkspace 3", "SendToWorkspace 4", "NextGroup", "PrevGroup", "Minimize", "Maximize", "Shade", "Stick", "Fullscreen", "ToggleDecor", "Raise", "Lower", "RaiseLayer", "LowerLayer", "Close", "KillWindow", "WindowMenu", "WorkspaceMenu", "RootMenu", "ReloadStyle", "CommandDialog", "WorkspaceNameDialog", "SetResourceValueDialog", "Deiconify last", "Deiconify lastworkspace", "Deiconify all", "Deiconify allworkspace", "ShowDesktop", "ArrangeWindows", "AttachClient", "DetachClient", "FirstTab", "LastTab", "NextTab", "PrevTab", "MoveTabNext", "MoveTabPrev", "ToggleTab" } -- get total number of fluxbox commands num_fb_commands = getn(fluxbox_commands)
function set_line() -- modify the keys file line -- a=mod# b=Control c=Shift d=key e=fluxcommand f=shellcommand if display.value > 0 and not strfind(display:text(display.value),"^#") 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 if fb_command.value == 0 then e = "" else e = " :"..fb_command.text end 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() -- find parts of selected keysfile line -- string of just the keys the_keystring = gsub(display:text(display.value),"%s*%s:.*","") -- find Mod<num> or "None" for modnum = 1,9 do if strfind(strlower(the_keystring),"mod"..modnum.." ") then mod_choice.value = modnum break else mod_choice.value = 0 end end -- find "Control" if strfind(strlower(the_keystring),"control ") then ctrl.value = 1 else ctrl.value = 0 end -- find "Shift" if strfind(strlower(the_keystring),"shift ") then shift.value = 1 else shift.value = 0 end -- find single key if not strfind(display:text(display.value),"^#") then key.value = gsub(the_keystring,".*%s","") else key.value = "" end -- find "ExecCommand" if strfind(strlower(display:text(display.value)),":execcommand ") then fb_command.value = 1 sh_command.value = gsub(display:text(display.value),".*:-ommand%s*%s","") sh_command:show() else -- else find other fluxbox commands sh_command:hide() sh_command.value="" for find_flux = 1,num_fb_commands do if strfind(strlower(display:text(display.value)),":"..strlower(fluxbox_commands[find_flux])) then fb_command.value = find_flux-1 break else fb_command.value = 0 end end end key:take_focus() 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*",default_keysfile) if not keysfile then keysfile = default_keysfile else display:load(keysfile) display.value=1 line_num.value=display.value get_line() end end file_save = Menu_Entry{"&File/&Save"} function file_save:callback() if display.value > 0 then writeto(keysfile) write(display:text(1)) start = 2 while start <= display.size do write("\n"..display:text(start)) start = start+1 end fl_message(keysfile.." written") writeto() end end help = Menu_Entry{"&File/&Help"} function help:callback() w_help:show() end file_quit = Menu_Entry{"&File/&Quit"} function file_quit:callback() exit(0) end edit_new = Menu_Entry{"&Edit/&New Key"} function edit_new:callback() if display.value > 0 then display:insert(display.value+1,display:text(display.value)) display.value=display.value+1 line_num.value=display.value get_line() end end edit_remove = Menu_Entry{"&Edit/&Remove Key"} function edit_remove:callback() if display.value > 0 then temp_line = display.value display:remove(display.value) display.value = temp_line get_line() end end mm:add(file_open) mm:add(file_save) mm:add(help) mm:add(file_quit) mm:add(edit_new) 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 if display.value > 0 then get_line() end end
-- CHOOSE MODIFIERS (Mod<num>, Ctrl, Shift) mod_choice = Choice{10,240,64,20} mod_choice:add(Menu_Entry{"NONE"}) for modline = 1,9 do mod_choice:add(Menu_Entry{"Mod"..modline}) end 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}
-- MAKE THE CHANGE commit = Button{80,265,80,20,"APPLY";labelfont=9} function commit:callback() set_line() end
-- CHOOSE FLUXBOX COMMAND -- shell command -- hidden unless "ExecCommand" is selected sh_command = Input{170,265,240,20} fb_command = Choice{170,240,240,20} for commline = 1,num_fb_commands do fb_command:add(Menu_Entry{fluxbox_commands[commline]}) end fb_command.value = 0 function fb_command:callback() if fb_command.text == "ExecCommand" then sh_command:show() else sh_command.value="" end end w_main:end_layout()
-- HELP WINDOW w_help = Window{ww,wh, "fluxkeys help"} w_help_text = Box{10,10,0,wh-20,"\n".. "fluxkeys.flua : version one.one : released 18 Oct, 2005 : mikshaw\n\n".. "This script might help you in creating or editing your Fluxbox\n".. "key bindings file. Hopefully the usage is pretty simple...use the\n".. "\"File -> Open\" menu to load your keys file, highlight a line, and\n".. "use the buttons and input fields to modify the line. The first\n".. "button and the toggles below it are used to choose your modifier\n".. "keys, the text field next to that is for entering the name of the\n".. "main key to press, and the inputs on the right are the command.\n".. "The APPLY button sends all your changes to the selected key line.\n".. "The \"Edit\" menu allows you to add and remove lines from the file,\n".. "and \"File -> Save\" will save your changes. You can select a line\n".. "in three ways: 1) click on the line, 2) type a line number into\n".. "the \"line:\" box, or 3) use arrows to scroll.\n" ;align=Align.right} w_help:end_layout() w_main:show() |
Posted by clacker on Oct. 18 2005,12:01
mikshaw, that is one awsume flua example. Absolutely fantastic. I had no idea flua could look and act so much like a real application.
The only thing I saw so far was when you use the file dialog to open a file, but then hit cancel you get an error from gsub.
Very nice work.
Posted by mikshaw on Oct. 18 2005,14:33
Thanks...I think i fixed the cancel bug, although it's not thoroughly tested.
I don't understand why Flua is so underappreciated....it's really an amazingly simple way to build some pretty decent interfaces, while remaining tiny and open. It's really annoying to search for tools online only to find so many based on KDE, Gtk2, and Java....even the simplest tools like this keys editor. Why make a 10k application a hundred times larger (and depend on even more) just for a prettier set of widgets? I'm hoping that eventually I can learn Lua well enough to not struggle so much with every project. Also hoping that the Flua project is not dead =o(
Posted by clacker on Oct. 18 2005,16:37
What's really missing from flua is decent documentation and a few kick-ass examples (like yours was). My beef with it is it's so hard to find how to do things that after a while you assume it's a crappy program, which your example proves it's not.
I don't think flua's dead, it just smells funny.
Posted by mikshaw on Oct. 18 2005,21:42
I was messing around for days using Lua5 syntax, and wondering why so many things didn't work. Even after reading through the lua4 manual and the flua docs a lot of stuff still doesn't make sense to me (I usually have both open for reference while scripting). The flua widget reference is extremely vague, and the example files are for the most part either incomplete or so simple that they don't provide much help. Personally I've learned much more from reading Robert's scripts than from reading those examples.
|