-- Bookmark system for Links-Lua.
-- $Id$
-----------------------------------------------------------------------
-- User options
---------------------------------------------------------------------
-- Default location to save and load bookmarks from.
bm_bookmark_file = home_dir.."/.links/bookmark.lst"
-- Set to non-`nil' to see URLs in the generated page.
bm_display_urls = nil
-- Set to non-`nil' to show links to category headers.
-- Only useful while sorting categories, otherwise just annoying.
bm_display_category_links = 1
-- Set to non-`nil' to automatically sort bookmarks alphabetically.
-- Do not set this if you care about the sorting of your bookmarks!
bm_auto_sort_bookmarks = nil
----------------------------------------------------------------------
-- Implementation
----------------------------------------------------------------------
-- We use a special syntax that looks like
-- user:bookmark/1 (for categories)
-- user:bookmark/1,2/http://some.phony.url/ (for bookmarks)
bm_marker = 'user:bookmark'
if not bm_bookmarks then
-- If the user reloads this script, we don't want to
-- lose all the bookmarks! :-)
bm_bookmarks = {}
end
function bm_is_category (str)
local _,n = gsub (str, bm_marker..'/%d+$', '')
return n ~= 0
end
function bm_is_bookmark (str)
local _,n = gsub (str, bm_marker..'/%d+,%d+/', '')
return n ~= 0
end
function bm_decode_info (str)
if bm_is_category (str) then
str = gsub (str, '.-/(%d+)', 'return %1')
else
str = gsub (str, '.-/(%d+),(%d+)/(.*)', 'return %1,%2,"%3"')
end
return dostring (str)
end
function bm_find_category (cat)
for i = 1, getn (bm_bookmarks) do
local table = bm_bookmarks[i]
if table.category == cat then return table end
end
end
function bm_sort_bookmarks ()
if not bm_auto_sort_bookmarks then return end
sort (bm_bookmarks, function (a, b) return a.category < b.category end)
foreachi (bm_bookmarks,
function (i, v)
sort (v, function (a, b) return a.name < b. name end)
end)
end
function bm_generate_html ()
local s = '
Bookmarks'
..'\n'
for i = 1, getn (bm_bookmarks) do
local table = bm_bookmarks[i]
s = s..'\n\n'
for j = 1, getn (table) do
local bm = table[j]
s = s..'- '..bm.name..'\n'
if bm_display_urls then s = s..'
'..bm.url..'\n' end
end
s = s..'
\n'
end
s = s..'
'..date ()..'\n'
return s..'\n'
end
-- Write bookmarks to disk.
function bm_save_bookmarks (filename)
if bm_dont_save then return end
function esc (str)
return gsub (str, "([^-%w \t_@#:/'().])",
function (s)
return format ("\\%03d", strbyte (s))
end)
end
if not filename then filename = bm_bookmark_file end
local tab = ' '
writeto (filename)
write ('return {\n')
for i = 1, getn (bm_bookmarks) do
local table = bm_bookmarks[i]
write (tab..'{\n'..tab..tab..'category = "'
..esc (table.category)..'";\n')
for i = 1, getn (table) do
local bm = table[i]
write (tab..tab..'{ name = "'..esc (bm.name)..'", url = "'
..esc (bm.url)..'" },\n')
end
write (tab..'},\n')
end
write ('}\n')
writeto ()
end
-- Load bookmarks from disk.
function bm_load_bookmarks (filename)
if not filename then filename = bm_bookmark_file end
local tmp = dofile (filename)
if type (tmp) == 'table' then
bm_bookmarks = tmp
bm_sort_bookmarks ()
bm_dont_save = nil
else
_ALERT ("Error loading "..filename)
bm_dont_save = 1
end
end
-- Return the URL of a bookmark.
function bm_get_bookmark_url (bm)
if bm_is_bookmark (bm) then
local _,_,url = bm_decode_info (bm)
return url
end
end
-- Bind this to a key to display bookmarks.
function bm_view_bookmarks ()
local tmp = tmpname()..'.html'
writeto (tmp)
write (bm_generate_html ())
writeto ()
tinsert (tmp_files, tmp)
return 'goto_url', tmp
end
function bm_do_add_bookmark (cat, name, url)
if cat == "" or name == "" or url == "" then
_ALERT ("Bad bookmark entry")
end
local table = bm_find_category (cat)
if not table then
table = { category = cat }
tinsert (bm_bookmarks, table)
end
tinsert (table, { name = name, url = url })
bm_sort_bookmarks ()
end
-- Bind this to a key to add a bookmark.
function bm_add_bookmark ()
edit_bookmark_dialog ('', current_title () or '', current_url () or '',
function (cat, name, url)
bm_do_add_bookmark (cat, name, url)
if current_title () == 'Bookmarks' then
return bm_view_bookmarks ()
end
end)
end
-- Bind this to a key to edit the currently highlighted bookmark.
function bm_edit_bookmark ()
local bm = current_link ()
if not bm then
elseif bm_is_category (bm) then
local i = bm_decode_info (bm)
edit_bookmark_dialog (bm_bookmarks[i].category, '', '',
function (cat)
if cat == '' then
_ALERT ('Bad input')
elseif bm_bookmarks[%i].category ~= cat then
local j = bm_find_category (cat)
if not j then
bm_bookmarks[%i].category = cat
else
local tmp = bm_bookmarks[%i]
for i = 1, getn (tmp) do
bm_do_add_bookmark (cat, tmp[i].name, tmp[i].url)
end
bm_delete_bookmark (%i)
end
return bm_view_bookmarks ()
end
end)
elseif bm_is_bookmark (bm) then
local i,j = bm_decode_info (bm)
local entry = bm_bookmarks[i][j]
edit_bookmark_dialog (bm_bookmarks[i].category,
entry.name, entry.url,
function (cat, name, url)
if cat == '' or name == '' or url == '' then
_ALERT ('Bad input')
else
if cat ~= bm_bookmarks[%i].category then
bm_do_delete_bookmark (%i, %j)
bm_do_add_bookmark (cat, name, url)
else
%entry.name = name
%entry.url = url
end
return bm_view_bookmarks ()
end
end)
end
end
function bm_do_delete_bookmark (i, j)
if not j then
tremove (bm_bookmarks, i)
else
tremove (bm_bookmarks[i], j)
if getn (bm_bookmarks[i]) == 0 then tremove (bm_bookmarks, i) end
end
end
-- Bind this to a key to delete the currently highlighted bookmark.
function bm_delete_bookmark ()
local bm = current_link ()
if bm and (bm_is_category (bm) or bm_is_bookmark (bm)) then
local i,j = bm_decode_info (bm)
bm_do_delete_bookmark (i, j)
return bm_view_bookmarks ()
end
end
function bm_do_move_bookmark (dir)
function tswap (t, i, j)
if i > 0 and j > 0 and i <= getn (t) and j <= getn (t) then
local x = t[i]; t[i] = t[j]; t[j] = x
return 1
end
end
local bm = current_link ()
if not bm then
elseif bm_is_category (bm) then
local i = bm_decode_info (bm)
if tswap (bm_bookmarks, i, i+dir) then
return bm_view_bookmarks ()
end
elseif bm_is_bookmark (bm) then
local i,j = bm_decode_info (bm)
if bm_bookmarks[i] and tswap (bm_bookmarks[i], j, j+dir) then
return bm_view_bookmarks ()
end
end
end
-- Bind this to a key to move the currently highlighted bookmark up.
function bm_move_bookmark_up ()
if not bm_auto_sort_bookmarks then return bm_do_move_bookmark (-1) end
end
-- Bind this to a key to move the currently highlighted bookmark down.
function bm_move_bookmark_down ()
if not bm_auto_sort_bookmarks then return bm_do_move_bookmark (1) end
end
-- vim: shiftwidth=4 softtabstop=4