Programming and Scripting :: MyDSL info parser



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]: ?

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.

That worked fine - thanks :)
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.

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

Next Page...
original here.