Programming and Scripting :: MyDSL info parser



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

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

Ah, you did both, grey out and popup.
Nice job!
Will put in RC2.

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.

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.
Next Page...
original here.