modes.lua

changeset 0
98e4b0c9fcac
child 1
4d7540af8518
equal deleted inserted replaced
-1:000000000000 0:98e4b0c9fcac
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("normal", {
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("insert", {
73 enter = function (w)
74 local i, p = w.ibar.input, w.ibar.prompt
75 i:hide()
76 i.text = ""
77 p.text = "-- INSERT --"
78 p:show()
79 end,
80 })
81
82 -- Setup command mode
83 new_mode("command", {
84 enter = function (w)
85 local i, p = w.ibar.input, w.ibar.prompt
86 p:hide()
87 i.text = ":"
88 i:show()
89 i:focus()
90 i:set_position(-1)
91 end,
92 changed = function (w, text)
93 -- Auto-exit command mode if user backspaces ":" in the input bar.
94 if not string.match(text, "^:") then w:set_mode() end
95 end,
96 activate = function (w, text)
97 w:cmd_hist_add(text)
98 w:match_cmd(string.sub(text, 2))
99 w:set_mode()
100 end,
101 })
102
103 -- Setup search mode
104 new_mode("search", {
105 enter = function (w)
106 -- Clear old search state
107 w.search_state = {}
108 local i, p = w.ibar.input, w.ibar.prompt
109 p:hide()
110 p.text = ""
111 i.text = "/"
112 i:show()
113 end,
114 leave = function (w)
115 -- Check if search was aborted and return to original position
116 local s = w.search_state
117 if s.marker then
118 w:get_current():set_scroll_vert(s.marker)
119 s.marker = nil
120 end
121 end,
122 changed = function (w, text)
123 -- Check that the first character is '/' or '?' and update search
124 if string.match(text, "^[\?\/]") then
125 w:search(string.sub(text, 2), (string.sub(text, 1, 1) == "/"))
126 else
127 w:clear_search()
128 w:set_mode()
129 end
130 end,
131 activate = function (w, text)
132 w.search_state.marker = nil
133 w:srch_hist_add(text)
134 w:set_mode()
135 -- Ghost the search term in the prompt
136 local p = w.ibar.prompt
137 p.text = lousy.util.escape(text)
138 p:show()
139 end,
140 })
141
142 -- Setup follow mode
143 new_mode("follow", {
144 enter = function (w)
145 local i, p = w.ibar.input, w.ibar.prompt
146 w:eval_js_from_file(lousy.util.find_data("scripts/follow.js"))
147 w:eval_js("clear(); show_hints();")
148 p.text = "Follow:"
149 p:show()
150 i.text = ""
151 i:show()
152 i:focus()
153 i:set_position(-1)
154 end,
155 leave = function (w)
156 if w.eval_js then w:eval_js("clear();") end
157 end,
158 changed = function (w, text)
159 local ret = w:eval_js(string.format("update(%q);", text))
160 w:emit_form_root_active_signal(ret)
161 end,
162 })

mercurial