-- Bookmark system for Links-Lua.
-- $Id: bm.lua,v 1.7 2005/03/27 22:59:41 miciah Exp $
-----------------------------------------------------------------------
-- User options
---------------------------------------------------------------------
-- Default location to save and load bookmarks from.
bm_bookmark_file = elinks_home.."/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 = string.gsub (str, bm_marker..'/%d+$', '')
return n ~= 0
end
function bm_is_bookmark (str)
local _,n = string.gsub (str, bm_marker..'/%d+,%d+/', '')
return n ~= 0
end
function bm_decode_info (str)
if bm_is_category (str) then
str = string.gsub (str, '.-/(%d+)', 'return %1')
else
str = string.gsub (str, '.-/(%d+),(%d+)/(.*)', 'return %1,%2,"%3"')
end
return dostring (str)
end
function bm_find_category (cat)
for i = 1, table.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
table.sort (bm_bookmarks, function (a, b) return a.category < b.category end)
foreachi (bm_bookmarks,
function (i, v)
table.sort (v, function (a, b) return a.name < b. name end)
end)
end
function bm_generate_html ()
local s = '
Bookmarks'
..'\n'
for i = 1, table.getn (bm_bookmarks) do
local table = bm_bookmarks[i]
s = s..'\n\n'
for j = 1, table.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..'
'..os.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 string.gsub (str, "([^-%w \t_@#:/'().])",
function (s)
return string.format ("\\%03d", string.byte (s))
end)
end
if not filename then filename = bm_bookmark_file end
local tab = ' '
writeto (filename)
write ('return {\n')
for i = 1, table.getn (bm_bookmarks) do
local table = bm_bookmarks[i]
write (tab..'{\n'..tab..tab..'category = "'
..esc (table.category)..'";\n')
for i = 1, table.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 ()
table.insert (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 }
table.insert (bm_bookmarks, table)
end
table.insert (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, table.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
table.remove (bm_bookmarks, i)
else
table.remove (bm_bookmarks[i], j)
if table.getn (bm_bookmarks[i]) == 0 then table.remove (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 <= table.getn (t) and j <= table.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
function bookmarks_follow_url_hook (url)
if bm_is_category (url) then
return nil,true
else
url = bm_get_bookmark_url (url)
if url then return url,true end
end
return url,nil
end
table.insert(follow_url_hooks, bookmarks_follow_url_hook)
function bookmarks_quit_hook ()
bm_save_bookmarks ()
end
table.insert(quit_hooks, bookmarks_quit_hook)
-- Be careful not to load bookmarks if this script is being
-- reloaded while in ELinks, or we will lose unsaved changes.
if not bm_bookmarks or table.getn (bm_bookmarks) == 0 then
bm_load_bookmarks ()
end
-- My bookmark key bindings.
-- bind_key ('main', 'a', bm_add_bookmark)
-- bind_key ('main', 's', bm_view_bookmarks)
-- bind_key ('main', 'Alt-e', bm_edit_bookmark)
-- bind_key ('main', 'Alt-d', bm_delete_bookmark)
-- bind_key ('main', 'Alt-k', bm_move_bookmark_up)
-- bind_key ('main', 'Alt-j', bm_move_bookmark_down)
-- vim: shiftwidth=4 softtabstop=4