MyDSL info parser
Forum: Programming and Scripting
Topic: MyDSL info parser
started by: mikshaw
Posted by mikshaw on Jan. 13 2008,15:39
Quote (roberts @ Jan. 13 2008,01:35) | Also note that I am also now updating a < Master List > of all extensions. Use your browser to search it, or download it and use Beaver to search it. Or have fun with grep. |
Here's a simple gui that can be used to parse this file, currently by filename, package builder, or extension category.
NOTE: This is a quick test, and should not be considered complete or stable. The list.txt file must be saved locally The application must be run from a terminal in order to view any output Text parsing needs work. The "filename" in particular could be handled better...it will accept Lua string patters, but needs further testing to determine whether certain input could be harmful.
Code Sample | listfile="list.txt"
inputfile=io.open(listfile) if not inputfile then print("can't open "..listfile) os.exit(1) end
data=inputfile:read("*a") inputfile:close()
function parse_info() if radio_buttons[1]:value()==1 then searchstring="Location:%s*"..inputs[1]:value() elseif radio_buttons[2]:value()==1 then searchstring="\nExtension.by:%s*"..inputs[2]:value() elseif radio_buttons[3]:value()==1 then searchstring="\nTitle:%s*"..inputs[3]:value() else searchstring=nil end if searchstring then for info in string.gmatch(data,"(Location:.-\n)Location:") do if string.find(info,searchstring) then print(info.."\n..........\n") end end end end
w=fltk:Fl_Window(350,200,"MyDSL Info Search")
radio_labels={"category","extension by","filename"} radio_buttons={};inputs={} for i=1,table.getn(radio_labels) do radio_buttons[i]=fltk:Fl_Radio_Round_Button(10,20*i,100,20,radio_labels[i]) inputs[i]=fltk:Fl_Input(120,20*i,200,20) end
gobutton=fltk:Fl_Button(10,100,100,20,"go") gobutton:callback(parse_info)
w:show() Fl:run()
|
Posted by roberts on Jan. 13 2008,16:18
Hi mikshaw,
I was going to do something here, but I am glad to see that you have started! This could be a replacement to the current box of buttons that I original did.
I was thinking of something along the lines of QBE (Query By Example). Where each field of the info file is displayed as input fields. Then search the list.txt testing each field for corresponding input fields. Display the results in a gui selection list. Then user can scroll results in the GUI and if select Title: field then use its postion -1 to get location. Then easy to feed mydsl-load. Of course, if the use selects something other than title field, display error with help, or iterate backwards to the title field and construct title location to feed mydsl-load.
Finally add a file browser to provide the Load Local feature and we could have a replacment to the existing box-of-buttons currently known as mydsl browser.
If a QBE form is created then it could also be used to create new .info files for those wishing to submit new extensions.
Posted by lucky13 on Jan. 13 2008,16:31
Quote | I was thinking of something along the lines of QBE (Query By Example). |
Does murgalua have functional sqlite bindings? I looked at the site but the links to examples and sqlite are broken.
Posted by roberts on Jan. 13 2008,16:58
Yes. murgaLua does. I tried importing this into an sqlite db but was only about 90% successful. The comments are full of odd characters that break things. Using blobs might help, but then not sure of search capabilities. Does 750 items warrant using an sql database? It would be easy moving forward. It is the past 10% of the data that is difficult.
Posted by mikshaw on Jan. 13 2008,17:04
I have no experience with or current knowledge of using databases of any kind, but as far as I understand, sqlite is useable in murgaLua.
I've read the QBE explanation 3 times now, and still don't follow it =o) But I assume it is directed mainly toward the ultimate goal of obtaining the url for a specific extension, which I suppose would be the main purpose of a tool like this. I was just doing it for the sake of figuring out how to grab the text of a specific info file or files, without a solid plan of actually putting that information to any useful purpose.
I'll have to save this thread for further digestion.
Posted by lucky13 on Jan. 13 2008,17:39
Quote | The comments are full of odd characters that break things. Using blobs might help, but then not sure of search capabilities.... It is the past 10% of the data that is difficult. |
If it's 10%, can those characters be changed? Or would you effectively be reformatting the info files altogether?
Quote | Does 750 items warrant using an sql database? It would be easy moving forward. |
It would be a lot easier moving forward.
Posted by roberts on Jan. 13 2008,17:49
I think I will take a second look. I have wanted to make an sqlite GUI for DSL. If I could exclude the comments it would be a snap.
The program that I wrote on the server side that generates the html tables is an awk program. Part by position, part by parsing field names. I have been wanting to replace it too. By using sqlite I can drop the awk program for the website tables and have a nice gui for the client side.
Posted by mikshaw on Jan. 13 2008,21:05
I made a variant that might be closer to what you were talking about. It creates two pulldown menus, but I can't say if they might have performance issues on slow machines.
The "Download and Install" button currently just prints the command that would ordinarily be executed. The "Download" button does nothing. I was debating whether or not to have a separate action to simply download the extension to a chosen directory for future use.
Code Sample | #!/bin/murgaLua -- mydsl info browser, 2008 mikshaw -- -- Changelog (yyyy/mm/dd) -- 2008/01/14: Fixed display of incorrect duplicate info file -- Check for trailing spaces in title string -- 2008/01/13: start of project
listfile="/home/dsl/WORK/mydsl_master_list/list.txt"
inputfile=io.open(listfile) if not inputfile then print("can't open "..listfile) os.exit(1) end
data=inputfile:read("*a") inputfile:close()
w=fltk:Fl_Window(350,400,"MyDSL Info Search")
b_loc=fltk:Fl_Choice(100,10,240,30,"category: ") b_loc:callback( function() while b_files:size()>1 do b_files:remove(0) end b_files:redraw() for i=1,info_count do if info[i].location==b_loc:text() then b_files:add(info[i].title) end end b_files:value(0) b_files:do_callback() end )
b_files=fltk:Fl_Choice(100,40,240,30,"file: ") b_files:callback( function() for i=1,info_count do if info[i].title == b_files:text() and info[i].location == b_loc:text() then info_display_buffer:text(info[i].text) break end end end )
info_display=fltk:Fl_Text_Display(10,70,330,280) --info_display:textfont(fltk.FL_COURIER) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer)
download=fltk:Fl_Button(10,350,120,30,"Download") install=fltk:Fl_Button(130,350,120,30,"Download and Install") install:callback( function() print("mydsl-load "..b_files:text().." "..b_loc:text()) end )
info={} info_count=0 -- breaks up each info file into a separate string for s in string.gmatch(data,"(Location:.-\n)Location:") do info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), text=s } b_loc:add(info[info_count].location) end
b_loc:value(0) b_loc:do_callback() w:resizable(info_display) w:show() Fl:run()
|
Posted by mikshaw on Jan. 14 2008,16:38
There seems to be two issues so far that I don't know how to deal with, one is with the list file itself and one I think is in my script.
There are a few infos in the text file that are run together, such as wvdial.dsl and zsh.uci in testing. This may be the result of a missing newline at the end of the file?
Some infos will not display in this tool, such as japanese_fonts.tar.gz in testing. I'm not sure why but it may be related to a mix of spaces and tabs. I thought %s* covered both of these, though.
EDIT: fixed the second issue. It was caused by trailing spaces that were getting included in the title string.
Posted by roberts on Jan. 14 2008,19:49
I think you are likely seeing issues that I have seen in trying to import into sql database.
The info files come from users all over the globle. Interestingly enough doing a 'file' command on the individual .info files reveals the following:
ASCII text ASCII English text ISO-8859 text ISO-8859 English text UTF-8 Unicode English text
This mix together with the array of special characters in the comments field, which, by the way, does not even exist for all .info files, has been challenging to say the least.
Not sure how or which murgaLua supports, or even the bash version within DSL.
Posted by mikshaw on Jan. 14 2008,21:22
Another thing that concerns me is the size of the list file. It's now 700kb and will only get larger over time. This is a pretty large download for a dialup user to have every time the app is loaded. You might want to consider the possibility of storing the file locally, maybe downloading it automatically if it doesn't already exist. After that, the user could have the option of either automatically downloading it or updating the file at the user's leisure.
I've implemented a kind of update function, although I'm not sure how reliable it is
Code Sample | #!/bin/murgaLua -- mydsl info browser, 2008 mikshaw -- -- Changelog (yyyy/mm/dd) -- 2008/01/14: Fixed display of incorrect duplicate info file -- Check for trailing spaces in title string -- Added "Update" function -- Code and interface tweaks -- 2008/01/13: start of project
listfile="/home/dsl/WORK/mydsl_master_list/list.txt" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/list.txt"
function load_list() inputfile=io.open(listfile) if not inputfile then print("can't open "..listfile) os.exit(1) end
data=inputfile:read("*a") inputfile:close()
info={} info_count=0 -- breaks up each info file into a separate string for s in string.gmatch(data,"(Location:.-\n)Location:") do info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), text=s } b_loc:add(info[info_count].location) end
b_loc:value(0) b_loc:do_callback() end
ww=420; wh=360; bh=25; bw=ww/2-5 w=fltk:Fl_Window(ww,wh,"MyDSL Info Browser")
b_loc=fltk:Fl_Choice(5,5,bw,bh) b_loc:callback( function() while b_files:size()>1 do b_files:remove(0) end b_files:redraw() for i=1,info_count do if info[i].location==b_loc:text() then b_files:add(info[i].title) end end b_files:value(0) b_files:do_callback() end )
b_files=fltk:Fl_Choice(ww/2,5,bw,bh) b_files:callback( function() for i=1,info_count do if info[i].title == b_files:text() and info[i].location == b_loc:text() then info_display_buffer:text(info[i].text) break end end end )
info_display=fltk:Fl_Text_Display(5,10+bh,ww-10,wh-(20+bh*2)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer)
install=fltk:Fl_Button(5,wh-bh-5,bw,bh,"Install Selected Package") install:callback( function() os.execute("mydsl-load "..b_files:text().." "..b_loc:text()) end )
updatedb=fltk:Fl_Button(bw+5,wh-bh-5,bw,bh,"Update Database") updatedb:callback( function() backup=os.rename(listfile,listfile..".bak") if backup then wget=os.execute("wget "..listurl.." -O "..listfile) if wget==0 then while b_loc:size()>1 do b_loc:remove(0) end load_list() else os.rename(listfile..".bak",listfile) end end end )
load_list() w:resizable(info_display) w:show() Fl:run()
|
Posted by ^thehatsrule^ on Jan. 14 2008,23:08
Quote | Another thing that concerns me is the size of the list file. It's now 700kb and will only get larger over time. This is a pretty large download for a dialup user to have every time the app is loaded. You might want to consider the possibility of storing the file locally, maybe downloading it automatically if it doesn't already exist. After that, the user could have the option of either automatically downloading it or updating the file at the user's leisure. | I'm pretty sure a gzip'd version could also be uploaded... and since it's all text, the compression ratio should be good enough to just replace the file if there is a requested update.
I was originally using a shell script for utilizing the list.txt, but I'm glad that a lua version is being developed since it will be more streamlined.
Posted by mikshaw on Jan. 14 2008,23:23
Quote | I'm pretty sure a gzip'd version could also be uploaded... and since it's all text, the compression ratio should be good enough to just replace the file if there is a requested update. | I like that idea. A test on the current file compresses it from 704k to 187k
Also edited the previous post. I made some cosmetic changes to the interface for better use of visual space.
Posted by mikshaw on Jan. 15 2008,20:46
Added text search: EDIT: made text search case insensitive (string.lower on both the match string and the info text contents)
Code Sample | #!/bin/murgaLua -- mydsl info browser, 2008 mikshaw -- -- Changelog (yyyy/mm/dd) -- 2008/01/15: Added text search -- 2008/01/14: Fixed display of incorrect duplicate info file -- Check for trailing spaces in title string -- Added "Update" function -- Code and interface tweaks -- 2008/01/13: start of project
listfile="/home/dsl/WORK/mydsl_master_list/list.txt" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/list.txt"
function load_list() inputfile=io.open(listfile) if not inputfile then print("can't open "..listfile) os.exit(1) end
data=inputfile:read("*a") inputfile:close()
info={} info_count=0 -- breaks up each info file into a separate string for s in string.gmatch(data,"(Location:.-\n)Location:") do info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), text=s } b_loc:add(info[info_count].location) end
b_loc:value(0) b_loc:do_callback() end
ww=420; wh=360; bh=25; bw=ww/2-5 w=fltk:Fl_Window(ww,wh,"MyDSL Info Browser")
tabs=fltk:Fl_Tabs(0,0,ww,wh)
tab1=fltk:Fl_Group(0,0,ww,wh-bh,"browse") b_loc=fltk:Fl_Choice(5,5,bw,bh) b_loc:callback( function() while b_files:size()>1 do b_files:remove(0) end b_files:redraw() for i=1,info_count do if info[i].location==b_loc:text() then b_files:add(info[i].title) end end b_files:value(0) b_files:do_callback() end )
b_files=fltk:Fl_Choice(ww/2,5,bw,bh) b_files:callback( function() for i=1,info_count do if info[i].title == b_files:text() and info[i].location == b_loc:text() then info_display_buffer:text(info[i].text) break end end end )
info_display=fltk:Fl_Text_Display(5,10+bh,ww-10,wh-(20+bh*3)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer)
install=fltk:Fl_Button(5,wh-bh*2-5,bw,bh,"Install Selected Package") install:callback( function() os.execute("mydsl-load "..b_files:text().." "..b_loc:text()) end )
updatedb=fltk:Fl_Button(bw+5,wh-bh*2-5,bw,bh,"Update Database") updatedb:callback( function() backup=os.rename(listfile,listfile..".bak") if backup then wget=os.execute("wget "..listurl.." -O "..listfile) if wget==0 then while b_loc:size()>1 do b_loc:remove(0) end load_list() else os.rename(listfile..".bak",listfile) end end end ) fltk:Fl_End()
tab2=fltk:Fl_Group(0,0,ww,wh-bh,"search text") search_b=fltk:Fl_Return_Button(5,5,80,bh,"search") search_b:callback( function() if search_text:value() ~= "" then results:clear() for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,true) then results:add(info[i].title.."\t\t"..info[i].location) end end end end ) search_text=fltk:Fl_Input(85,5,ww-90,bh) results=fltk:Fl_Hold_Browser(5,10+bh,ww-10,wh-(20+bh*2)) results:textfont(fltk.FL_SCREEN) results:textsize(12) results:callback( function() -- show selected info file in the browse tab if results:value() > 0 then get_loc=string.match(results:text(results:value()),"\t\t(.*)") get_fname=string.match(results:text(results:value()),"(.*)\t\t") for i=0,b_loc:size() do if get_loc == b_loc:text(i) then b_loc:value(i) break end end b_loc:do_callback() for i=0,b_files:size() do if get_fname == b_files:text(i) then b_files:value(i) break end end b_files:do_callback() tabs:value(tab1) end end ) fltk:Fl_End()
load_list() --w:resizable(info_display) --w:resizable(results) w:show() Fl:run()
|
Posted by roberts on Jan. 15 2008,21:59
Looking good, mikshaw.
I have bzip2 compresed the text database list.txt and renamed it to mydslinfo.bz2
Here are my requests:
1. Use the contents of /opt/.mydsl_dir to store the mydslinfo.bz2 database file. I am trying to keep all mydsl related items together.
2. Display a count of items in database and date last updated (downloaded).
3. When initially starting, call get (update) database to download as per item 1, as I don't want to place an initial mydslinfo.bz2 in the iso.
Posted by mikshaw on Jan. 15 2008,23:23
Those requests are very reasonable.
There are two things I'll need help with: 1) As the file is bzipped, I assume that means reading the file will require bunzipping before being able to read it into lua. This could be done by unzipping the file directly and then reading the unzipped file. Is it possible to pipe the output of bunzip to lua in order to prevent having to create a new file? 2) While testing mydsl-install from the "install" button I noticed that it downloaded the extension to /home/dsl rather than to the directory in /opt/mydsl.dir. Do I need to specify the directory? I assumed mydsl.dir was used by mydsl-load when it downoaded.
I'm also having a really difficult time creating a single resizeable widget. According to the FLTK docs resizable can be very specific, but I can't figure out how to resize just one single widget. I'd like to be able to make the main output fields be resizable, but nothing else =op
Posted by roberts on Jan. 15 2008,23:47
1. change inputfile to:
inputfile = io.popen("bunzip2 -c "..listfile)
2. I will adjust that in mydsl-load. Was presently not enforced, but expected users to be in the mydsl folder. But much better to be enforced.
Posted by mikshaw on Jan. 16 2008,00:59
It's very possible that /opt/mydsl.dir points to a read-only directory. In that case should it fall back to $HOME?
Posted by roberts on Jan. 16 2008,16:04
I am talking about v4.x, it is not likely to be read-only.
However booting 4.x, without specifying the mydsl boot option, results in a default of /tmp/mydsl/ being used and becomes the content of /opt/.mydsl_dir. As 4.x boots is sets the perms for user/group on the mydsl dir so should be accessible.
Even with a custom mydsl.iso containing a mydsl dir, that is read-only, the mydsl dir becomes secondary to a specified mydsl boot option or /tmp/mydsl.
Posted by mikshaw on Jan. 17 2008,00:19
WARNING: This version is half-baked. I need to rework the update function and do a better job of determining whether or not the mydslinfo.bz2 file is usable. I'm still working out how to visually show the user the status of the wget download. Since the current version uses the exit status of wget, that wouldn't work if wget was running in aterm, so I'll probably need to check the file after the download completes as mydsl-load does. But I don't feel like working on it any more today, so I'll post what I have for feedback.
I'm mostly happy, though, because I finally understand how to use the resizable method to specify a nested object to resize (a widget inside a group inside a group).
Code Sample | #!/bin/murgaLua -- mydsl info browser, 2008 mikshaw -- -- Changelog (yyyy/mm/dd) -- 2008/01/16: Fixed resizable behavior -- Uses file in .mydsl_dir -- Added auto update for first run -- 2008/01/15: Added text search -- 2008/01/14: Fixed display of incorrect duplicate info file -- Check for trailing spaces in title string -- Added "Update" function -- Code and interface tweaks -- 2008/01/13: start of project -- -- TODO: Fix the update function to not create empty file -- Let the user know what's happening during update
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then print("can't open "..mydsldirfile) os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
listfile=mydsl_dir.."/mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2"
function load_list() inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close()
info={} info_count=0 -- breaks up each info file into a separate string for s in string.gmatch(data,"(Location:.-\n)Location:") do info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), text=s } b_loc:add(info[info_count].location) end
b_loc:value(0) b_loc:do_callback() end
function updatedb(nofile) if not nofile then backup=os.rename(listfile,listfile..".bak") end -- if backup then wget=os.execute("wget "..listurl.." -O "..listfile) if wget==0 then while b_loc:size()>1 do b_loc:remove(0) end load_list() -- This is terrible else if not nofile then os.rename(listfile..".bak",listfile) end end -- end end
ww=420; wh=360; bh=25; bw=ww/2-5 w=fltk:Fl_Window(ww,wh,"MyDSL Info Browser")
tabs=fltk:Fl_Tabs(0,0,ww,wh)
tab1=fltk:Fl_Group(0,0,ww,wh-bh,"browse") b_loc=fltk:Fl_Choice(5,5,bw,bh) b_loc:callback( function() while b_files:size()>1 do b_files:remove(0) end b_files:redraw() for i=1,info_count do if info[i].location==b_loc:text() then b_files:add(info[i].title) end end b_files:value(0) b_files:do_callback() end )
b_files=fltk:Fl_Choice(ww/2,5,bw,bh) b_files:callback( function() for i=1,info_count do if info[i].title == b_files:text() and info[i].location == b_loc:text() then info_display_buffer:text(info[i].text) break end end end )
info_display=fltk:Fl_Text_Display(5,10+bh,ww-10,wh-(20+bh*3)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer)
install=fltk:Fl_Button(5,wh-bh*2-5,bw,bh,"Install Selected Package") install:callback( function() os.execute("mydsl-load "..b_files:text().." "..b_loc:text()) end )
b_updatedb=fltk:Fl_Button(bw+5,wh-bh*2-5,bw,bh,"Update Database") b_updatedb:callback(updatedb) fltk:Fl_End()
tab2=fltk:Fl_Group(0,0,ww,wh-bh,"search text") search_b=fltk:Fl_Return_Button(5,5,80,bh,"search") search_b:callback( function() if search_text:value() ~= "" then results:clear() for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,true) then results:add(info[i].title.."\t\t"..info[i].location) end end end end ) search_text=fltk:Fl_Input(85,5,ww-90,bh) results=fltk:Fl_Hold_Browser(5,10+bh,ww-10,wh-(20+bh*2)) results:textfont(fltk.FL_SCREEN) results:textsize(12) results:callback( function() -- show selected info file in the browse tab if results:value() > 0 then get_loc=string.match(results:text(results:value()),"\t\t(.*)") get_fname=string.match(results:text(results:value()),"(.*)\t\t") for i=0,b_loc:size() do if get_loc == b_loc:text(i) then b_loc:value(i) break end end b_loc:do_callback() for i=0,b_files:size() do if get_fname == b_files:text(i) then b_files:value(i) break end end b_files:do_callback() tabs:value(tab1) end end ) fltk:Fl_End()
w:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tab1:resizable(info_display) tab2:resizable(results) w:show() find_file=io.open(listfile) if find_file then find_file:close() load_list() else updatedb(1) end Fl:run()
|
Posted by mikshaw on Jan. 17 2008,00:22
Quote | As 4.x boots is sets the perms for user/group on the mydsl dir so should be accessible. | What if it's a read-only filesystem? You can't set permissions in that case. I think it's possible that a user could use the mydsl boot option to specify an NTFS or CDROM filesystem.
Posted by mikshaw on Jan. 17 2008,19:43
The update function still needs work, particularly in checking the validity of the downloaded file, and because the code is pretty sloppy. EDIT: minor change, fixed the error message if .mydsl_dir file can't be read.
Code Sample | #!/bin/murgaLua -- mydsl info browser, 2008 mikshaw -- -- Changelog (yyyy/mm/dd) -- 2008/01/17: Added date of last update -- Tweaked the update function (it's still sloppy) -- Fixed ".mydsl_dir not found" error message -- 2008/01/16: Fixed resizable behavior -- Uses file in .mydsl_dir -- Added auto update for first run -- 2008/01/15: Added text search -- 2008/01/14: Fixed display of incorrect duplicate info file -- Check for trailing spaces in title string -- Added "Update" function -- Code and interface tweaks -- 2008/01/13: start of project -- -- TODO: Clean up the update function
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then print(arg[0]..": Can't open /opt/.mydsl_dir") os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
listfile=mydsl_dir.."/mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2"
function load_list() while b_loc:size()>1 do b_loc:remove(0) end local getdate=io.popen("ls -lh "..listfile.."|awk '{print \"\\n\\n**\\nDatabase updated \"$6\" \"$7\"\\n"..fltk.fl_filename_name(listfile).." \"$5}'") mdate=getdate:read("*a") getdate:close() inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close()
if not string.find(data,"%w") then info_display_buffer:text("Cannot read database "..listfile.."\nPlease try updating again.") else info={} info_count=0 -- breaks up each info file into a separate string for s in string.gmatch(data,"(Location:.-\n)Location:") do info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), text=s } b_loc:add(info[info_count].location) end
b_loc:value(0) b_loc:do_callback() end end
function updatedb(nofile) if not nofile then backup=os.rename(listfile,listfile..".bak") end os.execute("aterm +tr -bg white -fg black -geometry 80x4 -title \"Database Update\" -e wget "..listurl.." -O "..listfile) load_list() end
ww=420; wh=360; bh=25; bw=ww/2-5 w=fltk:Fl_Window(ww,wh,"MyDSL Info Browser")
tabs=fltk:Fl_Tabs(0,0,ww,wh)
tab1=fltk:Fl_Group(0,0,ww,wh-bh,"browse") b_loc=fltk:Fl_Choice(5,5,bw,bh) b_loc:callback( function() while b_files:size()>1 do b_files:remove(0) end b_files:redraw() for i=1,info_count do if info[i].location==b_loc:text() then b_files:add(info[i].title) end end b_files:value(0) b_files:do_callback() end )
b_files=fltk:Fl_Choice(ww/2,5,bw,bh) b_files:callback( function() for i=1,info_count do if info[i].title == b_files:text() and info[i].location == b_loc:text() then info_display_buffer:text(info[i].text) info_display_buffer:append(mdate) break end end end )
info_display=fltk:Fl_Text_Display(5,10+bh,ww-10,wh-(20+bh*3)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer)
install=fltk:Fl_Button(5,wh-bh*2-5,bw,bh,"Install Selected Package") install:callback( function() os.execute("mydsl-load "..b_files:text().." "..b_loc:text()) end )
b_updatedb=fltk:Fl_Button(bw+5,wh-bh*2-5,bw,bh,"Update Database") b_updatedb:callback(updatedb) fltk:Fl_End()
tab2=fltk:Fl_Group(0,0,ww,wh-bh,"search text") search_b=fltk:Fl_Return_Button(5,5,80,bh,"search") search_b:callback( function() if search_text:value() ~= "" then results:clear() for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,true) then results:add(info[i].title.."\t\t"..info[i].location) end end end end ) search_text=fltk:Fl_Input(85,5,ww-90,bh) results=fltk:Fl_Hold_Browser(5,10+bh,ww-10,wh-(20+bh*2)) results:textfont(fltk.FL_SCREEN) results:textsize(12) results:callback( function() -- show selected info file in the browse tab if results:value() > 0 then get_loc=string.match(results:text(results:value()),"\t\t(.*)") get_fname=string.match(results:text(results:value()),"(.*)\t\t") for i=0,b_loc:size() do if get_loc == b_loc:text(i) then b_loc:value(i) break end end b_loc:do_callback() for i=0,b_files:size() do if get_fname == b_files:text(i) then b_files:value(i) break end end b_files:do_callback() tabs:value(tab1) end end ) fltk:Fl_End()
w:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tab1:resizable(info_display) tab2:resizable(results) w:show() find_file=io.open(listfile) if find_file then data=find_file:read("*a") else data="" end if string.find(data,"%w") then find_file:close() load_list() else updatedb(1) end Fl:run()
|
Posted by mikshaw on Jan. 24 2008,22:25
Made one small edit. The previous version would concatenate two files if there was no newline between them in the database. This change assumes that "Location:" is not found anywhere but the beginning of the first line of a given info.
EDIT: I'm noticing that some infos are not being found, even when doing a text search. Before this last change a search for gimp displayed the uci package in testing, but after it didn't. I do realize that the string used in string.gmatch is faulty, but I don't know if that's the only problem.
Code Sample | #!/bin/murgaLua -- mydsl info browser, 2008 mikshaw -- -- Changelog (yyyy/mm/dd) -- 2008/01/24: Fixed string.gmatch to break up files even if there is no newline between them -- 2008/01/17: Added date of last update -- Tweaked the update function (it's still sloppy) -- Fixed ".mydsl_dir not found" error message -- 2008/01/16: Fixed resizable behavior -- Uses file in .mydsl_dir -- Added auto update for first run -- 2008/01/15: Added text search -- 2008/01/14: Fixed display of incorrect duplicate info file -- Check for trailing spaces in title string -- Added "Update" function -- Code and interface tweaks -- 2008/01/13: start of project -- -- TODO: Clean up the update function
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then print(arg[0]..": Can't open /opt/.mydsl_dir") os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
listfile=mydsl_dir.."/mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2"
function load_list() while b_loc:size()>1 do b_loc:remove(0) end local getdate=io.popen("ls -lh "..listfile.."|awk '{print \"\\n\\n**\\nDatabase updated \"$6\" \"$7\"\\n"..fltk.fl_filename_name(listfile).." \"$5}'") mdate=getdate:read("*a") getdate:close() inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close()
if not string.find(data,"%w") then info_display_buffer:text("Cannot read database "..listfile.."\nPlease try updating again.") else info={} info_count=0 -- breaks up each info file into a separate string -- assumes "Location:" is found only once per info file for s in string.gmatch(data,"(Location:.-)Location:") do info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), text=s } b_loc:add(info[info_count].location) end
b_loc:value(0) b_loc:do_callback() end end
function updatedb(nofile) if not nofile then backup=os.rename(listfile,listfile..".bak") end os.execute("aterm +tr -bg white -fg black -geometry 80x4 -title \"Database Update\" -e wget "..listurl.." -O "..listfile) load_list() end
ww=420; wh=360; bh=25; bw=ww/2-5 w=fltk:Fl_Window(ww,wh,"MyDSL Info Browser")
tabs=fltk:Fl_Tabs(0,0,ww,wh)
tab1=fltk:Fl_Group(0,0,ww,wh-bh,"browse") b_loc=fltk:Fl_Choice(5,5,bw,bh) b_loc:callback( function() while b_files:size()>1 do b_files:remove(0) end b_files:redraw() for i=1,info_count do if info[i].location==b_loc:text() then b_files:add(info[i].title) end end b_files:value(0) b_files:do_callback() end )
b_files=fltk:Fl_Choice(ww/2,5,bw,bh) b_files:callback( function() for i=1,info_count do if info[i].title == b_files:text() and info[i].location == b_loc:text() then info_display_buffer:text(info[i].text) info_display_buffer:append(mdate) break end end end )
info_display=fltk:Fl_Text_Display(5,10+bh,ww-10,wh-(20+bh*3)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer)
install=fltk:Fl_Button(5,wh-bh*2-5,bw,bh,"Install Selected Package") install:callback( function() os.execute("mydsl-load "..b_files:text().." "..b_loc:text()) end )
b_updatedb=fltk:Fl_Button(bw+5,wh-bh*2-5,bw,bh,"Update Database") b_updatedb:callback(updatedb) fltk:Fl_End()
tab2=fltk:Fl_Group(0,0,ww,wh-bh,"search text") search_b=fltk:Fl_Return_Button(5,5,80,bh,"search") search_b:callback( function() if search_text:value() ~= "" then results:clear() for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,true) then results:add(info[i].title.."\t\t"..info[i].location) end end end end ) search_text=fltk:Fl_Input(85,5,ww-90,bh) results=fltk:Fl_Hold_Browser(5,10+bh,ww-10,wh-(20+bh*2)) results:textfont(fltk.FL_SCREEN) results:textsize(12) results:callback( function() -- show selected info file in the browse tab if results:value() > 0 then get_loc=string.match(results:text(results:value()),"\t\t(.*)") get_fname=string.match(results:text(results:value()),"(.*)\t\t") for i=0,b_loc:size() do if get_loc == b_loc:text(i) then b_loc:value(i) break end end b_loc:do_callback() for i=0,b_files:size() do if get_fname == b_files:text(i) then b_files:value(i) break end end b_files:do_callback() tabs:value(tab1) end end ) fltk:Fl_End()
w:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tab1:resizable(info_display) tab2:resizable(results) w:show() find_file=io.open(listfile) if find_file then data=find_file:read("*a") else data="" end if string.find(data,"%w") then find_file:close() load_list() else updatedb(1) end Fl:run() |
Posted by mikshaw on Mar. 15 2008,11:46
Since Robert improved the database file to include a space between each info, I reverted the last change to be more reliable. Also did a couple of bug fixes and made the whole thing keyboard friendly.
It's still not ideal. I need to work out a better way to handle the db update. As it is, a current database file can be clobbered by a failed update, even with the half-assed backup system in place, such as if the update fails twice. I probably should have it download to a temp file first, check the integrity of the file, and then overwrite the prior file, instead of making a backup copy.
Code Sample | #!/home/dsl/bin/murgaLua-0.6.4 --[[ MyDSL info browser, 2008 mikshaw
Changelog (yyyy/mm/dd) 2008/03/14: Undid gmatch change due to improvements to the database file Improved keyboard control Use Fl_Menu_Button for menus to add to keyboard control Fixed crash on search or install with an empty database 2008/01/24: Fixed string.gmatch to break up files even if there is no newline between them 2008/01/17: Added date of last update Tweaked the update function (it's still sloppy) Fixed ".mydsl_dir not found" error message 2008/01/16: Fixed resizable behavior Uses file in .mydsl_dir Added auto update for first run 2008/01/15: Added text search 2008/01/14: Fixed display of incorrect duplicate info file Check for trailing spaces in title string Added "Update" function Code and interface tweaks 2008/01/13: start of project TODO: Clean up the update function
--]]
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then print(arg[0]..": Can't open /opt/.mydsl_dir") os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
listfile=mydsl_dir.."/mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2"
function load_list() -- load the database while b_loc:size()>1 do b_loc:remove(0) end local getdate=io.popen("ls -lh "..listfile.."|awk '{print \"\\n\\n**\\nDatabase updated \"$6\" \"$7\"\\n"..fltk.fl_filename_name(listfile).." \"$5}'") mdate=getdate:read("*a") getdate:close() inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close() if not string.find(data,"%w") then info_display_buffer:text("Cannot read database "..listfile.."\nPlease try updating again.") else info={} info_count=0 -- breaks up each info file into a separate string for s in string.gmatch(data,"(Location:.-)\nLocation:") do info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), text=s } b_loc:add(info[info_count].location) end
b_loc:value(0) b_loc:do_callback() end end
function updatedb(nofile) if not nofile then backup=os.rename(listfile,listfile..".bak") end os.execute("aterm +tr -bg white -fg black -geometry 80x4 -title \"Database Update\" -e wget "..listurl.." -O "..listfile) load_list() end
function pick_search_result() if results:value() > 1 then -- show selected info file in the browse tab get_loc=string.match(results:text(results:value()),spacer.."(.*)") get_fname=string.match(results:text(results:value()),"(.*)"..spacer) results:deselect() for i=0,b_loc:size() do if get_loc == b_loc:text(i) then b_loc:value(i) break end end b_loc:do_callback() for i=0,b_files:size() do if get_fname == b_files:text(i) then b_files:value(i) break end end b_files:do_callback() tabs:value(tab1) end end
ww=420; wh=360; bh=30; bw=ww/2-5 win=fltk:Fl_Window(ww,wh,"MyDSL Info Browser")
tabs=fltk:Fl_Tabs(0,0,ww,wh)
tab1=fltk:Fl_Group(0,0,ww,wh-bh,"browse") b_loc=fltk:Fl_Menu_Button(5,5,bw,bh) b_loc:align(20) b_loc:callback( function() b_loc:label("&Location: "..b_loc:text()) while b_files:size()>1 do b_files:remove(0) end b_files:redraw() for i=1,info_count do if info[i].location==b_loc:text() then b_files:add(info[i].title) end end b_files:value(0) b_files:do_callback() end )
b_files=fltk:Fl_Menu_Button(ww/2,5,bw,bh) b_files:align(20) b_files:callback( function() b_files:label("&Filename: "..b_files:text()) for i=1,info_count do if info[i].title == b_files:text() and info[i].location == b_loc:text() then info_display_buffer:text(info[i].text) info_display_buffer:append(mdate) break end end end )
info_display=fltk:Fl_Text_Display(5,10+bh,ww-10,wh-(20+bh*3)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer)
install=fltk:Fl_Button(5,wh-bh*2-5,bw,bh,"&Install Selected Package") install:callback( function() if b_files:text() and b_loc:text() then os.execute("mydsl-load "..b_files:text().." "..b_loc:text()) end end )
b_updatedb=fltk:Fl_Button(bw+5,wh-bh*2-5,bw,bh,"&Update Database") b_updatedb:callback(updatedb) fltk:Fl_End() --end tab1
tab2=fltk:Fl_Group(0,0,ww,wh-bh,"search text") search_text=fltk:Fl_Input(70,5,ww-75,bh,"search text: ") search_text:when(fltk.FL_WHEN_ENTER_KEY) search_text:callback( function() if search_text:value() ~= "" and info_count and info_count>0 then results:clear() results:add("@b@B49PACKAGE NAME"..spacer.."@b@B49LOCATION") for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,true) then results:add(info[i].title..spacer..info[i].location) end end end end )
results=fltk:Fl_Hold_Browser(5,10+bh,ww-10,wh-(20+bh*2)) results:textfont(fltk.FL_SCREEN) results:textsize(12) -- column widths available in 0.6.4+ if Fl_Browser.column_widths then results:column_widths({results:w()/2,0}) spacer="\t" else spacer="\t\t" -- force some extra space for older versions end results:callback( -- react to click only function() if results:value() > 1 and Fl:event()==fltk.FL_RELEASE then pick_search_result() end end ) -- offscreen results_callback button for Enter key results_cb=fltk:Fl_Return_Button(ww,wh,bh,bh) results_cb:callback(pick_search_result) fltk:Fl_End() --end tab2 fltk:Fl_End() --end tabs group
-- offscreen button gives focus to text input rather than just the tab toggle_search=fltk:Fl_Button(ww,wh,bh,bh,"&s") toggle_search:callback( function() tabs:value(tab2) Fl:focus(search_text) end ) toggle_browse=fltk:Fl_Button(ww,wh,bh,bh,"&b") toggle_browse:callback(function() tabs:value(tab1) end)
win:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tab1:resizable(info_display) tab2:resizable(results) win:show() find_file=io.open(listfile) if find_file then data=find_file:read("*a") else data="" end if string.find(data,"%w") then find_file:close() load_list() else updatedb(1) end Fl:run()
|
Posted by mikshaw on Mar. 15 2008,12:28
OK, I think the update function works properly now. No backup file being shuffled around, it's just overwrting the old database file only if the new one is good.
Code Sample | #!/home/dsl/bin/murgaLua-0.6.4 --[[ MyDSL info browser, 2008 mikshaw
Changelog (yyyy/mm/dd) 2008/03/15: Improved the update function 2008/03/14: Undid gmatch change due to improvements to the database file Improved keyboard control Use Fl_Menu_Button for menus to add to keyboard control Fixed crash on search or install with an empty database 2008/01/24: Fixed string.gmatch to break up files even if there is no newline between them 2008/01/17: Added date of last update Tweaked the update function (it's still sloppy) Fixed ".mydsl_dir not found" error message 2008/01/16: Fixed resizable behavior Uses file in .mydsl_dir Added auto update for first run 2008/01/15: Added text search 2008/01/14: Fixed display of incorrect duplicate info file Check for trailing spaces in title string Added "Update" function Code and interface tweaks 2008/01/13: start of project --]]
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then print(arg[0]..": Can't open /opt/.mydsl_dir") os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
listfile=mydsl_dir.."/mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2"
function load_list() -- load the database while b_loc:size()>1 do b_loc:remove(0) end local getdate=io.popen("ls -lh "..listfile.."|awk '{print \"\\n\\n**\\nDatabase updated \"$6\" \"$7\"\\n"..fltk.fl_filename_name(listfile).." \"$5}'") mdate=getdate:read("*a") getdate:close() inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close() if not string.find(data,"%w") then info_display_buffer:text("Cannot read database "..listfile.."\nPlease try updating again.") else info={} info_count=0 -- breaks up each info file into a separate string for s in string.gmatch(data,"(Location:.-)\nLocation:") do info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), text=s } b_loc:add(info[info_count].location) end
b_loc:value(0) b_loc:do_callback() end end
function updatedb() -- download to temp file, check file integrity, and only then replace the old file tempfile=os.tmpname() os.execute("aterm +tr -bg white -fg black -geometry 80x4 -title \"Database Update\" -e wget "..listurl.." -O "..tempfile) if os.execute("bzip2 -t "..tempfile) == 0 then os.rename(tempfile,listfile) load_list() else fltk.fl_alert("Database check failed.\nThis may be the result of an incomplete download\nor gremlins in your internets.") os.remove(tempfile) end end
function pick_search_result() if results:value() > 1 then -- show selected info file in the browse tab get_loc=string.match(results:text(results:value()),spacer.."(.*)") get_fname=string.match(results:text(results:value()),"(.*)"..spacer) results:deselect() for i=0,b_loc:size() do if get_loc == b_loc:text(i) then b_loc:value(i) break end end b_loc:do_callback() for i=0,b_files:size() do if get_fname == b_files:text(i) then b_files:value(i) break end end b_files:do_callback() tabs:value(tab1) end end
ww=420; wh=360; bh=30; bw=ww/2-5 win=fltk:Fl_Window(ww,wh,"MyDSL Info Browser")
tabs=fltk:Fl_Tabs(0,0,ww,wh)
tab1=fltk:Fl_Group(0,0,ww,wh-bh,"browse") b_loc=fltk:Fl_Menu_Button(5,5,bw,bh) b_loc:align(20) b_loc:callback( function() b_loc:label("&Location: "..b_loc:text()) while b_files:size()>1 do b_files:remove(0) end b_files:redraw() for i=1,info_count do if info[i].location==b_loc:text() then b_files:add(info[i].title) end end b_files:value(0) b_files:do_callback() end )
b_files=fltk:Fl_Menu_Button(ww/2,5,bw,bh) b_files:align(20) b_files:callback( function() b_files:label("&Filename: "..b_files:text()) for i=1,info_count do if info[i].title == b_files:text() and info[i].location == b_loc:text() then info_display_buffer:text(info[i].text) info_display_buffer:append(mdate) break end end end )
info_display=fltk:Fl_Text_Display(5,10+bh,ww-10,wh-(20+bh*3)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer)
install=fltk:Fl_Button(5,wh-bh*2-5,bw,bh,"&Install Selected Package") install:callback( function() if b_files:text() and b_loc:text() then os.execute("mydsl-load "..b_files:text().." "..b_loc:text()) end end )
b_updatedb=fltk:Fl_Button(bw+5,wh-bh*2-5,bw,bh,"&Update Database") b_updatedb:callback(updatedb) fltk:Fl_End() --end tab1
tab2=fltk:Fl_Group(0,0,ww,wh-bh,"search text") search_text=fltk:Fl_Input(70,5,ww-75,bh,"search text: ") search_text:when(fltk.FL_WHEN_ENTER_KEY) search_text:callback( function() if search_text:value() ~= "" and info_count and info_count>0 then results:clear() if Fl_Browser.column_widths then results:add("@b@B49PACKAGE NAME"..spacer.."@b@B49LOCATION") else results:add("@b@B49PACKAGE NAME"..spacer.."LOCATION") end for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,true) then results:add(info[i].title..spacer..info[i].location) end end end end )
results=fltk:Fl_Hold_Browser(5,10+bh,ww-10,wh-(20+bh*2)) results:textfont(fltk.FL_SCREEN) results:textsize(12) -- column widths available in 0.6.4+ if Fl_Browser.column_widths then results:column_widths({results:w()/2,0}) spacer="\t" else spacer="\t\t" -- force some extra space for older versions end results:callback( -- react to click only function() if results:value() > 1 and Fl:event()==fltk.FL_RELEASE then pick_search_result() end end ) -- offscreen results_callback button for Enter key results_cb=fltk:Fl_Return_Button(ww,wh,bh,bh) results_cb:callback(pick_search_result) fltk:Fl_End() --end tab2 fltk:Fl_End() --end tabs group
-- offscreen button gives focus to text input rather than just the tab toggle_search=fltk:Fl_Button(ww,wh,bh,bh,"&s") toggle_search:callback( function() tabs:value(tab2) Fl:focus(search_text) end ) toggle_browse=fltk:Fl_Button(ww,wh,bh,bh,"&b") toggle_browse:callback(function() tabs:value(tab1) end)
win:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tab1:resizable(info_display) tab2:resizable(results) win:show() find_file=io.open(listfile) if find_file then data=find_file:read("*a") else data="" end if string.find(data,"%w") then find_file:close() load_list() else updatedb() end Fl:run()
|
Posted by mikshaw on Mar. 15 2008,14:45
More minor changes. The Tabs were replaced by Fl_Wizard. This allows the previously offscreen buttons to be used onscreen so there is only one control for switching tabs. This also gave me a way to display the last update time in the bottom right instead of printing it every time a new info is loaded.
The date check now uses murgaLua builtins instead of running ls | awk in a separate process.
Removed the 5-pixel gap between the text fields and the top/bottom widgets.
Code Sample | #!/home/dsl/bin/murgaLua-0.6.4 --[[ MyDSL info browser, 2008 mikshaw
Changelog (yyyy/mm/dd) 2008/03/15: Improved the update function Database date check uses os.date/lfs instead of os.popen/ls/awk Use wizard instead of tabs for better use of resources 2008/03/14: Undid gmatch change due to improvements to the database file Improved keyboard control Use Fl_Menu_Button for menus to add to keyboard control Fixed crash on search or install with an empty database 2008/01/24: Fixed string.gmatch to break up files even if there is no newline between them 2008/01/17: Added date of last update Tweaked the update function (it's still sloppy) Fixed ".mydsl_dir not found" error message 2008/01/16: Fixed resizable behavior Uses file in .mydsl_dir Added auto update for first run 2008/01/15: Added text search 2008/01/14: Fixed display of incorrect duplicate info file Check for trailing spaces in title string Added "Update" function Code and interface tweaks 2008/01/13: start of project --]]
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then print(arg[0]..": Can't open /opt/.mydsl_dir") os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
listfile=mydsl_dir.."/mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2"
function load_list() -- load the database while b_loc:size()>1 do b_loc:remove(0) end inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close() if not string.find(data,"%w") then info_display_buffer:text("Cannot read database "..listfile.."\nPlease try updating again.") else info={} info_count=0 -- breaks up each info file into a separate string for s in string.gmatch(data,"(Location:.-)\nLocation:") do info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), text=s } b_loc:add(info[info_count].location) end last_update:label("last update "..os.date("%d %b %Y",lfs.attributes(listfile).modification)) b_loc:value(0) b_loc:do_callback() end end
function updatedb() -- download to temp file, check file integrity, and only then replace the old file tempfile=os.tmpname() os.execute("aterm +tr -bg white -fg black -geometry 80x4 -title \"Database Update\" -e wget "..listurl.." -O "..tempfile) if os.execute("bzip2 -t "..tempfile) == 0 then os.rename(tempfile,listfile) load_list() else fltk.fl_alert("Database check failed.\nThis may be the result of an incomplete download\nor gremlins in your internets.") os.remove(tempfile) end end
function pick_search_result() if results:value() > 1 then -- show selected info file in the browse tab get_loc=string.match(results:text(results:value()),spacer.."(.*)") get_fname=string.match(results:text(results:value()),"(.*)"..spacer) results:deselect() for i=0,b_loc:size() do if get_loc == b_loc:text(i) then b_loc:value(i) break end end b_loc:do_callback() for i=0,b_files:size() do if get_fname == b_files:text(i) then b_files:value(i) break end end b_files:do_callback() tabs:value(tab1) end end
ww=500; wh=360; bh=30; bw=ww/2-5 win=fltk:Fl_Window(ww,wh,"MyDSL Info Browser")
tabs=fltk:Fl_Wizard(0,0,ww,wh-bh-5)
tab1=fltk:Fl_Group(0,0,ww,wh-bh-5,"browse") b_loc=fltk:Fl_Menu_Button(5,5,bw,bh) b_loc:align(20) b_loc:callback( function() b_loc:label("&Location: "..b_loc:text()) while b_files:size()>1 do b_files:remove(0) end b_files:redraw() for i=1,info_count do if info[i].location==b_loc:text() then b_files:add(info[i].title) end end b_files:value(0) b_files:do_callback() end )
b_files=fltk:Fl_Menu_Button(ww/2,5,bw,bh) b_files:align(20) b_files:callback( function() b_files:label("&Filename: "..b_files:text()) for i=1,info_count do if info[i].title == b_files:text() and info[i].location == b_loc:text() then info_display_buffer:text(info[i].text) tab_browse:setonly() break end end end )
info_display=fltk:Fl_Text_Display(5,5+bh,ww-10,wh-(10+bh*3)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer)
install=fltk:Fl_Button(5,wh-bh*2-5,bw,bh,"&Install Selected Package") install:callback( function() if b_files:text() and b_loc:text() then os.execute("mydsl-load "..b_files:text().." "..b_loc:text()) end end )
b_updatedb=fltk:Fl_Button(bw+5,wh-bh*2-5,bw,bh,"&Update Database") b_updatedb:callback(updatedb) fltk:Fl_End() --end tab1
tab2=fltk:Fl_Group(0,0,ww,wh-bh-5,"search text") search_text=fltk:Fl_Input(85,5,ww-90,bh,"search text ") search_text:when(fltk.FL_WHEN_ENTER_KEY) search_text:callback( function() if search_text:value() ~= "" and info_count and info_count>0 then results:clear() if Fl_Browser.column_widths then results:add("@B49@b@uPackage Name"..spacer.."@B49@b@uLocation") else -- default screen font does not have bold or underline -- and no columns means only one format string is used results:add("@B49PACKAGE NAME"..spacer.."LOCATION") end for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,true) then results:add(info[i].title..spacer..info[i].location) end end end end )
results=fltk:Fl_Hold_Browser(5,5+bh,ww-10,wh-(10+bh*2)) -- column widths available in 0.6.4+ if Fl_Browser.column_widths then results:column_widths({results:w()/2,0}) spacer="\t" else spacer="\t\t" -- force some extra space for older versions results:textfont(fltk.FL_SCREEN) -- fixed-width makes it closer to columns end results:callback( -- react to click only function() if results:value() > 1 and Fl:event()==fltk.FL_RELEASE then pick_search_result() end end ) -- offscreen results_callback button for Enter key results_cb=fltk:Fl_Return_Button(ww,wh,bh,bh) results_cb:callback(pick_search_result) fltk:Fl_End() --end tab2 fltk:Fl_End() --end tabs group
-- using buttons instead of tabs gives better keyboard control tabbuttons=fltk:Fl_Pack(5,wh-bh,200,bh-5) tabbuttons:type(fltk.FL_HORIZONTAL) tabbuttons:spacing(5) tab_browse=fltk:Fl_Radio_Button(0,0,100,bh-5,"&browse") tab_browse:when(fltk.FL_WHEN_CHANGED) tab_browse:box(fltk.FL_THIN_UP_BOX) tab_browse:callback(function() tabs:value(tab1) end) tab_search=fltk:Fl_Radio_Button(0,0,100,bh-5,"text &search") tab_search:when(fltk.FL_WHEN_CHANGED) tab_search:box(fltk.FL_THIN_UP_BOX) tab_search:callback( function() tabs:value(tab2) Fl:focus(search_text) end ) fltk:Fl_End() --end tabs buttons last_update=fltk:Fl_Box(bw+5,wh-bh-5,bw,bh+5)
win:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tab1:resizable(info_display) tab2:resizable(results) win:show() find_file=io.open(listfile) if find_file then data=find_file:read("*a") else data="" end if string.find(data,"%w") then find_file:close() load_list() else updatedb() end Fl:run()
|
Posted by mikshaw on Mar. 16 2008,02:56
I was messing around with extra colums in the results output, and when using the release date as a result, Xfree86-devel.unc is the only one that screws up. I can't figure out why this is.
Posted by roberts on Mar. 16 2008,04:08
Interestingly enough, as you may be aware, I am working on an sql version of this.
One extension that I was using as a test case is testing/compile-3.3.5.uci.
When using your latest mydsl info parser text search, I type compile and no compile-3.3.5.uci shows up? Your code appears to be doing a full text search including title (text=s)
It is interesting the two approaches that we have taken. I showed John my sql version during Scale and it was received as "possibly too dificult to use". I prefer the fine grained searching capabilitities of sql. But I realize that many users may not be comfortable typing sql queries. So I am adding a QBE tab. Still the state of the info files are not very structured and I am not an advanced sql user. It has been a real challenge to break the info files into sql tables and fields.
Posted by mikshaw on Mar. 16 2008,04:39
Quote | I type compile and no compile-3.3.5.uci shows up | I did that exact thing a couple days ago, and thought maybe the extension disappeared. I also checked the repository and didn't find it, though. However, I just tried "compile" again just now and compile-3.3.5.uci showed up. Odd.
I've been trying to do straight case-insensitive searches of the entire text, but I know there are still some issues to work out.
I know absolutely nothing about using sql, but I assume it's something that can be done entirely within murgaLua....at least if it's sqlite?
Posted by roberts on Mar. 16 2008,04:51
Yeah, I bunziped the mydslinfo.bz2 and did a grep compile and it was there. Strange.
I am doing sql all in murgaLua. Still not sure if it will be a go or not.
Yours with a flat file is easier to use and offers full text search. Also since flat file is just text it can be bzipped to a smaller download than a sqlite database..
Once I get some progress on the QBE screen I will post mine and see what happens. Afterall, it is always about a sharing and leaning experience. The more I do, the more complex it is getting.
On yours, I think your collapsable browser would be nicer than those two drop downs. Just a suggestion.
Posted by mikshaw on Mar. 16 2008,13:06
Quote | I think your collapsable browser would be nicer than those two drop downs. | I thought about that yesterday morning, but at the time I didn't feel it was worth attempting until after making the updatedb function more reliable.
Quote | Xfree86-devel.unc is the only one that screws up. | Just noticed that it contains two "Current:" lines
Posted by roberts on Mar. 16 2008,18:31
Quote (mikshaw @ Mar. 16 2008,05:06) | Quote | I think your collapsable browser would be nicer than those two drop downs. | I thought about that yesterday morning, but at the time I didn't feel it was worth attempting until after making the updatedb function more reliable.
Quote | Xfree86-devel.unc is the only one that screws up. | Just noticed that it contains two "Current:" lines |
Thanks for the update on XFree86-devel.unc. I have fixed it.
This is that sort of thing that I have been "cleaing up" to try to get data to be INSERTable to an SQL table. It has been more work that I originally thought.
Anyway, I have posted and updated mydslinfo.bz2
Posted by mikshaw on Mar. 16 2008,21:37
Quote | This is that sort of thing that I have been "cleaing up" to try to get data to be INSERTable to an SQL table. | I'm guessing that converting all dates to yyyy/mm/dd (if that's in your plan) is going to be a pain.
Here's a version that uses the collapsible browser rather than two separate menus.
There are a few things to consider....
It hasn't been thoroughly tested. There are probably issues I haven't seen yet.
In order for it to work as is, it needs the database to retain two existing qualities (besides the obvious keywords Location, Title, etc) 1) A line break between every package 2) The database has all apps together, all games together, etc. It currently compares the Location string to an existing variable to decide whether or not to create a submenu. If the categories get mixed in the database file, there will be multiple copies of some submenu headers.
It still needs some tweaks of the keyboard control. For example, after installation or database update, you need to either hit Tab a few times or switch to search and back to browse in order to get keyboard focus to the file list.
I don't yet know a way to change the sort order of the list, which is a feature I've had in the back of my mind since the beginning. I'm hoping to be able to allow the user to list files in alphabetical or chronological order (at least in the search window), and maybe have user-defined columns, like license, author, and maybe description.
I was also considering having only one category expanded at any one time, but for some reason that was giving me a lot more trouble than I had expected.
EDIT: fixed the browser doubling up after a db update. Also looking into an easier way to keep track of which info table index is required at any given time rather than having to run down through it each time.
Code Sample | #!/home/dsl/bin/murgaLua-0.6.4 --[[ MyDSL info browser, 2008 mikshaw
Changelog (yyyy/mm/dd) 2008/03/16: Interface tweaks 2008/03/15: Improved the update function Database date check uses os.date/lfs instead of os.popen/ls/awk Use wizard instead of tabs for better use of resources 2008/03/14: Undid gmatch change due to improvements to the database file Improved keyboard control Use Fl_Menu_Button for menus to add to keyboard control Fixed crash on search or install with an empty database 2008/01/24: Fixed string.gmatch to break up files even if there is no newline between them 2008/01/17: Added date of last update Tweaked the update function (it's still sloppy) Fixed ".mydsl_dir not found" error message 2008/01/16: Fixed resizable behavior Uses file in .mydsl_dir Added auto update for first run 2008/01/15: Added text search 2008/01/14: Fixed display of incorrect duplicate info file Check for trailing spaces in title string Added "Update" function Code and interface tweaks 2008/01/13: start of project --]]
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then print(arg[0]..": Can't open /opt/.mydsl_dir") os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
listfile=mydsl_dir.."/mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2" list_sep="@b@B50@u"
function toggle(b) local count,state,one,two=1 -- selected line and its label local me,label=b:value(),b:text(b:value()) if string.find(label,"%+%s*") then state,one,two="expanded","%+ ","%- " else state,one,two="collapsed","%- ","%+ " end b:text(me,string.gsub(label,one,two)) -- swap + and - -- toggle all lines until reaching the next section or the browser end while b:text(me+count) and not string.match(b:text(me+count),list_sep) do if state=="collapsed" then b:hide(me+count) else b:show(me+count) end count=count+1 end end
function fill_list() inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close() if not string.find(data,"%w") then -- if there's nothing readable in it info_display_buffer:text("Cannot read database "..listfile.."\nPlease try updating again.") else filelist:clear() header={} info={} -- table containing all package data: info[index].{location,title,date} info_count=0 -- number of packages local current_loc="" -- location string local headers=0 -- nuber of locations -- breaks up info for each package into a separate string for s in string.gmatch(data,"(Location:.-)\nLocation:") do info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), date=string.match(s,"Current:%s*(.-%d)%s"), text=s } if current_loc ~= info[info_count].location then -- create a header when location changes current_loc=info[info_count].location filelist:add(list_sep.."- "..current_loc) headers=headers+1 header[headers]=filelist:size() end filelist:add(info[info_count].title) end for i,v in ipairs(header) do filelist:value(header[i]); toggle(filelist) end last_update:label("last update "..os.date("%d %b %Y",lfs.attributes(listfile).modification)) end filelist:value(1) tab_browse:setonly() end
function updatedb() -- download to temp file, check file integrity, and only then replace the old file tempfile=os.tmpname() os.execute("aterm +tr -bg white -fg black -geometry 80x4 -title \"Database Update\" -e wget "..listurl.." -O "..tempfile) if os.execute("bzip2 -t "..tempfile) == 0 then os.rename(tempfile,listfile) fill_list() else fltk.fl_alert("Database check failed.\nThis may be the result of an incomplete download\nor gremlins in your internets.") os.remove(tempfile) end end
function pick_search_result() if results:value() > 1 then -- show selected info file in the browse tab get_loc=string.match(results:text(results:value()),spacer.."(.*)"..spacer) get_fname=string.match(results:text(results:value()),"(.-)"..spacer) -- select the package in filelist local myloc=1 while myloc<=filelist:size() do if not string.find(filelist:text(myloc)," "..get_loc,1,1) then myloc=myloc+1 else filelist:value(myloc) break end end -- open submenu if not open if string.find(filelist:text(myloc),list_sep.."+ ",1,1) then toggle(filelist) end while myloc<=filelist:size() do if filelist:text(myloc) ~= get_fname then myloc=myloc+1 else filelist:value(myloc) break end end for i=1,info_count do -- make sure you get the right info AND category if info[i].title == get_fname and info[i].location == get_loc then info_display_buffer:text(info[i].text) tab_browse:setonly() myfile=info[i] -- this is the file that will be downloaded break end end tabs:value(tab1) end end
function list_cb() if filelist:value()>0 then -- clicking a blank space can be fatal without this check if Fl:event() == fltk.FL_RELEASE or Fl:event_key()==fltk.FL_Enter then -- on click or Enter if string.find(filelist:text(filelist:value()),list_sep) then toggle(filelist) -- if it's a separator else -- find out what submenu we're under local myloc=filelist:value() while myloc > 0 do myloc=myloc-1 if string.find(filelist:text(myloc),list_sep) then myloc=string.gsub(filelist:text(myloc),".-%s%s","") break end end for i=1,info_count do -- make sure you get the right info AND category if info[i].title == filelist:text(filelist:value()) and info[i].location == myloc then info_display_buffer:text(info[i].text) myfile=info[i] tab_browse:setonly() break end end end end end end
ww=500; wh=360; bh=30; bw=ww/2-5 win=fltk:Fl_Window(ww,wh,"MyDSL Info Browser")
tabs=fltk:Fl_Wizard(0,0,ww,wh-bh-5) tab1=fltk:Fl_Group(0,0,ww,wh-bh-5,"browse")
tiles=fltk:Fl_Tile(5,5+bh,ww-10,wh-(15+bh*2)) filelist=fltk:Fl_Hold_Browser(5,5+bh,ww/2-5,wh-(15+bh*2)) filelist:callback(list_cb) info_display=fltk:Fl_Text_Display(ww/2,5+bh,ww/2-5,wh-(15+bh*2)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer) fltk:Fl_End() --end tiles
-- offscreen button that allows the list to respond to Enter key enter=fltk:Fl_Return_Button(ww,wh,10,10) enter:callback(function() filelist:do_callback() end)
install=fltk:Fl_Button(ww/2,5,bw,bh,"&Install Selected Package") install:callback( function() if myfile then mydslload=os.execute("mydsl-load "..myfile.title.." "..myfile.location) if mydslload~=0 then fltk.fl_alert(myfile.title..":\nDownload or Checksum error!") end end end )
b_updatedb=fltk:Fl_Button(5,5,bw,bh,"&Update Database") b_updatedb:callback(updatedb) fltk:Fl_End() --end tab1
tab2=fltk:Fl_Group(0,0,ww,wh-bh-5,"search text") search_text=fltk:Fl_Input(85,5,ww-90,bh,"search text ") search_text:when(fltk.FL_WHEN_ENTER_KEY) search_text:callback( function() if search_text:value() ~= "" and info_count and info_count>0 then results:clear() if Fl_Browser.column_widths then results:add("@B49@b@uPackage Name"..spacer.."@B49@b@uLocation"..spacer.."@B49@b@uRelease Date") else -- default screen font does not have bold or underline -- and no columns means only one format string is used results:add("@B49PACKAGE NAME"..spacer.."LOCATION"..spacer.."RELEASE DATE") end for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,true) then if not info[i].date then info[i].date="" end results:add(info[i].title..spacer..info[i].location..spacer..info[i].date) end end end end )
results=fltk:Fl_Hold_Browser(5,5+bh,ww-10,wh-(15+bh*2)) -- column widths available in 0.6.4+ if Fl_Browser.column_widths then results:column_widths({results:w()/2,200,0}) spacer="\t" else spacer="\t\t" -- force some extra space for older versions results:textfont(fltk.FL_SCREEN) -- fixed-width makes it closer to columns end results:callback( -- react to click only function() if results:value() > 1 and Fl:event()==fltk.FL_RELEASE then pick_search_result() end end ) -- offscreen results_callback button for Enter key results_cb=fltk:Fl_Return_Button(ww,wh,bh,bh) results_cb:callback(pick_search_result) fltk:Fl_End() --end tab2 fltk:Fl_End() --end tabs group
-- using buttons instead of tabs gives better keyboard control tabbuttons=fltk:Fl_Pack(5,wh-bh,200,bh-5) tabbuttons:type(fltk.FL_HORIZONTAL) tabbuttons:spacing(5) tab_browse=fltk:Fl_Radio_Button(0,0,100,bh-5,"&browse") tab_browse:when(fltk.FL_WHEN_CHANGED) tab_browse:box(fltk.FL_BORDER_BOX); tab_browse:selection_color(7) tab_browse:callback(function() tabs:value(tab1) end) tab_search=fltk:Fl_Radio_Button(0,0,100,bh-5,"text &search") tab_search:when(fltk.FL_WHEN_CHANGED) tab_search:box(fltk.FL_BORDER_BOX); tab_search:selection_color(7) tab_search:callback( function() tabs:value(tab2) Fl:focus(search_text) end ) fltk:Fl_End() --end tabs buttons last_update=fltk:Fl_Box(bw+5,wh-bh-5,bw,bh+5)
win:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tab1:resizable(tiles) tab2:resizable(results) win:show() find_file=io.open(listfile) if find_file then data=find_file:read("*a") else data="" end if string.find(data,"%w") then find_file:close() fill_list() else updatedb() end Fl:run()
|
Posted by roberts on Mar. 16 2008,22:52
I handled all the different date formats with standard Lua captures while building and inserting to sqlite.
I think it only fair for me to show you mine since we may want to join some features especially if you are wanting to sort etc.
I started by using your GUI and stripping all flatfile code. I added some "when" events and used "pack" on some layouts. I stared by creating a simple database ignoring comments and other "multiline/multivalue" fields. I then wrote standard lua and luasqlite as binding was available in murgaLua to query, display an index of 'hits' and then a view. Later I moved the GUI around using a menu for update and quit. Added the "comments" to database. Added QBE screen, still working on it.
This is a work in progress and I post it only as a preview. The next build of the database will break everything.
I post mainly for mikshaw but anyone can preview it. It currently only support direct sql queries. If you don't know sql don't preview it. The QBE is not implemented yet.
Of course you can download the mydsl.db open a shell start sqlite and issue sql commands too. murgaLua does not currently support readline in Linux so expect to do alot of CLI typing.
Open to suggestions on either the SQL database and the supporting GUI.
I am thinking that the multiline change-log and comments need to be separate tables.
I am not asking anyone to finish it as I am currently working on many parts. I start many sections of code before I "button" things up. That's just how I "work" er, play.
Oh, and this works with DSL 4.2.5 or DSL 3.4.11 no need to grab latest murgaLua
Code Sample |
#!/bin/murgaLua --[[ MyDSL Extension Browser, 2008 mikshaw - SQL and other GUI mods by Robert Shingledecker 2008/02/26: Added packed comments (probably needs sep table 2008/02/16: Added menu for Update database and Quit. 2008/02/14: Created QBE tab based on feedback not finished. 2008/02/08: Basic SQL queries working - take to Scale6x to show John. 2008/01/28: Dropped columns and switched to vertical VIEW layout. 2008/01/24: Created sqlite database mydsl.db with only simple cols. 2008/01/21: Gutted all flat file logic kept some GUI. 2008/01/13: Started from mikshaw's 2008 mydsl info browser. ]]--
function updatedb(nofile) if not nofile then backup=os.rename(database,database..".bak") end os.execute("aterm +tr -bg white -fg black -geometry 80x4 -title \"Database Update\" -e wget "..dburl.." -O "..database) end
function doSQL() if inputSQL:value() ~= "" then results:clear() selected = {} field_names = {} stmt = db:prepare(inputSQL:value()) if stmt == nil then fltk.fl_alert(db:errmsg()) else field_names = stmt:get_names() for row in stmt:rows(inputSQL:value()) do results:add(row[1].."\t"..row[2]) selected[#selected+1] = row end stmt:finalize() end end end
function showSQL() if results:value() > 0 then viewResults = "" for i = 1, #field_names do if field_names[i] == "comments" then selected[results:value()][i] = string.gsub(selected[results:value()][i],"%^","\n") end viewResults = viewResults .. field_names[i].."\t" viewResults = viewResults .. selected[results:value()][i].."\n" end info_display:value(viewResults) tabs:value(tab1) tab1:hide() tab3:show() end end
ww=420; wh=360; bh=25 w=fltk:Fl_Window(ww,wh,"MyDSL Extension Browser") w:callback( function(w) db:close() os.exit(0) end)
mb = fltk:Fl_Menu_Bar(0,0,ww,bh) mb:add("&File/&UpdateDB",0,updatedb) mb:add("&File/E&xit",0,quit) mb:callback(menu_items)
tabs=fltk:Fl_Tabs(0,bh,ww,wh-bh)
tab1=fltk:Fl_Pack(1,bh+1,ww,0,"SQL") inputSQL=fltk:Fl_Input(0,0,ww-10,bh) inputSQL:when(fltk.FL_WHEN_ENTER_KEY_ALWAYS) inputSQL:callback(doSQL)
results=fltk:Fl_Select_Browser(0,0,ww-10,wh-(8+bh*3)) results:textfont(fltk.FL_SCREEN) results:textsize(12) results:when(fltk.FL_WHEN_CHANGED) results:callback(showSQL) fltk:Fl_End()
tab2=fltk:Fl_Group(0,0,ww,wh-bh,"QBE") field_label = {"loc","title","desc","ver","author","site","policy","user","current","comments"} field_len = {120,180,325,240,320,290,325,285,110,335} field_in = {} for i = 1, #field_label do field_in[i] = fltk:Fl_Input(75,28+(28*(i-1)),field_len[i],bh,field_label[i]) end okBtn = fltk:Fl_Return_Button(340, 310, 70, 20, "OK"); okBtn:callback( function(okBtn) for i = 1, #field_label do if field_in[i]:value() ~= "" then print(field_label[i] .." ".. field_in[i]:value()) end end end) fltk:Fl_End()
tab3=fltk:Fl_Group(0,0,ww,wh-bh,"View") info_display=fltk:Fl_Multiline_Output(4,bh+4,ww-10,wh-(30+bh*2)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12)
install=fltk:Fl_Return_Button(340,310,70,20,"Install") install:callback( function() os.execute("mydsl-load "..selected[results:value()][2].." "..selected[results:value()][1]) end )
w:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tab1:resizable(info_display) tab2:resizable(results) w:show()
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then print("can't open "..mydsldirfile) os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
database = mydsl_dir.."/mydsl.db" dburl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydsl.db" databaseCheck = io.open(database) if databaseCheck then databaseCheck:close() else updatedb(1) end
selected = {} field_names = {} db = sqlite3.open(database) inputSQL:value("select * from mydsl order by loc;")
Fl:run()
|
Posted by mikshaw on Mar. 16 2008,22:58
Thanks for sharing. I'll try it very soon.
Quote | Oh, and this works with DSL 4.2.5 or DSL 3.4.11 no need to grab latest murgaLua | Are you implying there is trouble with my experiment beyond the lack of columns in murgaLua versions prior to 0.6.4? I tried to make sure it works in 0.5.5, but maybe I missed?
Posted by mikshaw on Mar. 16 2008,23:22
Also, sort of off-topic...
What is it that mydsl-load does initially that creates a pause before it begins to download? When I'm not connected to the internet it takes something like 10 seconds or so before wget starts. If I'm connected it's not nearly that bad, but still takes a couple of seconds.
Posted by mikshaw on Mar. 17 2008,18:03
I tried the sql version a little, although I don't yet understand how some of the features will be used. It was a little odd initially...I was offline and it created an empty database. After going online I had to manualy delete the database before it would download a new one. ____
Made more changes to the interface of the plain-text version. The file list can now be toggled with Alt+L. This was frustrating me for a long time because no matter what I did I couldn't get it to work if the list width was scaled smaller than its original width. I ended up creating it tiny and then resizing before showing the window. It looks like it might be a FLTK bug.
After running update or install, the filelist now gets back focus. This is to improve keyboard control.
The release date shown in the search results is formatted yyyy/mm/dd if the info originally is in mm/dd/yyyy or mm-dd-yyyy format. If the info has dd/mm/yyyy format, it will not convert properly...I don't think its possible to be 100% accurate in this case. I hope this will not be needed at some point in the future.
The "last update" box now also displays the total number of packages in the database.
I still want to find a way to grab the browser line that is associated witha specific info table index to make the code a little more streamlined, but so far my tests have caused more problems than they solve.
EDIT: added a function to jump from section to section in the browser, [ to go backward and ] to go forward
Code Sample | #!/home/dsl/bin/murgaLua-0.6.4 --[[ MyDSL info browser, 2008 mikshaw
Changelog (yyyy/mm/dd) 2008/03/17: More interface tweaks Convert date format to yyyy/mm/dd (hopefully a temp fix) 2008/03/16: Interface tweaks 2008/03/15: Improved the update function Database date check uses os.date/lfs instead of os.popen/ls/awk Use wizard instead of tabs for better use of resources 2008/03/14: Undid gmatch change due to improvements to the database file Improved keyboard control Use Fl_Menu_Button for menus to add to keyboard control Fixed crash on search or install with an empty database 2008/01/24: Fixed string.gmatch to break up files even if there is no newline between them 2008/01/17: Added date of last update Tweaked the update function (it's still sloppy) Fixed ".mydsl_dir not found" error message 2008/01/16: Fixed resizable behavior Uses file in .mydsl_dir Added auto update for first run 2008/01/15: Added text search 2008/01/14: Fixed display of incorrect duplicate info file Check for trailing spaces in title string Added "Update" function Code and interface tweaks 2008/01/13: start of project --]]
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then print(arg[0]..": Can't open /opt/.mydsl_dir") os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
listfile=mydsl_dir.."/mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2" list_sep="@b@B50@u"
function toggle(b) local count,state,one,two=1 -- selected line and its label local me,label=b:value(),b:text(b:value()) if string.find(label,"%+%s*") then state,one,two="expanded","%+ ","%- " else state,one,two="collapsed","%- ","%+ " end b:text(me,string.gsub(label,one,two)) -- swap + and - -- toggle all lines until reaching the next section or the browser end while b:text(me+count) and not string.match(b:text(me+count),list_sep) do if state=="collapsed" then b:hide(me+count) else b:show(me+count) end count=count+1 end end
function fill_list() inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close() if not string.find(data,"%w") then -- if there's nothing readable in it info_display_buffer:text("Cannot read database "..listfile.."\nPlease try updating again.") else filelist:clear() header={} info={} -- table containing all package data: info[index].{location,title,date} info_count=0 -- number of packages local current_loc="" -- location string local headers=0 -- nuber of locations -- breaks up info for each package into a separate string for s in string.gmatch(data,"(Location:.-)\nLocation:") do -- convert mm/dd/yyyy to yyyy/mm/dd local datestring=string.match(s,"Current:%s*(.-%d)%s") if string.find(datestring,"%d%d%D%d%d%D%d%d%d%d") then datestring=string.gsub(datestring,"(%d%d)%D(%d%d)%D(%d%d%d%d)","%3/%1/%2") end info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), date=string.gsub(datestring,"%D","/"), --datestring=string.match(s,"Current:%s*(.-%d)%s"), -- plain text=s } -- if not info[info_count].date then info[info_count].date="" end if current_loc ~= info[info_count].location then -- create a header when location string changes current_loc=info[info_count].location filelist:add(list_sep.."- "..current_loc) headers=headers+1 header[headers]=filelist:size() end filelist:add(info[info_count].title) end for i,v in ipairs(header) do filelist:value(header[i]); toggle(filelist) end last_update:label("last update "..os.date("%d %b %Y",lfs.attributes(listfile).modification)..", "..info_count.." packages") end filelist:value(1) tab_browse:setonly() end
function updatedb() -- download to temp file, check file integrity, and only then replace the old file tempfile=os.tmpname() os.execute("aterm +tr -bg white -fg black -geometry 80x4 -title \"Database Update\" -e wget "..listurl.." -O "..tempfile) if os.execute("bzip2 -t "..tempfile) == 0 then os.rename(tempfile,listfile) fill_list() else fltk.fl_alert("Database check failed.\nThis may be the result of an incomplete download\nor gremlins in your internets.") os.remove(tempfile) end filelist:take_focus() -- for better keyboard control end
function pick_search_result() -- show selected info file in the browse tab if results:value() > 1 then get_loc=string.match(results:text(results:value()),spacer.."(.*)"..spacer) get_fname=string.match(results:text(results:value()),"(.-)"..spacer) -- select the package in filelist local myloc=1 while myloc<=filelist:size() do if not string.find(filelist:text(myloc)," "..get_loc,1,1) then myloc=myloc+1 else filelist:value(myloc) break end end -- open submenu if not open if string.find(filelist:text(myloc),list_sep.."+ ",1,1) then toggle(filelist) end while myloc<=filelist:size() do if filelist:text(myloc) ~= get_fname then myloc=myloc+1 else filelist:value(myloc) break end end for i=1,info_count do -- make sure you get the right info AND category if info[i].title == get_fname and info[i].location == get_loc then info_display_buffer:text(info[i].text) tab_browse:setonly() myfile=info[i] -- this is the file that will be downloaded break end end tabs:value(tab1) end end
function list_cb() if filelist:value()>0 then -- clicking a blank space can be fatal without this check if Fl:event() == fltk.FL_RELEASE or Fl:event_key()==fltk.FL_Enter then -- on click or Enter if string.find(filelist:text(filelist:value()),list_sep) then toggle(filelist) -- if it's a separator else -- find out what submenu we're under local myloc=filelist:value() while myloc > 0 do myloc=myloc-1 if string.find(filelist:text(myloc),list_sep) then myloc=string.gsub(filelist:text(myloc),".-%s%s","") break end end for i=1,info_count do -- make sure you get the right info AND category if info[i].title == filelist:text(filelist:value()) and info[i].location == myloc then info_display_buffer:text(info[i].text) myfile=info[i] tab_browse:setonly() break end end end end end end
function toggle_list() if listw > 0 then oldw=listw tiles:position(listw+5,nil,6,nil) listw=0 info_display:take_focus() else tiles:position(6,nil,oldw+5,nil) listw=oldw filelist:take_focus() end end
ww=500; wh=360; bh=30; bw=ww/2-5 win=fltk:Fl_Window(ww,wh,"MyDSL Info Browser")
tabs=fltk:Fl_Wizard(0,0,ww,wh-bh-5) tab1=fltk:Fl_Group(0,0,ww,wh-bh-5,"browse")
-- the tiles are built weird initially (filelist is only 1px wide) -- this is a kluge; toggle_list doesn't seem to work if filelist -- is shrunk less than it's initial width tiles=fltk:Fl_Tile(5,5+bh,ww-10,wh-(15+bh*2)) --filelist=fltk:Fl_Hold_Browser(5,5+bh,ww/2-5,wh-(15+bh*2)) filelist=fltk:Fl_Hold_Browser(5,5+bh,1,wh-(15+bh*2)) filelist:callback(list_cb) --info_display=fltk:Fl_Text_Display(ww/2,5+bh,ww/2-5,wh-(15+bh*2)) info_display=fltk:Fl_Text_Display(6,5+bh,ww-11,wh-(15+bh*2)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer) fltk:Fl_End() --end tiles tiles:position(6,nil,ww/3,nil) -- resize the filelist tiles:callback(function() listw=filelist:w() end) listw=filelist:w() prevheader=fltk:Fl_Button(ww,wh,bh,bh,"&[") prevheader:callback( function() for i=table.getn(header),1,-1 do if header[i] < filelist:value() then filelist:value(header[i]) break end end filelist:take_focus() end ) nextheader=fltk:Fl_Button(ww,wh,bh,bh,"&]") nextheader:callback( function() for i=1,table.getn(header) do if header[i] > filelist:value() then filelist:value(header[i]) break end end filelist:take_focus() end ) -- offscreen button that allows the list to respond to Enter key enter=fltk:Fl_Return_Button(ww,wh,10,10) enter:callback(function() filelist:do_callback() end) togglist=fltk:Fl_Button(ww,wh,10,10,"&l") togglist:callback(toggle_list)
install=fltk:Fl_Button(ww/2,5,bw,bh,"&Install Selected Package") install:callback( function() if myfile then mydslload=os.execute("mydsl-load "..myfile.title.." "..myfile.location) if mydslload~=0 then fltk.fl_alert(myfile.title..":\nDownload or Checksum error!") end end filelist:take_focus() end )
b_updatedb=fltk:Fl_Button(5,5,bw,bh,"&Update Database") b_updatedb:callback(updatedb) fltk:Fl_End() --end tab1
tab2=fltk:Fl_Group(0,0,ww,wh-bh-5,"search text") search_text=fltk:Fl_Input(85,5,ww-90,bh,"search text ") search_text:when(fltk.FL_WHEN_ENTER_KEY) search_text:callback( function() if search_text:value() ~= "" and info_count and info_count>0 then results:clear() if Fl_Browser.column_widths then results:add("@B49@b@uPackage Name"..spacer.."@B49@b@uLocation"..spacer.."@B49@b@uRelease Date") else -- default screen font does not have bold or underline -- and no columns means only one format string is used results:add("@B49PACKAGE NAME"..spacer.."LOCATION"..spacer.."RELEASE DATE") end for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,true) then results:add(info[i].title..spacer..info[i].location..spacer..info[i].date) end end end end )
results=fltk:Fl_Hold_Browser(5,5+bh,ww-10,wh-(15+bh*2)) -- column widths available in 0.6.4+ if Fl_Browser.column_widths then results:column_widths({results:w()/2,200,0}) spacer="\t" else spacer="\t\t" -- force some extra space for older versions results:textfont(fltk.FL_SCREEN) -- fixed-width makes it closer to columns end results:callback( -- react to click only function() if results:value() > 1 and Fl:event()==fltk.FL_RELEASE then pick_search_result() end end ) -- offscreen results_callback button for Enter key results_cb=fltk:Fl_Return_Button(ww,wh,bh,bh) results_cb:callback(pick_search_result) fltk:Fl_End() --end tab2 fltk:Fl_End() --end tabs group
-- using buttons instead of tabs gives better keyboard control tabbuttons=fltk:Fl_Pack(5,wh-bh,200,bh-5) tabbuttons:type(fltk.FL_HORIZONTAL) tabbuttons:spacing(5) tab_browse=fltk:Fl_Radio_Button(0,0,100,bh-5,"&browse") tab_browse:when(fltk.FL_WHEN_CHANGED) tab_browse:box(fltk.FL_BORDER_BOX); tab_browse:selection_color(7) tab_browse:callback(function() tabs:value(tab1) end) tab_search=fltk:Fl_Radio_Button(0,0,100,bh-5,"text &search") tab_search:when(fltk.FL_WHEN_CHANGED) tab_search:box(fltk.FL_BORDER_BOX); tab_search:selection_color(7) tab_search:callback( function() tabs:value(tab2) Fl:focus(search_text) end ) fltk:Fl_End() --end tabs buttons --last_update=fltk:Fl_Box(bw+5,wh-bh-5,bw,bh+5) last_update=fltk:Fl_Box(ww-5,wh-bh-5,5,bh+5) last_update:align(fltk.FL_ALIGN_LEFT)
win:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tab1:resizable(tiles) tab2:resizable(results) win:show() find_file=io.open(listfile) if find_file then data=find_file:read("*a") else data="" end if string.find(data,"%w") then find_file:close() fill_list() else updatedb() end Fl:run()
|
Posted by roberts on Mar. 18 2008,02:34
Quote | I tried the sql version a little, although I don't yet understand how some of the features will be used. It was a little odd initially...I was offline and it created an empty database. After going online I had to manualy delete the database before it would download a new one. |
Interesting that you would think an initial offline status would work. Not that I needed debugging there. Beside use of the File menu ->UpdateDB would fetch it when you are online. No need to manually delete it.
The flow of the GUI is to type an valid SQL statement and upon presssing Enter, a hit list is displayed. Selecting one from such list switches to the View tab displaying the fields select in the SQL statement. Whereupon pressing enter will install the extension or select SQL one can make another choice from the displayed hit list or even decide to further expand or refine the SQL statement.
The QBE will be used to automatcially build the SQL statement via entering the data via corresponding fields. Kinda like SQL "training wheels". Once again the hit list and the generated SQL will be shown and selecting one from the hit will display the view of all fields selected just as before.
Posted by roberts on Mar. 18 2008,02:39
Quote (mikshaw @ Mar. 16 2008,14:58) | Thanks for sharing. I'll try it very soon.
Quote | Oh, and this works with DSL 4.2.5 or DSL 3.4.11 no need to grab latest murgaLua | Are you implying there is trouble with my experiment beyond the lack of columns in murgaLua versions prior to 0.6.4? I tried to make sure it works in 0.5.5, but maybe I missed? |
All of your scripts specify
Quote | #!/home/dsl/bin/murgaLua-0.6.4 |
Which would naturally lead one such assumption as it is not needed in DSL unless features that are only available in 0.6.4.were being attempted.
Posted by roberts on Mar. 18 2008,02:42
Quote (mikshaw @ Mar. 16 2008,15:22) | Also, sort of off-topic...
What is it that mydsl-load does initially that creates a pause before it begins to download? When I'm not connected to the internet it takes something like 10 seconds or so before wget starts. If I'm connected it's not nearly that bad, but still takes a couple of seconds. |
Many factors here including but not limited to: Multiple entry points to the mydsl loading system to support CLI as well as GUI. A mix of many shells and lua scripts being called. And the internet host name lookup based on configuration file. All of this before the actual download begins.
Posted by mikshaw on Mar. 19 2008,12:07
Quote (roberts @ Mar. 17 2008,21:39) | All of your scripts specify
Quote | #!/home/dsl/bin/murgaLua-0.6.4 |
Which would naturally lead one such assumption as it is not needed in DSL unless features that are only available in 0.6.4.were being attempted. |
I see.
I use the newer interpreter when testing newer features. It is not a requirement, though. Anything I write for use in DSL should be useable with murgaLua 0.5.5. The features of newer versions are used only if they are available....Code Sample | if Fl_Browser.column_widths then results:column_widths({results:w()/2,150,0}) spacer="\t" else spacer="\t\t" -- force some extra space for older versions |
Sometimes I remove the interpreter line when uploading, but usually I don't think about it.
Posted by roberts on Mar. 30 2008,03:52
Might be an issue with os.rename and the new mydslBrowser.lua formerly known as mydsl info parser.
It becomes apparent with the standard grub pendive installation, where the first partition is fat32 and the second is ext2.
Upon first invocation of the script, you can see the download of the mydslinfo.bz2 occur via wget but the result is:
"Cannot read database /mnt/sda1/mydsl/mydslinfo.bz2" "Please try updating again.
Upon each attempt at such results in the same message, each with another copy of mydslinfo.bz2 named as a lua tempfile. in the /tmp directory An endless loop.
Appears that line:
os.rename(tempfile,listfile)
quietly fails.
This can duplicated by: Code Sample | #!/bin/lua listfile = "/mnt/sda1/mydsl/mydslinfo.bz2" tempfile = "/tmp/lua_xCjkEa" os.rename(tempfile,listfile)
|
Where /mnt/sda1 is fat32 and /tmp is ext2.
This issue involves 4.3RC1.
This was not an issue in early versions of the script.
Posted by mikshaw on Mar. 30 2008,10:34
I assume "early versions" would be prior to March 15, when the messy version (i.e. overwriting with an empty file) of the updatedb function was still being used.
Considering the apparent simplicity of the function, I can't see how the script itself is faulty (not saying I'm genius of course). Perhaps there is an issue with fat32 + os.rename. The error you mentioned occurs if the database file is empty or non-existent, so I'm guessing it's not being moved. I can't think of any reason for this other than a problem with rename.
I assume the temp file download completes, since you didn't get the error "Database check failed".
What happens if you replace os.rename(tempfile,listfile) with os.execute("sudo mv -f "..tempfile.." "..listfile)?
Posted by roberts on Mar. 30 2008,13:41
I think that what I said with the first six words that I posted as well as the code posted. os.rename fails. I was just pointing that fact out.
Naturally the native mv works across different filesystems or we would all in trouble
sudo is not needed with the os.execute of the mv command as the target mydsl/ is setup with proper permissions.
I will make that adjustment to your script.
Posted by mikshaw on Mar. 30 2008,13:54
Quote | sudo is not needed with the os.execute of the mv command as the target mydsl/ is setup with proper permissions. | I just thought there might be a chance of problems with moving (as opposed to copying) from fat32. I have no experience with it, and know you're smart enough to notice that sudo is there =o)
Thanks. I'll make the change on my end too.
Posted by roberts on Mar. 30 2008,15:02
At the bottom it displays 450 packages. Yet upon bunzip mydslinfo.bz2 and performing
grep "^Title:" mydslinfo | wc -l
I get far more than 450. There are more than 450 packages in the repository.
[EDIT] After checking my local copy vs remote (ibiblio) vs grep vs find -name "*.info" the correct total "info" files as of this posting is 893
Posted by mikshaw on Mar. 31 2008,01:04
I had a feeling it wasn't working as I'd hoped. I got 901 lines using bunzip2 -c mydslinfo.bz2 |grep "^Title:" | wc -l
Not sure how to approach the problem at this time, but I'll look into it soon.
Posted by roberts on Mar. 31 2008,01:20
Yeah it was 901. I had a mismatch from the recently deleted extensions. If you update database you should get 893. Both local and remote directories are in complete sync.
Posted by mikshaw on Mar. 31 2008,10:50
893 now, yes. 446 listed in the gui...definitely something weird, must be either still cramming infos together or just dropping some of it. I haven't found anything close to an answer yet. I think I'm going to do a test with parsing the file line by line instead of reading the whole thing in. It might actually be faster, and probably easier to debug.
The "load local" mentioned in the RC thread might be a *little* less than easy, considering the application automatically tries to connect when it starts. If local was just plugged in, a user with a system not connected would have to wait several seconds every time the application is started, or manually close the terminal window every time.
I was thinking of a few possibilities:
1) Start the interface with a fl_choice -- local or web -- and load the main window only if you choose the internet. 2) Commandline/env option to prevent the initial update from running 3) Update automatically, but ask before doing it. This would be the easiest to implement of these 3 options.
Posted by mikshaw on Mar. 31 2008,11:59
446 is half of 893-1 (-1 being the last search for Location:) I know where the problem is, but I'm not sure how to fix it at the moment...it will require a different search string for gmatch.
Code Sample | for s in string.gmatch(data,"\n(Location:.-)\nLocation:") do | I thought the capture would be the only part of the actual match, but I think I was wrong. It seems that the gmatch function iterates over the input looking for "\n(Location:.-)\nLocation:" and just returns the capture, but that whole string is used as the match. So what it's doing is capturing every other info.
So far I haven't come up with a reliable search string.
Posted by mikshaw on Mar. 31 2008,13:47
Code Sample | for s in string.gmatch(data,"(Location:.-\n)\n") do |
This returns 982 packages.
Code Sample | bunzip2 -c mydslinfo.bz2|grep -B1 "^Location:"|grep "^ .*$" |
This shows the xorg72.uci and xpdf-3.02.uci are not separated by a blank line as all the others are. The Xorg info swallows Xpdf
I'll work on the load-local this afternoon or evening. Please let me know how you'd prefer it to be included.
Posted by roberts on Mar. 31 2008,14:25
Glad to hear. I will look at those extensions info files and try to correct on the mydslinfo side.
On the Load Local, what I had in mind was a third button at the top of the display.
Then upon invocation if no database has been downloaded, show all buttons top and bottom ghosted out except "Update Database" and "Load Local" and perhaps a text message of "No database currently loaded" where you were showing the database date and count.
That way no delay and user controls when to try to "fetch" the database.
Posted by roberts on Mar. 31 2008,15:21
xorg72.uci.info has no eol. Which explains why xorg72.uci,info swallowd xpdf-3.0.2. I corrected xorg72.uci.info and uploaded a new mydslinfo.bz2
Posted by Juanito on Mar. 31 2008,15:57
Quote | xorg72.uci.info has no eol |
- I guess eol = end of line, but for future reference and since I am the guilty party, could you explain the error in a little more detail?
Posted by roberts on Mar. 31 2008,16:39
Usually caused by the editor that was used in the creation of the info file. Not something that you particually caused. When I opened it in vi I could see the noeol indicator. I just re-filed it.
If you can recall, what editor did you use?
Posted by mikshaw on Mar. 31 2008,16:49
Quote | On the Load Local, what I had in mind was a third button at the top of the display. | That's in already =o)
Quote | Then upon invocation if no database has been downloaded, show all buttons top and bottom ghosted out except "Update Database" and "Load Local" and perhaps a text message of "No database currently loaded" where you were showing the database date and count. | Ok, disabling the buttons should be a snap, though i hadn't thought of that so it's not currently done.
Here's what I did before reading your post... If there is no database fl_choice asks if you want to download it. Cancelling the popup just displays the interface as usual, with no data displayed. The buttons that will be disabled are currently programed to do nothing if there is no applicable data to use, so at least it shouldn't break if the user tries them.
So this is what I've got so far.
Code Sample | #!/bin/murgaLua --[[ MyDSL browser, 2008 mikshaw
Changelog (yyyy/mm/dd) 2008/03/31: Replaced os.rename() with os.execute("mv") (thanks roberts) All infos are displayed (fixed bad gmatch string) Added "load local" button 2008/03/18: Added help screen 2008/03/17: More interface tweaks Convert date format to yyyy/mm/dd (hopefully a temp fix) 2008/03/16: Interface tweaks 2008/03/15: Improved the update function Database date check uses os.date/lfs instead of os.popen/ls/awk Use wizard instead of tabs for better use of resources 2008/03/14: Undid gmatch change due to improvements to the database file Improved keyboard control Use Fl_Menu_Button for menus to add to keyboard control Fixed crash on search or install with an empty database 2008/01/24: Fixed string.gmatch to break up files even if there is no newline between them 2008/01/17: Added date of last update Tweaked the update function (it's still sloppy) Fixed ".mydsl_dir not found" error message 2008/01/16: Fixed resizable behavior Uses file in .mydsl_dir Added auto update for first run 2008/01/15: Added text search 2008/01/14: Fixed display of incorrect duplicate info file Check for trailing spaces in title string Added "Update" function Code and interface tweaks 2008/01/13: start of project --]]
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then print(arg[0]..": Can't open /opt/.mydsl_dir") os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
listfile=mydsl_dir.."/mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2" list_sep="@b@B49@u"
help_text=[[
@sMyDSL Browser, Version 1? @- @bAbout
This program is used to view details of available myDSL extensions, and to install a selected package. An internet connection is required.
The first time the program runs it will attempt to download a database from a myDSL server, which will be saved to the directory listed in /opt/.mydsl_dir
Package installation is done using the existing myDSL system, which connects to the server listed in /opt/.dslrc @- @bBasic Usage
Choose a package to view either by browsing the file list or by entering a text string to search, and download and install that package if you discover that you must have it.
Text search of the entire database is available by clicking on the "search" button (Alt+S). The search is case-insensitive, but is otherwise literal, meaning that no translation is done for special characters like "*" or "?". Clicking on a search result will display the info for that package.
The database can be retrieved at any time by clicking "Update" (Alt+U). If the download fails the program continues to use the current database.
The "Install" button (Alt+I) attempts to download the package displayed in the info window, not necessarily the one highlighted in the file list.
The "Install Local" button lets you browse for packages saved on a disk. @- @bKeyboard
In addition to the key controls marked on the various buttons, there are some keys available to make keyboard control easier. In most cases the use of "Alt" is not needed in this application, and pressing just the appropriate key should work. When the search text input field has focus, however, it is necessary to Use "Alt" in addition to the key.
Enter : Activate the selected item in the file list or search T : Toggle the visibility of the file list ] : Jump to next section in the file list. [ : Jump to previous section in the file list.
These keys are not global. The widget that will receive the desired action must be onscreen at the time. For example, the database will not be updated if you press U when the main tab (browse) is not visible. @- @sCopyright (c) 2008 mikshaw @sThis script is free software, released without warranty and with no guarantee that it will do anything useful.
]]
function toggle(b) local count,state,one,two=1 -- selected line and its label local me,label=b:value(),b:text(b:value()) if string.find(label,"%+%s*") then state,one,two="expanded","%+ ","%- " else state,one,two="collapsed","%- ","%+ " end b:text(me,string.gsub(label,one,two)) -- swap + and - -- toggle all lines until reaching the next section or the browser end while b:text(me+count) and not string.match(b:text(me+count),list_sep) do if state=="collapsed" then b:hide(me+count) else b:show(me+count) end count=count+1 end end
function fill_list() inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close() if not string.find(data,"%w") then -- if there's nothing readable in it info_display_buffer:text("Cannot read database "..listfile.."\nPlease try updating again.") else filelist:clear() header={} info={} -- table containing all package data: info[index].{location,title,date} info_count=0 -- number of packages local current_loc="" -- location string local headers=0 -- number of locations -- breaks up info for each package into a separate string locount=0 for s in string.gmatch(data,"(Location:.-\n)\n") do -- convert mm/dd/yyyy to yyyy/mm/dd local datestring=string.match(s,"Current:%s*(.-%d)%s") if string.find(datestring,"%d%d%D%d%d%D%d%d%d%d") then datestring=string.gsub(datestring,"(%d%d)%D(%d%d)%D(%d%d%d%d)","%3/%1/%2") end info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), date=string.gsub(datestring,"%D","/"), --datestring=string.match(s,"Current:%s*(.-%d)%s"), -- plain text=s } if current_loc ~= info[info_count].location then -- create a header when location string changes current_loc=info[info_count].location filelist:add(list_sep.."- "..current_loc) headers=headers+1 header[headers]=filelist:size() end filelist:add(info[info_count].title) end for i,v in ipairs(header) do filelist:value(header[i]); toggle(filelist) end last_update:label("Database updated "..os.date("%d %b %Y",lfs.attributes(listfile).modification)..", "..info_count.." packages") end filelist:value(1) tab_browse:setonly() end
function updatedb() -- download to temp file, check file integrity, and only then replace the old file tempfile=os.tmpname() os.execute(terminal.." -title \"Database Update\" -e wget "..listurl.." -O "..tempfile) if os.execute("bzip2 -t "..tempfile) == 0 then os.execute("mv "..tempfile.." "..listfile) fill_list() else fltk.fl_alert("Database check failed.\nThis may be the result of an incomplete download\nor gremlins in your internets.") os.remove(tempfile) end filelist:take_focus() -- for better keyboard control end
function do_search() if search_text:value() ~= "" and info_count and info_count>0 then results:clear() if Fl_Browser.column_widths then results:add("@B49@b@uPackage Name"..spacer.."@B49@b@uLocation"..spacer.."@B49@b@uRelease Date") else results:add("@B49PACKAGE NAME"..spacer.."LOCATION"..spacer.."RELEASE DATE") end for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,1) then results:add(info[i].title..spacer..info[i].location..spacer..info[i].date) end end results:insert(1,"@B49@."..tostring(results:size()-1).." search results") end end
function pick_search_result() -- show selected info file in the browse tab if results:value() > 2 then get_loc=string.match(results:text(results:value()),spacer.."(.*)"..spacer) get_fname=string.match(results:text(results:value()),"(.-)"..spacer) -- select the package in filelist local myloc=1 while myloc<=filelist:size() do if not string.find(filelist:text(myloc)," "..get_loc,1,1) then myloc=myloc+1 else filelist:value(myloc) break end end -- open submenu if not open if string.find(filelist:text(myloc),list_sep.."+ ",1,1) then toggle(filelist) end while myloc<=filelist:size() do if filelist:text(myloc) ~= get_fname then myloc=myloc+1 else filelist:value(myloc) break end end for i=1,info_count do -- make sure you get the right info AND category if info[i].title == get_fname and info[i].location == get_loc then info_display_buffer:text(info[i].text) tab_browse:setonly() myfile=info[i] -- this is the file that will be downloaded break end end tabs:value(tab1) end end
function list_cb() if filelist:value()>0 then -- clicking a blank space can be fatal without this check if Fl:event() == fltk.FL_RELEASE or Fl:event_key()==fltk.FL_Enter then -- on click or Enter if string.find(filelist:text(filelist:value()),list_sep) then toggle(filelist) -- if it's a separator else -- find out what submenu we're under local myloc=filelist:value() while myloc > 0 do myloc=myloc-1 if string.find(filelist:text(myloc),list_sep) then myloc=string.gsub(filelist:text(myloc),".-%s%s","") break end end for i=1,info_count do -- make sure you get the right info AND category if info[i].title == filelist:text(filelist:value()) and info[i].location == myloc then info_display_buffer:text(info[i].text) myfile=info[i] tab_browse:setonly() break end end end end end end
function toggle_list() if listw > 0 then oldw=listw tiles:position(listw+5,nil,6,nil) listw=0 info_display:take_focus() else tiles:position(6,nil,oldw+5,nil) listw=oldw filelist:take_focus() end end
terminal="aterm +tr -bg white -fg black -geometry 80x4" ww=560; wh=380; bh=30; bw=(ww-10)/3 win=fltk:Fl_Window(ww,wh,"MyDSL Browser")
tabs=fltk:Fl_Wizard(0,0,ww,wh-bh-5) tab1=fltk:Fl_Group(0,0,ww,wh-bh-5,"browse")
-- the tiles are built weird initially (filelist is only 1px wide) -- this is a kluge; toggle_list doesn't seem to work if filelist -- is shrunk less than it's initial width tiles=fltk:Fl_Tile(5,5+bh,ww-10,wh-(15+bh*2)) filelist=fltk:Fl_Hold_Browser(5,5+bh,1,wh-(15+bh*2)) filelist:callback(list_cb)
info_display=fltk:Fl_Text_Display(6,5+bh,ww-11,wh-(15+bh*2)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer) fltk:Fl_End() --end tiles
tiles:position(6,nil,ww/3,nil) -- resize the filelist tiles:callback(function() listw=filelist:w() end) listw=filelist:w() -- for toggle_list()
-- offscreen buttons for keyboard control prevheader=fltk:Fl_Button(ww,wh,bh,bh,"&[") prevheader:callback( function() for i=table.getn(header),1,-1 do if header[i] < filelist:value() then filelist:value(header[i]); break end end filelist:take_focus() end) nextheader=fltk:Fl_Button(ww,wh,bh,bh,"&]") nextheader:callback( function() for i=1,table.getn(header) do if header[i] > filelist:value() then filelist:value(header[i]); break end end filelist:take_focus() end) enter=fltk:Fl_Return_Button(ww,wh,10,10) enter:callback(function() filelist:do_callback() end) togglist=fltk:Fl_Button(ww,wh,10,10,"&t") togglist:callback(toggle_list)
-- top buttons b_updatedb=fltk:Fl_Button(5,5,bw,bh,"&Update Database") b_updatedb:callback(updatedb) install=fltk:Fl_Button(bw+5,5,bw,bh,"&Install Selected Package") install:callback( function() if myfile then mydslload=os.execute("mydsl-load "..myfile.title.." "..myfile.location) if mydslload~=0 then fltk.fl_alert(myfile.title..":\nDownload or Checksum error!") end end filelist:take_focus() end) install_local=fltk:Fl_Button(bw*2+5,5,bw,bh,"Install &Local Package @DnArrow") install_local:callback( function() local filename=fltk.fl_file_chooser("Browse for a MyDSL file","Mydsl files (*.{dsl,tar.gz,uci,unc})",mydsl_dir,nil) if filename then os.execute("mydsl-load "..filename) end end) fltk:Fl_End() --end tab1
tab2=fltk:Fl_Group(0,0,ww,wh-bh-5,"search text") search_text=fltk:Fl_Input(bh*3+5,5,ww-10-bh*3,bh,"search text ") search_text:when(fltk.FL_WHEN_ENTER_KEY) search_text:callback(do_search)
results=fltk:Fl_Hold_Browser(5,5+bh,ww-10,wh-(15+bh*2)) -- column widths available in 0.6.4+ if Fl_Browser.column_widths then results:column_widths({results:w()/2,150,0}) spacer="\t" else spacer="\t\t" -- force some extra space for older versions results:textfont(fltk.FL_SCREEN) -- fixed-width makes it closer to columns end -- react to click only results:callback( function() if results:value() > 1 and Fl:event()==fltk.FL_RELEASE then pick_search_result() end end) -- offscreen results_callback button for Enter key results_cb=fltk:Fl_Return_Button(ww,wh,bh,bh) results_cb:callback(pick_search_result) fltk:Fl_End() --end tab2 tab3=fltk:Fl_Group(0,0,ww,wh-bh-5,"help") help=fltk:Fl_Browser(5,5,ww-10,wh-(15+bh)) fltk:Fl_End() --end tab3 fltk:Fl_End() --end tabs group for line in string.gmatch(help_text,".-\n") do help:add(line) end
-- using buttons instead of tabs gives better keyboard control tabbuttons=fltk:Fl_Pack(5,wh-bh,200,bh-5) tabbuttons:type(fltk.FL_HORIZONTAL) tabbuttons:spacing(5) tab_browse=fltk:Fl_Radio_Button(0,0,100,bh-5,"&browse") tab_browse:when(fltk.FL_WHEN_CHANGED) tab_browse:box(fltk.FL_BORDER_BOX); tab_browse:selection_color(7) tab_browse:callback(function() tabs:value(tab1) end) tab_search=fltk:Fl_Radio_Button(0,0,100,bh-5,"text &search") tab_search:when(fltk.FL_WHEN_CHANGED) tab_search:box(fltk.FL_BORDER_BOX); tab_search:selection_color(7) tab_search:callback(function() tabs:value(tab2); Fl:focus(search_text) end) tab_help=fltk:Fl_Radio_Button(0,0,50,bh-5,"&help") tab_help:when(fltk.FL_WHEN_CHANGED) tab_help:box(fltk.FL_BORDER_BOX); tab_help:selection_color(7) tab_help:callback(function() tabs:value(tab3) end) fltk:Fl_End() --end tabs buttons last_update=fltk:Fl_Box(ww-5,wh-bh-5,5,bh+5) last_update:align(fltk.FL_ALIGN_LEFT) last_update:labelsize(12)
win:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tabs:resizable(tab3) tab1:resizable(tiles) tab2:resizable(results) tab3:resizable(help) win:show()
find_file=io.open(listfile) if find_file then data=find_file:read("*a") else data="" end if string.find(data,"%w") then find_file:close(); fill_list() else ask4db=fltk.fl_choice("You have no database for online MyDSL apps.\nDo you want to download it now?","No","Yes",NULL) if ask4db==1 then Fl:check(); updatedb() end end Fl:run()
|
Posted by mikshaw on April 01 2008,15:52
I cut the size down drastically by removing some unnecessary stuff...
The help tab really didn't provide enough useful information to be worth the weight, so that's gone. It also allows everything but "update" and "install local" to be deactivated when no database is available.
The comments and changelog were removed. I'm keeping a copy with that info in case I need to refer to it in the future.
Also removed the code that checks for the existence of column_widths, which was there to support murgaLua older than 0.6.4
The script went from 15015 to 8800 bytes.
EDIT: I had tried to use io.popen to run the mydsl-load command, in order to grab the command output, and it was working well sometimes. Unfortunately mydsl-load failure (such as the "please mount" error we occasionally see) will bring down the whole gui. Does anyone know if FLTK has a means of handling errors more gracefully than just shutting down?
Code Sample | #!/bin/murgaLua -- MyDSL Browser, 2008 mikshaw
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then print(arg[0]..": Can't open /opt/.mydsl_dir") os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
listfile=mydsl_dir.."/mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2" list_sep="@b@B49@u"
function toggle(b) local count,state,one,two=1 local me,label=b:value(),b:text(b:value()) if string.find(label,"%+%s*") then state,one,two="expanded","%+ ","%- " else state,one,two="collapsed","%- ","%+ " end b:text(me,string.gsub(label,one,two)) while b:text(me+count) and not string.match(b:text(me+count),list_sep) do if state=="collapsed" then b:hide(me+count) else b:show(me+count) end count=count+1 end end
function fill_list() inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close() if not string.find(data,"%w") then info_display_buffer:text("Cannot read database "..listfile.."\nPlease try updating again.") else filelist:clear() header={} info={} info_count=0 local current_loc="" local headers=0 locount=0 for s in string.gmatch(data,"(Location:.-\n)\n") do local datestring=string.match(s,"Current:%s*(.-%d)%s") if string.find(datestring,"%d%d%D%d%d%D%d%d%d%d") then datestring=string.gsub(datestring,"(%d%d)%D(%d%d)%D(%d%d%d%d)","%3/%1/%2") end info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), date=string.gsub(datestring,"%D","/"), text=s } if current_loc ~= info[info_count].location then current_loc=info[info_count].location filelist:add(list_sep.."- "..current_loc) headers=headers+1 header[headers]=filelist:size() end filelist:add(info[info_count].title) end for i,v in ipairs(header) do filelist:value(header[i]); toggle(filelist) end last_update:label("Database updated "..os.date("%d %b %Y",lfs.attributes(listfile).modification)..", "..info_count.." packages") end filelist:value(1) tab_browse:setonly() end
function updatedb() tempfile=os.tmpname() os.execute(terminal.." -title \"Database Update\" -e wget "..listurl.." -O "..tempfile) if os.execute("bzip2 -t "..tempfile) == 0 then os.execute("mv "..tempfile.." "..listfile) install:activate() tab_search:activate() tab_browse:activate() info_display_buffer:text("\nDatabase updated successfully.") fill_list() else fltk.fl_alert("Database check failed.\nThis may be the result of an incomplete download\nor gremlins in your internets.") os.remove(tempfile) end filelist:take_focus() end
function do_search() if search_text:value() ~= "" and info_count and info_count>0 then results:clear() results:add("@B49@b@uPackage Name\t@B49@b@uLocation\t@B49@b@uRelease Date") for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,1) then results:add(info[i].title.."\t"..info[i].location.."\t"..info[i].date) end end results:insert(1,"@B49@."..tostring(results:size()-1).." search results") end end
function pick_search_result() if results:value() > 2 then get_loc=string.match(results:text(results:value()),"\t(.*)\t") get_fname=string.match(results:text(results:value()),"(.-)\t") local myloc=1 while myloc<=filelist:size() do if not string.find(filelist:text(myloc)," "..get_loc,1,1) then myloc=myloc+1 else filelist:value(myloc) break end end if string.find(filelist:text(myloc),list_sep.."+ ",1,1) then toggle(filelist) end while myloc<=filelist:size() do if filelist:text(myloc) ~= get_fname then myloc=myloc+1 else filelist:value(myloc) break end end for i=1,info_count do if info[i].title == get_fname and info[i].location == get_loc then info_display_buffer:text(info[i].text) tab_browse:setonly() myfile=info[i] break end end tabs:value(tab1) end end
function list_cb() if filelist:value()>0 then if Fl:event() == fltk.FL_RELEASE or Fl:event_key()==fltk.FL_Enter then if string.find(filelist:text(filelist:value()),list_sep) then toggle(filelist) else local myloc=filelist:value() while myloc > 0 do myloc=myloc-1 if string.find(filelist:text(myloc),list_sep) then myloc=string.gsub(filelist:text(myloc),".-%s%s","") break end end for i=1,info_count do if info[i].title == filelist:text(filelist:value()) and info[i].location == myloc then info_display_buffer:text(info[i].text) myfile=info[i] tab_browse:setonly() break end end end end end end
function toggle_list() if listw > 0 then oldw=listw tiles:position(listw+5,nil,6,nil) listw=0 info_display:take_focus() else tiles:position(6,nil,oldw+5,nil) listw=oldw filelist:take_focus() end end
terminal="aterm +tr -bg white -fg black -geometry 80x4" ww=560; wh=380; bh=30; bw=(ww-10)/3 win=fltk:Fl_Window(ww,wh,"MyDSL Browser")
tabs=fltk:Fl_Wizard(0,0,ww,wh-bh-5) tab1=fltk:Fl_Group(0,0,ww,wh-bh-5,"browse")
tiles=fltk:Fl_Tile(5,5+bh,ww-10,wh-(15+bh*2)) filelist=fltk:Fl_Hold_Browser(5,5+bh,1,wh-(15+bh*2)) filelist:callback(list_cb)
info_display=fltk:Fl_Text_Display(6,5+bh,ww-11,wh-(15+bh*2)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer) fltk:Fl_End()
tiles:position(6,nil,ww/3,nil) tiles:callback(function() listw=filelist:w() end) listw=filelist:w()
prevheader=fltk:Fl_Button(ww,wh,bh,bh,"&[") prevheader:callback( function() for i=table.getn(header),1,-1 do if header[i] < filelist:value() then filelist:value(header[i]); break end end filelist:take_focus() end) nextheader=fltk:Fl_Button(ww,wh,bh,bh,"&]") nextheader:callback( function() for i=1,table.getn(header) do if header[i] > filelist:value() then filelist:value(header[i]); break end end filelist:take_focus() end) enter=fltk:Fl_Return_Button(ww,wh,10,10) enter:callback(function() filelist:do_callback() end) togglist=fltk:Fl_Button(ww,wh,10,10,"&t") togglist:callback(toggle_list)
b_updatedb=fltk:Fl_Button(5,5,bw,bh,"&Update Database") b_updatedb:callback(updatedb) install=fltk:Fl_Button(bw+5,5,bw,bh,"&Install Selected Package") install:callback( function() if myfile then mydslload=os.execute("mydsl-load "..myfile.title.." "..myfile.location) if mydslload~=0 then fltk.fl_alert(myfile.title..":\nDownload or Checksum error!") end end filelist:take_focus() end) install_local=fltk:Fl_Button(bw*2+5,5,bw,bh,"Install &Local Package @DnArrow") install_local:callback( function() local filename=fltk.fl_file_chooser("Browse for a MyDSL file","Mydsl files (*.{dsl,tar.gz,uci,unc})",mydsl_dir,nil) if filename then os.execute("mydsl-load "..filename) end end) fltk:Fl_End()
tab2=fltk:Fl_Group(0,0,ww,wh-bh-5,"search text") search_text=fltk:Fl_Input(bh*3+5,5,ww-10-bh*3,bh,"search text ") search_text:when(fltk.FL_WHEN_ENTER_KEY) search_text:callback(do_search)
results=fltk:Fl_Hold_Browser(5,5+bh,ww-10,wh-(15+bh*2)) results:column_widths({results:w()/2,150,0}) results:callback( function() if results:value() > 1 and Fl:event()==fltk.FL_RELEASE then pick_search_result() end end) results_cb=fltk:Fl_Return_Button(ww,wh,bh,bh) results_cb:callback(pick_search_result) fltk:Fl_End() fltk:Fl_End()
tabbuttons=fltk:Fl_Pack(5,wh-bh,200,bh-5) tabbuttons:type(fltk.FL_HORIZONTAL) tabbuttons:spacing(5) tab_browse=fltk:Fl_Radio_Button(0,0,100,bh-5,"&browse") tab_browse:when(fltk.FL_WHEN_CHANGED) tab_browse:box(fltk.FL_BORDER_BOX); tab_browse:selection_color(7) tab_browse:callback(function() tabs:value(tab1) end) tab_search=fltk:Fl_Radio_Button(0,0,100,bh-5,"text &search") tab_search:when(fltk.FL_WHEN_CHANGED) tab_search:box(fltk.FL_BORDER_BOX); tab_search:selection_color(7) tab_search:callback(function() tabs:value(tab2); Fl:focus(search_text) end) fltk:Fl_End() last_update=fltk:Fl_Box(ww-5,wh-bh-5,5,bh+5) last_update:align(fltk.FL_ALIGN_LEFT) last_update:labelsize(12)
win:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tabs:resizable(tab3) tab1:resizable(tiles) tab2:resizable(results) win:show()
find_file=io.open(listfile) if find_file then data=find_file:read("*a") else data="" end if string.find(data,"%w") then find_file:close(); fill_list() else ask4db=fltk.fl_choice("You have no database for online MyDSL apps.\nDo you want to download it now?","No","Yes",NULL) if ask4db==1 then Fl:check(); updatedb() else install:deactivate(); tab_search:deactivate(); tab_browse:deactivate() info_display_buffer:text("\nThere is no MyDSL database installed.\nClick \"Update Database\" \(Alt+U\) to download it.") end end Fl:run()
|
Posted by roberts on April 01 2008,17:35
Ah, you did both, grey out and popup. Nice job! Will put in RC2.
Posted by ^thehatsrule^ on April 04 2008,22:09
Quote (mikshaw @ April 01 2008,10:52) | Unfortunately mydsl-load failure (such as the "please mount" error we occasionally see) will bring down the whole gui. Does anyone know if FLTK has a means of handling errors more gracefully than just shutting down? | Maybe pcall? See < http://www.lua.org/manual/5.1/manual.html#2.7 >
As an alternative: if you're talking about that popup dialog, maybe you could unset the DISPLAY env var. I haven't looked at the code nor tried it, so I don't know what the exact behaviour will be though.
Posted by mikshaw on April 05 2008,02:26
After posting that I thought it might be Lua rather than FLTK, which would make more sense. I've noticed a lot of Robert's scripts use "name,err=some_function" , which I assume grabs any error that might occur, but I've never looked into how that works.
Posted by ^thehatsrule^ on April 05 2008,05:09
"retval, err" are just the return codes for some function... it depends on their declarations afaik. It doesn't do anything except that you could print out the error contents (ie message), assuming that the function error was handled correctly and did not exit prematurely.
Posted by mikshaw on April 05 2008,11:32
Quote | if you're talking about that popup dialog, maybe you could unset the DISPLAY env var | I can't say for sure, and haven't tested yet. The popup still displays, but it only displays when there is an error. There's no way to tell if the error or popup is the trouble unless I changed mountci to show a popup on success as well....haven't tried it yet.
Thanks for the info on the return codes. I guess you pretty much have to know exactly what a function returns before deciding to use it. It took a few confusing mistakes before realizing that many functions return multiple values, and I still have trouble making use of them sometimes.
This looks promising. Thanks. It sometimes seems to me that either murgaLua itself does not know how to handle Lua errors, or I should be using something other than Fl:run to start the FLTK display (maybe a main loop or something). Considering interactive Lua doesn't completely shut down on an error, I would think the same behavior could be forced with non-interactive.
Posted by mikshaw on April 22 2008,01:33
This version addresses a couple of bugs found by JLS.
1) Added change directory at line 12 2) Removed (actually just commented for now) line 228
Code Sample | #!/bin/murgaLua -- MyDSL Browser, 2008 mikshaw
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then fltk.fl_alert("Can't open /opt/.mydsl_dir") os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close()
if not lfs.chdir(mydsl_dir) then fltk.fl_alert("Could not enter directory\n"..mydsl_dir) os.exit(2) end
listfile=mydsl_dir.."/mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2" list_sep="@b@B49@u"
function toggle(b) local count,state,one,two=1 local me,label=b:value(),b:text(b:value()) if string.find(label,"%+%s*") then state,one,two="expanded","%+ ","%- " else state,one,two="collapsed","%- ","%+ " end b:text(me,string.gsub(label,one,two)) while b:text(me+count) and not string.match(b:text(me+count),list_sep) do if state=="collapsed" then b:hide(me+count) else b:show(me+count) end count=count+1 end end
function fill_list() inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close() if not string.find(data,"%w") then info_display_buffer:text("Cannot read database "..listfile.."\nPlease try updating again.") else filelist:clear() header={} info={} info_count=0 local current_loc="" local headers=0 locount=0 for s in string.gmatch(data,"(Location:.-\n)\n") do local datestring=string.match(s,"Current:%s*(.-%d)%s") if string.find(datestring,"%d%d%D%d%d%D%d%d%d%d") then datestring=string.gsub(datestring,"(%d%d)%D(%d%d)%D(%d%d%d%d)","%3/%1/%2") end info_count=info_count+1 info[info_count]={ location=string.match(s,"Location:%s*(.-)%s*\n"), title=string.match(s,"Title:%s*(.-)%s*\n"), date=string.gsub(datestring,"%D","/"), text=s } if current_loc ~= info[info_count].location then current_loc=info[info_count].location filelist:add(list_sep.."- "..current_loc) headers=headers+1 header[headers]=filelist:size() end filelist:add(info[info_count].title) end for i,v in ipairs(header) do filelist:value(header[i]); toggle(filelist) end last_update:label("Database updated "..os.date("%d %b %Y",lfs.attributes(listfile).modification)..", "..info_count.." packages") end filelist:value(1) tab_browse:setonly() end
function updatedb() tempfile=os.tmpname() os.execute(terminal.." -title \"Database Update\" -e wget "..listurl.." -O "..tempfile) if os.execute("bzip2 -t "..tempfile) == 0 then os.execute("mv "..tempfile.." "..listfile) install:activate() tab_search:activate() tab_browse:activate() info_display_buffer:text("\nDatabase updated successfully.") fill_list() else fltk.fl_alert("Database check failed.\nThis may be the result of an incomplete download\nor gremlins in your internets.") os.remove(tempfile) end filelist:take_focus() end
function do_search() if search_text:value() ~= "" and info_count and info_count>0 then results:clear() results:add("@B49@b@uPackage Name\t@B49@b@uLocation\t@B49@b@uRelease Date") for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,1) then results:add(info[i].title.."\t"..info[i].location.."\t"..info[i].date) end end results:insert(1,"@B49@."..tostring(results:size()-1).." search results") end end
function pick_search_result() if results:value() > 2 then get_loc=string.match(results:text(results:value()),"\t(.*)\t") get_fname=string.match(results:text(results:value()),"(.-)\t") local myloc=1 while myloc<=filelist:size() do if not string.find(filelist:text(myloc)," "..get_loc,1,1) then myloc=myloc+1 else filelist:value(myloc) break end end if string.find(filelist:text(myloc),list_sep.."+ ",1,1) then toggle(filelist) end while myloc<=filelist:size() do if filelist:text(myloc) ~= get_fname then myloc=myloc+1 else filelist:value(myloc) break end end for i=1,info_count do if info[i].title == get_fname and info[i].location == get_loc then info_display_buffer:text(info[i].text) tab_browse:setonly() myfile=info[i] break end end tabs:value(tab1) end end
function list_cb() if filelist:value()>0 then if Fl:event() == fltk.FL_RELEASE or Fl:event_key()==fltk.FL_Enter then if string.find(filelist:text(filelist:value()),list_sep) then toggle(filelist) else local myloc=filelist:value() while myloc > 0 do myloc=myloc-1 if string.find(filelist:text(myloc),list_sep) then myloc=string.gsub(filelist:text(myloc),".-%s%s","") break end end for i=1,info_count do if info[i].title == filelist:text(filelist:value()) and info[i].location == myloc then info_display_buffer:text(info[i].text) myfile=info[i] tab_browse:setonly() break end end end end end end
function toggle_list() if listw > 0 then oldw=listw tiles:position(listw+5,nil,6,nil) listw=0 info_display:take_focus() else tiles:position(6,nil,oldw+5,nil) listw=oldw filelist:take_focus() end end
terminal="aterm +tr -bg white -fg black -geometry 80x4" ww=560; wh=380; bh=30; bw=(ww-10)/3 win=fltk:Fl_Window(ww,wh,"MyDSL Browser")
tabs=fltk:Fl_Wizard(0,0,ww,wh-bh-5) tab1=fltk:Fl_Group(0,0,ww,wh-bh-5,"browse")
tiles=fltk:Fl_Tile(5,5+bh,ww-10,wh-(15+bh*2)) filelist=fltk:Fl_Hold_Browser(5,5+bh,1,wh-(15+bh*2)) filelist:callback(list_cb)
info_display=fltk:Fl_Text_Display(6,5+bh,ww-11,wh-(15+bh*2)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer) fltk:Fl_End()
tiles:position(6,nil,ww/3,nil) tiles:callback(function() listw=filelist:w() end) listw=filelist:w()
prevheader=fltk:Fl_Button(ww,wh,bh,bh,"&[") prevheader:callback( function() for i=table.getn(header),1,-1 do if header[i] < filelist:value() then filelist:value(header[i]); break end end filelist:take_focus() end) nextheader=fltk:Fl_Button(ww,wh,bh,bh,"&]") nextheader:callback( function() for i=1,table.getn(header) do if header[i] > filelist:value() then filelist:value(header[i]); break end end filelist:take_focus() end) enter=fltk:Fl_Return_Button(ww,wh,10,10) enter:callback(function() filelist:do_callback() end) togglist=fltk:Fl_Button(ww,wh,10,10,"&t") togglist:callback(toggle_list)
b_updatedb=fltk:Fl_Button(5,5,bw,bh,"&Update Database") b_updatedb:callback(updatedb) install=fltk:Fl_Button(bw+5,5,bw,bh,"&Install Selected Package") install:callback( function() if myfile then mydslload=os.execute("mydsl-load "..myfile.title.." "..myfile.location) -- if mydslload~=0 then fltk.fl_alert(myfile.title..":\nDownload or Checksum error!") end end filelist:take_focus() end) install_local=fltk:Fl_Button(bw*2+5,5,bw,bh,"Install &Local Package @DnArrow") install_local:callback( function() local filename=fltk.fl_file_chooser("Browse for a MyDSL file","Mydsl files (*.{dsl,tar.gz,uci,unc})",mydsl_dir,nil) if filename then os.execute("mydsl-load "..filename) end end) fltk:Fl_End()
tab2=fltk:Fl_Group(0,0,ww,wh-bh-5,"search text") search_text=fltk:Fl_Input(bh*3+5,5,ww-10-bh*3,bh,"search text ") search_text:when(fltk.FL_WHEN_ENTER_KEY) search_text:callback(do_search)
results=fltk:Fl_Hold_Browser(5,5+bh,ww-10,wh-(15+bh*2)) results:column_widths({results:w()/2,150,0}) results:callback( function() if results:value() > 1 and Fl:event()==fltk.FL_RELEASE then pick_search_result() end end) results_cb=fltk:Fl_Return_Button(ww,wh,bh,bh) results_cb:callback(pick_search_result) fltk:Fl_End() fltk:Fl_End()
tabbuttons=fltk:Fl_Pack(5,wh-bh,200,bh-5) tabbuttons:type(fltk.FL_HORIZONTAL) tabbuttons:spacing(5) tab_browse=fltk:Fl_Radio_Button(0,0,100,bh-5,"&browse") tab_browse:when(fltk.FL_WHEN_CHANGED) tab_browse:box(fltk.FL_BORDER_BOX); tab_browse:selection_color(7) tab_browse:callback(function() tabs:value(tab1) end) tab_search=fltk:Fl_Radio_Button(0,0,100,bh-5,"text &search") tab_search:when(fltk.FL_WHEN_CHANGED) tab_search:box(fltk.FL_BORDER_BOX); tab_search:selection_color(7) tab_search:callback(function() tabs:value(tab2); Fl:focus(search_text) end) fltk:Fl_End() last_update=fltk:Fl_Box(ww-5,wh-bh-5,5,bh+5) last_update:align(fltk.FL_ALIGN_LEFT) last_update:labelsize(12)
win:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tabs:resizable(tab3) tab1:resizable(tiles) tab2:resizable(results) win:show()
find_file=io.open(listfile) if find_file then data=find_file:read("*a") else data="" end if string.find(data,"%w") then find_file:close(); fill_list() else ask4db=fltk.fl_choice("You have no database for online MyDSL apps.\nDo you want to download it now?","No","Yes",NULL) if ask4db==1 then Fl:check(); updatedb() else install:deactivate(); tab_search:deactivate(); tab_browse:deactivate() info_display_buffer:text("\nThere is no MyDSL database installed.\nClick \"Update Database\" \(Alt+U\) to download it.") end end Fl:run()
|
Posted by roberts on April 22 2008,03:55
Thanks. I am including it in final 4.3 image. You just made the cutoff.
Posted by mikshaw on April 22 2008,12:47
=o)
Posted by Juanito on April 24 2008,17:40
Should this work in dsl-3.4.11? I just tried and got:Code Sample | $ /opt/mydsl_browser.lua /bin/murgaLua: /opt/mydsl_browser.lua:246: attempt to call method 'column_widths' (a nil value) stack traceback: /opt/mydsl_browser.lua:246: in main chunk [C]: ? |
Posted by roberts on April 24 2008,18:28
Several releases of murgaLua have transpired since v.3.4.11. With each release of murgaLua new features have become available. Likely you can grab the murgaLua binary from 4.3 to try in 3.4.11.
Posted by Juanito on April 24 2008,18:40
That worked fine - thanks
Posted by mikshaw on April 24 2008,23:51
column_widths was added to murgaLua with version 0.6.4 It provided a much needed way to split a browser into clean columns.
In previous versions of the mydsl browser I had a check for this feature before using it, but since it was added to DSL the check was removed to reduce the file size.
Posted by mikshaw on April 30 2008,16:06
The following version is for testing purposes only, and should not be considered stable.
Changes include adding columns for application version and package size in the search results, some tweaks to prevent crashes if the database somehow gets corrupted to the point where one or more records cannot be found, and a button to download a package without installing it. Also removed the mydsl_dir string from certain places where it is no longer needed now that lfs.chdir is being used.
The download does not yet acquire the md5 and info files. The Busybox version of wget does not support multiple files or a file list, and I haven't decided the best course of action to retrieve all three files. Is it possible to run a string of commands with "aterm -e"? Also still need to add a check for a successful download or installation.
Question: Is the file list being mirrored, and if so can that URL be changed to use the user's chosen mirror? Maybe the fact that it is updated often would mean it's best to stick with < ftp://ibiblio.org >
Code Sample | #!/bin/murgaLua -- MyDSL Browser, 2008 mikshaw
-- TODO: check for /opt/mydsl.installed/* or for downloaded file
dofile("/etc/init.d/functions5.lua")
mydsldirfile=io.open("/opt/.mydsl_dir") if not mydsldirfile then fltk.fl_alert("Can't open /opt/.mydsl_dir") os.exit(1) end mydsl_dir=mydsldirfile:read("*l") mydsldirfile:close() if not lfs.chdir(mydsl_dir) then fltk.fl_alert("Could not enter directory\n"..mydsl_dir) os.exit(2) end listfile="mydslinfo.bz2" listurl="ftp://ibiblio.org/pub/Linux/distributions/damnsmall/mydsl/mydslinfo.bz2" list_sep="@b@B49@u" terminal="aterm +tr -bg white -fg black -geometry 80x6" mirror=getOption("/opt/.dslrc","Protocol").."://"..getOption("/opt/.dslrc","Mirror").."/mydsl/"
function toggle(b) local count,state,one,two=1 local me,label=b:value(),b:text(b:value()) if string.find(label,"%+%s*") then state,one,two="expanded","%+ ","%- " else state,one,two="collapsed","%- ","%+ " end b:text(me,string.gsub(label,one,two)) while b:text(me+count) and not string.match(b:text(me+count),list_sep) do if state=="collapsed" then b:hide(me+count) else b:show(me+count) end count=count+1 end end
function fill_list() inputfile = io.popen("bunzip2 -c "..listfile) data=inputfile:read("*a") inputfile:close() if not string.find(data,"%w") then info_display_buffer:text("Cannot read database "..listfile.."\nPlease try updating again.") else filelist:clear() header={} info={} info_count=0 local current_loc="" local headers=0 locount=0 for s in string.gmatch(data,"(Location:.-\n)\n") do local datestring=string.match(s,"Current:%s*(.-%d)%s") if not datestring then datestring="-" elseif string.find(datestring,"%d%d%D%d%d%D%d%d%d%d") then datestring=string.gsub(datestring,"(%d%d)%D(%d%d)%D(%d%d%d%d)","%3/%1/%2") end local location=string.match(s,"Location:%s*(.-)%s*\n") local title=string.match(s,"Title:%s*(.-)%s*\n") local filesize=string.match(s,"Filesize:%s*(.-)%s") local date=string.gsub(datestring,"%D","/") local version=string.match(s,"Version:%s*(.-)%s*\n") local text=s info_count=info_count+1 info[info_count]={ location=location or "-", title=title or "-", filesize=filesize or "-", date=date or "-", version=version or "-", text=text or "-" } if current_loc ~= info[info_count].location then current_loc=info[info_count].location filelist:add(list_sep.."- "..current_loc) headers=headers+1 header[headers]=filelist:size() end filelist:add(info[info_count].title) end for i,v in ipairs(header) do filelist:value(header[i]); toggle(filelist) end last_update:label("Database updated ".. os.date("%d %b %Y",lfs.attributes(listfile).modification).. ", "..info_count.." packages") end filelist:value(1) tab_browse:setonly() end
function updatedb() tempfile=os.tmpname() os.execute(terminal.." -title \"Database Update\" -e wget "..listurl.." -O "..tempfile) if os.execute("bzip2 -t "..tempfile) == 0 then os.execute("mv "..tempfile.." "..listfile) install:activate() tab_search:activate() tab_browse:activate() info_display_buffer:text("\nDatabase updated successfully.") fill_list() else fltk.fl_alert("Database check failed.\nThis may be the result of an incomplete download\nor gremlins in your internets.") os.remove(tempfile) end filelist:take_focus() end
function do_search() if search_text:value() ~= "" and info_count and info_count>0 then results:clear() results:add("@B49@b@uPackage Name\t@B49@b@uLocation\t@B49@b@uFile Size\t@B49@b@uRelease Date\t@B49@b@uVersion") for i=1,info_count do if string.find(string.lower(info[i].text),string.lower(search_text:value()),1,1) then results:add(info[i].title.."\t"..info[i].location.."\t"..info[i].filesize.."\t"..info[i].date.."\t"..info[i].version) end end results:insert(1,"@B49@."..tostring(results:size()-1).." search results") end end
function pick_search_result() if results:value() > 2 then get_loc=string.match(results:text(results:value()),"\t(.-)\t") get_fname=string.match(results:text(results:value()),"(.-)\t") local myloc=1 while myloc<=filelist:size() do if not string.find(filelist:text(myloc)," "..get_loc,1,1) then myloc=myloc+1 else filelist:value(myloc) break end end if string.find(filelist:text(myloc),list_sep.."+ ",1,1) then toggle(filelist) end while myloc<=filelist:size() do if filelist:text(myloc) ~= get_fname then myloc=myloc+1 else filelist:value(myloc) break end end for i=1,info_count do if info[i].title == get_fname and info[i].location == get_loc then info_display_buffer:text(info[i].text) tab_browse:setonly() myfile=info[i] break end end tabs:value(tab1) end end
function list_cb() if filelist:value()>0 then if Fl:event() == fltk.FL_RELEASE or Fl:event_key()==fltk.FL_Enter then if string.find(filelist:text(filelist:value()),list_sep) then toggle(filelist) else local myloc=filelist:value() while myloc > 0 do myloc=myloc-1 if string.find(filelist:text(myloc),list_sep) then myloc=string.gsub(filelist:text(myloc),".-%s%s","") break end end for i=1,info_count do if info[i].title == filelist:text(filelist:value()) and info[i].location == myloc then info_display_buffer:text(info[i].text) myfile=info[i] tab_browse:setonly() break end end end end end end
function toggle_list() if listw > 0 then oldw=listw tiles:position(listw+5,nil,6,nil) listw=0 info_display:take_focus() else tiles:position(6,nil,oldw+5,nil) listw=oldw filelist:take_focus() end end
function instpkg() if myfile then mydslload=os.execute("mydsl-load "..myfile.title.." "..myfile.location) -- if mydslload~=0 then fltk.fl_alert(myfile.title..":\nDownload or Checksum error!") end end filelist:take_focus() end
function instlocal() local filename=fltk.fl_file_chooser("Browse for a MyDSL file","Mydsl files (*.{dsl,tar.gz,uci,unc})",nil,nil) if filename then os.execute("mydsl-load "..filename) end end
function dlonly() if myfile then local dirname=fltk.fl_dir_chooser("Save to...",nil,nil) if dirname and fltk.fl_filename_isdir(dirname)~=0 then Fl:check() os.execute(terminal.." -title \"Downloading "..myfile.title.."\" -e wget ".. mirror..myfile.location.."/"..myfile.title.." -P "..dirname) else print("no") end end end
ww=570; wh=380; bh=30; bw=(ww-10)/4 win=fltk:Fl_Window(ww,wh,"MyDSL Browser")
tabs=fltk:Fl_Wizard(0,0,ww,wh-bh-5) tab1=fltk:Fl_Group(0,0,ww,wh-bh-5,"browse")
tiles=fltk:Fl_Tile(5,5+bh,ww-10,wh-(15+bh*2)) filelist=fltk:Fl_Hold_Browser(5,5+bh,1,wh-(15+bh*2)) filelist:callback(list_cb)
info_display=fltk:Fl_Text_Display(6,5+bh,ww-11,wh-(15+bh*2)) info_display:textfont(fltk.FL_SCREEN) info_display:textsize(12) info_display_buffer=fltk:Fl_Text_Buffer() info_display:buffer(info_display_buffer) fltk:Fl_End()
tiles:position(6,nil,ww/3,nil) tiles:callback(function() listw=filelist:w() end) listw=filelist:w()
prevheader=fltk:Fl_Button(ww,wh,bh,bh,"&[") prevheader:callback( function() for i=table.getn(header),1,-1 do if header[i] < filelist:value() then filelist:value(header[i]); break end end filelist:take_focus() end) nextheader=fltk:Fl_Button(ww,wh,bh,bh,"&]") nextheader:callback( function() for i=1,table.getn(header) do if header[i] > filelist:value() then filelist:value(header[i]); break end end filelist:take_focus() end) enter=fltk:Fl_Return_Button(ww,wh,10,10) enter:callback(function() filelist:do_callback() end) togglist=fltk:Fl_Button(ww,wh,10,10,"&t") togglist:callback(toggle_list)
b_updatedb=fltk:Fl_Button(5,5,bw,bh,"&Update Database") b_updatedb:callback(updatedb) install=fltk:Fl_Button(bw+5,5,bw,bh,"&Install Selected") install:callback(instpkg) download=fltk:Fl_Button(bw*2+5,5,bw,bh,"&Download only") download:callback(dlonly) install_local=fltk:Fl_Button(bw*3+5,5,bw,bh,"Install &Local @DnArrow") install_local:callback(instlocal) fltk:Fl_End()
tab2=fltk:Fl_Group(0,0,ww,wh-bh-5,"search text") search_text=fltk:Fl_Input(bh*3+5,5,ww-10-bh*3,bh,"search text ") search_text:when(fltk.FL_WHEN_ENTER_KEY) search_text:callback(do_search)
results=fltk:Fl_Hold_Browser(5,5+bh,ww-10,wh-(15+bh*2)) results:column_widths({results:w()/2,120,120,120,0}) results:callback( function() if results:value() > 1 and Fl:event()==fltk.FL_RELEASE then pick_search_result() end end) results_cb=fltk:Fl_Return_Button(ww,wh,bh,bh) results_cb:callback(pick_search_result) fltk:Fl_End() fltk:Fl_End()
tabbuttons=fltk:Fl_Pack(5,wh-bh,200,bh-5) tabbuttons:type(fltk.FL_HORIZONTAL) tabbuttons:spacing(5) tab_browse=fltk:Fl_Radio_Button(0,0,100,bh-5,"&browse") tab_browse:when(fltk.FL_WHEN_CHANGED) tab_browse:box(fltk.FL_BORDER_BOX); tab_browse:selection_color(7) tab_browse:callback(function() tabs:value(tab1) end) tab_search=fltk:Fl_Radio_Button(0,0,100,bh-5,"text &search") tab_search:when(fltk.FL_WHEN_CHANGED) tab_search:box(fltk.FL_BORDER_BOX); tab_search:selection_color(7) tab_search:callback(function() tabs:value(tab2); Fl:focus(search_text) end) fltk:Fl_End() last_update=fltk:Fl_Box(ww-5,wh-bh-5,5,bh+5) last_update:align(fltk.FL_ALIGN_LEFT) last_update:labelsize(12)
win:resizable(tabs) tabs:resizable(tab1) tabs:resizable(tab2) tabs:resizable(tab3) tab1:resizable(tiles) tab2:resizable(results) win:show()
find_file=io.open(listfile) if find_file then data=find_file:read("*a") else data="" end if string.find(data,"%w") then find_file:close(); fill_list() else ask4db=fltk.fl_choice("You have no database for online MyDSL apps.\nDo you want to download it now?","No","Yes",NULL) if ask4db==1 then Fl:check(); updatedb() else install:deactivate(); tab_search:deactivate(); tab_browse:deactivate() info_display_buffer:text("\nThere is no MyDSL database installed.\nClick \"Update Database\" \(Alt+U\) to download it.") end end Fl:run()
|
Posted by lucky13 on April 30 2008,16:47
It executes one command. You can always run aterm -e somescript
where somescript contains the commands you want executed.
Posted by ^thehatsrule^ on April 30 2008,17:36
You could always pass them to the shell to execute, i.e. aterm -e sh -c "echo 1 && echo 2; echo $? > retval.txt; read"
I don't think you can use the return code from os.execute since it would get it from aterm - not the commands you specified. It's not elegant, but it's an alternative that I think would work for now :P
afaik most(all?) of the mirrors do regular rsync updates to ibiblio... so it should be OK.
Posted by mikshaw on April 30 2008,17:52
Quote | You can always run aterm -e somescript | I was thinking about that, although I need to decide the best way to create the script (probably use the existing tempfile). I don't really want it to be a separate script file.
Quote | You could always pass them to the shell to execute, i.e. aterm -e sh -c "echo 1 && echo 2; echo $? > retval.txt; read" | That looks like a variation of writing to a temp file from lua and then executing the temp file...except using sh instead of lua. Is that right?
Quote | I don't think you can use the return code from os.execute since it would get it from aterm - not the commands you specified. | Yeah, I ran into that issue when trying to get the return value from mydsl-load, which was causing an error dialog even on success. I plan to do checks on the files themselves, after the os.execute has run, in order to give the user a visual clue of the success of the download/installation. I just haven't bothered with it yet.
Quote | afaik most(all?) of the mirrors do regular rsync updates to ibiblio... so it should be OK. | I was hoping that would be the case. Since the script now uses /opt/.dslrc for the "download only" fuction, it might make sense to use that mirror for the database as well.
Thanks for the input guys. It's always appreciated, and usually helpful.
Posted by ^thehatsrule^ on April 30 2008,18:20
Quote | That looks like a variation of writing to a temp file from lua and then executing the temp file...except using sh instead of lua. Is that right? | Not quite... it does something like 1. run the first command "echo 1" 2. if the last command was successful, run the 2nd command "echo 2" 3. save the return code from the previous statement "echo 1 && echo 2" to a file called retval.txt 4. "read" does nothing - it's just to keep the window open
Quote | Yeah, I ran into that issue when trying to get the return value from mydsl-load, which was causing an error dialog even on success. I plan to do checks on the files themselves, after the os.execute has run, in order to give the user a visual clue of the success of the download/installation. I just haven't bothered with it yet. | Did you try changing the DISPLAY variable like what I suggested in the other post? [ah, not yet] Just tested it and it seems to work under 3.x.
Posted by mikshaw on May 01 2008,03:12
I don't see why you'd want to unset the DISPLAY variable. The error dialog that mydsl-load provides is a desired behavior. The error dialog I was getting was one that was part of this script. It was not working properly, however, because of the issue you mentioned...applications running in an X terminal do not return to the shell that started the terminal.
Your idea of redirecting the output of the last command is a good one, but I'm not sure if it will work in this case. It might at least require unsetting the DISPLAY variable in order to prevent a second terminal, meaning I'd still need to have my own error dialog, which is the exact thing I'm looking to prevent. Since that function is already in place in DSL, I'd prefer to use it rather than mimic it. I'll have to run some tests. Any way I look at it, though, it seems like there will be some redundancy...either in presenting the dialog or doing the md5sum test myself.
Although, with the read command + unsetting DISPLAY, the user will be presented with the success or failure message in that term, without the need for a FLTK message or md5sum check. Interesting idea....I wish I hadn't typed all that out before realizing what you were getting at....
Posted by Juanito on May 01 2008,15:01
'tried your latest version in dsl-3.4.11 using murgaLua from dsl-4.3 - works fine for me.
I like the option to download without loading
Posted by mikshaw on May 02 2008,13:28
^thehatsrule^: That's brilliant! It took a few tries to get the syntax right, but it works using unset DISPLAY and sh -c
If you weren't so ugly I'd give you a hug =o)
Code Sample | function dlonly() if myfile then local dirname=fltk.fl_dir_chooser("Save to...",nil,nil) if dirname and fltk.fl_filename_isdir(dirname)~=0 then Fl:check() os.execute(terminal..[[ -title "Downloading ]].. myfile.title..[[" -e sh -c "unset DISPLAY && cd ]]..dirname.. [[ && wget ]]..mirror..myfile.location..[[/]]..myfile.title.. [[{.info,.md5.txt,}]]..[[ && md5sum -c ]]..myfile.title.. [[.md5.txt && echo Press \"Enter\" to continue && read"]]) end end end
|
Still need to test some more, and probably reconsider using && for every command (want to keep the term open regardless of failure)
|