File: modes.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 (163 lines) | stat: -rw-r--r-- 5,034 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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
-------------------------------
-- luakit mode configuration --
-------------------------------

-- Table of modes and their callback hooks
local modes = {}
local lousy = require "lousy"
local join = lousy.util.table.join
local order = 0

-- Add new mode table (optionally merges with original mode)
function new_mode(name, desc, mode, replace)
    assert(string.match(name, "^[%w-_]+$"), "invalid mode name: " .. name)
    -- Detect optional description
    if type(desc) == "table" then
        desc, mode, replace = nil, desc, mode
    end
    local traceback = debug.traceback("Creation traceback:", 2)
    order = order + 1
    modes[name] = join({ order = order, traceback = traceback },
        (not replace and modes[name]) or {}, mode or {},
        { name = name, desc = desc })
end

-- Get mode table
function get_mode(name) return modes[name] end

function get_modes() return lousy.util.table.clone(modes) end

-- Attach window & input bar signals for mode hooks
window.init_funcs.modes_setup = function (w)
    -- Calls the `enter` and `leave` mode hooks.
    w:add_signal("mode-changed", function (_, name, ...)
        local leave = (w.mode or {}).leave

        -- Get new modes functions/hooks/data
        local mode = assert(modes[name], "invalid mode: " .. name)

        -- Call last modes leave hook.
        if leave then leave(w) end

        -- Create w.mode object
        w.mode = mode

        -- Update window binds
        w:update_binds(name)

        -- Call new modes enter hook.
        if mode.enter then mode.enter(w, ...) end

        w:emit_signal("mode-entered", mode)
    end)

    local input = w.ibar.input

    -- Calls the changed hook on input widget changed.
    input:add_signal("changed", function ()
        local changed = w.mode.changed
        if changed then changed(w, input.text) end
    end)

    input:add_signal("property::position", function ()
        local move_cursor = w.mode.move_cursor
        if move_cursor then move_cursor(w, input.position) end
    end)

    -- Calls the `activate` hook on input widget activate.
    input:add_signal("activate", function ()
        local mode = w.mode
        if mode and mode.activate then
            local text, hist = input.text, mode.history
            if mode.activate(w, text) == false then return end
            -- Check if last history item is identical
            if hist and hist.items and hist.items[hist.len or -1] ~= text then
                table.insert(hist.items, text)
            end
        end
    end)
end

-- Add mode related window methods
window.methods.set_mode = lousy.mode.set
local mget = lousy.mode.get
window.methods.is_mode = function (w, name) return name == mget(w) end

-- Setup normal mode
new_mode("normal", [[When luakit first starts you will find yourself in this
    mode.]], {
    enter = function (w)
        w:set_prompt()
        w:set_input()
    end,
})

new_mode("all", [[Special meta-mode in which the bindings for this mode are
    present in all modes.]])

-- Setup insert mode
new_mode("insert", [[When clicking on form fields luakit will enter the insert
    mode which allows you to enter text in form fields without accidentally
    triggering normal mode bindings.]], {
    enter = function (w)
        w:set_prompt("-- INSERT --")
        w:set_input()
        w.view:focus()
    end,
    -- Send key events to webview
    passthrough = true,
})

new_mode("passthrough", [[Luakit will pass every key event to the WebView
    until the user presses Escape.]], {
    enter = function (w)
        w:set_prompt("-- PASS THROUGH --")
        w:set_input()
    end,
    -- Send key events to webview
    passthrough = true,
    -- Don't exit mode when clicking outside of form fields
    reset_on_focus = false,
    -- Don't exit mode on navigation
    reset_on_navigation = false,
})

-- Setup command mode
new_mode("command", [[Enter commands.]], {
    enter = function (w)
        w:set_prompt()
        w:set_input(":")
    end,
    changed = function (w, text)
        -- Auto-exit command mode if user backspaces ":" in the input bar.
        if not string.match(text, "^:") then w:set_mode() end
    end,
    activate = function (w, text)
        w:set_mode()
        local cmd = string.sub(text, 2)
        if not string.find(cmd, "%S") then return end

        local success, match = xpcall(
            function () return w:match_cmd(cmd) end,
            function (err) w:error(debug.traceback(err, 3)) end)

        if success and not match then
            w:error(string.format("Not a browser command: %q", cmd))
        end
    end,
    history = {maxlen = 50},
})

new_mode("lua", [[Execute arbitrary Lua commands within the luakit
    environment.]], {
    enter = function (w)
        w:set_prompt(">")
        w:set_input("")
    end,
    activate = function (w, text)
        w:set_input("")
        local ret = assert(loadstring("return function(w) return "..text.." end"))()(w)
        if ret then print(ret) end
    end,
    history = {maxlen = 50},
})