|
1 ------------------ |
|
2 -- Window class -- |
|
3 ------------------ |
|
4 |
|
5 -- Window class table |
|
6 window = {} |
|
7 |
|
8 -- Widget construction aliases |
|
9 local function entry() return widget{type="entry"} end |
|
10 local function eventbox() return widget{type="eventbox"} end |
|
11 local function hbox() return widget{type="hbox"} end |
|
12 local function label() return widget{type="label"} end |
|
13 local function notebook() return widget{type="notebook"} end |
|
14 local function vbox() return widget{type="vbox"} end |
|
15 |
|
16 -- Build and pack window widgets |
|
17 function window.build() |
|
18 -- Create a table for widgets and state variables for a window |
|
19 local w = { |
|
20 win = widget{type="window"}, |
|
21 ebox = eventbox(), |
|
22 layout = vbox(), |
|
23 tabs = notebook(), |
|
24 -- Tab bar widgets |
|
25 tbar = { |
|
26 layout = hbox(), |
|
27 ebox = eventbox(), |
|
28 titles = { }, |
|
29 }, |
|
30 -- Status bar widgets |
|
31 sbar = { |
|
32 layout = hbox(), |
|
33 ebox = eventbox(), |
|
34 -- Left aligned widgets |
|
35 l = { |
|
36 layout = hbox(), |
|
37 ebox = eventbox(), |
|
38 uri = label(), |
|
39 loaded = label(), |
|
40 }, |
|
41 -- Fills space between the left and right aligned widgets |
|
42 sep = eventbox(), |
|
43 -- Right aligned widgets |
|
44 r = { |
|
45 layout = hbox(), |
|
46 ebox = eventbox(), |
|
47 buf = label(), |
|
48 ssl = label(), |
|
49 tabi = label(), |
|
50 scroll = label(), |
|
51 }, |
|
52 }, |
|
53 -- Input bar widgets |
|
54 ibar = { |
|
55 layout = hbox(), |
|
56 ebox = eventbox(), |
|
57 prompt = label(), |
|
58 input = entry(), |
|
59 }, |
|
60 } |
|
61 |
|
62 -- Assemble window |
|
63 w.ebox:set_child(w.layout) |
|
64 w.win:set_child(w.ebox) |
|
65 |
|
66 -- Pack tab bar |
|
67 local t = w.tbar |
|
68 t.ebox:set_child(t.layout, false, false, 0) |
|
69 w.layout:pack_start(t.ebox, false, false, 0) |
|
70 |
|
71 -- Pack notebook |
|
72 w.layout:pack_start(w.tabs, true, true, 0) |
|
73 |
|
74 -- Pack left-aligned statusbar elements |
|
75 local l = w.sbar.l |
|
76 l.layout:pack_start(l.uri, false, false, 0) |
|
77 l.layout:pack_start(l.loaded, false, false, 0) |
|
78 l.ebox:set_child(l.layout) |
|
79 |
|
80 -- Pack right-aligned statusbar elements |
|
81 local r = w.sbar.r |
|
82 r.layout:pack_start(r.buf, false, false, 0) |
|
83 r.layout:pack_start(r.ssl, false, false, 0) |
|
84 r.layout:pack_start(r.tabi, false, false, 0) |
|
85 r.layout:pack_start(r.scroll, false, false, 0) |
|
86 r.ebox:set_child(r.layout) |
|
87 |
|
88 -- Pack status bar elements |
|
89 local s = w.sbar |
|
90 s.layout:pack_start(l.ebox, false, false, 0) |
|
91 s.layout:pack_start(s.sep, true, true, 0) |
|
92 s.layout:pack_start(r.ebox, false, false, 0) |
|
93 s.ebox:set_child(s.layout) |
|
94 w.layout:pack_start(s.ebox, false, false, 0) |
|
95 |
|
96 -- Pack input bar |
|
97 local i = w.ibar |
|
98 i.layout:pack_start(i.prompt, false, false, 0) |
|
99 i.layout:pack_start(i.input, true, true, 0) |
|
100 i.ebox:set_child(i.layout) |
|
101 w.layout:pack_start(i.ebox, false, false, 0) |
|
102 |
|
103 -- Other settings |
|
104 i.input.show_frame = false |
|
105 w.tabs.show_tabs = false |
|
106 l.loaded:hide() |
|
107 l.uri.selectable = true |
|
108 r.ssl:hide() |
|
109 |
|
110 return w |
|
111 end |
|
112 |
|
113 -- Table of functions to call on window creation. Normally used to add signal |
|
114 -- handlers to the new windows widgets. |
|
115 window.init_funcs = { |
|
116 -- Attach notebook widget signals |
|
117 notebook_signals = function (w) |
|
118 w.tabs:add_signal("page-added", function (nbook, view, idx) |
|
119 w:update_tab_count(idx) |
|
120 w:update_tab_labels() |
|
121 end) |
|
122 w.tabs:add_signal("switch-page", function (nbook, view, idx) |
|
123 w:set_mode() |
|
124 w:update_tab_count(idx) |
|
125 w:update_win_title(view) |
|
126 w:update_uri(view) |
|
127 w:update_progress(view) |
|
128 w:update_tab_labels(idx) |
|
129 w:update_buf() |
|
130 w:update_ssl(view) |
|
131 end) |
|
132 end, |
|
133 |
|
134 last_win_check = function (w) |
|
135 w.win:add_signal("destroy", function () |
|
136 -- call the quit function if this was the last window left |
|
137 if #luakit.windows == 0 then luakit.quit() end |
|
138 end) |
|
139 end, |
|
140 |
|
141 key_press_match = function (w) |
|
142 w.win:add_signal("key-press", function (_, mods, key) |
|
143 -- Reset command line completion |
|
144 if w:get_mode() == "command" and key ~= "Tab" and w.compl_start then |
|
145 w:update_uri() |
|
146 w.compl_index = 0 |
|
147 end |
|
148 |
|
149 if w:hit(mods, key) then |
|
150 return true |
|
151 end |
|
152 end) |
|
153 end, |
|
154 |
|
155 apply_window_theme = function (w) |
|
156 local theme = lousy.theme.get() |
|
157 local s, i = w.sbar, w.ibar |
|
158 |
|
159 -- Set foregrounds |
|
160 for wi, v in pairs({ |
|
161 [s.l.uri] = theme.uri_sbar_fg, |
|
162 [s.l.loaded] = theme.loaded_sbar_fg, |
|
163 [s.r.buf] = theme.buf_sbar_fg, |
|
164 [s.r.tabi] = theme.tabi_sbar_fg, |
|
165 [s.r.scroll] = theme.scroll_sbar_fg, |
|
166 [i.prompt] = theme.prompt_ibar_fg, |
|
167 [i.input] = theme.input_ibar_fg, |
|
168 }) do wi.fg = v end |
|
169 |
|
170 -- Set backgrounds |
|
171 for wi, v in pairs({ |
|
172 [s.l.ebox] = theme.sbar_bg, |
|
173 [s.r.ebox] = theme.sbar_bg, |
|
174 [s.sep] = theme.sbar_bg, |
|
175 [s.ebox] = theme.sbar_bg, |
|
176 [i.ebox] = theme.ibar_bg, |
|
177 [i.input] = theme.input_ibar_bg, |
|
178 }) do wi.bg = v end |
|
179 |
|
180 -- Set fonts |
|
181 for wi, v in pairs({ |
|
182 [s.l.uri] = theme.uri_sbar_font, |
|
183 [s.l.loaded] = theme.loaded_sbar_font, |
|
184 [s.r.buf] = theme.buf_sbar_font, |
|
185 [s.r.ssl] = theme.ssl_sbar_font, |
|
186 [s.r.tabi] = theme.tabi_sbar_font, |
|
187 [s.r.scroll] = theme.scroll_sbar_font, |
|
188 [i.prompt] = theme.prompt_ibar_font, |
|
189 [i.input] = theme.input_ibar_font, |
|
190 }) do wi.font = v end |
|
191 end, |
|
192 } |
|
193 |
|
194 -- Helper functions which operate on the window widgets or structure. |
|
195 window.methods = { |
|
196 -- Return the widget in the currently active tab |
|
197 get_current = function (w) return w.tabs:atindex(w.tabs:current()) end, |
|
198 -- Check if given widget is the widget in the currently active tab |
|
199 is_current = function (w, wi) return w.tabs:indexof(wi) == w.tabs:current() end, |
|
200 |
|
201 get_tab_title = function (w, view) |
|
202 if not view then view = w:get_current() end |
|
203 return view:get_prop("title") or view.uri or "(Untitled)" |
|
204 end, |
|
205 |
|
206 new_tab = function (w, uri) |
|
207 local view = webview.new(w, uri) |
|
208 w.tabs:append(view) |
|
209 w:update_tab_count() |
|
210 return view |
|
211 end, |
|
212 |
|
213 -- Wrapper around the bind plugin's hit method |
|
214 hit = function (w, mods, key) |
|
215 local caught, newbuf = lousy.bind.hit(w.binds or {}, mods, key, w.buffer, w:is_mode("normal"), w) |
|
216 if w.win then |
|
217 w.buffer = newbuf |
|
218 w:update_buf() |
|
219 end |
|
220 return caught |
|
221 end, |
|
222 |
|
223 -- Wrapper around the bind plugin's match_cmd method |
|
224 match_cmd = function (w, buffer) |
|
225 return lousy.bind.match_cmd(binds.commands, buffer, w) |
|
226 end, |
|
227 |
|
228 -- enter command or characters into command line |
|
229 enter_cmd = function (w, cmd) |
|
230 local i = w.ibar.input |
|
231 w:set_mode("command") |
|
232 i.text = cmd |
|
233 i:set_position(-1) |
|
234 end, |
|
235 |
|
236 -- insert a string into the command line at the current cursor position |
|
237 insert_cmd = function (w, str) |
|
238 if not str then return end |
|
239 local i = w.ibar.input |
|
240 local text = i.text |
|
241 local pos = i:get_position() |
|
242 local left, right = string.sub(text, 1, pos), string.sub(text, pos+1) |
|
243 i.text = left .. str .. right |
|
244 i:set_position(pos + #str + 1) |
|
245 end, |
|
246 |
|
247 -- Command line completion of available commands |
|
248 cmd_completion = function (w) |
|
249 local i = w.ibar.input |
|
250 local s = w.sbar.l.uri |
|
251 local cmpl = {} |
|
252 |
|
253 -- Get last completion (is reset on key press other than <Tab>) |
|
254 if not w.compl_start or w.compl_index == 0 then |
|
255 w.compl_start = "^" .. string.sub(i.text, 2) |
|
256 w.compl_index = 1 |
|
257 end |
|
258 |
|
259 -- Get suitable commands |
|
260 for _, b in ipairs(binds.commands) do |
|
261 for _, c in pairs(b.commands) do |
|
262 if c and string.match(c, w.compl_start) then |
|
263 table.insert(cmpl, c) |
|
264 end |
|
265 end |
|
266 end |
|
267 |
|
268 table.sort(cmpl) |
|
269 |
|
270 if #cmpl > 0 then |
|
271 local text = "" |
|
272 for index, comp in pairs(cmpl) do |
|
273 if index == w.compl_index then |
|
274 i.text = ":" .. comp .. " " |
|
275 i:set_position(-1) |
|
276 end |
|
277 if text ~= "" then |
|
278 text = text .. " | " |
|
279 end |
|
280 text = text .. comp |
|
281 end |
|
282 |
|
283 -- cycle through all possible completions |
|
284 if w.compl_index == #cmpl then |
|
285 w.compl_index = 1 |
|
286 else |
|
287 w.compl_index = w.compl_index + 1 |
|
288 end |
|
289 s.text = lousy.util.escape(text) |
|
290 end |
|
291 end, |
|
292 |
|
293 del_word = function (w) |
|
294 local i = w.ibar.input |
|
295 local text = i.text |
|
296 local pos = i:get_position() |
|
297 if text and #text > 1 and pos > 1 then |
|
298 local left, right = string.sub(text, 2, pos), string.sub(text, pos+1) |
|
299 if not string.find(left, "%s") then |
|
300 left = "" |
|
301 elseif string.find(left, "%w+%s*$") then |
|
302 left = string.sub(left, 0, string.find(left, "%w+%s*$") - 1) |
|
303 elseif string.find(left, "%W+%s*$") then |
|
304 left = string.sub(left, 0, string.find(left, "%W+%s*$") - 1) |
|
305 end |
|
306 i.text = string.sub(text, 1, 1) .. left .. right |
|
307 i:set_position(#left + 2) |
|
308 end |
|
309 end, |
|
310 |
|
311 del_line = function (w) |
|
312 local i = w.ibar.input |
|
313 if i.text ~= ":" then |
|
314 i.text = ":" |
|
315 i:set_position(-1) |
|
316 end |
|
317 end, |
|
318 |
|
319 -- Search history adding |
|
320 srch_hist_add = function (w, srch) |
|
321 if not w.srch_hist then w.srch_hist = {} end |
|
322 -- Check overflow |
|
323 local max_hist = globals.max_srch_history or 100 |
|
324 if #w.srch_hist > (max_hist + 5) then |
|
325 while #w.srch_hist > max_hist do |
|
326 table.remove(w.srch_hist, 1) |
|
327 end |
|
328 end |
|
329 table.insert(w.srch_hist, srch) |
|
330 end, |
|
331 |
|
332 -- Search history traversing |
|
333 srch_hist_prev = function (w) |
|
334 if not w.srch_hist then w.srch_hist = {} end |
|
335 if not w.srch_hist_cursor then |
|
336 w.srch_hist_cursor = #w.srch_hist + 1 |
|
337 w.srch_hist_current = w.ibar.input.text |
|
338 end |
|
339 local c = w.srch_hist_cursor - 1 |
|
340 if w.srch_hist[c] then |
|
341 w.srch_hist_cursor = c |
|
342 w.ibar.input.text = w.srch_hist[c] |
|
343 w.ibar.input:set_position(-1) |
|
344 end |
|
345 end, |
|
346 |
|
347 srch_hist_next = function (w) |
|
348 if not w.srch_hist then w.srch_hist = {} end |
|
349 local c = (w.srch_hist_cursor or #w.srch_hist) + 1 |
|
350 if w.srch_hist[c] then |
|
351 w.srch_hist_cursor = c |
|
352 w.ibar.input.text = w.srch_hist[c] |
|
353 w.ibar.input:set_position(-1) |
|
354 elseif w.srch_hist_current then |
|
355 w.srch_hist_cursor = nil |
|
356 w.ibar.input.text = w.srch_hist_current |
|
357 w.ibar.input:set_position(-1) |
|
358 end |
|
359 end, |
|
360 |
|
361 -- Command history adding |
|
362 cmd_hist_add = function (w, cmd) |
|
363 if not w.cmd_hist then w.cmd_hist = {} end |
|
364 -- Make sure history doesn't overflow |
|
365 local max_hist = globals.max_cmd_hist or 100 |
|
366 if #w.cmd_hist > (max_hist + 5) then |
|
367 while #w.cmd_hist > max_hist do |
|
368 table.remove(w.cmd_hist, 1) |
|
369 end |
|
370 end |
|
371 table.insert(w.cmd_hist, cmd) |
|
372 end, |
|
373 |
|
374 -- Command history traversing |
|
375 cmd_hist_prev = function (w) |
|
376 if not w.cmd_hist then w.cmd_hist = {} end |
|
377 if not w.cmd_hist_cursor then |
|
378 w.cmd_hist_cursor = #w.cmd_hist + 1 |
|
379 w.cmd_hist_current = w.ibar.input.text |
|
380 end |
|
381 local c = w.cmd_hist_cursor - 1 |
|
382 if w.cmd_hist[c] then |
|
383 w.cmd_hist_cursor = c |
|
384 w.ibar.input.text = w.cmd_hist[c] |
|
385 w.ibar.input:set_position(-1) |
|
386 end |
|
387 end, |
|
388 |
|
389 cmd_hist_next = function (w) |
|
390 if not w.cmd_hist then w.cmd_hist = {} end |
|
391 local c = (w.cmd_hist_cursor or #w.cmd_hist) + 1 |
|
392 if w.cmd_hist[c] then |
|
393 w.cmd_hist_cursor = c |
|
394 w.ibar.input.text = w.cmd_hist[c] |
|
395 w.ibar.input:set_position(-1) |
|
396 elseif w.cmd_hist_current then |
|
397 w.cmd_hist_cursor = nil |
|
398 w.ibar.input.text = w.cmd_hist_current |
|
399 w.ibar.input:set_position(-1) |
|
400 end |
|
401 end, |
|
402 |
|
403 -- GUI content update functions |
|
404 update_tab_count = function (w, i, t) |
|
405 w.sbar.r.tabi.text = string.format("[%d/%d]", i or w.tabs:current(), t or w.tabs:count()) |
|
406 end, |
|
407 |
|
408 update_win_title = function (w, view) |
|
409 if not view then view = w:get_current() end |
|
410 local title = view:get_prop("title") |
|
411 local uri = view.uri |
|
412 if not title and not uri then |
|
413 w.win.title = "luakit" |
|
414 else |
|
415 w.win.title = (title or "luakit") .. " - " .. (uri or "about:blank") |
|
416 end |
|
417 end, |
|
418 |
|
419 update_uri = function (w, view, uri) |
|
420 if not view then view = w:get_current() end |
|
421 w.sbar.l.uri.text = lousy.util.escape((uri or (view and view.uri) or "about:blank")) |
|
422 end, |
|
423 |
|
424 update_progress = function (w, view, p) |
|
425 if not view then view = w:get_current() end |
|
426 if not p then p = view:get_prop("progress") end |
|
427 local loaded = w.sbar.l.loaded |
|
428 if not view:loading() or p == 1 then |
|
429 loaded:hide() |
|
430 else |
|
431 loaded:show() |
|
432 loaded.text = string.format("(%d%%)", p * 100) |
|
433 end |
|
434 end, |
|
435 |
|
436 update_scroll = function (w, view) |
|
437 if not view then view = w:get_current() end |
|
438 local scroll = w.sbar.r.scroll |
|
439 if view then |
|
440 local val, max = view:get_scroll_vert() |
|
441 if max == 0 then val = "All" |
|
442 elseif val == 0 then val = "Top" |
|
443 elseif val == max then val = "Bot" |
|
444 else val = string.format("%2d%%", (val/max) * 100) |
|
445 end |
|
446 if scroll.text ~= val then scroll.text = val end |
|
447 scroll:show() |
|
448 else |
|
449 scroll:hide() |
|
450 end |
|
451 end, |
|
452 |
|
453 update_ssl = function (w, view) |
|
454 if not view then view = w:get_current() end |
|
455 local trusted = view:ssl_trusted() |
|
456 local theme = lousy.theme.get() |
|
457 local ssl = w.sbar.r.ssl |
|
458 if trusted ~= nil and not w.checking_ssl then |
|
459 ssl.fg = theme.notrust_fg |
|
460 ssl.text = "(nocheck)" |
|
461 ssl:show() |
|
462 elseif trusted == true then |
|
463 ssl.fg = theme.trust_fg |
|
464 ssl.text = "(trust)" |
|
465 ssl:show() |
|
466 elseif trusted == false then |
|
467 ssl.fg = theme.notrust_fg |
|
468 ssl.text = "(notrust)" |
|
469 ssl:show() |
|
470 else |
|
471 ssl:hide() |
|
472 end |
|
473 end, |
|
474 |
|
475 update_buf = function (w) |
|
476 local buf = w.sbar.r.buf |
|
477 if w.buffer then |
|
478 buf.text = lousy.util.escape(string.format(" %-3s", w.buffer)) |
|
479 buf:show() |
|
480 else |
|
481 buf:hide() |
|
482 end |
|
483 end, |
|
484 |
|
485 update_binds = function (w, mode) |
|
486 -- Generate the list of active key & buffer binds for this mode |
|
487 w.binds = lousy.util.table.join(binds.mode_binds[mode], binds.mode_binds.all) |
|
488 -- Clear & hide buffer |
|
489 w.buffer = nil |
|
490 w:update_buf() |
|
491 end, |
|
492 |
|
493 -- Tab label functions |
|
494 -- TODO: Move these functions into a module (I.e. lousy.widget.tablist) |
|
495 make_tab_label = function (w, pos) |
|
496 local theme = lousy.theme.get() |
|
497 local t = { |
|
498 label = label(), |
|
499 sep = eventbox(), |
|
500 ebox = eventbox(), |
|
501 layout = hbox(), |
|
502 } |
|
503 t.label.font = theme.tab_font |
|
504 t.label:set_width(1) |
|
505 t.layout:pack_start(t.label, true, true, 0) |
|
506 t.layout:pack_start(t.sep, false, false, 0) |
|
507 t.ebox:set_child(t.layout) |
|
508 t.ebox:add_signal("button-release", function (e, m, b) |
|
509 if b == 1 then |
|
510 w.tabs:switch(pos) |
|
511 return true |
|
512 elseif b == 2 then |
|
513 w:close_tab(w.tabs:atindex(pos)) |
|
514 return true |
|
515 end |
|
516 end) |
|
517 return t |
|
518 end, |
|
519 |
|
520 destroy_tab_label = function (w, t) |
|
521 if not t then t = table.remove(w.tbar.titles) end |
|
522 -- Destroy widgets without their own windows first (I.e. labels) |
|
523 for _, wi in ipairs{ t.label, t.sep, t.ebox, t.layout } do wi:destroy() end |
|
524 end, |
|
525 |
|
526 update_tab_labels = function (w, current) |
|
527 local tb = w.tbar |
|
528 local count, current = w.tabs:count(), current or w.tabs:current() |
|
529 tb.ebox:hide() |
|
530 |
|
531 -- Leave the tablist hidden if there is only one tab open |
|
532 if count <= 1 then |
|
533 return nil |
|
534 end |
|
535 |
|
536 if count ~= #tb.titles then |
|
537 -- Grow the number of labels |
|
538 while count > #tb.titles do |
|
539 local t = w:make_tab_label(#tb.titles + 1) |
|
540 tb.layout:pack_start(t.ebox, true, true, 0) |
|
541 table.insert(tb.titles, t) |
|
542 end |
|
543 -- Prune number of labels |
|
544 while count < #tb.titles do |
|
545 w:destroy_tab_label() |
|
546 end |
|
547 end |
|
548 |
|
549 if count ~= 0 then |
|
550 for i = 1, count do |
|
551 local view = w.tabs:atindex(i) |
|
552 local t = tb.titles[i] |
|
553 local title = " " ..i.. " "..w:get_tab_title(view) |
|
554 t.label.text = lousy.util.escape(string.format("%-40s", title)) |
|
555 w:apply_tablabel_theme(t, i == current) |
|
556 end |
|
557 end |
|
558 tb.ebox:show() |
|
559 end, |
|
560 |
|
561 -- Theme functions |
|
562 apply_tablabel_theme = function (w, t, selected) |
|
563 local theme = lousy.theme.get() |
|
564 selected = (selected and "_selected") or "" |
|
565 t.label.fg = theme[string.format("tab%s_fg", selected)] |
|
566 t.ebox.bg = theme[string.format("tab%s_bg", selected)] |
|
567 end, |
|
568 |
|
569 close_win = function (w) |
|
570 -- Close all tabs |
|
571 while w.tabs:count() ~= 0 do |
|
572 w:close_tab() |
|
573 end |
|
574 |
|
575 -- Recursively remove widgets from window |
|
576 local children = lousy.util.recursive_remove(w.win) |
|
577 -- Destroy all widgets |
|
578 for i, c in ipairs(lousy.util.table.join(children, {w.win})) do |
|
579 if c.hide then c:hide() end |
|
580 c:destroy() |
|
581 end |
|
582 |
|
583 -- Clear window struct |
|
584 w = setmetatable(w, {}) |
|
585 for k, _ in pairs(w) do w[k] = nil end |
|
586 |
|
587 -- Quit if closed last window |
|
588 if #luakit.windows == 0 then luakit.quit() end |
|
589 end, |
|
590 } |
|
591 |
|
592 -- Ordered list of class index functions. Other classes (E.g. webview) are able |
|
593 -- to add their own index functions to this list. |
|
594 window.indexes = { |
|
595 -- Find function in window.methods first |
|
596 function (w, k) return window.methods[k] end |
|
597 } |
|
598 |
|
599 -- Create new window |
|
600 function window.new(uris) |
|
601 local w = window.build() |
|
602 |
|
603 -- Set window metatable |
|
604 setmetatable(w, { |
|
605 __index = function (_, k) |
|
606 -- Check widget structure first |
|
607 local v = rawget(w, k) |
|
608 if v then return v end |
|
609 -- Call each window index function |
|
610 for _, index in ipairs(window.indexes) do |
|
611 v = index(w, k) |
|
612 if v then return v end |
|
613 end |
|
614 end, |
|
615 }) |
|
616 |
|
617 -- Call window init functions |
|
618 for _, func in pairs(window.init_funcs) do |
|
619 func(w) |
|
620 end |
|
621 |
|
622 -- Populate notebook with tabs |
|
623 for _, uri in ipairs(uris or {}) do |
|
624 w:new_tab(uri) |
|
625 end |
|
626 |
|
627 -- Make sure something is loaded |
|
628 if w.tabs:count() == 0 then |
|
629 w:new_tab(globals.homepage) |
|
630 end |
|
631 |
|
632 -- Set initial mode |
|
633 w:set_mode() |
|
634 |
|
635 return w |
|
636 end |
|
637 |
|
638 -- vim: et:sw=4:ts=8:sts=4:tw=80 |