1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
--- Simple sqlite3 bookmarks.
--
-- This module provides a Lua API for accessing and modifying bookmarks,
-- but does not provide a user interface. In order to add/remove bookmarks and
-- view all bookmarks in a single page, you'll need the `bookmarks_chrome`
-- module.
--
-- @module bookmarks
-- @author Mason Larobina <mason.larobina@gmail.com>
-- @copyright 2012 Mason Larobina <mason.larobina@gmail.com>
local lousy = require "lousy"
local keys = lousy.util.table.keys
local _M = {}
lousy.signal.setup(_M, true)
--- Path to bookmarks database.
-- @readwrite
_M.db_path = luakit.data_dir .. "/bookmarks.db"
--- Connect to and initialize the bookmarks database.
function _M.init()
_M.db = sqlite3{ filename = _M.db_path }
_M.db:exec [[
PRAGMA synchronous = OFF;
PRAGMA secure_delete = 1;
CREATE TABLE IF NOT EXISTS bookmarks (
id INTEGER PRIMARY KEY,
uri TEXT NOT NULL,
title TEXT NOT NULL,
desc TEXT NOT NULL,
tags TEXT NOT NULL,
created INTEGER,
modified INTEGER
);
]]
end
luakit.idle_add(_M.init)
--- Get a bookmark entry by its ID number.
-- @tparam number id The ID of the bookmark entry to get.
-- @treturn table The bookmark entry.
function _M.get(id)
assert(type(id) == "number", "invalid bookmark id (number expected)")
local rows = _M.db:exec([[ SELECT * FROM bookmarks WHERE id = ? ]], { id })
return rows[1]
end
--- Remove a bookmark entry by its ID number.
-- @tparam number id The ID of the bookmark entry to remove.
function _M.remove(id)
assert(type(id) == "number", "invalid bookmark id (number expected)")
_M.emit_signal("remove", id)
_M.db:exec([[ DELETE FROM bookmarks WHERE id = ? ]], { id })
end
local function parse_tags(tags)
local ret = {}
local remains = string.gsub(tags, "%S+",
function (tag) ret[tag] = true return "" end)
return ret, remains
end
local function update_tags(b, tags)
table.sort(tags)
tags = table.concat(tags, " ")
_M.db:exec([[ UPDATE bookmarks SET tags = ?, modified = ? WHERE id = ? ]],
{ tags, os.time(), b.id })
_M.emit_signal("update", b.id)
end
--- Update the tags on a bookmark entry.
-- @tparam number id The ID of the bookmark entry to update.
-- @tparam table|string new_tags The tags to add to the bookmark entry.
-- @tparam boolean replace `true` if the new tags should replace all existing
-- tags.
function _M.tag(id, new_tags, replace)
local b = assert(_M.get(id), "bookmark not found")
if type(new_tags) == "table" then
new_tags = table.concat(new_tags, " ")
end
local all_tags = string.format("%s %s", new_tags,
(not replace and b.tags) or "")
local tags, remains = parse_tags(all_tags)
if string.find(remains, "[^%s,]") then
error("invalid tags: " .. remains)
end
update_tags(b, keys(tags))
end
--- Remove a tag from a bookmark entry.
-- @tparam number id The ID of the bookmark entry to update.
-- @tparam string name The tag to remove from the bookmark entry.
function _M.untag(id, name)
local b = assert(_M.get(id), "bookmark not found")
if b.tags then
local tags = parse_tags(b.tags)
tags[name] = nil
update_tags(b, keys(tags))
end
end
--- Add a new bookmark entry.
-- @tparam string uri The URI to bookmark.
-- @tparam table opts A table of options.
-- @treturn number The ID of the new bookmark entry.
function _M.add(uri, opts)
opts = opts or {}
assert(type(uri) == "string" and #uri > 0, "invalid bookmark uri")
assert(opts.title == nil or type(opts.title) == "string",
"invalid bookmark title")
assert(opts.desc == nil or type(opts.desc) == "string",
"invalid bookmark description")
assert(opts.created == nil or type(opts.created) == "number",
"invalid creation time")
-- Default to http:// scheme if none provided
if not string.match(uri, "^%w+://") then
uri = "http://" .. uri
end
_M.db:exec("INSERT INTO bookmarks VALUES (NULL, ?, ?, ?, ?, ?, ?)", {
uri, opts.title or "", opts.desc or "", "", opts.created or os.time(),
os.time() -- modified time (now)
})
local id = _M.db:exec("SELECT last_insert_rowid() AS id")[1].id
_M.emit_signal("add", id)
-- Add bookmark tags
if opts.tags then _M.tag(id, opts.tags) end
return id
end
return _M
-- vim: et:sw=4:ts=8:sts=4:tw=80
|