summaryrefslogtreecommitdiff
path: root/.config/luakit/window.lua
diff options
context:
space:
mode:
authorYuval Adam <yuv.adm@gmail.com>2014-02-15 01:05:08 +0200
committerYuval Adam <yuv.adm@gmail.com>2014-02-15 01:05:08 +0200
commitf0d0bcc1e4fff649db80316de4df40c1d19d89a4 (patch)
tree3e35ee2e560ff0c07759f27117b45027d4473f3c /.config/luakit/window.lua
parentf03f2de688e6adf9a073ea2e71105675ce99da3c (diff)
Add initia luakit files
Diffstat (limited to '.config/luakit/window.lua')
-rw-r--r--.config/luakit/window.lua859
1 files changed, 859 insertions, 0 deletions
diff --git a/.config/luakit/window.lua b/.config/luakit/window.lua
new file mode 100644
index 0000000..5e921d6
--- /dev/null
+++ b/.config/luakit/window.lua
@@ -0,0 +1,859 @@
+------------------
+-- Window class --
+------------------
+
+require "lfs"
+
+-- Window class table
+window = {}
+
+-- List of active windows by window widget
+window.bywidget = setmetatable({}, { __mode = "k" })
+
+-- Widget construction aliases
+local function entry() return widget{type="entry"} end
+local function eventbox() return widget{type="eventbox"} end
+local function hbox() return widget{type="hbox"} end
+local function label() return widget{type="label"} end
+local function notebook() return widget{type="notebook"} end
+local function vbox() return widget{type="vbox"} end
+
+-- Build and pack window widgets
+function window.build()
+ -- Create a table for widgets and state variables for a window
+ local w = {
+ win = widget{type="window"},
+ ebox = eventbox(),
+ layout = vbox(),
+ paned = widget{type="vpaned"},
+ tabs = notebook(),
+ -- Tablist widget
+ tablist = lousy.widget.tablist(),
+ -- Status bar widgets
+ sbar = {
+ layout = hbox(),
+ ebox = eventbox(),
+ -- Left aligned widgets
+ l = {
+ layout = hbox(),
+ ebox = eventbox(),
+ uri = label(),
+ hist = label(),
+ loaded = label(),
+ },
+ -- Fills space between the left and right aligned widgets
+ sep = eventbox(),
+ -- Right aligned widgets
+ r = {
+ layout = hbox(),
+ ebox = eventbox(),
+ buf = label(),
+ ssl = label(),
+ tabi = label(),
+ scroll = label(),
+ },
+ },
+
+ -- Vertical menu window widget (completion results, bookmarks, qmarks, ..)
+ menu = lousy.widget.menu(),
+
+ -- Input bar widgets
+ ibar = {
+ layout = hbox(),
+ ebox = eventbox(),
+ prompt = label(),
+ input = entry(),
+ },
+ closed_tabs = {}
+ }
+
+ -- Assemble window
+ w.ebox.child = w.paned
+ w.paned:pack1(w.layout)
+ w.win.child = w.ebox
+
+ -- Pack tablist
+ w.layout:pack(w.tablist.widget)
+
+ -- Pack notebook
+ w.layout:pack(w.tabs, { expand = true, fill = true })
+
+ -- Pack left-aligned statusbar elements
+ local l = w.sbar.l
+ l.layout:pack(l.uri)
+ l.layout:pack(l.hist)
+ l.layout:pack(l.loaded)
+ l.ebox.child = l.layout
+
+ -- Pack right-aligned statusbar elements
+ local r = w.sbar.r
+ r.layout:pack(r.buf)
+ r.layout:pack(r.ssl)
+ r.layout:pack(r.tabi)
+ r.layout:pack(r.scroll)
+ r.ebox.child = r.layout
+
+ -- Pack status bar elements
+ local s = w.sbar
+ s.layout:pack(l.ebox)
+ s.layout:pack(s.sep, { expand = true, fill = true })
+ s.layout:pack(r.ebox)
+ s.ebox.child = s.layout
+ w.layout:pack(s.ebox)
+
+ -- Pack menu widget
+ w.layout:pack(w.menu.widget)
+ w.menu:hide()
+
+ -- Pack input bar
+ local i = w.ibar
+ i.layout:pack(i.prompt)
+ i.layout:pack(i.input, { expand = true, fill = true })
+ i.ebox.child = i.layout
+ w.layout:pack(i.ebox)
+
+ -- Other settings
+ i.input.show_frame = false
+ w.tabs.show_tabs = false
+ l.loaded:hide()
+ l.hist:hide()
+ l.uri.selectable = true
+ r.ssl:hide()
+
+ -- Allows indexing of window struct by window widget
+ window.bywidget[w.win] = w
+
+ return w
+end
+
+-- Table of functions to call on window creation. Normally used to add signal
+-- handlers to the new windows widgets.
+window.init_funcs = {
+ -- Attach notebook widget signals
+ notebook_signals = function (w)
+ w.tabs:add_signal("page-added", function (nbook, view, idx)
+ luakit.idle_add(function ()
+ w:update_tab_count()
+ w:update_tablist()
+ return false
+ end)
+ end)
+ w.tabs:add_signal("switch-page", function (nbook, view, idx)
+ w.view = nil
+ w:set_mode()
+ -- Update widgets after tab switch
+ luakit.idle_add(function ()
+ w:update_tab_count()
+ w:update_win_title()
+ w:update_uri()
+ w:update_progress()
+ w:update_tablist()
+ w:update_buf()
+ w:update_ssl()
+ w:update_hist()
+ return false
+ end)
+ end)
+ w.tabs:add_signal("page-reordered", function (nbook, view, idx)
+ w:update_tab_count()
+ w:update_tablist()
+ end)
+ end,
+
+ last_win_check = function (w)
+ w.win:add_signal("destroy", function ()
+ -- call the quit function if this was the last window left
+ if #luakit.windows == 0 then luakit.quit() end
+ if w.close_win then w:close_win() end
+ end)
+ end,
+
+ key_press_match = function (w)
+ w.win:add_signal("key-press", function (_, mods, key)
+ -- Match & exec a bind
+ local success, match = xpcall(
+ function () return w:hit(mods, key) end,
+ function (err) w:error(debug.traceback(err, 3)) end)
+
+ if success and match then
+ return true
+ end
+ end)
+ end,
+
+ tablist_tab_click = function (w)
+ w.tablist:add_signal("tab-clicked", function (_, index, mods, button)
+ if button == 1 then
+ w.tabs:switch(index)
+ return true
+ elseif button == 2 then
+ w:close_tab(w.tabs[index])
+ return true
+ end
+ end)
+ end,
+
+ apply_window_theme = function (w)
+ local s, i = w.sbar, w.ibar
+
+ -- Set foregrounds
+ for wi, v in pairs({
+ [s.l.uri] = theme.uri_sbar_fg,
+ [s.l.hist] = theme.hist_sbar_fg,
+ [s.l.loaded] = theme.sbar_loaded_fg,
+ [s.r.buf] = theme.buf_sbar_fg,
+ [s.r.tabi] = theme.tabi_sbar_fg,
+ [s.r.scroll] = theme.scroll_sbar_fg,
+ [i.prompt] = theme.prompt_ibar_fg,
+ [i.input] = theme.input_ibar_fg,
+ }) do wi.fg = v end
+
+ -- Set backgrounds
+ for wi, v in pairs({
+ [s.l.ebox] = theme.sbar_bg,
+ [s.r.ebox] = theme.sbar_bg,
+ [s.sep] = theme.sbar_bg,
+ [s.ebox] = theme.sbar_bg,
+ [i.ebox] = theme.ibar_bg,
+ [i.input] = theme.input_ibar_bg,
+ }) do wi.bg = v end
+
+ -- Set fonts
+ for wi, v in pairs({
+ [s.l.uri] = theme.uri_sbar_font,
+ [s.l.hist] = theme.hist_sbar_font,
+ [s.l.loaded] = theme.sbar_loaded_font,
+ [s.r.buf] = theme.buf_sbar_font,
+ [s.r.ssl] = theme.ssl_sbar_font,
+ [s.r.tabi] = theme.tabi_sbar_font,
+ [s.r.scroll] = theme.scroll_sbar_font,
+ [i.prompt] = theme.prompt_ibar_font,
+ [i.input] = theme.input_ibar_font,
+ }) do wi.font = v end
+ end,
+
+ set_default_size = function (w)
+ local size = globals.default_window_size or "800x600"
+ if string.match(size, "^%d+x%d+$") then
+ w.win:set_default_size(string.match(size, "^(%d+)x(%d+)$"))
+ else
+ warn("E: window.lua: invalid window size: %q", size)
+ end
+ end,
+
+ set_window_icon = function (w)
+ local path = (luakit.dev_paths and os.exists("./extras/luakit.png")) or
+ os.exists("/usr/share/pixmaps/luakit.png")
+ if path then w.win.icon = path end
+ end,
+
+ clear_urgency_hint = function (w)
+ w.win:add_signal("focus", function ()
+ w.win.urgency_hint = false
+ end)
+ end,
+}
+
+-- Helper functions which operate on the window widgets or structure.
+window.methods = {
+ -- Wrapper around the bind plugin's hit method
+ hit = function (w, mods, key, opts)
+ local opts = lousy.util.table.join(opts or {}, {
+ enable_buffer = w:is_mode("normal"),
+ buffer = w.buffer,
+ })
+
+ local caught, newbuf = lousy.bind.hit(w, w.binds, mods, key, opts)
+ if w.win then -- Check binding didn't cause window to exit
+ w.buffer = newbuf
+ w:update_buf()
+ end
+ return caught
+ end,
+
+ -- Wrapper around the bind plugin's match_cmd method
+ match_cmd = function (w, buffer)
+ return lousy.bind.match_cmd(w, get_mode("command").binds, buffer)
+ end,
+
+ -- enter command or characters into command line
+ enter_cmd = function (w, cmd, opts)
+ w:set_mode("command")
+ w:set_input(cmd, opts)
+ end,
+
+ -- run command as if typed into the command line
+ run_cmd = function (w, cmd, opts)
+ w:enter_cmd(cmd, opts)
+ w:activate()
+ end,
+
+ -- insert a string into the command line at the current cursor position
+ insert_cmd = function (w, str)
+ if not str then return end
+ local i = w.ibar.input
+ local text = i.text
+ local pos = i.position
+ local left, right = string.sub(text, 1, pos), string.sub(text, pos+1)
+ i.text = left .. str .. right
+ i.position = pos + #str
+ end,
+
+ -- Emulates pressing the Return key in input field
+ activate = function (w)
+ w.ibar.input:emit_signal("activate")
+ end,
+
+ del_word = function (w)
+ local i = w.ibar.input
+ local text = i.text
+ local pos = i.position
+ if text and #text > 1 and pos > 1 then
+ local left, right = string.sub(text, 2, pos), string.sub(text, pos+1)
+ if not string.find(left, "%s") then
+ left = ""
+ elseif string.find(left, "%w+%s*$") then
+ left = string.sub(left, 0, string.find(left, "%w+%s*$") - 1)
+ elseif string.find(left, "%W+%s*$") then
+ left = string.sub(left, 0, string.find(left, "%W+%s*$") - 1)
+ end
+ i.text = string.sub(text, 1, 1) .. left .. right
+ i.position = #left + 1
+ end
+ end,
+
+ del_line = function (w)
+ local i = w.ibar.input
+ if not string.match(i.text, "^[:/?]$") then
+ i.text = string.sub(i.text, 1, 1)
+ i.position = -1
+ end
+ end,
+
+ del_backward_char = function (w)
+ local i = w.ibar.input
+ local text = i.text
+ local pos = i.position
+
+ if pos > 1 then
+ i.text = string.sub(text, 0, pos - 1) .. string.sub(text, pos + 1)
+ i.position = pos - 1
+ end
+ end,
+
+ del_forward_char = function (w)
+ local i = w.ibar.input
+ local text = i.text
+ local pos = i.position
+
+ i.text = string.sub(text, 0, pos) .. string.sub(text, pos + 2)
+ i.position = pos
+ end,
+
+ beg_line = function (w)
+ local i = w.ibar.input
+ i.position = 1
+ end,
+
+ end_line = function (w)
+ local i = w.ibar.input
+ i.position = -1
+ end,
+
+ forward_char = function (w)
+ local i = w.ibar.input
+ i.position = i.position + 1
+ end,
+
+ backward_char = function (w)
+ local i = w.ibar.input
+ local pos = i.position
+ if pos > 1 then
+ i.position = pos - 1
+ end
+ end,
+
+ forward_word = function (w)
+ local i = w.ibar.input
+ local text = i.text
+ local pos = i.position
+ if text and #text > 1 then
+ local right = string.sub(text, pos+1)
+ if string.find(right, "%w+") then
+ local _, move = string.find(right, "%w+")
+ i.position = pos + move
+ end
+ end
+ end,
+
+ backward_word = function (w)
+ local i = w.ibar.input
+ local text = i.text
+ local pos = i.position
+ if text and #text > 1 and pos > 1 then
+ local left = string.reverse(string.sub(text, 2, pos))
+ if string.find(left, "%w+") then
+ local _, move = string.find(left, "%w+")
+ i.position = pos - move
+ end
+ end
+ end,
+
+ -- Shows a notification until the next keypress of the user.
+ notify = function (w, msg, set_mode)
+ if set_mode ~= false then w:set_mode() end
+ w:set_prompt(msg, { fg = theme.notif_fg, bg = theme.notif_bg })
+ end,
+
+ warning = function (w, msg, set_mode)
+ if set_mode ~= false then w:set_mode() end
+ w:set_prompt(msg, { fg = theme.warning_fg, bg = theme.warning_bg })
+ end,
+
+ error = function (w, msg, set_mode)
+ if set_mode ~= false then w:set_mode() end
+ w:set_prompt("Error: "..msg, { fg = theme.error_fg, bg = theme.error_bg })
+ end,
+
+ -- Set and display the prompt
+ set_prompt = function (w, text, opts)
+ local prompt, ebox, opts = w.ibar.prompt, w.ibar.ebox, opts or {}
+ prompt:hide()
+ -- Set theme
+ fg, bg = opts.fg or theme.ibar_fg, opts.bg or theme.ibar_bg
+ if prompt.fg ~= fg then prompt.fg = fg end
+ if ebox.bg ~= bg then ebox.bg = bg end
+ -- Set text or remain hidden
+ if text then
+ prompt.text = lousy.util.escape(text)
+ prompt:show()
+ end
+ end,
+
+ -- Set display and focus the input bar
+ set_input = function (w, text, opts)
+ local input, opts = w.ibar.input, opts or {}
+ input:hide()
+ -- Set theme
+ fg, bg = opts.fg or theme.ibar_fg, opts.bg or theme.ibar_bg
+ if input.fg ~= fg then input.fg = fg end
+ if input.bg ~= bg then input.bg = bg end
+ -- Set text or remain hidden
+ if text then
+ input.text = ""
+ input:show()
+ input:focus()
+ input.text = text
+ input.position = opts.pos or -1
+ end
+ end,
+
+ -- GUI content update functions
+ update_tab_count = function (w)
+ w.sbar.r.tabi.text = string.format("[%d/%d]", w.tabs:current(), w.tabs:count())
+ end,
+
+ update_win_title = function (w)
+ local uri, title = w.view.uri, w.view.title
+ title = (title or "luakit") .. ((uri and " - " .. uri) or "")
+ local max = globals.max_title_len or 80
+ if #title > max then title = string.sub(title, 1, max) .. "..." end
+ w.win.title = title
+ end,
+
+ update_uri = function (w, link)
+ w.sbar.l.uri.text = lousy.util.escape((link and "Link: " .. link)
+ or (w.view and w.view.uri) or "about:blank")
+ end,
+
+ update_progress = function (w)
+ local p = w.view.progress
+ local loaded = w.sbar.l.loaded
+ if not w.view:loading() or p == 1 then
+ loaded:hide()
+ else
+ loaded:show()
+ loaded.text = string.format("(%d%%)", p * 100)
+ end
+ end,
+
+ update_scroll = function (w)
+ local scroll, label = w.view.scroll, w.sbar.r.scroll
+ local y, max, text = scroll.y, scroll.ymax
+ if max == 0 then text = "All"
+ elseif y == 0 then text = "Top"
+ elseif y == max then text = "Bot"
+ else text = string.format("%2d%%", (y / max) * 100)
+ end
+ if label.text ~= text then label.text = text end
+ end,
+
+ update_ssl = function (w)
+ local trusted = w.view:ssl_trusted()
+ local ssl = w.sbar.r.ssl
+ if trusted ~= nil and not w.checking_ssl then
+ ssl.fg = theme.notrust_fg
+ ssl.text = "(nocheck)"
+ ssl:show()
+ elseif trusted == true then
+ ssl.fg = theme.trust_fg
+ ssl.text = "(trust)"
+ ssl:show()
+ elseif trusted == false then
+ ssl.fg = theme.notrust_fg
+ ssl.text = "(notrust)"
+ ssl:show()
+ else
+ ssl:hide()
+ end
+ end,
+
+ update_hist = function (w)
+ local hist = w.sbar.l.hist
+ local back, forward = w.view:can_go_back(), w.view:can_go_forward()
+ local s = (back and "+" or "") .. (forward and "-" or "")
+ if s ~= "" then
+ hist.text = '['..s..']'
+ hist:show()
+ else
+ hist:hide()
+ end
+ end,
+
+ update_buf = function (w)
+ local buf = w.sbar.r.buf
+ if w.buffer then
+ buf.text = lousy.util.escape(string.format(" %-3s", w.buffer))
+ buf:show()
+ else
+ buf:hide()
+ end
+ end,
+
+ update_binds = function (w, mode)
+ -- Generate the list of active key & buffer binds for this mode
+ w.binds = lousy.util.table.join((get_mode(mode) or {}).binds or {}, get_mode('all').binds or {})
+ -- Clear & hide buffer
+ w.buffer = nil
+ w:update_buf()
+ end,
+
+ update_tablist = function (w)
+ local current = w.tabs:current()
+ local fg, bg, nfg, snfg = theme.tab_fg, theme.tab_bg, theme.tab_ntheme, theme.selected_ntheme
+ local lfg, bfg, gfg = theme.tab_loading_fg, theme.tab_notrust_fg, theme.tab_trust_fg
+ local escape = lousy.util.escape
+ local tabs, tfmt = {}, ' <span foreground="%s">%s</span> %s'
+
+ for i, view in ipairs(w.tabs.children) do
+ -- Get tab number theme
+ local ntheme = nfg
+ if view:loading() then -- Show loading on all tabs
+ ntheme = lfg
+ elseif current == i then -- Show ssl trusted/untrusted on current tab
+ local trusted = view:ssl_trusted()
+ ntheme = snfg
+ if trusted == false or (trusted ~= nil and not w.checking_ssl) then
+ ntheme = bfg
+ elseif trusted then
+ ntheme = gfg
+ end
+ end
+ local title = view.title or view.uri or "(Untitled)"
+ tabs[i] = {
+ title = string.format(tfmt, ntheme or fg, i, escape(title)),
+ fg = (current == i and theme.tab_selected_fg) or fg,
+ bg = (current == i and theme.tab_selected_bg) or bg,
+ }
+ end
+
+ if #tabs < 2 then tabs, current = {}, 0 end
+ w.tablist:update(tabs, current)
+ end,
+
+ new_tab = function (w, arg, switch, order)
+ local view
+ -- Use blank tab first
+ if w.has_blank and w.tabs:count() == 1 and w.tabs[1].uri == "about:blank" then
+ view = w.tabs[1]
+ end
+ w.has_blank = nil
+ -- Make new webview widget
+ if not view then
+ view = webview.new(w)
+ -- Get tab order function
+ if not order and taborder then
+ order = (switch == false and taborder.default_bg)
+ or taborder.default
+ end
+ pos = w.tabs:insert((order and order(w, view)) or -1, view)
+ if switch ~= false then w.tabs:switch(pos) end
+ end
+ -- Load uri or webview history table
+ if type(arg) == "string" then view.uri = arg
+ elseif type(arg) == "table" then view.history = arg end
+ -- Update statusbar widgets
+ w:update_tab_count()
+ w:update_tablist()
+ return view
+ end,
+
+ -- close the current tab
+ close_tab = function (w, view, blank_last)
+ view = view or w.view
+ -- Treat a blank last tab as an empty notebook (if blank_last=true)
+ if blank_last ~= false and w.tabs:count() == 1 then
+ if not view:loading() and view.uri == "about:blank" then return end
+ w:new_tab("about:blank", false)
+ w.has_blank = true
+ end
+ -- Save tab history
+ local tab = {hist = view.history,}
+ -- And relative location
+ local index = w.tabs:indexof(view)
+ if index ~= 1 then tab.after = w.tabs[index-1] end
+ table.insert(w.closed_tabs, tab)
+ view:destroy()
+ w:update_tab_count()
+ w:update_tablist()
+ end,
+
+ close_win = function (w, force)
+ -- Ask plugins if it's OK to close last window
+ if not force and (#luakit.windows == 1) then
+ local emsg = luakit.emit_signal("can-close", w)
+ if emsg then
+ assert(type(emsg) == "string", "invalid exit error message")
+ w:error(string.format("Can't close luakit: %s (force close "
+ .. "with :q! or :wq!)", emsg))
+ return false
+ end
+ end
+
+ w:emit_signal("close")
+
+ -- Close all tabs
+ while w.tabs:count() ~= 0 do
+ w:close_tab(nil, false)
+ end
+
+ -- Destroy tablist
+ w.tablist:destroy()
+
+ -- Remove from window index
+ window.bywidget[w.win] = nil
+
+ -- Clear window struct
+ w = setmetatable(w, {})
+
+ -- Recursively remove widgets from window
+ local children = lousy.util.recursive_remove(w.win)
+ -- Destroy all widgets
+ for i, c in ipairs(lousy.util.table.join(children, {w.win})) do
+ if c.hide then c:hide() end
+ c:destroy()
+ end
+
+ -- Remove all window table vars
+ for k, _ in pairs(w) do w[k] = nil end
+
+ -- Quit if closed last window
+ if #luakit.windows == 0 then luakit.quit() end
+ end,
+
+ -- Navigate current view or open new tab
+ navigate = function (w, uri, view)
+ view = view or w.view
+ if view then
+ local js = string.match(uri, "^javascript:(.+)$")
+ if js then
+ return view:eval_js(luakit.uri_decode(js))
+ end
+ view.uri = uri
+ else
+ return w:new_tab(uri)
+ end
+ end,
+
+ -- Save, restart luakit and reload session.
+ restart = function (w)
+ -- Generate luakit launch command.
+ local args = {({string.gsub(luakit.execpath, " ", "\\ ")})[1]}
+ if luakit.verbose then table.insert(args, "-v") end
+ -- Relaunch without libunique bindings?
+ if luakit.nounique then table.insert(args, "-U") end
+
+ -- Get new config path
+ local conf
+ if luakit.confpath ~= "/etc/xdg/luakit/rc.lua" and os.exists(luakit.confpath) then
+ conf = luakit.confpath
+ table.insert(args, string.format("-c %q", conf))
+ end
+
+ -- Check config has valid syntax
+ local cmd = table.concat(args, " ")
+ if luakit.spawn_sync(cmd .. " -k") ~= 0 then
+ return w:error("Cannot restart, syntax error in configuration file"..((conf and ": "..conf) or "."))
+ end
+
+ -- Save session.
+ local wins = {}
+ for _, w in pairs(window.bywidget) do table.insert(wins, w) end
+ session.save(wins)
+
+ -- Replace current process with new luakit instance.
+ luakit.exec(cmd)
+ end,
+
+ -- Intelligent open command which can detect a uri or search argument.
+ search_open = function (w, arg)
+ local lstring = lousy.util.string
+ local match, find = string.match, string.find
+
+ -- Detect blank uris
+ if not arg or match(arg, "^%s*$") then return "about:blank" end
+
+ -- Strip whitespace and split by whitespace into args table
+ local args = lstring.split(lstring.strip(arg))
+
+ -- Guess if first argument is an address, search engine, file
+ if #args == 1 then
+ local uri = args[1]
+ if uri == "about:blank" then return uri end
+
+ -- Check if search engine name
+ if search_engines[uri] then
+ return string.format(search_engines[uri], "")
+ end
+
+ -- Navigate if . or / in uri (I.e. domains, IP's, scheme://)
+ if find(uri, "%.") or find(uri, "/") then return uri end
+
+ -- Navigate if this is a javascript-uri
+ if find(uri, "^javascript:") then return uri end
+
+ -- Valid hostnames to check
+ local hosts = { "localhost" }
+ if globals.load_etc_hosts ~= false then
+ hosts = lousy.util.get_etc_hosts()
+ end
+
+ -- Check hostnames
+ for _, h in pairs(hosts) do
+ if h == uri or match(uri, "^"..h..":%d+$") then return uri end
+ end
+
+ -- Check for file in filesystem
+ if globals.check_filepath ~= false then
+ if lfs.attributes(uri) then return "file://" .. uri end
+ end
+ end
+
+ -- Find search engine (or use search_engines.default)
+ local engine = "default"
+ if args[1] and search_engines[args[1]] then
+ engine = args[1]
+ table.remove(args, 1)
+ end
+
+ -- URI encode search terms
+ local terms = luakit.uri_encode(table.concat(args, " "))
+ return string.format(search_engines[engine], terms)
+ end,
+
+ -- Increase (or decrease) the last found number in the current uri
+ inc_uri = function (w, arg)
+ local uri = string.gsub(w.view.uri, "(%d+)([^0-9]*)$", function (num, rest)
+ return string.format("%0"..#num.."d", tonumber(num) + (arg or 1)) .. rest
+ end)
+ return uri
+ end,
+
+ -- Tab traversing functions
+ next_tab = function (w, n)
+ w.tabs:switch((((n or 1) + w.tabs:current() -1) % w.tabs:count()) + 1)
+ end,
+
+ prev_tab = function (w, n)
+ w.tabs:switch(((w.tabs:current() - (n or 1) -1) % w.tabs:count()) + 1)
+ end,
+
+ goto_tab = function (w, n)
+ if n and (n == -1 or n > 0) then
+ return w.tabs:switch((n <= w.tabs:count() and n) or -1)
+ end
+ end,
+
+ -- For each tab, switches to that tab and calls the given function passing
+ -- it the view contained in the tab.
+ each_tab = function (w, fn)
+ for index = 1, w.tabs:count() do
+ w:goto_tab(index)
+ fn(w.tabs[index])
+ end
+ end,
+
+ -- If argument is form-active or root-active, emits signal. Ignores all
+ -- other signals.
+ emit_form_root_active_signal = function (w, s)
+ if s == "form-active" then
+ w.view:emit_signal("form-active")
+ elseif s == "root-active" then
+ w.view:emit_signal("root-active")
+ end
+ end,
+}
+
+-- Ordered list of class index functions. Other classes (E.g. webview) are able
+-- to add their own index functions to this list.
+window.indexes = {
+ -- Find function in window.methods first
+ function (w, k) return window.methods[k] end
+}
+
+-- Create new window
+function window.new(uris)
+ local w = window.build()
+
+ -- Set window metatable
+ setmetatable(w, {
+ __index = function (_, k)
+ -- Check widget structure first
+ local v = rawget(w, k)
+ if v then return v end
+ -- Call each window index function
+ for _, index in ipairs(window.indexes) do
+ v = index(w, k)
+ if v then return v end
+ end
+ end,
+ })
+
+ -- Setup window widget for signals
+ lousy.signal.setup(w)
+
+ -- Call window init functions
+ for _, func in pairs(window.init_funcs) do
+ func(w)
+ end
+
+ -- Populate notebook with tabs
+ for _, uri in ipairs(uris or {}) do
+ w:new_tab(w:search_open(uri), false)
+ end
+
+ -- Make sure something is loaded
+ if w.tabs:count() == 0 then
+ w:new_tab(w:search_open(globals.homepage), false)
+ end
+
+ -- Set initial mode
+ w:set_mode()
+
+ -- Show window
+ w.win:show()
+
+ return w
+end
+
+-- vim: et:sw=4:ts=8:sts=4:tw=80