File: bookmarks.lua

package info (click to toggle)
luakit 2012.09.13-r1-8
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 1,160 kB
  • ctags: 1,276
  • sloc: ansic: 6,086; makefile: 153; ruby: 79; sh: 38
file content (137 lines) | stat: -rw-r--r-- 3,684 bytes parent folder | download
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
-----------------------------------------------------------
-- Simple sqlite3 bookmarks                              --
-- © 2010-2012 Mason Larobina <mason.larobina@gmail.com> --
-----------------------------------------------------------

local lousy = require "lousy"
local string = string
local table = table
local type = type
local assert = assert
local ipairs = ipairs
local os = os
local error = error
local capi = { luakit = luakit, sqlite3 = sqlite3 }
local keys = lousy.util.table.keys

module("bookmarks")

lousy.signal.setup(_M, true)

-- Path to users bookmarks database
db_path = capi.luakit.data_dir .. "/bookmarks.db"

function init()
    db = capi.sqlite3{ filename = _M.db_path }
    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

capi.luakit.idle_add(init)

-- Validate tag name
local function valid_tag_name(name)
    return not not string.match(name, "^%w[%w-]*$")
end

function get(id)
    assert(type(id) == "number", "invalid bookmark id (number expected)")
    local rows = db:exec([[ SELECT * FROM bookmarks WHERE id = ? ]], { id })
    return rows[1]
end

function remove(id)
    assert(type(id) == "number", "invalid bookmark id (number expected)")

    _M.emit_signal("remove", id)

    db:exec([[ DELETE FROM bookmarks WHERE id = ? ]], { id })
end

local function parse_tags(tags)
    local ret = {}
    local remains = string.gsub(tags, "%w[%w-]*",
        function (tag) ret[tag] = true return "" end)
    return ret, remains
end

local function update_tags(b, tags)
    table.sort(tags)
    tags = table.concat(tags, " ")
    db:exec([[ UPDATE bookmarks SET tags = ?, modified = ? WHERE id = ? ]],
        { tags, os.time(), b.id })
    _M.emit_signal("update", id)
end

function tag(id, new_tags, replace)
    local b = assert(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

function untag(id, name)
    local b = assert(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 new bookmark
function 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

    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 = db:exec("SELECT last_insert_rowid() AS id")[1].id
    _M.emit_signal("add", id)

    -- Add bookmark tags
    if opts.tags then tag(id, opts.tags) end

    return id
end

-- vim: et:sw=4:ts=8:sts=4:tw=80