File: bookmarks.lua

package info (click to toggle)
luakit 1%3A2.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,844 kB
  • sloc: ansic: 12,519; makefile: 140; ruby: 79; sh: 48
file content (150 lines) | stat: -rw-r--r-- 4,475 bytes parent folder | download | duplicates (4)
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