Programming and Scripting :: Flua string parsing



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()

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/

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()

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.

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(

Next Page...
original here.