modes.lua

1
-------------------------------
2
-- luakit mode configuration --
3
-------------------------------
4
 
5
-- Table of modes and their callback hooks
6
modes = {}
7
 
8
-- Currently active mode hooks
9
local current
10
 
11
-- Update a modes hook table with new hooks
12
function new_mode(mode, hooks)
13
    modes[mode] = lousy.util.table.join(modes[mode] or {}, hooks)
14
end
15
 
16
-- Attach window & input bar signals for mode hooks
17
window.init_funcs.modes_setup = function (w)
18
    -- Calls the `enter` and `leave` mode hooks.
19
    w.win:add_signal("mode-changed", function (_, mode)
20
        -- Call the last modes `leave` hook.
21
        if current and current.leave then
22
            current.leave(w)
23
        end
24
 
25
        -- Update window binds
26
        w:update_binds(mode)
27
 
28
        -- Get new modes functions
29
        current = modes[mode]
30
        if not current then
31
            error("changed to un-handled mode: " .. mode)
32
        end
33
 
34
        -- Call new modes `enter` hook.
35
        if current.enter then current.enter(w) end
36
    end)
37
 
38
    -- Calls the `changed` hook on input widget changed.
39
    w.ibar.input:add_signal("changed", function()
40
        local text = w.ibar.input.text
41
        if current and current.changed then
42
            current.changed(w, text)
43
        end
44
    end)
45
 
46
    -- Calls the `activate` hook on input widget activate.
47
    w.ibar.input:add_signal("activate", function()
48
        local text = w.ibar.input.text
49
        if current and current.activate then
50
            current.activate(w, text)
51
        end
52
    end)
53
end
54
 
55
-- Add mode related window methods
56
for name, func in pairs({
57
    set_mode = function (w, name) lousy.mode.set(w.win, name)  end,
58
    get_mode = function (w)       return lousy.mode.get(w.win) end,
59
    is_mode  = function (w, name) return name == w:get_mode()  end,
60
}) do window.methods[name] = func end
61
 
62
-- Setup normal mode
63
new_mode("key", {
64
    enter = function (w)
65
        local i, p = w.ibar.input, w.ibar.prompt
66
        i:hide()
67
        p:hide()
68
    end,
69
})
70
 
71
-- Setup insert mode
72
new_mode("normal", {
73
    enter = function (w)
74
        local i, p = w.ibar.input, w.ibar.prompt
75
        i:hide();
76
        i.text = ""
77
        p:hide();
78
        p.text = ""
79
    end,
80
})
81
 
82
new_mode("url-entry", {
83
	enter = function (w)
84
		local i, p = w.ibar.input, w.ibar.prompt;
85
		p.text = "Open:";
86
		p:show();
87
		i.text = (w:get_current() or {}).uri or "";
88
		i:show();
89
		i:focus();
90
		-- Requires patch to 2010.08.30:
91
		-- http://matthewwild.co.uk/code/luakit-select-region.patch
92
		i:select_region(0);
93
	end;
94
	activate = function (w, url)
95
		w:navigate(url);
96
		w:set_mode();
97
	end;
98
});
99
 
100
new_mode("web-search", {
101
	enter = function (w)
102
		local i, p = w.ibar.input, w.ibar.prompt;
103
		p.text = "Open:";
104
		p:show();
105
		i.text = (w:get_current() or {}).uri or "";
106
		i:show();
107
		i:focus();
108
		i:set_position(-1);
109
	end;
110
	activate = function (w, url)
111
		w:navigate(url);
112
		w:set_mode();
113
	end;
114
});
115
 
116
-- Setup command mode
117
new_mode("command", {
118
    enter = function (w)
119
        local i, p = w.ibar.input, w.ibar.prompt
120
        p:hide()
121
        i.text = ":"
122
        i:show()
123
        i:focus()
124
        i:set_position(-1)
125
    end,
126
    changed = function (w, text)
127
        -- Auto-exit command mode if user backspaces ":" in the input bar.
128
        if not string.match(text, "^:") then w:set_mode() end
129
    end,
130
    activate = function (w, text)
131
        w:cmd_hist_add(text)
132
        w:match_cmd(string.sub(text, 2))
133
        w:set_mode()
134
    end,
135
})
136
 
137
-- Setup search mode
138
new_mode("search", {
139
    enter = function (w)
140
        -- Clear old search state
141
        w.search_state = {}
142
        local i, p = w.ibar.input, w.ibar.prompt
143
        p:hide()
144
        p.text = ""
145
        i.text = "/"
146
        i:show()
147
    end,
148
    leave = function (w)
149
        -- Check if search was aborted and return to original position
150
        local s = w.search_state
151
        if s.marker then
152
            w:get_current():set_scroll_vert(s.marker)
153
            s.marker = nil
154
        end
155
    end,
156
    changed = function (w, text)
157
        -- Check that the first character is '/' or '?' and update search
158
        if string.match(text, "^[\?\/]") then
159
            w:search(string.sub(text, 2), (string.sub(text, 1, 1) == "/"))
160
        else
161
            w:clear_search()
162
            w:set_mode()
163
        end
164
    end,
165
    activate = function (w, text)
166
        w.search_state.marker = nil
167
        w:srch_hist_add(text)
168
        w:set_mode()
169
        -- Ghost the search term in the prompt
170
        local p = w.ibar.prompt
171
        p.text = lousy.util.escape(text)
172
        p:show()
173
    end,
174
})
175
 
176
-- Setup follow mode
177
new_mode("follow", {
178
    enter = function (w)
179
        local i, p = w.ibar.input, w.ibar.prompt
180
        w:eval_js_from_file(lousy.util.find_data("scripts/follow.js"))
181
        w:eval_js("clear(); show_hints();")
182
        p.text = "Follow:"
183
        p:show()
184
        i.text = ""
185
        i:show()
186
        i:focus()
187
        i:set_position(-1)
188
    end,
189
    leave = function (w)
190
        if w.eval_js then w:eval_js("clear();") end
191
    end,
192
    changed = function (w, text)
193
        local ret = w:eval_js(string.format("update(%q);", text))
194
        w:emit_form_root_active_signal(ret)
195
    end,
196
})