Merging and updating vimrc
commit
2b2f8e09e5
@ -1,3 +1,6 @@
|
||||
*.log
|
||||
weechat/logs/*
|
||||
vim/.netrwhist
|
||||
vim/bundle/*
|
||||
!vim/bundle/vundle/*
|
||||
mutt/hcache
|
||||
|
@ -1,46 +1,133 @@
|
||||
! General
|
||||
|
||||
! Urxvt
|
||||
urxvt*loginShell: true
|
||||
urxvt*scrollBar: false
|
||||
urxvt*secondaryScroll: true
|
||||
urxvt*saveLines: 65535
|
||||
urxvt*cursorBlink: false
|
||||
urxvt*urgentOnBell: true
|
||||
urxvt*urlLauncher: /usr/bin/uzbl-browser
|
||||
urxvt*urlLauncher: /usr/bin/luakit
|
||||
!urxvt*termName: xterm-256color
|
||||
!urxvt*termName: rxvt-256color
|
||||
urxvt*termName: rxvt-unicode
|
||||
urxvt*termName: rxvt-unicode-256color
|
||||
|
||||
! Font
|
||||
!urxvt*font: -xos4-terminus-medium-*-*-*-12-*-*-*-*-*-*-*
|
||||
!urxvt*font: xft:DejaVu Sans Mono:pixelsize=10:antialias=true:hinting=true
|
||||
!urxvt*font: xft:Liberation Mono:pixelsize=10:antialias=true:hinting=true
|
||||
!urxvt*boldFont: -xos4-terminus-bold-*-*-*-12-*-*-*-*-*-*-*
|
||||
!urxvt*font: xft:inconsolata:size=9
|
||||
!urxvt*font: xft:inconsolata:size=10
|
||||
!urxvt*font: -*-ohsnapu-medium-r-normal-*-11-*-*-*-*-*-*-*
|
||||
!urxvt*boldFont: -*-ohsnapu-bold-r-normal-*-11-*-*-*-*-*-*-*
|
||||
urxvt*font: xft:termsyn:pixelsize=10
|
||||
!urxvt*font: xft:termsyn:pixelsize=10
|
||||
!urxvt*font: xft:DejaVu Sans Mono:pixelsize=10:antialias=false:hinting=true
|
||||
urxvt*font: xft:terminus:size=9
|
||||
urxvt*boldFont: xft:terminus:size=9
|
||||
|
||||
! Colors
|
||||
urxvt*depth: 32
|
||||
!urxvt*cursorColor: #DCDCCC
|
||||
!urxvt*background: #000000
|
||||
urxvt*foreground: #FFFFFF
|
||||
urxvt*background: rgba:0000/0000/0000/dddd
|
||||
|
||||
*color0: #1c1c1c
|
||||
*color8: #3d3a3a
|
||||
*color1: #d770af
|
||||
*color9: #d28abf
|
||||
*color2 : #9acc79
|
||||
*color10: #8fb676
|
||||
*color3: #d0d26b
|
||||
*color11: #c8bc45
|
||||
*color4 : #77b6c5
|
||||
*color12: #8fa7b9
|
||||
*color5: #a488d9
|
||||
*color13: #bd89de
|
||||
*color6: #7fcab3
|
||||
*color14: #6ec2a8
|
||||
*color7: #8d8d8d
|
||||
*color15: #dad3d3
|
||||
urxvt*background: rgba:0000/0000/0000/ee00
|
||||
|
||||
!*color0: #1c1c1c
|
||||
!*color8: #3d3a3a
|
||||
!*color1: #d770af
|
||||
!*color9: #d28abf
|
||||
!*color2 : #9acc79
|
||||
!*color10: #8fb676
|
||||
!*color3: #d0d26b
|
||||
!*color11: #c8bc45
|
||||
!*color4 : #77b6c5
|
||||
!*color12: #8fa7b9
|
||||
!*color5: #a488d9
|
||||
!*color13: #bd89de
|
||||
!*color6: #7fcab3
|
||||
!*color14: #6ec2a8
|
||||
!*color7: #8d8d8d
|
||||
!*color15: #dad3d3
|
||||
|
||||
|
||||
|
||||
!! drop in Solarized colorscheme for Xresources
|
||||
!!
|
||||
!! ## Installation
|
||||
!! 1) Write to $HOME/.Xresources
|
||||
!! 2) If not using Xsession, you must add the line `xrdb -merge ~/.Xresources`
|
||||
!! to `.xinitrc`. See http://manpages.ubuntu.com/Xsession for more details.
|
||||
!!
|
||||
!!SOLARIZED HEX 16/8 TERMCOL XTERM/HEX L*A*B RGB HSB
|
||||
!!--------- ------- ---- ------- ----------- ---------- ----------- -----------
|
||||
!!base03 #002b36 8/4 brblack 234 #1c1c1c 15 -12 -12 0 43 54 193 100 21
|
||||
!!base02 #073642 0/4 black 235 #262626 20 -12 -12 7 54 66 192 90 26
|
||||
!!base01 #586e75 10/7 brgreen 240 #585858 45 -07 -07 88 110 117 194 25 46
|
||||
!!base00 #657b83 11/7 bryellow 241 #626262 50 -07 -07 101 123 131 195 23 51
|
||||
!!base0 #839496 12/6 brblue 244 #808080 60 -06 -03 131 148 150 186 13 59
|
||||
!!base1 #93a1a1 14/4 brcyan 245 #8a8a8a 65 -05 -02 147 161 161 180 9 63
|
||||
!!base2 #eee8d5 7/7 white 254 #e4e4e4 92 -00 10 238 232 213 44 11 93
|
||||
!!base3 #fdf6e3 15/7 brwhite 230 #ffffd7 97 00 10 253 246 227 44 10 99
|
||||
!!yellow #b58900 3/3 yellow 136 #af8700 60 10 65 181 137 0 45 100 71
|
||||
!!orange #cb4b16 9/3 brred 166 #d75f00 50 50 55 203 75 22 18 89 80
|
||||
!!red #dc322f 1/1 red 160 #d70000 50 65 45 220 50 47 1 79 86
|
||||
!!magenta #d33682 5/5 magenta 125 #af005f 50 65 -05 211 54 130 331 74 83
|
||||
!!violet #6c71c4 13/5 brmagenta 61 #5f5faf 50 15 -45 108 113 196 237 45 77
|
||||
!!blue #268bd2 4/4 blue 33 #0087ff 55 -10 -45 38 139 210 205 82 82
|
||||
!!cyan #2aa198 6/6 cyan 37 #00afaf 60 -35 -05 42 161 152 175 74 63
|
||||
!!green #859900 2/2 green 64 #5f8700 60 -20 65 133 153 0 68 100 60
|
||||
|
||||
#define S_base03 #002b36
|
||||
#define S_base02 #073642
|
||||
#define S_base01 #586e75
|
||||
#define S_base00 #657b83
|
||||
#define S_base0 #839496
|
||||
#define S_base1 #93a1a1
|
||||
#define S_base2 #eee8d5
|
||||
#define S_base3 #fdf6e3
|
||||
#define S_yellow #b58900
|
||||
#define S_orange #cb4b16
|
||||
#define S_red #dc322f
|
||||
#define S_magenta #d33682
|
||||
#define S_violet #6c71c4
|
||||
#define S_blue #268bd2
|
||||
#define S_cyan #2aa198
|
||||
#define S_green #859900
|
||||
|
||||
!*background: S_base03
|
||||
!*foreground: S_base0
|
||||
*fading: 40
|
||||
*fadeColor: S_base03
|
||||
*cursorColor: S_base1
|
||||
*pointerColorBackground:S_base01
|
||||
*pointerColorForeground:S_base1
|
||||
|
||||
!! black dark/light
|
||||
*color0: S_base02
|
||||
*color8: S_base03
|
||||
|
||||
!! red dark/light
|
||||
*color1: S_red
|
||||
*color9: S_orange
|
||||
|
||||
!! green dark/light
|
||||
*color2: S_green
|
||||
*color10: S_base01
|
||||
|
||||
!! yellow dark/light
|
||||
*color3: S_yellow
|
||||
*color11: S_base00
|
||||
|
||||
!! blue dark/light
|
||||
*color4: S_blue
|
||||
*color12: S_base0
|
||||
|
||||
!! magenta dark/light
|
||||
*color5: S_magenta
|
||||
*color13: S_violet
|
||||
|
||||
!! cyan dark/light
|
||||
*color6: S_cyan
|
||||
*color14: S_base1
|
||||
|
||||
!! white dark/light
|
||||
*color7: S_base2
|
||||
*color15: S_base3
|
||||
|
@ -0,0 +1,588 @@
|
||||
-----------------
|
||||
-- Keybindings --
|
||||
-----------------
|
||||
|
||||
-- Binding aliases
|
||||
local key, buf, but = lousy.bind.key, lousy.bind.buf, lousy.bind.but
|
||||
local cmd, any = lousy.bind.cmd, lousy.bind.any
|
||||
|
||||
-- Util aliases
|
||||
local match, join = string.match, lousy.util.table.join
|
||||
local strip, split = lousy.util.string.strip, lousy.util.string.split
|
||||
|
||||
-- Globals or defaults that are used in binds
|
||||
local scroll_step = globals.scroll_step or 20
|
||||
local zoom_step = globals.zoom_step or 0.1
|
||||
|
||||
-- Add binds to a mode
|
||||
function add_binds(mode, binds, before)
|
||||
assert(binds and type(binds) == "table", "invalid binds table type: " .. type(binds))
|
||||
mode = type(mode) ~= "table" and {mode} or mode
|
||||
for _, m in ipairs(mode) do
|
||||
local mdata = get_mode(m)
|
||||
if mdata and before then
|
||||
mdata.binds = join(binds, mdata.binds or {})
|
||||
elseif mdata then
|
||||
mdata.binds = mdata.binds or {}
|
||||
for _, b in ipairs(binds) do table.insert(mdata.binds, b) end
|
||||
else
|
||||
new_mode(m, { binds = binds })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Add commands to command mode
|
||||
function add_cmds(cmds, before)
|
||||
add_binds("command", cmds, before)
|
||||
end
|
||||
|
||||
-- Adds the default menu widget bindings to a mode
|
||||
menu_binds = {
|
||||
-- Navigate items
|
||||
key({}, "j", function (w) w.menu:move_down() end),
|
||||
key({}, "k", function (w) w.menu:move_up() end),
|
||||
key({}, "Down", function (w) w.menu:move_down() end),
|
||||
key({}, "Up", function (w) w.menu:move_up() end),
|
||||
key({}, "Tab", function (w) w.menu:move_down() end),
|
||||
key({"Shift"}, "Tab", function (w) w.menu:move_up() end),
|
||||
}
|
||||
|
||||
-- Add binds to special mode "all" which adds its binds to all modes.
|
||||
add_binds("all", {
|
||||
key({}, "Escape", "Return to `normal` mode.",
|
||||
function (w) w:set_mode() end),
|
||||
|
||||
key({"Control"}, "[", "Return to `normal` mode.",
|
||||
function (w) w:set_mode() end),
|
||||
|
||||
-- Mouse bindings
|
||||
but({}, 8, "Go back.",
|
||||
function (w) w:back() end),
|
||||
|
||||
but({}, 9, "Go forward.",
|
||||
function (w) w:forward() end),
|
||||
|
||||
-- Open link in new tab or navigate to selection
|
||||
but({}, 2, [[Open link under mouse cursor in new tab or navigate to the
|
||||
contents of `luakit.selection.primary`.]],
|
||||
function (w, m)
|
||||
-- Ignore button 2 clicks in form fields
|
||||
if not m.context.editable then
|
||||
-- Open hovered uri in new tab
|
||||
local uri = w.view.hovered_uri
|
||||
if uri then
|
||||
w:new_tab(uri, false)
|
||||
else -- Open selection in current tab
|
||||
uri = luakit.selection.primary
|
||||
if uri then w:navigate(w:search_open(uri)) end
|
||||
end
|
||||
end
|
||||
end),
|
||||
|
||||
-- Open link in new tab when Ctrl-clicked.
|
||||
but({"Control"}, 1, "Open link under mouse cursor in new tab.",
|
||||
function (w, m)
|
||||
local uri = w.view.hovered_uri
|
||||
if uri then
|
||||
w:new_tab(uri, false)
|
||||
end
|
||||
end),
|
||||
|
||||
-- Zoom binds
|
||||
but({"Control"}, 4, "Increase text zoom level.",
|
||||
function (w, m) w:zoom_in() end),
|
||||
|
||||
but({"Control"}, 5, "Reduce text zoom level.",
|
||||
function (w, m) w:zoom_out() end),
|
||||
|
||||
-- Horizontal mouse scroll binds
|
||||
but({"Shift"}, 4, "Scroll left.",
|
||||
function (w, m) w:scroll{ xrel = -scroll_step } end),
|
||||
|
||||
but({"Shift"}, 5, "Scroll right.",
|
||||
function (w, m) w:scroll{ xrel = scroll_step } end),
|
||||
})
|
||||
|
||||
add_binds("normal", {
|
||||
-- Autoparse the `[count]` before a binding and re-call the hit function
|
||||
-- with the count removed and added to the opts table.
|
||||
any([[Meta-binding to detect the `^[count]` syntax. The `[count]` is parsed
|
||||
and stripped from the internal buffer string and the value assigned to
|
||||
`state.count`. Then `lousy.bind.hit()` is re-called with the modified
|
||||
buffer string & original modifier state.
|
||||
|
||||
#### Example binding
|
||||
|
||||
lousy.bind.key({}, "%", function (w, state)
|
||||
w:scroll{ ypct = state.count }
|
||||
end, { count = 0 })
|
||||
|
||||
This binding demonstrates several concepts. Firstly that you are able to
|
||||
specify per-binding default values of `count`. In this case if the user
|
||||
types `"%"` the document will be scrolled vertically to `0%` (the top).
|
||||
|
||||
If the user types `"100%"` then the document will be scrolled to `100%`
|
||||
(the bottom). All without the need to use `lousy.bind.buf` bindings
|
||||
everywhere and or using a `^(%d*)` pattern prefix on every binding which
|
||||
would like to make use of the `[count]` syntax.]],
|
||||
function (w, m)
|
||||
local count, buf
|
||||
if m.buffer then
|
||||
count = string.match(m.buffer, "^(%d+)")
|
||||
end
|
||||
if count then
|
||||
buf = string.sub(m.buffer, #count + 1, (m.updated_buf and -2) or -1)
|
||||
local opts = join(m, {count = tonumber(count)})
|
||||
opts.buffer = (#buf > 0 and buf) or nil
|
||||
if lousy.bind.hit(w, m.binds, m.mods, m.key, opts) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end),
|
||||
|
||||
key({}, "i", "Enter `insert` mode.",
|
||||
function (w) w:set_mode("insert") end),
|
||||
|
||||
key({}, ":", "Enter `command` mode.",
|
||||
function (w) w:set_mode("command") end),
|
||||
|
||||
-- Scrolling
|
||||
key({}, "j", "Scroll document down.",
|
||||
function (w) w:scroll{ yrel = scroll_step } end),
|
||||
|
||||
key({}, "k", "Scroll document up.",
|
||||
function (w) w:scroll{ yrel = -scroll_step } end),
|
||||
|
||||
key({}, "h", "Scroll document left.",
|
||||
function (w) w:scroll{ xrel = -scroll_step } end),
|
||||
|
||||
key({}, "l", "Scroll document right.",
|
||||
function (w) w:scroll{ xrel = scroll_step } end),
|
||||
|
||||
key({}, "Down", "Scroll document down.",
|
||||
function (w) w:scroll{ yrel = scroll_step } end),
|
||||
|
||||
key({}, "Up", "Scroll document up.",
|
||||
function (w) w:scroll{ yrel = -scroll_step } end),
|
||||
|
||||
key({}, "Left", "Scroll document left.",
|
||||
function (w) w:scroll{ xrel = -scroll_step } end),
|
||||
|
||||
key({}, "Right", "Scroll document right.",
|
||||
function (w) w:scroll{ xrel = scroll_step } end),
|
||||
|
||||
key({}, "^", "Scroll to the absolute left of the document.",
|
||||
function (w) w:scroll{ x = 0 } end),
|
||||
|
||||
key({}, "$", "Scroll to the absolute right of the document.",
|
||||
function (w) w:scroll{ x = -1 } end),
|
||||
|
||||
key({}, "0", "Scroll to the absolute left of the document.",
|
||||
function (w, m)
|
||||
if not m.count then w:scroll{ y = 0 } else return false end
|
||||
end),
|
||||
|
||||
key({"Control"}, "e", "Scroll document down.",
|
||||
function (w) w:scroll{ yrel = scroll_step } end),
|
||||
|
||||
key({"Control"}, "y", "Scroll document up.",
|
||||
function (w) w:scroll{ yrel = -scroll_step } end),
|
||||
|
||||
key({"Control"}, "d", "Scroll half page down.",
|
||||
function (w) w:scroll{ ypagerel = 0.5 } end),
|
||||
|
||||
key({"Control"}, "u", "Scroll half page up.",
|
||||
function (w) w:scroll{ ypagerel = -0.5 } end),
|
||||
|
||||
key({"Control"}, "f", "Scroll page down.",
|
||||
function (w) w:scroll{ ypagerel = 1.0 } end),
|
||||
|
||||
key({"Control"}, "b", "Scroll page up.",
|
||||
function (w) w:scroll{ ypagerel = -1.0 } end),
|
||||
|
||||
key({}, "space", "Scroll page down.",
|
||||
function (w) w:scroll{ ypagerel = 1.0 } end),
|
||||
|
||||
key({"Shift"}, "space", "Scroll page up.",
|
||||
function (w) w:scroll{ ypagerel = -1.0 } end),
|
||||
|
||||
key({}, "BackSpace", "Scroll page up.",
|
||||
function (w) w:scroll{ ypagerel = -1.0 } end),
|
||||
|
||||
key({}, "Page_Down", "Scroll page down.",
|
||||
function (w) w:scroll{ ypagerel = 1.0 } end),
|
||||
|
||||
key({}, "Page_Up", "Scroll page up.",
|
||||
function (w) w:scroll{ ypagerel = -1.0 } end),
|
||||
|
||||
key({}, "Home", "Go to the end of the document.",
|
||||
function (w) w:scroll{ y = 0 } end),
|
||||
|
||||
key({}, "End", "Go to the top of the document.",
|
||||
function (w) w:scroll{ y = -1 } end),
|
||||
|
||||
-- Specific scroll
|
||||
buf("^gg$", "Go to the top of the document.",
|
||||
function (w, b, m) w:scroll{ ypct = m.count } end, {count=0}),
|
||||
|
||||
buf("^G$", "Go to the bottom of the document.",
|
||||
function (w, b, m) w:scroll{ ypct = m.count } end, {count=100}),
|
||||
|
||||
buf("^%%$", "Go to `[count]` percent of the document.",
|
||||
function (w, b, m) w:scroll{ ypct = m.count } end),
|
||||
|
||||
-- Zooming
|
||||
key({}, "+", "Enlarge text zoom of the current page.",
|
||||
function (w, m) w:zoom_in(zoom_step * m.count) end, {count=1}),
|
||||
|
||||
key({}, "-", "Reduce text zom of the current page.",
|
||||
function (w, m) w:zoom_out(zoom_step * m.count) end, {count=1}),
|
||||
|
||||
key({}, "=", "Reset zoom level.",
|
||||
function (w, m) w:zoom_set() end),
|
||||
|
||||
buf("^z[iI]$", [[Enlarge text zoom of current page with `zi` or `zI` to
|
||||
reduce full zoom.]],
|
||||
function (w, b, m)
|
||||
w:zoom_in(zoom_step * m.count, b == "zI")
|
||||
end, {count=1}),
|
||||
|
||||
buf("^z[oO]$", [[Reduce text zoom of current page with `zo` or `zO` to
|
||||
reduce full zoom.]],
|
||||
function (w, b, m)
|
||||
w:zoom_out(zoom_step * m.count, b == "zO")
|
||||
end, {count=1}),
|
||||
|
||||
-- Zoom reset or specific zoom ([count]zZ for full content zoom)
|
||||
buf("^z[zZ]$", [[Set current page zoom to `[count]` percent with
|
||||
`[count]zz`, use `[count]zZ` to set full zoom percent.]],
|
||||
function (w, b, m)
|
||||
w:zoom_set(m.count/100, b == "zZ")
|
||||
end, {count=100}),
|
||||
|
||||
-- Fullscreen
|
||||
key({}, "F11", "Toggle fullscreen mode.",
|
||||
function (w) w.win.fullscreen = not w.win.fullscreen end),
|
||||
|
||||
-- Clipboard
|
||||
key({}, "p", [[Open a URL based on the current primary selection contents
|
||||
in the current tab.]],
|
||||
function (w)
|
||||
local uri = luakit.selection.primary
|
||||
if not uri then w:notify("No primary selection...") return end
|
||||
w:navigate(w:search_open(uri))
|
||||
end),
|
||||
|
||||
key({}, "P", [[Open a URL based on the current primary selection contents
|
||||
in `[count=1]` new tab(s).]],
|
||||
function (w, m)
|
||||
local uri = luakit.selection.primary
|
||||
if not uri then w:notify("No primary selection...") return end
|
||||
for i = 1, m.count do w:new_tab(w:search_open(uri)) end
|
||||
end, {count = 1}),
|
||||
|
||||
-- Yanking
|
||||
key({}, "y", "Yank current URI to primary selection.",
|
||||
function (w)
|
||||
local uri = string.gsub(w.view.uri or "", " ", "%%20")
|
||||
luakit.selection.primary = uri
|
||||
w:notify("Yanked uri: " .. uri)
|
||||
end),
|
||||
|
||||
-- Commands
|
||||
key({"Control"}, "a", "Increment last number in URL.",
|
||||
function (w) w:navigate(w:inc_uri(1)) end),
|
||||
|
||||
key({"Control"}, "x", "Decrement last number in URL.",
|
||||
function (w) w:navigate(w:inc_uri(-1)) end),
|
||||
|
||||
key({}, "o", "Open one or more URLs.",
|
||||
function (w) w:enter_cmd(":open ") end),
|
||||
|
||||
key({}, "t", "Open one or more URLs in a new tab.",
|
||||
function (w) w:enter_cmd(":tabopen ") end),
|
||||
|
||||
key({}, "w", "Open one or more URLs in a new window.",
|
||||
function (w) w:enter_cmd(":winopen ") end),
|
||||
|
||||
key({}, "O", "Open one or more URLs based on current location.",
|
||||
function (w) w:enter_cmd(":open " .. (w.view.uri or "")) end),
|
||||
|
||||
key({}, "T",
|
||||
"Open one or more URLs based on current location in a new tab.",
|
||||
function (w) w:enter_cmd(":tabopen " .. (w.view.uri or "")) end),
|
||||
|
||||
key({}, "W",
|
||||
"Open one or more URLs based on current locaton in a new window.",
|
||||
function (w) w:enter_cmd(":winopen " .. (w.view.uri or "")) end),
|
||||
|
||||
-- History
|
||||
key({}, "H", "Go back in the browser history `[count=1]` items.",
|
||||
function (w, m) w:back(m.count) end),
|
||||
|
||||
key({}, "L", "Go forward in the browser history `[count=1]` times.",
|
||||
function (w, m) w:forward(m.count) end),
|
||||
|
||||
key({}, "XF86Back", "Go back in the browser history.",
|
||||
function (w, m) w:back(m.count) end),
|
||||
|
||||
key({}, "XF86Forward", "Go forward in the browser history.",
|
||||
function (w, m) w:forward(m.count) end),
|
||||
|
||||
key({"Control"}, "o", "Go back in the browser history.",
|
||||
function (w, m) w:back(m.count) end),
|
||||
|
||||
key({"Control"}, "i", "Go forward in the browser history.",
|
||||
function (w, m) w:forward(m.count) end),
|
||||
|
||||
-- Tab
|
||||
key({"Control"}, "Page_Up", "Go to previous tab.",
|
||||
function (w) w:prev_tab() end),
|
||||
|
||||
key({"Control"}, "Page_Down", "Go to next tab.",
|
||||
function (w) w:next_tab() end),
|
||||
|
||||
key({"Control"}, "Tab", "Go to next tab.",
|
||||
function (w) w:next_tab() end),
|
||||
|
||||
key({"Shift","Control"}, "Tab", "Go to previous tab.",
|
||||
function (w) w:prev_tab() end),
|
||||
|
||||
buf("^gT$", "Go to previous tab.",
|
||||
function (w) w:prev_tab() end),
|
||||
|
||||
buf("^gt$", "Go to next tab (or `[count]` nth tab).",
|
||||
function (w, b, m)
|
||||
if not w:goto_tab(m.count) then w:next_tab() end
|
||||
end, {count=0}),
|
||||
|
||||
buf("^g0$", "Go to first tab.",
|
||||
function (w) w:goto_tab(1) end),
|
||||
|
||||
buf("^g$$", "Go to last tab.",
|
||||
function (w) w:goto_tab(-1) end),
|
||||
|
||||
key({"Control"}, "t", "Open a new tab.",
|
||||
function (w) w:new_tab(globals.homepage) end),
|
||||
|
||||
key({"Control"}, "w", "Close current tab.",
|
||||
function (w) w:close_tab() end),
|
||||
|
||||
key({}, "d", "Close current tab (or `[count]` tabs).",
|
||||
function (w, m) for i=1,m.count do w:close_tab() end end, {count=1}),
|
||||
|
||||
key({}, "<", "Reorder tab left `[count=1]` positions.",
|
||||
function (w, m)
|
||||
w.tabs:reorder(w.view, w.tabs:current() - m.count)
|
||||
end, {count=1}),
|
||||
|
||||
key({}, ">", "Reorder tab right `[count=1]` positions.",
|
||||
function (w, m)
|
||||
w.tabs:reorder(w.view,
|
||||
(w.tabs:current() + m.count) % w.tabs:count())
|
||||
end, {count=1}),
|
||||
|
||||
buf("^gH$", "Open homepage in new tab.",
|
||||
function (w) w:new_tab(globals.homepage) end),
|
||||
|
||||
buf("^gh$", "Open homepage.",
|
||||
function (w) w:navigate(globals.homepage) end),
|
||||
|
||||
buf("^gy$", "Duplicate current tab.",
|
||||
function (w) w:new_tab(w.view.history or "") end),
|
||||
|
||||
key({}, "r", "Reload current tab.",
|
||||
function (w) w:reload() end),
|
||||
|
||||
key({}, "R", "Reload current tab (skipping cache).",
|
||||
function (w) w:reload(true) end),
|
||||
|
||||
key({"Control"}, "c", "Stop loading the current tab.",
|
||||
function (w) w.view:stop() end),
|
||||
|
||||
key({"Control", "Shift"}, "R", "Restart luakit (reloading configs).",
|
||||
function (w) w:restart() end),
|
||||
|
||||
-- Window
|
||||
buf("^ZZ$", "Quit and save the session.",
|
||||
function (w) w:save_session() w:close_win() end),
|
||||
|
||||
buf("^ZQ$", "Quit and don't save the session.",
|
||||
function (w) w:close_win() end),
|
||||
|
||||
buf("^D$", "Quit and don't save the session.",
|
||||
function (w) w:close_win() end),
|
||||
|
||||
-- Enter passthrough mode
|
||||
key({"Control"}, "z",
|
||||
"Enter `passthrough` mode, ignores all luakit keybindings.",
|
||||
function (w) w:set_mode("passthrough") end),
|
||||
})
|
||||
|
||||
add_binds("insert", {
|
||||
key({"Control"}, "z",
|
||||
"Enter `passthrough` mode, ignores all luakit keybindings.",
|
||||
function (w) w:set_mode("passthrough") end),
|
||||
})
|
||||
|
||||
readline_bindings = {
|
||||
key({"Shift"}, "Insert",
|
||||
"Insert contents of primary selection at cursor position.",
|
||||
function (w) w:insert_cmd(luakit.selection.primary) end),
|
||||
|
||||
key({"Control"}, "w", "Delete previous word.",
|
||||
function (w) w:del_word() end),
|
||||
|
||||
key({"Control"}, "u", "Delete until beginning of current line.",
|
||||
function (w) w:del_line() end),
|
||||
|
||||
key({"Control"}, "h", "Delete character to the left.",
|
||||
function (w) w:del_backward_char() end),
|
||||
|
||||
key({"Control"}, "d", "Delete character to the right.",
|
||||
function (w) w:del_forward_char() end),
|
||||
|
||||
key({"Control"}, "a", "Move cursor to beginning of current line.",
|
||||
function (w) w:beg_line() end),
|
||||
|
||||
key({"Control"}, "e", "Move cursor to end of current line.",
|
||||
function (w) w:end_line() end),
|
||||
|
||||
key({"Control"}, "f", "Move cursor forward one character.",
|
||||
function (w) w:forward_char() end),
|
||||
|
||||
key({"Control"}, "b", "Move cursor backward one character.",
|
||||
function (w) w:backward_char() end),
|
||||
|
||||
key({"Mod1"}, "f", "Move cursor forward one word.",
|
||||
function (w) w:forward_word() end),
|
||||
|
||||
key({"Mod1"}, "b", "Move cursor backward one word.",
|
||||
function (w) w:backward_word() end),
|
||||
}
|
||||
|
||||
add_binds({"command", "search"}, readline_bindings)
|
||||
|
||||
-- Switching tabs with Mod1+{1,2,3,...}
|
||||
mod1binds = {}
|
||||
for i=1,10 do
|
||||
table.insert(mod1binds,
|
||||
key({"Mod1"}, tostring(i % 10), "Jump to tab at index "..i..".",
|
||||
function (w) w.tabs:switch(i) end))
|
||||
end
|
||||
add_binds("normal", mod1binds)
|
||||
|
||||
-- Command bindings which are matched in the "command" mode from text
|
||||
-- entered into the input bar.
|
||||
add_cmds({
|
||||
buf("^%S+!",
|
||||
[[Detect bang syntax in `:command!` and recursively calls
|
||||
`lousy.bind.match_cmd(..)` removing the bang from the command string
|
||||
and setting `bang = true` in the bind opts table.]],
|
||||
function (w, cmd, opts)
|
||||
local cmd, args = string.match(cmd, "^(%S+)!+(.*)")
|
||||
if cmd then
|
||||
opts = join(opts, { bang = true })
|
||||
return lousy.bind.match_cmd(w, opts.binds, cmd .. args, opts)
|
||||
end
|
||||
end),
|
||||
|
||||
cmd("c[lose]", "Close current tab.",
|
||||
function (w) w:close_tab() end),
|
||||
|
||||
cmd("print", "Print current page.",
|
||||
function (w) w.view:eval_js("print()") end),
|
||||
|
||||
cmd("stop", "Stop loading.",
|
||||
function (w) w.view:stop() end),
|
||||
|
||||
cmd("reload", "Reload page",
|
||||
function (w) w:reload() end),
|
||||
|
||||
cmd("restart", "Restart browser (reload config files).",
|
||||
function (w) w:restart() end),
|
||||
|
||||
cmd("write", "Save current session.",
|
||||
function (w) w:save_session() end),
|
||||
|
||||
cmd("noh[lsearch]", "Clear search highlighting.",
|
||||
function (w) w:clear_search() end),
|
||||
|
||||
cmd("back", "Go back in the browser history `[count=1]` items.",
|
||||
function (w, a) w:back(tonumber(a) or 1) end),
|
||||
|
||||
cmd("f[orward]", "Go forward in the browser history `[count=1]` items.",
|
||||
function (w, a) w:forward(tonumber(a) or 1) end),
|
||||
|
||||
cmd("inc[rease]", "Increment last number in URL.",
|
||||
function (w, a) w:navigate(w:inc_uri(tonumber(a) or 1)) end),
|
||||
|
||||
cmd("o[pen]", "Open one or more URLs.",
|
||||
function (w, a) w:navigate(w:search_open(a)) end),
|
||||
|
||||
cmd("t[abopen]", "Open one or more URLs in a new tab.",
|
||||
function (w, a) w:new_tab(w:search_open(a)) end),
|
||||
|
||||
cmd("w[inopen]", "Open one or more URLs in a new window.",
|
||||
function (w, a) window.new{w:search_open(a)} end),
|
||||
|
||||
cmd({"javascript", "js"}, "Evaluate JavaScript snippet.",
|
||||
function (w, a) w.view:eval_js(a) end),
|
||||
|
||||
-- Tab manipulation commands
|
||||
cmd("tab", "Execute command and open result in new tab.",
|
||||
function (w, a) w:new_tab() w:run_cmd(":" .. a) end),
|
||||
|
||||
cmd("tabd[o]", "Execute command in each tab.",
|
||||
function (w, a) w:each_tab(function (v) w:run_cmd(":" .. a) end) end),
|
||||
|
||||
cmd("tabdu[plicate]", "Duplicate current tab.",
|
||||
function (w) w:new_tab(w.view.history) end),
|
||||
|
||||
cmd("tabfir[st]", "Switch to first tab.",
|
||||
function (w) w:goto_tab(1) end),
|
||||
|
||||
cmd("tabl[ast]", "Switch to last tab.",
|
||||
function (w) w:goto_tab(-1) end),
|
||||
|
||||
cmd("tabn[ext]", "Switch to the next tab.",
|
||||
function (w) w:next_tab() end),
|
||||
|
||||
cmd("tabp[revious]", "Switch to the previous tab.",
|
||||
function (w) w:prev_tab() end),
|
||||
|
||||
cmd("q[uit]", "Close the current window.",
|
||||
function (w, a, o) w:close_win(o.bang) end),
|
||||
|
||||
cmd({"viewsource", "vs"}, "View the source code of the current document.",
|
||||
function (w, a, o) w:toggle_source(not o.bang and true or nil) end),
|
||||
|
||||
cmd({"wqall", "wq"}, "Save the session and quit.",
|
||||
function (w, a, o) w:save_session() w:close_win(o.bang) end),
|
||||
|
||||
cmd("lua", "Evaluate Lua snippet.", function (w, a)
|
||||
if a then
|
||||
local ret = assert(
|
||||
loadstring("return function(w) return "..a.." end"))()(w)
|
||||
if ret then print(ret) end
|
||||
else
|
||||
w:set_mode("lua")
|
||||
end
|
||||
end),
|
||||
|
||||
cmd("dump", "Dump current tabs html to file.",
|
||||
function (w, a)
|
||||
local fname = string.gsub(w.win.title, '[^%w%.%-]', '_')..'.html' -- sanitize filename
|
||||
local file = a or luakit.save_file("Save file", w.win, xdg.download_dir or '.', fname)
|
||||
if file then
|
||||
local fd = assert(io.open(file, "w"), "failed to open: " .. file)
|
||||
local html = assert(w.view:eval_js("document.documentElement.outerHTML"), "Unable to get HTML")
|
||||
assert(fd:write(html), "unable to save html")
|
||||
io.close(fd)
|
||||
w:notify("Dumped HTML to: " .. file)
|
||||
end
|
||||
end),
|
||||
})
|
||||
|
||||
-- vim: et:sw=4:ts=8:sts=4:tw=80
|
@ -0,0 +1,85 @@
|
||||
-- Global variables for luakit
|
||||
globals = {
|
||||
homepage = "http://luakit.org/",
|
||||
-- homepage = "http://github.com/mason-larobina/luakit",
|
||||
scroll_step = 40,
|
||||
zoom_step = 0.1,
|
||||
max_cmd_history = 100,
|
||||
max_srch_history = 100,
|
||||
-- http_proxy = "http://example.com:3128",
|
||||
default_window_size = "800x600",
|
||||
|
||||
-- Disables loading of hostnames from /etc/hosts (for large host files)
|
||||
-- load_etc_hosts = false,
|
||||
-- Disables checking if a filepath exists in search_open function
|
||||
-- check_filepath = false,
|
||||
}
|
||||
|
||||
-- Make useragent
|
||||
local _, arch = luakit.spawn_sync("uname -sm")
|
||||
-- Only use the luakit version if in date format (reduces identifiability)
|
||||
local lkv = string.match(luakit.version, "^(%d+.%d+.%d+)")
|
||||
globals.useragent = string.format("Mozilla/5.0 (%s) AppleWebKit/%s+ (KHTML, like Gecko) WebKitGTK+/%s luakit%s",
|
||||
string.sub(arch, 1, -2), luakit.webkit_user_agent_version,
|
||||
luakit.webkit_version, (lkv and ("/" .. lkv)) or "")
|
||||
|
||||
-- Search common locations for a ca file which is used for ssl connection validation.
|
||||
local ca_files = {
|
||||
-- $XDG_DATA_HOME/luakit/ca-certificates.crt
|
||||
luakit.data_dir .. "/ca-certificates.crt",
|
||||
"/etc/certs/ca-certificates.crt",
|
||||
"/etc/ssl/certs/ca-certificates.crt",
|
||||
}
|
||||
-- Use the first ca-file found
|
||||
for _, ca_file in ipairs(ca_files) do
|
||||
if os.exists(ca_file) then
|
||||
soup.ssl_ca_file = ca_file
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Change to stop navigation sites with invalid or expired ssl certificates
|
||||
soup.ssl_strict = false
|
||||
|
||||
-- Set cookie acceptance policy
|
||||
cookie_policy = { always = 0, never = 1, no_third_party = 2 }
|
||||
soup.accept_policy = cookie_policy.always
|
||||
|
||||
-- List of search engines. Each item must contain a single %s which is
|
||||
-- replaced by URI encoded search terms. All other occurances of the percent
|
||||
-- character (%) may need to be escaped by placing another % before or after
|
||||
-- it to avoid collisions with lua's string.format characters.
|
||||
-- See: http://www.lua.org/manual/5.1/manual.html#pdf-string.format
|
||||
search_engines = {
|
||||
duckduckgo = "https://duckduckgo.com/?q=%s",
|
||||
github = "https://github.com/search?q=%s",
|
||||
google = "https://google.com/search?q=%s",
|
||||
imdb = "http://www.imdb.com/find?s=all&q=%s",
|
||||
wikipedia = "https://en.wikipedia.org/wiki/Special:Search?search=%s",
|
||||
}
|
||||
|
||||
-- Set google as fallback search engine
|
||||
search_engines.default = search_engines.google
|
||||
-- Use this instead to disable auto-searching
|
||||
--search_engines.default = "%s"
|
||||
|
||||
-- Per-domain webview properties
|
||||
-- See http://webkitgtk.org/reference/webkitgtk/stable/WebKitWebSettings.html
|
||||
domain_props = { --[[
|
||||
["all"] = {
|
||||
enable_scripts = false,
|
||||
enable_plugins = false,
|
||||
enable_private_browsing = false,
|
||||
user_stylesheet_uri = "",
|
||||
},
|
||||
["youtube.com"] = {
|
||||
enable_scripts = true,
|
||||
enable_plugins = true,
|
||||
},
|
||||
["bbs.archlinux.org"] = {
|
||||
user_stylesheet_uri = "file://" .. luakit.data_dir .. "/styles/dark.css",
|
||||
enable_private_browsing = true,
|
||||
}, ]]
|
||||
}
|
||||
|
||||
-- vim: et:sw=4:ts=8:sts=4:tw=80
|
@ -0,0 +1,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},
|
||||
})
|
@ -0,0 +1,216 @@
|
||||
----------------------------------------------------------------
|
||||
-- Multi-Session save/restore Plugin --
|
||||
----------------------------------------------------------------
|
||||
|
||||
local ipairs = ipairs
|
||||
local tostring = tostring
|
||||
local lfs = lfs
|
||||
local os = os
|
||||
local io = io
|
||||
local table = table
|
||||
local string = string
|
||||
local unpack = unpack
|
||||
local lousy = require "lousy"
|
||||
local util = lousy.util
|
||||
local luakit = luakit
|
||||
local window = window
|
||||
local add_binds, add_cmds = add_binds, add_cmds
|
||||
local new_mode, menu_binds = new_mode, menu_binds
|
||||
local cmd = lousy.bind.cmd
|
||||
local buf = lousy.bind.buf
|
||||
|
||||
module("plugins.multisession")
|
||||
|
||||
local sessions_dir = luakit.data_dir .. "/sessions"
|
||||
|
||||
local rm = function (file)
|
||||
luakit.spawn(string.format("rm %q", file))
|
||||
end
|
||||
|
||||
local session_save = function (w, name)
|
||||
if not name then return end
|
||||
local fpath = sessions_dir .. "/" .. (name or "")
|
||||
-- Save all given windows uris to file.
|
||||
local lines = {}
|
||||
-- Save tabs from all the given window, keep the window-index to keep
|
||||
-- comptability with default sessions format
|
||||
local current = w.tabs:current()
|
||||
for ti, tab in ipairs(w.tabs.children) do
|
||||
table.insert(lines, string.format("%d\t%d\t%s\t%s", 1, ti,
|
||||
tostring(current == ti), tab.uri))
|
||||
end
|
||||
-- Only save a non-empty session
|
||||
if #lines > 0 then
|
||||
local fh = io.open(fpath, "w")
|
||||
fh:write(table.concat(lines, "\n"))
|
||||
io.close(fh)
|
||||
else
|
||||
rm(session.file)
|
||||
end
|
||||
end
|
||||
|
||||
local session_load = function (name)
|
||||
local fpath = sessions_dir .. "/" .. (name or "")
|
||||
if not name or not os.exists(fpath) then return end
|
||||
local ret = {}
|
||||
|
||||
-- Read file
|
||||
local lines = {}
|
||||
local fh = io.open(fpath, "r")
|
||||
for line in fh:lines() do table.insert(lines, line) end
|
||||
io.close(fh)
|
||||
|
||||
-- Parse session file, again, ignore the window-index, keeping for
|
||||
-- compatibility
|
||||
for _, line in ipairs(lines) do
|
||||
local wi, ti, current, uri = unpack(util.string.split(line, "\t"))
|
||||
current = (current == "true")
|
||||
table.insert(ret, {uri = uri, current = current})
|
||||
end
|
||||
|
||||
return (#ret > 0 and ret) or nil
|
||||
end
|
||||
|
||||
-- Create a new window and open all tabs in the session in it
|
||||
local session_restore = function (name)
|
||||
win = session_load(name)
|
||||
if not win or #win == 0 then return end
|
||||
|
||||
-- Spawn windows
|
||||
local w
|
||||
for _, item in ipairs(win) do
|
||||
if not w then
|
||||
w = window.new({item.uri})
|
||||
else
|
||||
w:new_tab(item.uri, item.current)
|
||||
end
|
||||
end
|
||||
return w
|
||||
end
|
||||
|
||||
-- Opens all tabs in named session in current window
|
||||
local session_append = function (w, name)
|
||||
ses = session_load(name)
|
||||
if not ses or #ses == 0 then return false end
|
||||
for _, item in ipairs(ses) do
|
||||
w:new_tab(item.uri, item.current)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local session_del = function (name)
|
||||
if not name then return end
|
||||
local fpath = sessions_dir .. "/" .. (name or "")
|
||||
if not os.exists(fpath) then return false end
|
||||
rm(fpath)
|
||||
return true
|
||||
end
|
||||
|
||||
local load = function ()
|
||||
local curdir = lfs.currentdir()
|
||||
if not lfs.chdir(sessions_dir) then
|
||||
lfs.mkdir(sessions_dir)
|
||||
else
|
||||
lfs.chdir(curdir)
|
||||
end
|
||||
end
|
||||
|
||||
add_cmds({
|
||||
cmd("session", "view list of sessions", function (w) w:set_mode("sessionmenu") end),
|
||||
cmd({"session-write", "sw"}, "save a session to file",
|
||||
function (w, a)
|
||||
local name = util.string.strip(a) or "default"
|
||||
session_save(w, name)
|
||||
w:notify("Saved " .. tostring(w.tabs:count()) .. " tabs to session " .. name .. ".")
|
||||
end),
|
||||
cmd({"session-delete", "sd"}, "delete a saved session",
|
||||
function(w, a)
|
||||
local name = util.string.strip(a)
|
||||
if session_del(name) then
|
||||
w:notify("Deleted session " .. name .. ".")
|
||||
else
|
||||
w:error("No saved session named " .. name .."!")
|
||||
end
|
||||
end),
|
||||
cmd({"session-restore", "sr"}, "load a saved session in a new window",
|
||||
function(w, a)
|
||||
local name = util.string.strip(a) or "default"
|
||||
if not session_restore(name) then
|
||||
w:error("Unable to restore session " .. name .. "!")
|
||||
end
|
||||
end),
|
||||
cmd({"session-open", "so"}, "open a saved session in new tabs in current window",
|
||||
function(w, a)
|
||||
local name = util.string.strip(a) or "default"
|
||||
if not session_append(w, name) then
|
||||
w:error("Unable to open session " .. name .. "!")
|
||||
else
|
||||
w:notify("Appended session " .. name .. " to tabs.")
|
||||
end
|
||||
end),
|
||||
})
|
||||
|
||||
add_binds("normal", {
|
||||
buf("^sm$", "open list of saved sessions", function(w) w:set_mode("sessionmenu") end),
|
||||
})
|
||||
|
||||
|
||||
|
||||
new_mode("sessionmenu", {
|
||||
enter = function (w)
|
||||
local rows = {{"Saved Sessions (# of tabs)", title = true}}
|
||||
|
||||
for filename in lfs.dir(sessions_dir) do
|
||||
if not string.match(filename, "^%.-$") then
|
||||
local fh = io.open(sessions_dir .. "/" .. filename)
|
||||
local tabcnt = 0
|
||||
for _ in fh:lines() do tabcnt = tabcnt + 1 end
|
||||
io.close(fh)
|
||||
table.insert(rows, {string.format(" %s (%d)", filename, tabcnt), name = filename})
|
||||
end
|
||||
end
|
||||
if #rows == 1 then
|
||||
table.insert(rows, {"No saved sessions!"})
|
||||
end
|
||||
w.menu:build(rows)
|
||||
w:notify("Use j/k to move, d to delete a session, t to append session to current window, Enter to open session (in new window)", false)
|
||||
end,
|
||||
|
||||
leave = function (w)
|
||||
w.menu:hide()
|
||||
end,
|
||||
})
|
||||
|
||||
local key = lousy.bind.key
|
||||
add_binds("sessionmenu", lousy.util.table.join({
|
||||
key({}, "Return", function (w)
|
||||
local row = w.menu:get()
|
||||
if row and row.name then
|
||||
w:set_mode()
|
||||
session_restore(row.name)
|
||||
end
|
||||
end),
|
||||
|
||||
key({}, "t", function (w)
|
||||
local row = w.menu:get()
|
||||
if row and row.name then
|
||||
w:set_mode()
|
||||
session_append(w, row.name)
|
||||
end
|
||||
end),
|
||||
|
||||
key({}, "d", function (w)
|
||||
local row = w.menu:get()
|
||||
if row and row.name then
|
||||
w.menu:del()
|
||||
session_del(row.name)
|
||||
end
|
||||
end),
|
||||
|
||||
-- Exit menu
|
||||
key({}, "q", function (w) w:set_mode() end),
|
||||
|
||||
}, menu_binds))
|
||||
|
||||
load()
|
||||
-- vim: et:sw=4:ts=8:sts=4:tw=80
|
@ -0,0 +1,66 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- --
|
||||
-- No-Scipt Status Widget --
|
||||
-- Adds a simple, skinnable, widget to the status bar to indicate the --
|
||||
-- current status of scripts and plugins --
|
||||
-- --
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local string = string
|
||||
local window = window
|
||||
local webview = webview
|
||||
local widget = widget
|
||||
local theme = theme
|
||||
local luakit = luakit
|
||||
local domain_props = domain_props
|
||||
local lousy = require("lousy")
|
||||
local history = require("history")
|
||||
|
||||
module("plugins.nscript_widget")
|
||||
|
||||
-- Strings widget uses
|
||||
local script_str = { enabled = "s", disabled = "!s" }
|
||||
local plugin_str = { enabled = "p", disabled = "!p" }
|
||||
|
||||
|
||||
-- Load themes, if undefined fallback
|
||||
theme.nsw_enabled = theme.nsw_enabled or "#0f0"
|
||||
theme.nsw_disabled = theme.nsw_disabled or "#f00"
|
||||
|
||||
-- Create the indictor widget on window creation
|
||||
window.init_funcs.build_ns_indicator = function(w)
|
||||
local i = w.sbar.r
|
||||
i.noscr = widget{type="label"}
|
||||
i.layout:pack(w.sbar.r.noscr)
|
||||
i.layout:reorder(w.sbar.r.noscr, 2)
|
||||
i.noscr.font = theme.buf_sbar_font
|
||||
w:update_noscr()
|
||||
-- Update indicator on tab change
|
||||
w.tabs:add_signal("switch-page", function (_,view)
|
||||
luakit.idle_add(function() w:update_noscr(w) return false end)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Update indicator on page navigation
|
||||
webview.init_funcs.noscr_update = function(view, w)
|
||||
view:add_signal("load-status", function (v, status)
|
||||
if status == "committed" or status == "failed" or status == "finished" then
|
||||
w:update_noscr()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Method wrapper
|
||||
window.methods.update_noscr = function(w)
|
||||
if not w.view then return end
|
||||
local scripts = w.view.enable_scripts
|
||||
local plugins = w.view.enable_plugins
|
||||
local noscr = w.sbar.r.noscr
|
||||
local tmpl = '<span foreground="%s">%s</span> <span foreground="%s">%s</span>'
|
||||
noscr.text = string.format(tmpl,
|
||||
( scripts and theme.nsw_enabled ) or theme.nsw_disabled,
|
||||
( scripts and script_str.enabled ) or script_str.disabled,
|
||||
( plugins and theme.nsw_enabled ) or theme.nsw_disabled,
|
||||
( plugins and plugin_str.enabled ) or plugin_str.disabled)
|
||||
noscr:show()
|
||||
end
|
@ -0,0 +1,969 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- Advanced URI-based content filter v0.1.1a --
|
||||
-- Combines functionality of AdBlock via pattern-match based blocking, --
|
||||
-- domain/sub-domain matching white and black listing, --
|
||||
-- a RequestPolicy-like rule system to default-deny 3rd-party requests --
|
||||
-- and rough per-domain file-type filtering based on URI patterns --
|
||||
-- --
|
||||
-- Disclaimer: while this is intended to increase browser security and --
|
||||
-- help protect privacy, there is no guarantee. Rely on it at your own risk! --
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local info = info
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
local assert = assert
|
||||
local unpack = unpack
|
||||
local type = type
|
||||
local io = io
|
||||
local os = os
|
||||
local string = string
|
||||
local table = table
|
||||
local tostring = tostring
|
||||
local tonumber = tonumber
|
||||
local webview = webview
|
||||
local window = window
|
||||
local lousy = require("lousy")
|
||||
local theme = theme
|
||||
local widget = widget
|
||||
local util = lousy.util
|
||||
local chrome = require("chrome")
|
||||
local capi = { luakit = luakit , sqlite3 = sqlite3 }
|
||||
local sql_escape = lousy.util.sql_escape
|
||||
local add_binds, add_cmds = add_binds, add_cmds
|
||||
local new_mode, menu_binds = new_mode, menu_binds
|
||||
local lfs = require("lfs")
|
||||
local setmetatable = setmetatable
|
||||
|
||||
-- Public Suffix Lib
|
||||
local tld = require("tld")
|
||||
local getdomain = tld.getdomain
|
||||
|
||||
-- Calls modifed adblock
|
||||
--local adblock = require("plugins.adblock")
|
||||
|
||||
module("plugins.policy")
|
||||
|
||||
pdebug = function (...) io.stdout:write(string.format(...) .. "\n") end
|
||||
|
||||
-- Settings Flags =============================================================
|
||||
filtering = {
|
||||
-- Flag to accept all requests (disabled all blocking)
|
||||
acceptall = false,
|
||||
-- Flag to enable/disable AdBlock / Pattern-Based Blocking
|
||||
adblock = true,
|
||||
-- Flag to enable/disable additional scrutiny of 3rd-party requests
|
||||
requestpolicy = true,
|
||||
-- Flag to enable/disable file-type blocking policy
|
||||
typepolicy = true,
|
||||
-- Flag for whether a subdomain is treated as a 3rd party relative to other subdomains or master domain
|
||||
strictsubdomain = false,
|
||||
-- Flas for whether to show status bar widget
|
||||
widget = true
|
||||
}
|
||||
|
||||
local policy_dir = capi.luakit.data_dir
|
||||
|
||||
-- Below is the actual internals of the plugin, here be dragons ---------------
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
-- Cache to reduce sql calls
|
||||
local cache = {}
|
||||
setmetatable(cache, { __mode = "k" })
|
||||
|
||||
-- A table to store data for navigation and resource requests
|
||||
-- it has per-view instances, indexed via navto[v].fields
|
||||
local navto = {}
|
||||
setmetatable(navto, { __mode = "k" })
|
||||
|
||||
-- Exception listing
|
||||
local exlist = { white = {}, third = {white = {} } }
|
||||
|
||||
-- Makes the following more clear... eg: return codes and internal constants
|
||||
-- allowing is zero so that reasons for denial can be communicated
|
||||
local ALLOW = 0
|
||||
local DENIED = { BLACKLIST = 1, ADBLOCK = 2, NO_WHITELIST = 3, BLACKLISTED_TP = 4 , BLOCKED_TYPE = 5 }
|
||||
local ANY_PARTY, THIRD_PARTY = 1, 2
|
||||
local reasonstring = {"Blacklisted", "ABP", "CDR", "Blacklisted-CDR", "F-TYPE", "Other"}
|
||||
|
||||
-- sqlite command stings
|
||||
local create_tables = [[
|
||||
PRAGMA synchronous = OFF;
|
||||
PRAGMA secure_delete = 1;
|
||||
CREATE TABLE IF NOT EXISTS whitelist (
|
||||
id INTEGER PRIMARY KEY,
|
||||
domain TEXT UNIQUE);
|
||||
CREATE TABLE IF NOT EXISTS blacklist (
|
||||
id INTEGER PRIMARY KEY,
|
||||
domain TEXT UNIQUE);
|
||||
CREATE TABLE IF NOT EXISTS tp_whitelist (
|
||||
id INTEGER PRIMARY KEY,
|
||||
domain TEXT,
|
||||
rdomain TEXT);
|
||||
CREATE TABLE IF NOT EXISTS tp_blacklist (
|
||||
id INTEGER PRIMARY KEY,
|
||||
domain TEXT,
|
||||
rdomain TEXT);
|
||||
]]
|
||||
|
||||
local sql_format = {
|
||||
match_list = "SELECT * FROM %slist WHERE domain == %s;",
|
||||
add_list = "INSERT INTO %slist VALUES (NULL, %s);",
|
||||
remove_list = "DELETE FROM %slist WHERE domain == %s;",
|
||||
match_tp_list = "SELECT * FROM tp_%slist WHERE domain == %s and rdomain == %s;",
|
||||
add_tp_list = "INSERT INTO tp_%slist VALUES (NULL, %s, %s);",
|
||||
remove_tp_list_exact = "DELETE FROM tp_%slist WHERE domain == %s and rdomain == %s;",
|
||||
|
||||
remove_tp_list_domain = "DELETE FROM tp_%slist WHERE domain == %s;",
|
||||
remove_tp_list_rdomain = "DELETE FROM tp_%slist WHERE rdomain == %s;",
|
||||
}
|
||||
|
||||
-- Open or create & initiaze dbi
|
||||
initalize_rpdb = function()
|
||||
if rpdb then return end
|
||||
rpdb = capi.sqlite3{ filename = policy_dir .. "/policy.db" }
|
||||
rpdb:exec(create_tables)
|
||||
end
|
||||
|
||||
-- Helper functions that perform various utility functions ========================
|
||||
|
||||
-- Attempt to parse a uri for the extension of the requested file
|
||||
-- return file extension in lower case or "NONE" if no extension
|
||||
local getextension = function (uri)
|
||||
if uri then
|
||||
local puri = lousy.uri.parse(uri)
|
||||
local ext = string.match(puri and puri.path or "", "%.([a-zA-Z0-9]-)$")
|
||||
return ext and string.lower(ext) or "NONE"
|
||||
end
|
||||
return "NONE"
|
||||
end
|
||||
|
||||
-- Check if query is domain or a subdomain of host
|
||||
local subdomainmatch = function(host, query)
|
||||
if host == query then
|
||||
return true
|
||||
else
|
||||
local abits = util.string.split(string.reverse(host or ""), "%.")
|
||||
local bbits = util.string.split(string.reverse(query or ""), "%.")
|
||||
-- If host is an IP abort, eg: 10.8.4.1 is not a subdomain of 8.4.1
|
||||
if host and string.match(host, "^%d%.%d%.%d%.%d$") then return false end
|
||||
-- TODO ipv6 match
|
||||
for i,s in ipairs(abits) do
|
||||
if s ~= bbits[i] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- Checks domains for a match
|
||||
local domainmatch = function (a, b)
|
||||
-- If main uri (a) is nil, then it is always "first party"
|
||||
-- If a == b then they are the same domain
|
||||
-- Otherwise do a match score and make a fuzzy match
|
||||
if not a or a == b then
|
||||
return true
|
||||
elseif not filtering.strictsubdomain then
|
||||
local abits = util.string.split(string.reverse(a) or "", "%.")
|
||||
local bbits = util.string.split(string.reverse(b) or "", "%.")
|
||||
local matching = 0
|
||||
-- If an IP, don't do partial matches, TODO ipv6 match
|
||||
if string.match(a, "^%d%.%d%.%d%.%d$") then return false end
|
||||
-- Count matching bits
|
||||
for i,s in ipairs(abits) do
|
||||
if s == bbits[i] then
|
||||
matching = matching + 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
-- Check the effective tlds of a and b and use that + 1 as the minimum matching requirement
|
||||
local ab = util.string.split(getdomain(a), "%.")
|
||||
local bb = util.string.split(getdomain(b), "%.")
|
||||
local needed_match = ( (#ab > #bb) and #ab) or #bb
|
||||
if matching >= needed_match then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Returns whether or not rhost is whitelisted
|
||||
local islisted = function (host, rhost, typ, party)
|
||||
if party == THIRD_PARTY then
|
||||
local host_bits = util.table.reverse(util.string.split(host or "", "%.") or {})
|
||||
-- Get base domain, we do not want to match vs. just public suffixes
|
||||
local n = 1
|
||||
local phost = getdomain(host)
|
||||
if not string.match(phost, "^[0-9%.]$") then
|
||||
local pbits = util.string.split(phost, "%.")
|
||||
n = #pbits + 1
|
||||
else
|
||||
n = #host_bits
|
||||
end
|
||||
local list, tlist
|
||||
-- Make list to match rhost against, use cache if valid
|
||||
if cache[host] and cache[host][typ] then
|
||||
list = cache[host][typ]
|
||||
if typ == "white" then
|
||||
tlist = exlist.third.white["all"]
|
||||
repeat
|
||||
tlist = util.table.join(tlist, exlist.third.white[phost] or {})
|
||||
phost = (host_bits[n] or "").. "." .. phost
|
||||
n = n + 1
|
||||
until n > #host_bits + 1
|
||||
end
|
||||
else
|
||||
list = rpdb:exec(string.format("SELECT * FROM tp_%slist WHERE domain = %s;", typ, sql_escape("all")))
|
||||
tlist = exlist.third.white["all"]
|
||||
repeat
|
||||
local rows = rpdb:exec(string.format("SELECT * FROM tp_%slist WHERE domain = %s;", typ, sql_escape(phost)))
|
||||
list = util.table.join(list, rows or {})
|
||||
if typ == "white" then
|
||||
tlist = util.table.join(tlist, exlist.third.white[phost] or {})
|
||||
end
|
||||
phost = (host_bits[n] or "").. "." .. phost
|
||||
n = n + 1
|
||||
until n > #host_bits + 1
|
||||
-- Save list in cache
|
||||
if not cache[host] then cache[host] = {} end
|
||||
cache[host][typ] = list
|
||||
end
|
||||
-- Match vs lists
|
||||
for _,v in pairs(list) do
|
||||
if subdomainmatch(v.rdomain, rhost) or v.rdomain == "all" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
-- Only check exceptions if checking a whitelist
|
||||
if typ == "white" then
|
||||
for k,v in pairs(tlist) do
|
||||
if subdomainmatch(v, rhost) or v == "all" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
else
|
||||
local list
|
||||
if cache[typ] then
|
||||
list = cache[typ]
|
||||
else
|
||||
list = rpdb:exec(string.format("SELECT * FROM %slist;", typ))
|
||||
cache[typ] = list
|
||||
end
|
||||
|
||||
for _,v in pairs(list) do
|
||||
if subdomainmatch(v.domain, rhost) then
|
||||
return true;
|
||||
end
|
||||
end
|
||||
-- Only check exceptions if checking a whitelist
|
||||
if typ == "white" then
|
||||
for k,v in pairs(exlist.white) do
|
||||
if subdomainmatch(k, rhost) then
|
||||
return true;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- No match was found
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check Pattern list for matches to rules (aka AdBlocking)
|
||||
local patternMatch = function (req)
|
||||
-- This checks that the AdBlock Module is loaded, and if so it calls the matching function
|
||||
-- I originally intended to re-implement this as part of this plugin, but I decided that
|
||||
-- it was better to just use a minimally modified version of the upstream AdBlock plugin
|
||||
if filtering.adblock and adblock and adblock.match then
|
||||
return not adblock.match(req, "none")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Main logic checking if a request should be allowed or denied
|
||||
local checkpolicy = function (host, requested, nav, firstnav)
|
||||
-- A request for a nil uri is denied (should never happen)
|
||||
if not requested then
|
||||
return DENIED.BLACKLIST
|
||||
end
|
||||
-- Should always accept these
|
||||
if string.match(requested, "about:blank") or filtering.acceptall then
|
||||
return ACCEPT
|
||||
end
|
||||
-- Get host from requested uri and file-type extension
|
||||
local rpuri = lousy.uri.parse(requested)
|
||||
local req = { host = string.lower(rpuri and rpuri.host or ""), ftype = getextension(requested) }
|
||||
-- webview.uri is nil for the first requests when loading a page (they are always first party)
|
||||
local puri = lousy.uri.parse(host or "")
|
||||
host = puri and puri.host or req.host
|
||||
|
||||
local wlisted = false
|
||||
-- Skip checks for data: uris - they would be covered by the policies of whatever they were embedded in
|
||||
if not string.match(requested, "^data:") then
|
||||
-- Blacklisting overrides whitelist
|
||||
if islisted(nil, req.host, "black", ANY_PARTY) then
|
||||
return DENIED.BLACKLIST
|
||||
end
|
||||
|
||||
-- Check if requested domain is whitelisted
|
||||
wlisted = islisted(nil, req.host, "white", ANY_PARTY)
|
||||
|
||||
-- Whitelisting overrides AdBlocking/Pattern Block
|
||||
if not wlisted and filtering.adblock then
|
||||
-- If AdBlock / Pattern matching is enabled, check if requested uri matches and should be blocked
|
||||
if patternMatch(requested) then
|
||||
return DENIED.ADBLOCK
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- If RequestPolicy is disabled or this is a first party request only type-blocking is checked
|
||||
-- If this is a a navigation request or the first request post-navigation, relax CDR, we likely clicked on a link
|
||||
-- data: uri's are not cross-domain, however we might want to check those with file filtering
|
||||
if nav or firstnav or not filtering.requestpolicy or domainmatch(host, req.host) or string.match(requested, "^data:")then
|
||||
-- TODO: file-type blocking
|
||||
return ACCEPT
|
||||
else
|
||||
-- Check if this domain is blacklised for ALL 3rd-party requests -OR-
|
||||
-- blacklisted for 3rd party requests for the main domain
|
||||
if islisted(host, req.host, "black", THIRD_PARTY) then
|
||||
return DENIED.BLACKLISTED_TP
|
||||
end
|
||||
|
||||
-- If requested host is whitelisted universally or for this host for this third party, set to accept
|
||||
local wlistedtp = islisted(host, req.host, "white", THIRD_PARTY)
|
||||
if not wlistedtp then
|
||||
return DENIED.NO_WHITELIST
|
||||
end
|
||||
-- TODO: file-type blocking that overrides whitelisted 3rd party requrests
|
||||
return ACCEPT
|
||||
end
|
||||
end
|
||||
|
||||
-- Make a table of request's hosts and keep a count of accepted and denied requests
|
||||
local concatRes = function (l, uri, r)
|
||||
if uri then
|
||||
local puri = lousy.uri.parse(uri)
|
||||
if puri and puri.host then
|
||||
-- If the host doesn't have a table yet, add it
|
||||
if not l[puri.host] then
|
||||
l[puri.host] = {accept = 0, deny = 0, reasons = {}}
|
||||
end
|
||||
-- Increment counter (s)
|
||||
if not r then
|
||||
l[puri.host].accept = 1 + l[puri.host].accept
|
||||
else
|
||||
l[puri.host].deny = 1 + l[puri.host].deny
|
||||
-- TODO get make this not so hacky ??
|
||||
l[puri.host].reasons[reasonstring[r]] = (l[puri.host].reasons[reasonstring[r]] or 0) + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Connect signals to all webview widgets on creation
|
||||
-- TODO check robustness of the firstnav system
|
||||
webview.init_funcs.policu_signals = function (view, w)
|
||||
view:add_signal("navigation-request",
|
||||
function (v, uri)
|
||||
-- Check if request should be accepted or denied
|
||||
local r = checkpolicy(v.uri, uri, true , false)
|
||||
|
||||
-- if navto[v] does not exist set to empty table
|
||||
navto[v] = navto[v] or {}
|
||||
|
||||
-- Only do the following if request was accepted (r = 0)
|
||||
if not r then
|
||||
-- Set temp navigation uri to the requested uri
|
||||
navto[v].uri = uri
|
||||
-- Make an empty request table if one does not exist
|
||||
navto[v].res = navto[v].res or {}
|
||||
-- Add request to the resource request table
|
||||
--concatRes(navto[v].res, uri, r) -- TODO I don't think this is needed?
|
||||
-- XXX "bug-fix" ensures uri bar gets updated on clicking intra-page links
|
||||
w:update_uri()
|
||||
elseif r == DENIED.BLACKLIST then
|
||||
w:error("Policy: Blacklisted domain '" .. uri .. "'")
|
||||
end
|
||||
-- Hack to get luakit:// pages to load
|
||||
local puri = lousy.uri.parse(uri or "")
|
||||
if puri and puri.scheme == "luakit" then
|
||||
else
|
||||
return not r
|
||||
end
|
||||
end)
|
||||
|
||||
view:add_signal("resource-request-starting",
|
||||
function (v, uri)
|
||||
-- Check if request should be accepted or denied
|
||||
local r = checkpolicy(navto[v].uri or v.uri, uri, false, (navto[v] or {}).first)
|
||||
|
||||
-- if w.navto[v] does not exist set to empty table
|
||||
navto[v] = navto[v] or {}
|
||||
-- Clear temp navigation uri
|
||||
navto[v].uri = nil
|
||||
-- Clear first flag
|
||||
navto[v].first = false
|
||||
-- Add the request to the request table
|
||||
concatRes(navto[v].res, uri, r)
|
||||
|
||||
-- Hack to get luakit;// pages to load
|
||||
local puri = lousy.uri.parse(uri or "")
|
||||
if puri and puri.scheme == "luakit" then
|
||||
else
|
||||
return not r
|
||||
end
|
||||
end)
|
||||
|
||||
view:add_signal("load-status",
|
||||
function (v, status)
|
||||
--pdebug(("policy: load-status signal uri = " .. (v.uri or "") .. "status = " .. status) or "policy: load-status ???")
|
||||
navto[v] = navto[v] or {}
|
||||
if status == "provisional" then
|
||||
-- Resets Resource requests
|
||||
navto[v].res = {}
|
||||
navto[v].first = true
|
||||
elseif status == "committed" then
|
||||
navto[v].first = false
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- TODO - All the chrome stuff...
|
||||
-- luakit://policy/help help page, lists commands and explains how to use plugin
|
||||
-- luakit://policy displys settings status and links to other pages
|
||||
-- luakit://policy/whitelist list of whitelisted domains (button to remove, search, and add new entries)
|
||||
-- luakit://policy/blacklist list of blacklisted domains (button to remove, search, and add new entries)
|
||||
-- luakit://policy/cdr/whitelist list of CDR whitelist entries (")
|
||||
-- luakit://policy/cdr/blacklist list of CDR blacklist entries (")
|
||||
-- luakit://policy/adblock redirects to luakit://adblock
|
||||
|
||||
load = function ()
|
||||
-- Load the db with the white/black lists
|
||||
initalize_rpdb()
|
||||
end
|
||||
|
||||
-- Functions called by user commands ==========================================
|
||||
local togglestrings = {
|
||||
acceptall = "unconditional accepting of all requests.",
|
||||
adblock = "pattern-based blocking (aka AdBlock).",
|
||||
requestpolicy = "cross-domain request policy blocking.",
|
||||
typepolicy = "cross-domain file-type blocking",
|
||||
strictsubdomain = "strict matching for subdomains.",
|
||||
widget = "visibility of status widget.",
|
||||
}
|
||||
|
||||
local rp_setting = function (field, value, w)
|
||||
-- Check that field is a valid settings field
|
||||
if togglestrings[field] then
|
||||
-- Check is toggling or setting value
|
||||
if value == "toggle" then
|
||||
filtering[field] = not filtering[field]
|
||||
else
|
||||
filtering[field] = value
|
||||
end
|
||||
-- User feedback on what setting was changed and what it was changed to
|
||||
w:notify("Policy: " .. (value and "en" or "dis") .. "abled " .. togglestrings[field])
|
||||
end
|
||||
-- return validity of the setting
|
||||
return togglestrings[field] and true
|
||||
end
|
||||
|
||||
-- Clears Excption lists and returns the number of items they contained
|
||||
local clear_exlist = function ()
|
||||
local listlen = #exlist.white
|
||||
for _,v in pairs(exlist.third.white) do
|
||||
for _,_ in pairs(v) do
|
||||
listlen = listlen + 1
|
||||
end
|
||||
end
|
||||
exlist.white = {}
|
||||
exlist.third.white = {}
|
||||
return listlen or 0
|
||||
end
|
||||
|
||||
-- Returns true if entery exists
|
||||
local checkList = function (typ, hosts)
|
||||
local host = hosts[1]
|
||||
local rhost = hosts[2]
|
||||
if rhost then
|
||||
if typ == "ex" then
|
||||
return exlist.third.white[host] and util.table.hasitem(exlist.third.white[host], rhost) and true
|
||||
elseif typ == "white" or typ == "black" then
|
||||
local row = rpdb:exec(string.format(sql_format.match_tp_list, typ, sql_escape(host), sql_escape(rhost)))
|
||||
return row and row[1] and true
|
||||
end
|
||||
else
|
||||
if typ == "ex" then
|
||||
return util.table.hasitem(exlist.white, host) and true
|
||||
elseif typ == "white" or typ == "black" then
|
||||
local row = rpdb:exec(string.format(sql_format.match_list, typ, sql_escape(host)))
|
||||
return row and row[1] and true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Return Strings, makes localization easier
|
||||
local retStr = {
|
||||
sucess = {
|
||||
add = {
|
||||
one = {
|
||||
ex = "Exception added for %s",
|
||||
white = "Added %s to whitelist",
|
||||
black = "Added %s to blacklist"},
|
||||
mul = {
|
||||
ex = "Exception added for requests from %s to %s",
|
||||
white = "Whitelisted requests from %s made to %s",
|
||||
black = "Blacklisted requests from %s made to %s"},
|
||||
},
|
||||
del = {
|
||||
one = {
|
||||
ex = "Removed exception for %s",
|
||||
white = "Removed %s from whitelist",
|
||||
black = "Removed %s from blacklist"},
|
||||
mul = {
|
||||
ex = "Exception removed for requests from %s to %s",
|
||||
white = "Removed whitelisting of requests from %s to %s",
|
||||
black = "Removed blacklisting of requests from %s to %s"},
|
||||
},
|
||||
},
|
||||
failure = {
|
||||
add = {
|
||||
one = {
|
||||
ex = "Exception had already been granted to %s!",
|
||||
white = "%s was already whitelisted!",
|
||||
black = "%s was already blacklisted!"},
|
||||
mul = {
|
||||
ex = "Exception had already been granted to requests from %s to %s!",
|
||||
white = "Requests from %s to %s were already whitelisted!",
|
||||
black = "Requests from %s to %s were already blacklisted!"},
|
||||
},
|
||||
del = {
|
||||
one = {
|
||||
ex = "Exception had not been granted to %s!",
|
||||
white = "%s was not whitelisted!",
|
||||
black = "%s was not blacklsited!"},
|
||||
mul = {
|
||||
ex = "Requests from %s to %s had not been granted an exception!",
|
||||
white = "Requests from %s to %s were not whitelisted!",
|
||||
black = "Requests from %s to %s were not blacklisted!"},
|
||||
},
|
||||
}} -- end retStr
|
||||
|
||||
local modList = function (cmd, typ, hosts, w)
|
||||
local host = hosts[1]
|
||||
local rhost = hosts[2]
|
||||
local listed = checkList(typ, hosts)
|
||||
local num = (rhost and "mul") or "one"
|
||||
local suc = "failure"
|
||||
if cmd == "add" then
|
||||
if not listed then
|
||||
if rhost then
|
||||
if typ == "white" or typ == "black" then
|
||||
rpdb:exec(string.format(sql_format.add_tp_list,
|
||||
typ, sql_escape(host), sql_escape(rhost)))
|
||||
else
|
||||
if not exlist.third.white[host] then
|
||||
exlist.third.white[host] = {}
|
||||
end
|
||||
table.insert(exlist.third.white[host], rhost)
|
||||
end
|
||||
else
|
||||
if typ == "white" or typ == "black" then
|
||||
rpdb:exec(string.format(sql_format.add_list, typ, sql_escape(host)))
|
||||
else
|
||||
table.insert(exlist.white, host)
|
||||
end
|
||||
end
|
||||
suc = "sucess"
|
||||
end
|
||||
elseif cmd == "del" then
|
||||
if listed then
|
||||
if rhost then
|
||||
if typ == "white" or typ == "black" then
|
||||
rpdb:exec(string.format(sql_format.remove_tp_list_exact,
|
||||
typ, sql_escape(host), sql_escape(rhost)))
|
||||
else
|
||||
local i = util.table.hasitem(exlist.third.white[host] or {}, rhost)
|
||||
if i then table.remove(exlist.third.white[host], i) end
|
||||
end
|
||||
else
|
||||
if typ == "white" or typ == "black" then
|
||||
rpdb:exec(string.format(sql_format.remove_list, typ, sql_escape(host)))
|
||||
else
|
||||
local i = util.table.hasitem(exlist.white, host)
|
||||
if i then table.remove(exlist.white, i) end
|
||||
end
|
||||
end
|
||||
suc = "sucess"
|
||||
end
|
||||
end
|
||||
-- Feedback on sucess/failure
|
||||
if suc == "sucess" then
|
||||
-- Changed [typ]-list, clear cache
|
||||
cache = {}
|
||||
w:notify(string.format(retStr[suc][cmd][num][typ], host or "", rhost or ""))
|
||||
else
|
||||
w:error(string.format(retStr[suc][cmd][num][typ], host or "", rhost or ""))
|
||||
end
|
||||
end
|
||||
|
||||
-- Master user commands parser
|
||||
local rp_command = function(command, w, a)
|
||||
a = string.lower(a or "")
|
||||
local args = util.string.split(util.string.strip(a or ""), " ")
|
||||
|
||||
if command == "set" then
|
||||
-- Set request policy behaviors
|
||||
local val = not string.match(args[1], "!$")
|
||||
local set = string.match(args[1], "(.*)!$") or args[1]
|
||||
if not rp_setting(set, val, w) then
|
||||
w:error("Policy: set '" .. args[1] .. "' is not a valid setting. (adblock[!], requestpolicy[!], typepolicy[!], acceptall[!], strictsubdomain[!])")
|
||||
end
|
||||
elseif command == "clear" then
|
||||
w:notify(string.format("Removed %d policy exceptions.", clear_exlist()))
|
||||
else
|
||||
-- else it's wl/bl/ex and args will be hosts and require special parsing
|
||||
if #args == 0 or #args > 2 then
|
||||
w:error("Policy: Wrong number of arguments!")
|
||||
return
|
||||
end
|
||||
-- Attempt to get a host/rhost out of args
|
||||
local host = args[1] and ((args[1] == "all" and "all") or (lousy.uri.parse(args[1]) or {}).host)
|
||||
local rhost = args[2] and ((args[2] == "all" and "all") or (lousy.uri.parse(args[2]) or {}).host)
|
||||
|
||||
-- Convert empty rhost to nil
|
||||
if rhost == "" then rhost = nil end
|
||||
--TODO add host/rhost cheking vs public suffixes with getdomain()
|
||||
if #args == 1 then
|
||||
if not host then
|
||||
w:error("Bad argument error. (" .. host .. ")")
|
||||
return
|
||||
end
|
||||
else
|
||||
if not host or not rhost then
|
||||
w:error("Bad argument error. (" .. host .. ", " .. rhost ..")")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if command == "wl" or command == "whitelist" then
|
||||
modList("add", "white", {host, rhost}, w)
|
||||
elseif command == "bl" or comamnd == "blacklist" then
|
||||
modList("add", "black", {host, rhost}, w)
|
||||
elseif command == "ex" or command == "exception" then
|
||||
modList("add", "ex", {host, rhost}, w)
|
||||
elseif command == "wl!" or command == "whitelist!" then
|
||||
modList("del", "white", {host, rhost}, w)
|
||||
elseif command == "bl!" or command == "blacklist!" then
|
||||
modList("del", "black", {host, rhost}, w)
|
||||
elseif command == "ex!" or command == "exception!" then
|
||||
modList("del", "ex", {host, rhost}, w)
|
||||
else
|
||||
w:error("Policy: '" .. command .. "' is not a valid request policy command!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Add commands ===============================================================
|
||||
new_mode("policymenu", {
|
||||
enter = function (w)
|
||||
local afg = theme.rpolicy_active_menu_fg or theme.proxy_active_menu_fg
|
||||
local ifg = theme.rpolicy_inactive_menu_fg or theme.proxy_inactive_menu_fg
|
||||
local abg = theme.rpolicy_active_menu_bg or theme.proxy_active_menu_bg
|
||||
local ibg = theme.rpolicy_inactive_menu_bg or theme.proxy_inactive_menu_bg
|
||||
|
||||
local template = ' Allowed: <span foreground = "#0f0">%2d</span> Blocked: <span foreground = "#f00">%2d</span> %s'
|
||||
local reason = { start = "[Reason(s):", ends = "]"}
|
||||
|
||||
local main = (lousy.uri.parse(w.view.uri) or {}).host or "about:config"
|
||||
local rows = {}
|
||||
local main_row
|
||||
for host,pol in pairs(navto[w.view].res) do
|
||||
-- Generate a list of reason why requests were blocked
|
||||
local reasons = ""
|
||||
for k,_ in pairs(pol.reasons) do
|
||||
reasons = reasons .. (k and " ") .. k
|
||||
end
|
||||
local notcdr = domainmatch(main, host)
|
||||
-- Underline the main domain of the host
|
||||
local domain = string.gsub(getdomain(host), "[%.%-]", "%%%1")
|
||||
local formhost = string.gsub(host, domain, "<u>" .. domain .. "</u>")
|
||||
if host == main then
|
||||
main_row = {
|
||||
" " .. formhost .. "", string.format(template, pol.accept ,pol.deny, ((reasons ~= "") and reason.start .. reasons .. reason.ends) or ""),
|
||||
host = host, pol = pol,
|
||||
fg = (notcdr and afg) or ifg,
|
||||
bg = ibg}
|
||||
else
|
||||
table.insert(rows, (notcdr and 1) or #rows +1,
|
||||
{ " " .. formhost .. "", string.format(template, pol.accept ,pol.deny, ((reasons ~= "") and reason.start .. reasons .. reason.ends) or ""),
|
||||
host = host, pol = pol,
|
||||
fg = (notcdr and afg) or ifg,
|
||||
bg = ibg,
|
||||
})
|
||||
end
|
||||
end
|
||||
-- Add main host to top of the list
|
||||
if main_row then
|
||||
table.insert(rows, 1, main_row)
|
||||
end
|
||||
-- Add title row entry
|
||||
table.insert(rows, 1, { "Domains requested by " .. main, "Actions Taken", title = true })
|
||||
w.menu:build(rows)
|
||||
w:notify("Use j/k to move, Enter to select a host and open actions submenu, or h to open policy help (and full list of actions).", false)
|
||||
end,
|
||||
|
||||
leave = function (w)
|
||||
w.menu:hide()
|
||||
end,
|
||||
})
|
||||
|
||||
local genLine = function ( fmt, cFmt, cm, h, rh, ifg, ibg)
|
||||
return {string.format(fmt, h, rh),
|
||||
string.format(cFmt, cm, h, rh),
|
||||
host = h, rhost = rh, cmd = cm,
|
||||
fg = ifg, bg = ibg}
|
||||
end
|
||||
|
||||
new_mode("policysubmenu", {
|
||||
enter = function (w)
|
||||
local ifg = theme.rpolicy_inactive_menu_fg or theme.inactive_menu_fg
|
||||
local ibg = theme.rpolicy_inactive_menu_bg or theme.inactive_menu_bg
|
||||
local host = navto[w.view].selectedhost or "REQ_HOST"
|
||||
local main = (lousy.uri.parse(w.view.uri or "") or {}).host or "HOST"
|
||||
local rows = {{ "Actions for " .. host , "Command", title = true }}
|
||||
-- Any host
|
||||
if checkList("white", {host, nil}) then
|
||||
table.insert(rows, genLine("Remove %s from whitelist", " :rp %s %s", "wl!", host, nil, ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Add %s to whitelist", " :rp %s %s", "wl", host, nil, ifg, ibg))
|
||||
end
|
||||
|
||||
if checkList("black", {host, nil}) then
|
||||
table.insert(rows, genLine("Remove %s from blacklist", " :rp %s %s", "bl!", host, nil, ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Add %s to blacklist", " :rp %s %s", "bl", host, nil, ifg, ibg))
|
||||
end
|
||||
|
||||
if checkList("ex", {host, nil}) then
|
||||
table.insert(rows, genLine("Revoke exception for %s", " :rp %s %s", "ex!", host, nil, ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Grant an exception for %s", " :rp %s %s", "ex", host, nil, ifg, ibg))
|
||||
end
|
||||
|
||||
-- For main host
|
||||
if host == main then
|
||||
if checkList("white", {host, "all"}) then
|
||||
table.insert(rows, genLine("Revoke complete CDR whitelisting from %s", " :rp %s %s %s", "wl!", host, "ALL", ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Allow all CDRs from %s", " :rp %s %s %s", "wl", host, "ALL", ifg, ibg))
|
||||
end
|
||||
|
||||
if checkList("black", {host, "all"}) then
|
||||
table.insert(rows, genLine("Revoke complete CDR blacklisting from %s", " :rp %s %s %s", "bl!", host, "ALL", ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Deny all CDRs from %s", " :rp %s %s %s", "bl", host, "ALL", ifg, ibg))
|
||||
end
|
||||
|
||||
if checkList("ex", {host, "all"}) then
|
||||
table.insert(rows, genLine("Revoke complete CDR exception from %s", " :rp %s %s %s", "ex!", host, "ALL", ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Grant an excpetion for all CDRs from %s", " :rp %s %s %s", "ex", host, "ALL", ifg, ibg))
|
||||
end
|
||||
|
||||
-- For other hosts
|
||||
else
|
||||
if checkList("white", {main, host}) then
|
||||
table.insert(rows, genLine("Revoke whitelisting of CDRs from %s to %s", " :rp %s %s %s", "wl!", main, host, ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Allow CDRs from %s to %s", " :rp %s %s %s", "wl", main, host, ifg, ibg))
|
||||
end
|
||||
|
||||
if checkList("black", {main, host}) then
|
||||
table.insert(rows, genLine("Revoke whitelisting of CDRs from %s to %s", " :rp %s %s %s", "bl!", main, host, ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Deny CDRs from %s to %s", " :rp %s %s %s", "bl", main, host, ifg, ibg))
|
||||
end
|
||||
|
||||
if checkList("white", {"all", host}) then
|
||||
table.insert(rows, genLine("Revoke whitelisting of CDRs from %s to %s", " :rp %s %s %s", "wl!", "ALL", host, ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Allow CDRs from %s to %s", " :rp %s %s %s", "wl", "ALL", host, ifg, ibg))
|
||||
end
|
||||
|
||||
if checkList("black", {"all", host}) then
|
||||
table.insert(rows, genLine("Revoke whitelisting of CDRs from %s to %s", " :rp %s %s %s", "bl!", "ALL", host, ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Deny CDRs from %s to %s", " :rp %s %s %s", "bl", "ALL", host, ifg, ibg))
|
||||
end
|
||||
|
||||
if checkList("ex", {main, host}) then
|
||||
table.insert(rows, genLine("Revoke exception for CDRs from %s to %s", " :rp %s %s %s", "ex!", main, host, ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Grant an excpetion for CDRs from %s to %s", " :rp %s %s %s", "ex", main, host, ifg, ibg))
|
||||
end
|
||||
|
||||
if checkList("ex", {"all", host}) then
|
||||
table.insert(rows, genLine("Revoke exception for CDRs from %s to %s", " :rp %s %s %s", "ex!", "ALL", host, ifg, ibg))
|
||||
else
|
||||
table.insert(rows, genLine("Grant an excpetion for CDRs from %s to %s", " :rp %s %s %s", "ex", "ALL", host, ifg, ibg))
|
||||
end
|
||||
end
|
||||
|
||||
w.menu:build(rows)
|
||||
w:notify("Use j/k to move, Enter to execute action, S-Enter to edit command, or q to exit.", false)
|
||||
end,
|
||||
|
||||
leave = function (w)
|
||||
w.menu:hide()
|
||||
end,
|
||||
})
|
||||
|
||||
-- Adds keybindings for the policy menus
|
||||
local key = lousy.bind.key
|
||||
add_binds("policymenu", lousy.util.table.join({
|
||||
-- Select user agent
|
||||
key({}, "Return",
|
||||
function (w)
|
||||
local row = w.menu:get()
|
||||
if row then
|
||||
navto[w.view].selectedhost = row.host
|
||||
w:set_mode("policysubmenu")
|
||||
end
|
||||
end),
|
||||
-- Exit menu
|
||||
key({}, "q", function (w) w:set_mode() end),
|
||||
|
||||
}, menu_binds))
|
||||
|
||||
add_binds("policysubmenu", lousy.util.table.join({
|
||||
key({}, "Return",
|
||||
function (w)
|
||||
local row = w.menu:get()
|
||||
if row and row.cmd then
|
||||
w:set_mode()
|
||||
rp_command(row.cmd, w, (row.host or "") .. " " .. (row.rhost or ""))
|
||||
end
|
||||
end),
|
||||
key({"Shift"}, "Return",
|
||||
function (w)
|
||||
local row = w.menu:get()
|
||||
if row and row[2] then
|
||||
w:enter_cmd(util.string.strip(row[2]))
|
||||
end
|
||||
end),
|
||||
-- Exit menu
|
||||
key({}, "q", function (w) w:set_mode() end),
|
||||
|
||||
}, menu_binds))
|
||||
|
||||
-- Add ex-mode commands
|
||||
local cmd = lousy.bind.cmd
|
||||
add_cmds({
|
||||
cmd({"requestpolicy", "rp"}, "view current page requests",
|
||||
function (w, a)
|
||||
if not a then
|
||||
w:set_mode("policymenu")
|
||||
else
|
||||
-- if called with an argument, try to interprate the command
|
||||
local args = util.string.split(util.string.strip(a or ""), " ")
|
||||
local aa = string.match(a, ".- (.*)")
|
||||
rp_command(args[1], w, aa)
|
||||
end
|
||||
end),
|
||||
cmd({"rp-whitelist", "rp-wl"}, "add a whitelist entry",
|
||||
function(w, a, o)
|
||||
rp_command((o.bang and "wl!") or "wl", w, a)
|
||||
end),
|
||||
cmd({"rp-blacklist", "rp-bl"}, "add a blacklist entry",
|
||||
function(w, a, o)
|
||||
rp_command((o.bang and "bl!") or "bl", w, a)
|
||||
end),
|
||||
cmd({"rp-exception", "rp-ex"}, "grant temporary exceptions to request polices",
|
||||
function(w, a, o)
|
||||
rp_command((o.bang and "ex!") or "ex", w, a)
|
||||
end),
|
||||
cmd({"rp-set"}, "set request policy plugin behaviors",
|
||||
function(w, a)
|
||||
rp_command("set", w, a)
|
||||
end),
|
||||
cmd({"rp-clear"}, "clear request policy exceptions",
|
||||
function(w, a)
|
||||
rp_command("clear", w, a)
|
||||
end),
|
||||
})
|
||||
|
||||
-- Adds buffer command to invoke the policy menu and temp-allow all
|
||||
-- ,pp = open policy menu
|
||||
-- ,pa = allow all CDR from current host for this session
|
||||
-- ,pt = toggle CDR filtering
|
||||
local buf = lousy.bind.buf
|
||||
add_binds("normal", {
|
||||
buf("^,pp$", function (w) w:set_mode("policymenu") end),
|
||||
buf("^,pa$", function(w)
|
||||
if w.view and w.view.uri ~= "about:blank" then
|
||||
rp_command("ex", w, w.view.uri .. " all")
|
||||
end end),
|
||||
buf("^,pt$", function (w) rp_setting("requestpolicy", "toggle" ,w) end),
|
||||
})
|
||||
|
||||
-- Status Bar Widget ==========================================================
|
||||
-- Create the indictor widget on window creation
|
||||
window.init_funcs.build_policy_indicator = function(w)
|
||||
local i = w.sbar.r
|
||||
i.policy = widget{type="label"}
|
||||
i.layout:pack(w.sbar.r.policy)
|
||||
i.layout:reorder(w.sbar.r.policy, 1)
|
||||
i.policy.fg = theme.buf_sbar_fg
|
||||
i.policy.font = theme.buf_sbar_font
|
||||
w:update_policy()
|
||||
-- Update indicator on tab change
|
||||
w.tabs:add_signal("switch-page", function (_,view)
|
||||
capi.luakit.idle_add(function() w:update_policy(w) return false end)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Update indicator on page navigation
|
||||
webview.init_funcs.policy_update = function(view, w)
|
||||
view:add_signal("load-status", function (v, status)
|
||||
if status == "committed" or status == "provisional" then
|
||||
w:update_policy(false)
|
||||
elseif status == "failed" or status == "finished" then
|
||||
w:update_policy(true)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Update contents of request policy widget
|
||||
window.methods.update_policy = function(w, fin)
|
||||
if not w.view then return end
|
||||
local pw = w.sbar.r.policy
|
||||
if filtering.widget then
|
||||
local text
|
||||
if not fin then
|
||||
text = "[Loading...]"
|
||||
else
|
||||
text = "["
|
||||
if navto[w.view].res then
|
||||
local acc, rej = 0, 0
|
||||
for _,pol in pairs(navto[w.view].res) do
|
||||
acc = acc + pol.accept
|
||||
rej = rej + pol.deny
|
||||
end
|
||||
text = text .. string.format("<span foreground=\"#0f0\">A%d</span> <span foreground=\"#f00\">B%d</span>", acc, rej)
|
||||
end
|
||||
text = text .. "]"
|
||||
end
|
||||
pw.text = text
|
||||
pw:show()
|
||||
else
|
||||
pw:hide()
|
||||
end
|
||||
end
|
||||
-- Call load()
|
||||
load()
|
@ -0,0 +1,89 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- --
|
||||
-- Blocks Adding "Private Browsing" Hosts to History DB --
|
||||
-- --
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local string = string
|
||||
local window = window
|
||||
local webview = webview
|
||||
local widget = widget
|
||||
local theme = theme
|
||||
local luakit = luakit
|
||||
local domain_props = domain_props
|
||||
local lousy = require("lousy")
|
||||
local util = lousy.util
|
||||
local history = require("history")
|
||||
local nohist = globals.history_blacklist or {}
|
||||
|
||||
local print = print
|
||||
module("plugins.private_browsing")
|
||||
|
||||
local indicator = { private = "!hist", notprivate = "" }
|
||||
|
||||
-- Load themes, if undefined fallback
|
||||
theme.pbm_font = theme.pbm_font or theme.buf_sbar_font
|
||||
theme.pbm_fg = theme.pbm_fg or theme.buf_sbar_fg
|
||||
theme.pbm_bg = theme.pbm_bg or theme.buf_sbar_bg
|
||||
|
||||
-- Create the indictor widget on window creation
|
||||
window.init_funcs.build_pindicator = function(w)
|
||||
local i = w.sbar.r
|
||||
i.prvt = widget{type="label"}
|
||||
i.layout:pack(w.sbar.r.prvt)
|
||||
i.layout:reorder(w.sbar.r.prvt, 2)
|
||||
i.prvt.font = theme.buf_sbar_font
|
||||
i.prvt.fg = theme.buf_sbar_fg
|
||||
w:update_prvt()
|
||||
-- Update indicator on tab change
|
||||
w.tabs:add_signal("switch-page", function (_,view)
|
||||
luakit.idle_add(function() w:update_prvt(w) return false end)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Update indicator on page navigation
|
||||
webview.init_funcs.prvt_update = function(view, w)
|
||||
view:add_signal("load-status", function (v, status)
|
||||
if status == "comitted" or status == "failed" or status == "finished" then
|
||||
w:update_prvt()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Updates widget based on status
|
||||
window.methods.update_prvt = function(w)
|
||||
if not w.view then return end
|
||||
local private_br = w.view.enable_private_browsing
|
||||
|
||||
local domain = (lousy.uri.parse(w.view.uri) or {}).host or ""
|
||||
domain = string.match(domain, "^www%.(.+)") or domain
|
||||
repeat
|
||||
private_br = private_br or util.table.hasitem(nohist, domain)
|
||||
domain = string.match(domain, "%.(.+)")
|
||||
until not domain
|
||||
|
||||
local prvt = w.sbar.r.prvt
|
||||
-- Set widget text based on privacy setting
|
||||
prvt.text = (private_br and indicator.private) or indicator.notprivate
|
||||
-- Hide blank widget
|
||||
if string.len(prvt.text) then
|
||||
prvt:show()
|
||||
else
|
||||
prvt:hide()
|
||||
end
|
||||
end
|
||||
|
||||
-- Hook to intercept history additions
|
||||
history.add_signal("add", function (uri, title)
|
||||
local domain = lousy.uri.parse(uri).host
|
||||
domain = string.match(domain or "", "^www%.(.+)") or domain or "all"
|
||||
-- Build list of domains and subdomains, pulling private browsing.
|
||||
-- I.e. for luakit.org load .luakit.org, luakit.org, .org
|
||||
local no_hist = domain_props.all.enable_private_browsing or (domain_props[domain] or {}).enable_private_browsing
|
||||
repeat
|
||||
no_hist = no_hist or (domain_props["."..domain] or {}).enable_private_browsing
|
||||
no_hist = no_hist or util.table.hasitem(nohist, domain)
|
||||
domain = string.match(domain, "%.(.+)")
|
||||
until not domain
|
||||
return not no_hist
|
||||
end)
|
@ -0,0 +1,186 @@
|
||||
-----------------------------------------------------------------------
|
||||
-- luakit configuration file, more information at http://luakit.org/ --
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
require "lfs"
|
||||
|
||||
if unique then
|
||||
unique.new("org.luakit")
|
||||
-- Check for a running luakit instance
|
||||
if unique.is_running() then
|
||||
if uris[1] then
|
||||
for _, uri in ipairs(uris) do
|
||||
if lfs.attributes(uri) then uri = os.abspath(uri) end
|
||||
unique.send_message("tabopen " .. uri)
|
||||
end
|
||||
else
|
||||
unique.send_message("winopen")
|
||||
end
|
||||
luakit.quit()
|
||||
end
|
||||
end
|
||||
|
||||
-- Load library of useful functions for luakit
|
||||
require "lousy"
|
||||
|
||||
-- Small util functions to print output (info prints only when luakit.verbose is true)
|
||||
function warn(...) io.stderr:write(string.format(...) .. "\n") end
|
||||
function info(...) if luakit.verbose then io.stdout:write(string.format(...) .. "\n") end end
|
||||
|
||||
-- Load users global config
|
||||
-- ("$XDG_CONFIG_HOME/luakit/globals.lua" or "/etc/xdg/luakit/globals.lua")
|
||||
require "globals"
|
||||
|
||||
-- Load users theme
|
||||
-- ("$XDG_CONFIG_HOME/luakit/theme.lua" or "/etc/xdg/luakit/theme.lua")
|
||||
lousy.theme.init(lousy.util.find_config("theme.lua"))
|
||||
theme = assert(lousy.theme.get(), "failed to load theme")
|
||||
|
||||
-- Load users window class
|
||||
-- ("$XDG_CONFIG_HOME/luakit/window.lua" or "/etc/xdg/luakit/window.lua")
|
||||
require "window"
|
||||
|
||||
-- Load users webview class
|
||||
-- ("$XDG_CONFIG_HOME/luakit/webview.lua" or "/etc/xdg/luakit/webview.lua")
|
||||
require "webview"
|
||||
|
||||
-- Load users mode configuration
|
||||
-- ("$XDG_CONFIG_HOME/luakit/modes.lua" or "/etc/xdg/luakit/modes.lua")
|
||||
require "modes"
|
||||
|
||||
-- Load users keybindings
|
||||
-- ("$XDG_CONFIG_HOME/luakit/binds.lua" or "/etc/xdg/luakit/binds.lua")
|
||||
require "binds"
|
||||
|
||||
----------------------------------
|
||||
-- Optional user script loading --
|
||||
----------------------------------
|
||||
|
||||
require "webinspector"
|
||||
|
||||
-- Add sqlite3 cookiejar
|
||||
require "cookies"
|
||||
|
||||
-- Cookie blocking by domain (extends cookies module)
|
||||
-- Add domains to the whitelist at "$XDG_CONFIG_HOME/luakit/cookie.whitelist"
|
||||
-- and blacklist at "$XDG_CONFIG_HOME/luakit/cookie.blacklist".
|
||||
-- Each domain must be on it's own line and you may use "*" as a
|
||||
-- wildcard character (I.e. "*google.com")
|
||||
--require "cookie_blocking"
|
||||
|
||||
-- Block all cookies by default (unless whitelisted)
|
||||
--cookies.default_allow = false
|
||||
|
||||
-- Add uzbl-like form filling
|
||||
require "formfiller"
|
||||
|
||||
-- Add proxy support & manager
|
||||
require "proxy"
|
||||
|
||||
-- Add quickmarks support & manager
|
||||
require "quickmarks"
|
||||
|
||||
-- Add session saving/loading support
|
||||
require "session"
|
||||
|
||||
-- Add command to list closed tabs & bind to open closed tabs
|
||||
require "undoclose"
|
||||
|
||||
-- Add command to list tab history items
|
||||
require "tabhistory"
|
||||
|
||||
-- Add greasemonkey-like javascript userscript support
|
||||
require "userscripts"
|
||||
|
||||
-- Add bookmarks support
|
||||
require "bookmarks"
|
||||
require "bookmarks_chrome"
|
||||
|
||||
-- Add download support
|
||||
require "downloads"
|
||||
require "downloads_chrome"
|
||||
|
||||
-- Example using xdg-open for opening downloads / showing download folders
|
||||
--downloads.add_signal("open-file", function (file, mime)
|
||||
-- luakit.spawn(string.format("xdg-open %q", file))
|
||||
-- return true
|
||||
--end)
|
||||
|
||||
-- Add vimperator-like link hinting & following
|
||||
require "follow"
|
||||
|
||||
-- Use a custom charater set for hint labels
|
||||
--local s = follow.label_styles
|
||||
--follow.label_maker = s.sort(s.reverse(s.charset("asdfqwerzxcv")))
|
||||
|
||||
-- Match only hint labels
|
||||
--follow.pattern_maker = follow.pattern_styles.match_label
|
||||
|
||||
-- Add command history
|
||||
require "cmdhist"
|
||||
|
||||
-- Add search mode & binds
|
||||
require "search"
|
||||
|
||||
-- Add ordering of new tabs
|
||||
require "taborder"
|
||||
|
||||
-- Save web history
|
||||
require "history"
|
||||
require "history_chrome"
|
||||
|
||||
require "introspector"
|
||||
|
||||
-- Add command completion
|
||||
require "completion"
|
||||
|
||||
-- NoScript plugin, toggle scripts and or plugins on a per-domain basis.
|
||||
-- `,ts` to toggle scripts, `,tp` to toggle plugins, `,tr` to reset.
|
||||
-- Remove all "enable_scripts" & "enable_plugins" lines from your
|
||||
-- domain_props table (in config/globals.lua) as this module will conflict.
|
||||
--require "noscript"
|
||||
|
||||
require "follow_selected"
|
||||
require "go_input"
|
||||
require "go_next_prev"
|
||||
require "go_up"
|
||||
|
||||
-----------------------------
|
||||
-- End user script loading --
|
||||
-----------------------------
|
||||
|
||||
-- Restore last saved session
|
||||
local w = (session and session.restore())
|
||||
if w then
|
||||
for i, uri in ipairs(uris) do
|
||||
w:new_tab(uri, i == 1)
|
||||
end
|
||||
else
|
||||
-- Or open new window
|
||||
window.new(uris)
|
||||
end
|
||||
|
||||
-------------------------------------------
|
||||
-- Open URIs from other luakit instances --
|
||||
-------------------------------------------
|
||||
|
||||
if unique then
|
||||
unique.add_signal("message", function (msg, screen)
|
||||
local cmd, arg = string.match(msg, "^(%S+)%s*(.*)")
|
||||
local w = lousy.util.table.values(window.bywidget)[1]
|
||||
if cmd == "tabopen" then
|
||||
w:new_tab(arg)
|
||||
elseif cmd == "winopen" then
|
||||
w = window.new((arg ~= "") and { arg } or {})
|
||||
end
|
||||
w.win.screen = screen
|
||||
w.win.urgency_hint = true
|
||||
end)
|
||||
end
|
||||
|
||||
-- Some plugins I found
|
||||
-- require "nscript_widget"
|
||||
-- require "private_browsing"
|
||||
require "useragent"
|
||||
|
||||
-- vim: et:sw=4:ts=8:sts=4:tw=80
|
@ -0,0 +1,74 @@
|
||||
--------------------------
|
||||
-- Default luakit theme --
|
||||
--------------------------
|
||||
|
||||
local theme = {}
|
||||
|
||||
-- Default settings
|
||||
theme.font = "terminus 8"
|
||||
theme.fg = "#fff"
|
||||
theme.bg = "#000"
|
||||
|
||||
-- Genaral colours
|
||||
theme.success_fg = "#0f0"
|
||||
theme.loaded_fg = "#33AADD"
|
||||
theme.error_fg = "#FFF"
|
||||
theme.error_bg = "#F00"
|
||||
|
||||
-- Warning colours
|
||||
theme.warning_fg = "#F00"
|
||||
theme.warning_bg = "#FFF"
|
||||
|
||||
-- Notification colours
|
||||
theme.notif_fg = "#444"
|
||||
theme.notif_bg = "#FFF"
|
||||
|
||||
-- Menu colours
|
||||
theme.menu_fg = "#000"
|
||||
theme.menu_bg = "#fff"
|
||||
theme.menu_selected_fg = "#000"
|
||||
theme.menu_selected_bg = "#FF0"
|
||||
theme.menu_title_bg = "#fff"
|
||||
theme.menu_primary_title_fg = "#f00"
|
||||
theme.menu_secondary_title_fg = "#666"
|
||||
|
||||
-- Proxy manager
|
||||
theme.proxy_active_menu_fg = '#000'
|
||||
theme.proxy_active_menu_bg = '#FFF'
|
||||
theme.proxy_inactive_menu_fg = '#888'
|
||||
theme.proxy_inactive_menu_bg = '#FFF'
|
||||
|
||||
-- Statusbar specific
|
||||
theme.sbar_fg = "#fff"
|
||||
theme.sbar_bg = "#000"
|
||||
|
||||
-- Downloadbar specific
|
||||
theme.dbar_fg = "#fff"
|
||||
theme.dbar_bg = "#000"
|
||||
theme.dbar_error_fg = "#F00"
|
||||
|
||||
-- Input bar specific
|
||||
--theme.ibar_fg = "#000"
|
||||
--theme.ibar_bg = "#fff"
|
||||
theme.ibar_bg = "#000"
|
||||
theme.ibar_fg = "#fff"
|
||||
|
||||
-- Tab label
|
||||
--theme.tab_fg = "#888"
|
||||
theme.tab_fg = "#aaa"
|
||||
--theme.tab_bg = "#222"
|
||||
theme.tab_bg = "#000"
|
||||
theme.tab_ntheme = "#ddd"
|
||||
theme.selected_fg = "#fff"
|
||||
--theme.selected_bg = "#000"
|
||||
theme.selected_bg = "#056"
|
||||
theme.selected_ntheme = "#ddd"
|
||||
theme.loading_fg = "#33AADD"
|
||||
theme.loading_bg = "#000"
|
||||
|
||||
-- Trusted/untrusted ssl colours
|
||||
theme.trust_fg = "#0F0"
|
||||
theme.notrust_fg = "#F00"
|
||||
|
||||
return theme
|
||||
-- vim: et:sw=4:ts=8:sts=4:tw=80
|
@ -0,0 +1,343 @@
|
||||
------------------------------------------------------------
|
||||
-- Dynamic useragent settings --
|
||||
-- Written by lokichaos based upon proxy.lua by: --
|
||||
--
|
||||
-- Copyright © Piotr Husiatyński <phusiatynski@gmail.com> --
|
||||
------------------------------------------------------------
|
||||
|
||||
-- TODO
|
||||
-- make per-tab widget & add hooks to update it
|
||||
-- save ua in table
|
||||
-- clean table for GC pruning
|
||||
-- set behavior: set-current, set-all, set-new
|
||||
|
||||
-- Grab environment we need
|
||||
local io = io
|
||||
local os = os
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
local error = error
|
||||
local string = string
|
||||
local lousy = require "lousy"
|
||||
local theme = theme
|
||||
local unpack = unpack
|
||||
local table = table
|
||||
local capi = { luakit = luakit, soup = soup }
|
||||
local webview = webview
|
||||
local widget = widget
|
||||
local window = window
|
||||
local util = lousy.util
|
||||
local globals = globals
|
||||
-- Check for mode/bind functions
|
||||
local add_binds, add_cmds = add_binds, add_cmds
|
||||
local new_mode, menu_binds = new_mode, menu_binds
|
||||
local setmetatable = setmetatable
|
||||
|
||||
module("plugin.useragent")
|
||||
|
||||
|
||||
-- Store each webview's ua-name
|
||||
local uas = {}
|
||||
setmetatable(uas, { __mode = "k" })
|
||||
|
||||
--- Module global variables
|
||||
local agents_file = capi.luakit.data_dir .. '/useragentmenu'
|
||||
|
||||
local useragents = {}
|
||||
local realagent = { name = 0, uastring = globals.useragent }
|
||||
local active = realagent
|
||||
local default_name = nil
|
||||
|
||||
-- Return ordered list of user agent names
|
||||
function get_names()
|
||||
return lousy.util.table.keys(useragents)
|
||||
end
|
||||
|
||||
-- Return ua string of user agent given by name
|
||||
function get(name)
|
||||
return useragents[name]
|
||||
end
|
||||
|
||||
--- Load user agents list from file
|
||||
-- @param fd_name custom user agent storage of nil to use default
|
||||
function load(fd_name)
|
||||
local fd_name = fd_name or agents_file
|
||||
if not os.exists(fd_name) then return end
|
||||
local strip = lousy.util.string.strip
|
||||
|
||||
for line in io.lines(fd_name) do
|
||||
local status, name, uastring = string.match(line, "^(.)%s(.+)%s\"(.+)\"$")
|
||||
if uastring then
|
||||
name, uastring = strip(name), strip(uastring)
|
||||
if status == '*' then
|
||||
active = { uastring = uastring, name = name }
|
||||
end
|
||||
useragents[name] = uastring
|
||||
end
|
||||
end
|
||||
-- Set saved default ua string
|
||||
globals.useragent = active.uastring
|
||||
default_name = active.name
|
||||
end
|
||||
|
||||
--- Save user agents list to file
|
||||
-- @param fd_name custom user agent storage of nil to use default
|
||||
function save(fd_name)
|
||||
local fd = io.open(fd_name or agents_file, "w")
|
||||
for name, uastring in pairs(useragents) do
|
||||
if uastrings ~= "" then
|
||||
local status = (active.name == name and '*') or ' '
|
||||
fd:write(string.format("%s %s \"%s\"\n", status, name, uastring))
|
||||
end
|
||||
end
|
||||
io.close(fd)
|
||||
end
|
||||
|
||||
--- Add new user agent to current list
|
||||
-- @param name user agent configuration name
|
||||
-- @param uastring user agent string
|
||||
-- @param save_file do not save configuration if false
|
||||
function set(name, uastring, save_file)
|
||||
local name = lousy.util.string.strip(name)
|
||||
if not string.match(name, "^([%w%p]+)$") then
|
||||
error("Invalid user agent name: " .. name)
|
||||
end
|
||||
useragents[name] = lousy.util.string.strip(uastring)
|
||||
if save_file ~= false then save() end
|
||||
end
|
||||
|
||||
--- Delete selected user agent from list
|
||||
-- @param name user agent name
|
||||
-- TODO check all tabs
|
||||
function del(name, w)
|
||||
local name = lousy.util.string.strip(name)
|
||||
if useragents[name] then
|
||||
-- if deleted user agent was the active one, use real/default uastring
|
||||
if name == active.name then
|
||||
active = realagent
|
||||
end
|
||||
useragents[name] = nil
|
||||
save()
|
||||
end
|
||||
end
|
||||
|
||||
--- Set given user agent to active. Return true on success, else false
|
||||
-- @param name user agents configuration name or nil to unset user agent.
|
||||
function set_active(name)
|
||||
if name ~= 0 then
|
||||
local name = lousy.util.string.strip(name)
|
||||
if not useragents[name] then
|
||||
error("Unknown user agent: " .. name)
|
||||
end
|
||||
active = { name = name, uastring = useragents[name] }
|
||||
else
|
||||
active = realagent
|
||||
end
|
||||
save()
|
||||
return true
|
||||
end
|
||||
|
||||
-- Create a user agent indicator widget and add it to the status bar
|
||||
window.init_funcs.build_ua_indicator = function (w)
|
||||
local r = w.sbar.r
|
||||
r.uai = widget{type="label"}
|
||||
r.layout:pack(r.uai)
|
||||
r.layout:reorder(r.uai, 2)
|
||||
r.uai.fg = theme.useragenti_sbar_fg or theme.sbar_fg
|
||||
r.uai.font = theme.useragenti_sbar_font or theme.sbar_font
|
||||
w.tabs:add_signal("switch-page", function (nbook, view, idx)
|
||||
capi.luakit.idle_add(function() w:update_ua_indicator() return false end)
|
||||
end)
|
||||
w:update_ua_indicator()
|
||||
end
|
||||
|
||||
-- Helper function to update text in user agent indicator
|
||||
window.methods.update_ua_indicator = function (w)
|
||||
local name = uas[w.view] or (uas[w.view] == 0 and 0) or default_name
|
||||
local uai = w.sbar.r.uai
|
||||
if name ~= 0 then
|
||||
local text = string.format("(%s)", name)
|
||||
if uai.text ~= text then uai.text = text end
|
||||
uai:show()
|
||||
else
|
||||
uai:hide()
|
||||
end
|
||||
end
|
||||
|
||||
new_mode("uagentmenu", {
|
||||
enter = function (w)
|
||||
-- Set all tab's uas entires
|
||||
for index = 1, w.tabs:count() do
|
||||
uas[w.tabs[index]] = uas[w.tabs[index]] or default_name
|
||||
end
|
||||
|
||||
local afg = theme.useragent_active_menu_fg or theme.proxy_active_menu_fg
|
||||
local ifg = theme.useragent_inactive_menu_fg or theme.proxy_inactive_menu_fg
|
||||
local abg = theme.useragent_active_menu_bg or theme.proxy_active_menu_bg
|
||||
local ibg = theme.useragent_inactive_menu_bg or theme.proxy_inactive_menu_bg
|
||||
|
||||
-- "Active" user agent, this is the one that is saved as a default between sessions
|
||||
local act_ua = uas[w.view]
|
||||
-- Add titlebar, and "Default" UA entry
|
||||
local dname = string.format(" %s %s%s", "Default Luakit User Agent",
|
||||
(active.name == 0 and "[Default]") or "",
|
||||
(default_name == 0 and "[Session]") or "")
|
||||
local rows = {{ "User Agent Name", " User Agent String", title = true },
|
||||
{ dname, " " .. realagent.uastring or "", name = 0, uastring = '',
|
||||
fg = (act_ua == 0 and afg) or ifg,
|
||||
bg = (act_ua == 0 and abg) or ibg},}
|
||||
|
||||
for _, name in ipairs(get_names()) do
|
||||
local uastring = get(name)
|
||||
local uaname = string.format(" %s %s%s", name,
|
||||
(active.name == name and "[Default]") or "",
|
||||
(default_name == name and "[Session]") or "")
|
||||
table.insert(rows, {
|
||||
uaname, " " .. uastring,
|
||||
name = name, uastring = lousy.util.escape(uastring),
|
||||
fg = (act_ua == name and afg) or ifg,
|
||||
bg = (act_ua == name and abg) or ibg,
|
||||
})
|
||||
end
|
||||
w.menu:build(rows)
|
||||
w:notify("Use j/k to move, [d]elete, [e]dit, [a]dd, [S]et default, [s]et for all tabs, [n] set for new tabs, return to set for current tab.", false)
|
||||
end,
|
||||
|
||||
leave = function (w)
|
||||
w.menu:hide()
|
||||
end,
|
||||
})
|
||||
|
||||
local cmd = lousy.bind.cmd
|
||||
add_cmds({
|
||||
cmd({"agent", "ua"}, "add new or select useragent",
|
||||
function (w, a)
|
||||
if not a then
|
||||
w:set_mode("uagentmenu")
|
||||
else
|
||||
local name, uastring = string.match(a, "(.+)%s\"(.+)\"")
|
||||
if name and uastring then
|
||||
set(name, uastring)
|
||||
else
|
||||
w:error("Bad usage. Correct format :agent <name> \"<agent string>\"")
|
||||
end
|
||||
end
|
||||
end),
|
||||
})
|
||||
|
||||
|
||||
local ua_set = function(mode, ua, w)
|
||||
if mode == "current" then
|
||||
w.view.user_agent = ua.uastring or realagent.uastring
|
||||
uas[w.view] = ua.name
|
||||
if ua.name ~= 0 then
|
||||
w:notify(string.format("Set user agent on this tab to: %s (%s).", ua.name, ua.uastring))
|
||||
else
|
||||
w:notify("Set user agent for current tab to default.")
|
||||
end
|
||||
|
||||
elseif mode == "newtabs" then
|
||||
globals.useragent = ua.uastring
|
||||
default_name = ua.name
|
||||
if ua.name ~= 0 then
|
||||
w:notify(string.format("Set user agent for all new tabs to: %s (%s).", ua.name, ua.uastring))
|
||||
else
|
||||
w:notify("Set user agent for all new tabs to default Luakit.")
|
||||
end
|
||||
|
||||
elseif mode == "all" then
|
||||
-- New Tabs will use this
|
||||
globals.useragent = ua.uastring
|
||||
default_name = ua.name
|
||||
-- Set user agent for all existing tabs
|
||||
for index = 1, w.tabs:count() do
|
||||
w.tabs[index].user_agent = ua.uastring
|
||||
uas[w.tabs[index]] = ua.name
|
||||
end
|
||||
if ua.name ~= 0 then
|
||||
w:notify(string.format("Set user agent for all tabs to: %s (%s).", ua.name, ua.uastring))
|
||||
else
|
||||
w:notify("Set user agent for all tabs to default.")
|
||||
end
|
||||
|
||||
elseif mode == "default" then
|
||||
globals.useragent = ua.uastring
|
||||
default_name = ua.name
|
||||
set_active(ua.name)
|
||||
if ua.name ~= 0 then
|
||||
w:notify(string.format("Set %s as default useragent (%s)", ua.name, ua.uastring))
|
||||
else
|
||||
w:notify("Unset default useragent, will default to real Luakit one.")
|
||||
end
|
||||
|
||||
end
|
||||
-- Update useragent statusbar widget
|
||||
w:update_ua_indicator()
|
||||
end
|
||||
|
||||
local key = lousy.bind.key
|
||||
add_binds("uagentmenu", lousy.util.table.join({
|
||||
-- Select user agent
|
||||
key({}, "Return",
|
||||
function (w)
|
||||
local row = w.menu:get()
|
||||
if row then
|
||||
w:set_mode()
|
||||
ua_set("current", row, w)
|
||||
end
|
||||
end),
|
||||
key({}, "S",
|
||||
function (w)
|
||||
local row = w.menu:get()
|
||||
if row then
|
||||
w:set_mode()
|
||||
ua_set("default", row, w)
|
||||
end
|
||||
end),
|
||||
key({}, "s",
|
||||
function (w)
|
||||
local row = w.menu:get()
|
||||
if row then
|
||||
w:set_mode()
|
||||
ua_set("all", row, w)
|
||||
end
|
||||
end),
|
||||
key({}, "n",
|
||||
function (w)
|
||||
local row = w.menu:get()
|
||||
if row then
|
||||
w:set_mode()
|
||||
ua_set("newtabs", row, w)
|
||||
end
|
||||
end),
|
||||
-- Delete user agent
|
||||
key({}, "d",
|
||||
function (w)
|
||||
local row = w.menu:get()
|
||||
if row and row.name then
|
||||
del(row.name)
|
||||
w.menu:del()
|
||||
end
|
||||
end),
|
||||
|
||||
-- Edit user agent
|
||||
key({}, "e",
|
||||
function (w)
|
||||
local row = w.menu:get()
|
||||
if row and row.name then
|
||||
w:enter_cmd(string.format(":agent %s \"%s\"", row.name, row.uastring))
|
||||
end
|
||||
end),
|
||||
|
||||
-- New user agent
|
||||
key({}, "a", function (w) w:enter_cmd(":agent ") end),
|
||||
|
||||
-- Exit menu
|
||||
key({}, "q", function (w) w:set_mode() end),
|
||||
|
||||
}, menu_binds))
|
||||
|
||||
-- Initialize module
|
||||
load()
|
||||
|
||||
-- vim: et:sw=4:ts=8:sts=4
|
@ -0,0 +1,10 @@
|
||||
camino "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.6; en; rv:1.9.2.14pre) Gecko/20101212 Camino/2.1a1pre (like Firefox/3.6.14pre)"
|
||||
googlebot "Googlebot/2.1 ( http://www.googlebot.com/bot.html)"
|
||||
firefox15 "Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120427 Firefox/15.0a1"
|
||||
safari "Mozilla/5.0 (Macintosh; PPC Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10"
|
||||
inferfox "Mozilla/6.0 (compatible; AppleWebKit/latest; like Gecko/20120405; };-> infernal_edition:goto-hell) Firefox/666"
|
||||
firefox11 "Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko Firefox/11.0"
|
||||
firefox13 "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20120403211507 Firefox/12.0"
|
||||
ie10 "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
|
||||
firefox14 "Mozilla/5.0 (Windows NT 6.1; rv:14.0) Gecko/20120405 Firefox/14.0a1"
|
||||
opera10 "Opera/9.80 (Macintosh; Intel Mac OS X; U; en) Presto/2.2.15 Version/10.10"
|
@ -0,0 +1,350 @@
|
||||
--------------------------
|
||||
-- WebKit WebView class --
|
||||
--------------------------
|
||||
|
||||
-- Webview class table
|
||||
webview = {}
|
||||
|
||||
-- Table of functions which are called on new webview widgets.
|
||||
webview.init_funcs = {
|
||||
-- Set useragent
|
||||
set_useragent = function (view, w)
|
||||
view.user_agent = globals.useragent
|
||||
end,
|
||||
|
||||
-- Check if checking ssl certificates
|
||||
checking_ssl = function (view, w)
|
||||
local ca_file = soup.ssl_ca_file
|
||||
if ca_file and os.exists(ca_file) then
|
||||
w.checking_ssl = true
|
||||
end
|
||||
end,
|
||||
|
||||
-- Update window and tab titles
|
||||
title_update = function (view, w)
|
||||
view:add_signal("property::title", function (v)
|
||||
w:update_tablist()
|
||||
if w.view == v then
|
||||
w:update_win_title()
|
||||
end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Update uri label in statusbar
|
||||
uri_update = function (view, w)
|
||||
view:add_signal("property::uri", function (v)
|
||||
w:update_tablist()
|
||||
if w.view == v then
|
||||
w:update_uri()
|
||||
end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Update history indicator
|
||||
hist_update = function (view, w)
|
||||
view:add_signal("load-status", function (v, status)
|
||||
if w.view == v then
|
||||
w:update_hist()
|
||||
end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Update tab titles
|
||||
tablist_update = function (view, w)
|
||||
view:add_signal("load-status", function (v, status)
|
||||
if status == "provisional" or status == "finished" or status == "failed" then
|
||||
w:update_tablist()
|
||||
end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Update scroll widget
|
||||
scroll_update = function (view, w)
|
||||
view:add_signal("expose", function (v)
|
||||
if w.view == v then
|
||||
w:update_scroll()
|
||||
end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Update progress widget
|
||||
progress_update = function (view, w)
|
||||
for _, sig in ipairs({"load-status", "property::progress"}) do
|
||||
view:add_signal(sig, function (v)
|
||||
if w.view == v then
|
||||
w:update_progress()
|
||||
w:update_ssl()
|
||||
end
|
||||
end)
|
||||
end
|
||||
end,
|
||||
|
||||
-- Display hovered link in statusbar
|
||||
link_hover_display = function (view, w)
|
||||
view:add_signal("link-hover", function (v, link)
|
||||
if w.view == v and link then
|
||||
w:update_uri(link)
|
||||
end
|
||||
end)
|
||||
view:add_signal("link-unhover", function (v)
|
||||
if w.view == v then
|
||||
w:update_uri()
|
||||
end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Clicking a form field automatically enters insert mode.
|
||||
form_insert_mode = function (view, w)
|
||||
view:add_signal("button-press", function (v, mods, button, context)
|
||||
-- Clear start search marker
|
||||
(w.search_state or {}).marker = nil
|
||||
|
||||
if button == 1 and context.editable then
|
||||
view:emit_signal("form-active")
|
||||
end
|
||||
end)
|
||||
-- Emit root-active event in button release to prevent "missing"
|
||||
-- buttons or links when the input bar hides.
|
||||
view:add_signal("button-release", function (v, mods, button, context)
|
||||
if button == 1 and not context.editable then
|
||||
view:emit_signal("root-active")
|
||||
end
|
||||
end)
|
||||
view:add_signal("form-active", function ()
|
||||
if not w.mode.passthrough then
|
||||
w:set_mode("insert")
|
||||
end
|
||||
end)
|
||||
view:add_signal("root-active", function ()
|
||||
if w.mode.reset_on_focus ~= false then
|
||||
w:set_mode()
|
||||
end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Catch keys in non-passthrough modes
|
||||
mode_key_filter = function (view, w)
|
||||
view:add_signal("key-press", function ()
|
||||
if not w.mode.passthrough then
|
||||
return true
|
||||
end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Try to match a button event to a users button binding else let the
|
||||
-- press hit the webview.
|
||||
button_bind_match = function (view, w)
|
||||
view:add_signal("button-release", function (v, mods, button, context)
|
||||
(w.search_state or {}).marker = nil
|
||||
if w:hit(mods, button, { context = context }) then
|
||||
return true
|
||||
end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Reset the mode on navigation
|
||||
mode_reset_on_nav = function (view, w)
|
||||
view:add_signal("load-status", function (v, status)
|
||||
if status == "provisional" and w.view == v then
|
||||
if w.mode.reset_on_navigation ~= false then
|
||||
w:set_mode()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Domain properties
|
||||
domain_properties = function (view, w)
|
||||
view:add_signal("load-status", function (v, status)
|
||||
if status ~= "committed" or v.uri == "about:blank" then return end
|
||||
-- Get domain
|
||||
local domain = lousy.uri.parse(v.uri).host
|
||||
-- Strip leading www.
|
||||
domain = string.match(domain or "", "^www%.(.+)") or domain or "all"
|
||||
-- Build list of domain props tables to join & load.
|
||||
-- I.e. for luakit.org load .luakit.org, luakit.org, .org
|
||||
local props = {domain_props.all or {}, domain_props[domain] or {}}
|
||||
repeat
|
||||
table.insert(props, 2, domain_props["."..domain] or {})
|
||||
domain = string.match(domain, "%.(.+)")
|
||||
until not domain
|
||||
-- Join all property tables
|
||||
for k, v in pairs(lousy.util.table.join(unpack(props))) do
|
||||
info("Domain prop: %s = %s (%s)", k, tostring(v), domain)
|
||||
view[k] = v
|
||||
end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Action to take on mime type decision request.
|
||||
mime_decision = function (view, w)
|
||||
-- Return true to accept or false to reject from this signal.
|
||||
view:add_signal("mime-type-decision", function (v, uri, mime)
|
||||
info("Requested link: %s (%s)", uri, mime)
|
||||
-- i.e. block binary files like *.exe
|
||||
--if mime == "application/octet-stream" then
|
||||
-- return false
|
||||
--end
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Action to take on window open request.
|
||||
--window_decision = function (view, w)
|
||||
-- view:add_signal("new-window-decision", function (v, uri, reason)
|
||||
-- if reason == "link-clicked" then
|
||||
-- window.new({uri})
|
||||
-- else
|
||||
-- w:new_tab(uri)
|
||||
-- end
|
||||
-- return true
|
||||
-- end)
|
||||
--end,
|
||||
|
||||
create_webview = function (view, w)
|
||||
-- Return a newly created webview in a new tab
|
||||
view:add_signal("create-web-view", function (v)
|
||||
return w:new_tab()
|
||||
end)
|
||||
end,
|
||||
|
||||
-- Creates context menu popup from table (and nested tables).
|
||||
-- Use `true` for menu separators.
|
||||
--populate_popup = function (view, w)
|
||||
-- view:add_signal("populate-popup", function (v)
|
||||
-- return {
|
||||
-- true,
|
||||
-- { "_Toggle Source", function () w:toggle_source() end },
|
||||
-- { "_Zoom", {
|
||||
-- { "Zoom _In", function () w:zoom_in() end },
|
||||
-- { "Zoom _Out", function () w:zoom_out() end },
|
||||
-- true,
|
||||
-- { "Zoom _Reset", function () w:zoom_set() end }, }, },
|
||||
-- }
|
||||
-- end)
|
||||
--end,
|
||||
|
||||
-- Action to take on resource request.
|
||||
resource_request_decision = function (view, w)
|
||||
view:add_signal("resource-request-starting", function(v, uri)
|
||||
info("Requesting: %s", uri)
|
||||
-- Return false to cancel the request.
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
-- These methods are present when you index a window instance and no window
|
||||
-- method is found in `window.methods`. The window then checks if there is an
|
||||
-- active webview and calls the following methods with the given view instance
|
||||
-- as the first argument. All methods must take `view` & `w` as the first two
|
||||
-- arguments.
|
||||
webview.methods = {
|
||||
-- Reload with or without ignoring cache
|
||||
reload = function (view, w, bypass_cache)
|
||||
if bypass_cache then
|
||||
view:reload_bypass_cache()
|
||||
else
|
||||
view:reload()
|
||||
end
|
||||
end,
|
||||
|
||||
-- Toggle source view
|
||||
toggle_source = function (view, w, show)
|
||||
if show == nil then
|
||||
view.view_source = not view.view_source
|
||||
else
|
||||
view.view_source = show
|
||||
end
|
||||
view:reload()
|
||||
end,
|
||||
|
||||
-- Zoom functions
|
||||
zoom_in = function (view, w, step, full_zoom)
|
||||
view.full_content_zoom = not not full_zoom
|
||||
step = step or globals.zoom_step or 0.1
|
||||
view.zoom_level = view.zoom_level + step
|
||||
end,
|
||||
|
||||
zoom_out = function (view, w, step, full_zoom)
|
||||
view.full_content_zoom = not not full_zoom
|
||||
step = step or globals.zoom_step or 0.1
|
||||
view.zoom_level = math.max(0.01, view.zoom_level) - step
|
||||
end,
|
||||
|
||||
zoom_set = function (view, w, level, full_zoom)
|
||||
view.full_content_zoom = not not full_zoom
|
||||
view.zoom_level = level or 1.0
|
||||
end,
|
||||
|
||||
-- History traversing functions
|
||||
back = function (view, w, n)
|
||||
view:go_back(n or 1)
|
||||
end,
|
||||
|
||||
forward = function (view, w, n)
|
||||
view:go_forward(n or 1)
|
||||
end,
|
||||
}
|
||||
|
||||
function webview.methods.scroll(view, w, new)
|
||||
local s = view.scroll
|
||||
for _, axis in ipairs{ "x", "y" } do
|
||||
-- Relative px movement
|
||||
if rawget(new, axis.."rel") then
|
||||
s[axis] = s[axis] + new[axis.."rel"]
|
||||
|
||||
-- Relative page movement
|
||||
elseif rawget(new, axis .. "pagerel") then
|
||||
s[axis] = s[axis] + math.ceil(s[axis.."page_size"] * new[axis.."pagerel"])
|
||||
|
||||
-- Absolute px movement
|
||||
elseif rawget(new, axis) then
|
||||
local n = new[axis]
|
||||
if n == -1 then
|
||||
s[axis] = s[axis.."max"]
|
||||
else
|
||||
s[axis] = n
|
||||
end
|
||||
|
||||
-- Absolute page movement
|
||||
elseif rawget(new, axis.."page") then
|
||||
s[axis] = math.ceil(s[axis.."page_size"] * new[axis.."page"])
|
||||
|
||||
-- Absolute percent movement
|
||||
elseif rawget(new, axis .. "pct") then
|
||||
s[axis] = math.ceil(s[axis.."max"] * (new[axis.."pct"]/100))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function webview.new(w)
|
||||
local view = widget{type = "webview"}
|
||||
|
||||
view.show_scrollbars = false
|
||||
view.enforce_96_dpi = false
|
||||
|
||||
-- Call webview init functions
|
||||
for k, func in pairs(webview.init_funcs) do
|
||||
func(view, w)
|
||||
end
|
||||
return view
|
||||
end
|
||||
|
||||
-- Insert webview method lookup on window structure
|
||||
table.insert(window.indexes, 1, function (w, k)
|
||||
if k == "view" then
|
||||
local view = w.tabs[w.tabs:current()]
|
||||
if view and type(view) == "widget" and view.type == "webview" then
|
||||
w.view = view
|
||||
return view
|
||||
end
|
||||
end
|
||||
-- Lookup webview method
|
||||
local func = webview.methods[k]
|
||||
if not func then return end
|
||||
local view = w.view
|
||||
if view then
|
||||
return function (_, ...) return func(view, w, ...) end
|
||||
end
|
||||
end)
|
||||
|
||||
-- vim: et:sw=4:ts=8:sts=4:tw=80
|
@ -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
|
Binary file not shown.
@ -0,0 +1,2 @@
|
||||
macro index,pager \cb <pipe-entry>'urlscan'<enter> 'Follow links with urlview'
|
||||
macro attach,compose \cb <pipe-entry>'urlscan'<enter> 'Follow links with urlview'
|
@ -0,0 +1,2 @@
|
||||
text/html; luakit %s &; test=test -n "%DISPLAY"; needsterminal;
|
||||
text/html; w3m -I %{charset} -T text/html; copiousoutput;
|
@ -0,0 +1,151 @@
|
||||
# vim: filetype=muttrc
|
||||
|
||||
#
|
||||
#
|
||||
# make sure that you are using mutt linked against slang, not ncurses, or
|
||||
# suffer the consequences of weird color issues. use "mutt -v" to check this.
|
||||
|
||||
# custom body highlights -----------------------------------------------
|
||||
# highlight my name and other personally relevant strings
|
||||
#color body yellow default "(ethan|schoonover)"
|
||||
# custom index highlights ----------------------------------------------
|
||||
# messages which mention my name in the body
|
||||
#color index yellow default "~b \"phil(_g|\!| gregory| gold)|pgregory\" !~N !~T !~F !~p !~P"
|
||||
#color index J_cream brightwhite "~b \"phil(_g|\!| gregory| gold)|pgregory\" ~N !~T !~F !~p !~P"
|
||||
#color index yellow cyan "~b \"phil(_g|\!| gregory| gold)|pgregory\" ~T !~F !~p !~P"
|
||||
#color index yellow J_magent "~b \"phil(_g|\!| gregory| gold)|pgregory\" ~F !~p !~P"
|
||||
## messages which are in reference to my mails
|
||||
#color index J_magent default "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" !~N !~T !~F !~p !~P"
|
||||
#color index J_magent brightwhite "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" ~N !~T !~F !~p !~P"
|
||||
#color index J_magent cyan "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" ~T !~F !~p !~P"
|
||||
#color index J_magent red "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" ~F !~p !~P"
|
||||
|
||||
# for background in 16 color terminal, valid background colors include:
|
||||
# base03, bg, black, any of the non brights
|
||||
|
||||
# basic colors ---------------------------------------------------------
|
||||
color normal brightyellow default
|
||||
color error red default
|
||||
color tilde black default
|
||||
color message cyan default
|
||||
color markers red white
|
||||
color attachment white default
|
||||
color search brightmagenta default
|
||||
#color status J_black J_status
|
||||
color status brightyellow black
|
||||
color indicator brightblack yellow
|
||||
color tree yellow default # arrow in threads
|
||||
|
||||
# basic monocolor screen
|
||||
mono bold bold
|
||||
mono underline underline
|
||||
mono indicator reverse
|
||||
mono error bold
|
||||
|
||||
# index ----------------------------------------------------------------
|
||||
|
||||
#color index red default "~D(!~p|~p)" # deleted
|
||||
#color index black default ~F # flagged
|
||||
#color index brightred default ~= # duplicate messages
|
||||
#color index brightgreen default "~A!~N!~T!~p!~Q!~F!~D!~P" # the rest
|
||||
#color index J_base default "~A~N!~T!~p!~Q!~F!~D" # the rest, new
|
||||
color index red default "~A" # all messages
|
||||
color index brightred default "~E" # expired messages
|
||||
color index blue default "~N" # new messages
|
||||
color index blue default "~O" # old messages
|
||||
color index brightmagenta default "~Q" # messages that have been replied to
|
||||
color index brightgreen default "~R" # read messages
|
||||
color index blue default "~U" # unread messages
|
||||
color index blue default "~U~$" # unread, unreferenced messages
|
||||
color index brightyellow default "~v" # messages part of a collapsed thread
|
||||
color index brightyellow default "~P" # messages from me
|
||||
color index cyan default "~p!~F" # messages to me
|
||||
color index cyan default "~N~p!~F" # new messages to me
|
||||
color index cyan default "~U~p!~F" # unread messages to me
|
||||
color index brightgreen default "~R~p!~F" # messages to me
|
||||
color index red default "~F" # flagged messages
|
||||
color index red default "~F~p" # flagged messages to me
|
||||
color index red default "~N~F" # new flagged messages
|
||||
color index red default "~N~F~p" # new flagged messages to me
|
||||
color index red default "~U~F~p" # new flagged messages to me
|
||||
color index black red "~D" # deleted messages
|
||||
color index brightcyan default "~v~(!~N)" # collapsed thread with no unread
|
||||
color index yellow default "~v~(~N)" # collapsed thread with some unread
|
||||
color index green default "~N~v~(~N)" # collapsed thread with unread parent
|
||||
# statusbg used to indicated flagged when foreground color shows other status
|
||||
# for collapsed thread
|
||||
color index red black "~v~(~F)!~N" # collapsed thread with flagged, no unread
|
||||
color index yellow black "~v~(~F~N)" # collapsed thread with some unread & flagged
|
||||
color index green black "~N~v~(~F~N)" # collapsed thread with unread parent & flagged
|
||||
color index green black "~N~v~(~F)" # collapsed thread with unread parent, no unread inside, but some flagged
|
||||
color index cyan black "~v~(~p)" # collapsed thread with unread parent, no unread inside, some to me directly
|
||||
color index yellow red "~v~(~D)" # thread with deleted (doesn't differentiate between all or partial)
|
||||
#color index yellow default "~(~N)" # messages in threads with some unread
|
||||
#color index green default "~S" # superseded messages
|
||||
#color index red default "~T" # tagged messages
|
||||
#color index brightred red "~=" # duplicated messages
|
||||
|
||||
# message headers ------------------------------------------------------
|
||||
|
||||
#color header brightgreen default "^"
|
||||
color hdrdefault brightgreen default
|
||||
color header brightyellow default "^(From)"
|
||||
color header blue default "^(Subject)"
|
||||
|
||||
# body -----------------------------------------------------------------
|
||||
|
||||
color quoted blue default
|
||||
color quoted1 cyan default
|
||||
color quoted2 yellow default
|
||||
color quoted3 red default
|
||||
color quoted4 brightred default
|
||||
|
||||
color signature brightgreen default
|
||||
color bold black default
|
||||
color underline black default
|
||||
color normal default default
|
||||
#
|
||||
color body brightcyan default "[;:][-o][)/(|]" # emoticons
|
||||
color body brightcyan default "[;:][)(|]" # emoticons
|
||||
color body brightcyan default "[*]?((N)?ACK|CU|LOL|SCNR|BRB|BTW|CWYL|\
|
||||
|FWIW|vbg|GD&R|HTH|HTHBE|IMHO|IMNSHO|\
|
||||
|IRL|RTFM|ROTFL|ROFL|YMMV)[*]?"
|
||||
color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon?
|
||||
color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon?
|
||||
|
||||
## pgp
|
||||
|
||||
color body red default "(BAD signature)"
|
||||
color body cyan default "(Good signature)"
|
||||
color body brightblack default "^gpg: Good signature .*"
|
||||
color body brightyellow default "^gpg: "
|
||||
color body brightyellow red "^gpg: BAD signature from.*"
|
||||
mono body bold "^gpg: Good signature"
|
||||
mono body bold "^gpg: BAD signature from.*"
|
||||
|
||||
# yes, an insance URL regex
|
||||
color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]"
|
||||
# and a heavy handed email regex
|
||||
#color body J_magent default "((@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]),)*@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]):)?[0-9a-z_.+%$-]+@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\])"
|
||||
|
||||
# Various smilies and the like
|
||||
#color body brightwhite default "<[Gg]>" # <g>
|
||||
#color body brightwhite default "<[Bb][Gg]>" # <bg>
|
||||
#color body yellow default " [;:]-*[})>{(<|]" # :-) etc...
|
||||
# *bold*
|
||||
#color body blue default "(^|[[:space:][:punct:]])\\*[^*]+\\*([[:space:][:punct:]]|$)"
|
||||
#mono body bold "(^|[[:space:][:punct:]])\\*[^*]+\\*([[:space:][:punct:]]|$)"
|
||||
# _underline_
|
||||
#color body blue default "(^|[[:space:][:punct:]])_[^_]+_([[:space:][:punct:]]|$)"
|
||||
#mono body underline "(^|[[:space:][:punct:]])_[^_]+_([[:space:][:punct:]]|$)"
|
||||
# /italic/ (Sometimes gets directory names)
|
||||
#color body blue default "(^|[[:space:][:punct:]])/[^/]+/([[:space:][:punct:]]|$)"
|
||||
#mono body underline "(^|[[:space:][:punct:]])/[^/]+/([[:space:][:punct:]]|$)"
|
||||
|
||||
# Border lines.
|
||||
#color body blue default "( *[-+=#*~_]){6,}"
|
||||
|
||||
#folder-hook . "color status J_black J_status "
|
||||
#folder-hook gmail/inbox "color status J_black yellow "
|
||||
#folder-hook gmail/important "color status J_black yellow "
|
||||
|
@ -0,0 +1,151 @@
|
||||
# vim: filetype=muttrc
|
||||
|
||||
#
|
||||
#
|
||||
# make sure that you are using mutt linked against slang, not ncurses, or
|
||||
# suffer the consequences of weird color issues. use "mutt -v" to check this.
|
||||
|
||||
# custom body highlights -----------------------------------------------
|
||||
# highlight my name and other personally relevant strings
|
||||
#color body color136 color234 "(ethan|schoonover)"
|
||||
# custom index highlights ----------------------------------------------
|
||||
# messages which mention my name in the body
|
||||
#color index color136 color234 "~b \"phil(_g|\!| gregory| gold)|pgregory\" !~N !~T !~F !~p !~P"
|
||||
#color index J_cream color230 "~b \"phil(_g|\!| gregory| gold)|pgregory\" ~N !~T !~F !~p !~P"
|
||||
#color index color136 color37 "~b \"phil(_g|\!| gregory| gold)|pgregory\" ~T !~F !~p !~P"
|
||||
#color index color136 J_magent "~b \"phil(_g|\!| gregory| gold)|pgregory\" ~F !~p !~P"
|
||||
## messages which are in reference to my mails
|
||||
#color index J_magent color234 "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" !~N !~T !~F !~p !~P"
|
||||
#color index J_magent color230 "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" ~N !~T !~F !~p !~P"
|
||||
#color index J_magent color37 "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" ~T !~F !~p !~P"
|
||||
#color index J_magent color160 "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" ~F !~p !~P"
|
||||
|
||||
# for background in 16 color terminal, valid background colors include:
|
||||
# base03, bg, black, any of the non brights
|
||||
|
||||
# basic colors ---------------------------------------------------------
|
||||
color normal color241 color234
|
||||
color error color160 color234
|
||||
color tilde color235 color234
|
||||
color message color37 color234
|
||||
color markers color160 color254
|
||||
color attachment color254 color234
|
||||
color search color61 color234
|
||||
#color status J_black J_status
|
||||
color status color241 color235
|
||||
color indicator color234 color136
|
||||
color tree color136 color234 # arrow in threads
|
||||
|
||||
# basic monocolor screen
|
||||
mono bold bold
|
||||
mono underline underline
|
||||
mono indicator reverse
|
||||
mono error bold
|
||||
|
||||
# index ----------------------------------------------------------------
|
||||
|
||||
#color index color160 color234 "~D(!~p|~p)" # deleted
|
||||
#color index color235 color234 ~F # flagged
|
||||
#color index color166 color234 ~= # duplicate messages
|
||||
#color index color240 color234 "~A!~N!~T!~p!~Q!~F!~D!~P" # the rest
|
||||
#color index J_base color234 "~A~N!~T!~p!~Q!~F!~D" # the rest, new
|
||||
color index color160 color234 "~A" # all messages
|
||||
color index color166 color234 "~E" # expired messages
|
||||
color index color33 color234 "~N" # new messages
|
||||
color index color33 color234 "~O" # old messages
|
||||
color index color61 color234 "~Q" # messages that have been replied to
|
||||
color index color240 color234 "~R" # read messages
|
||||
color index color33 color234 "~U" # unread messages
|
||||
color index color33 color234 "~U~$" # unread, unreferenced messages
|
||||
color index color241 color234 "~v" # messages part of a collapsed thread
|
||||
color index color241 color234 "~P" # messages from me
|
||||
color index color37 color234 "~p!~F" # messages to me
|
||||
color index color37 color234 "~N~p!~F" # new messages to me
|
||||
color index color37 color234 "~U~p!~F" # unread messages to me
|
||||
color index color240 color234 "~R~p!~F" # messages to me
|
||||
color index color160 color234 "~F" # flagged messages
|
||||
color index color160 color234 "~F~p" # flagged messages to me
|
||||
color index color160 color234 "~N~F" # new flagged messages
|
||||
color index color160 color234 "~N~F~p" # new flagged messages to me
|
||||
color index color160 color234 "~U~F~p" # new flagged messages to me
|
||||
color index color235 color160 "~D" # deleted messages
|
||||
color index color245 color234 "~v~(!~N)" # collapsed thread with no unread
|
||||
color index color136 color234 "~v~(~N)" # collapsed thread with some unread
|
||||
color index color64 color234 "~N~v~(~N)" # collapsed thread with unread parent
|
||||
# statusbg used to indicated flagged when foreground color shows other status
|
||||
# for collapsed thread
|
||||
color index color160 color235 "~v~(~F)!~N" # collapsed thread with flagged, no unread
|
||||
color index color136 color235 "~v~(~F~N)" # collapsed thread with some unread & flagged
|
||||
color index color64 color235 "~N~v~(~F~N)" # collapsed thread with unread parent & flagged
|
||||
color index color64 color235 "~N~v~(~F)" # collapsed thread with unread parent, no unread inside, but some flagged
|
||||
color index color37 color235 "~v~(~p)" # collapsed thread with unread parent, no unread inside, some to me directly
|
||||
color index color136 color160 "~v~(~D)" # thread with deleted (doesn't differentiate between all or partial)
|
||||
#color index color136 color234 "~(~N)" # messages in threads with some unread
|
||||
#color index color64 color234 "~S" # superseded messages
|
||||
#color index color160 color234 "~T" # tagged messages
|
||||
#color index color166 color160 "~=" # duplicated messages
|
||||
|
||||
# message headers ------------------------------------------------------
|
||||
|
||||
#color header color240 color234 "^"
|
||||
color hdrdefault color240 color234
|
||||
color header color241 color234 "^(From)"
|
||||
color header color33 color234 "^(Subject)"
|
||||
|
||||
# body -----------------------------------------------------------------
|
||||
|
||||
color quoted color33 color234
|
||||
color quoted1 color37 color234
|
||||
color quoted2 color136 color234
|
||||
color quoted3 color160 color234
|
||||
color quoted4 color166 color234
|
||||
|
||||
color signature color240 color234
|
||||
color bold color235 color234
|
||||
color underline color235 color234
|
||||
color normal color244 color234
|
||||
#
|
||||
color body color245 color234 "[;:][-o][)/(|]" # emoticons
|
||||
color body color245 color234 "[;:][)(|]" # emoticons
|
||||
color body color245 color234 "[*]?((N)?ACK|CU|LOL|SCNR|BRB|BTW|CWYL|\
|
||||
|FWIW|vbg|GD&R|HTH|HTHBE|IMHO|IMNSHO|\
|
||||
|IRL|RTFM|ROTFL|ROFL|YMMV)[*]?"
|
||||
color body color245 color234 "[ ][*][^*]*[*][ ]?" # more emoticon?
|
||||
color body color245 color234 "[ ]?[*][^*]*[*][ ]" # more emoticon?
|
||||
|
||||
## pgp
|
||||
|
||||
color body color160 color234 "(BAD signature)"
|
||||
color body color37 color234 "(Good signature)"
|
||||
color body color234 color234 "^gpg: Good signature .*"
|
||||
color body color241 color234 "^gpg: "
|
||||
color body color241 color160 "^gpg: BAD signature from.*"
|
||||
mono body bold "^gpg: Good signature"
|
||||
mono body bold "^gpg: BAD signature from.*"
|
||||
|
||||
# yes, an insance URL regex
|
||||
color body color160 color234 "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]"
|
||||
# and a heavy handed email regex
|
||||
#color body J_magent color234 "((@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]),)*@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]):)?[0-9a-z_.+%$-]+@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\])"
|
||||
|
||||
# Various smilies and the like
|
||||
#color body color230 color234 "<[Gg]>" # <g>
|
||||
#color body color230 color234 "<[Bb][Gg]>" # <bg>
|
||||
#color body color136 color234 " [;:]-*[})>{(<|]" # :-) etc...
|
||||
# *bold*
|
||||
#color body color33 color234 "(^|[[:space:][:punct:]])\\*[^*]+\\*([[:space:][:punct:]]|$)"
|
||||
#mono body bold "(^|[[:space:][:punct:]])\\*[^*]+\\*([[:space:][:punct:]]|$)"
|
||||
# _underline_
|
||||
#color body color33 color234 "(^|[[:space:][:punct:]])_[^_]+_([[:space:][:punct:]]|$)"
|
||||
#mono body underline "(^|[[:space:][:punct:]])_[^_]+_([[:space:][:punct:]]|$)"
|
||||
# /italic/ (Sometimes gets directory names)
|
||||
#color body color33 color234 "(^|[[:space:][:punct:]])/[^/]+/([[:space:][:punct:]]|$)"
|
||||
#mono body underline "(^|[[:space:][:punct:]])/[^/]+/([[:space:][:punct:]]|$)"
|
||||
|
||||
# Border lines.
|
||||
#color body color33 color234 "( *[-+=#*~_]){6,}"
|
||||
|
||||
#folder-hook . "color status J_black J_status "
|
||||
#folder-hook gmail/inbox "color status J_black color136 "
|
||||
#folder-hook gmail/important "color status J_black color136 "
|
||||
|
@ -0,0 +1,57 @@
|
||||
# Get passwords from gpg'd file
|
||||
source "gpg -dq ~/.my-pwds.gpg |"
|
||||
|
||||
# General
|
||||
set realname = "Dustin Swan"
|
||||
|
||||
# Gmail IMAP
|
||||
set imap_user = "dustinswan@gmail.com"
|
||||
set imap_pass = $my_pw_personal
|
||||
set folder = "imaps://imap.gmail.com/"
|
||||
set spoolfile = +INBOX
|
||||
set imap_check_subscribed
|
||||
set header_cache = ~/.mutt/hcache
|
||||
set record = "+[Gmail]/Sent Mail"
|
||||
set postponed = "+[Gmail]/Drafts"
|
||||
unset imap_passive
|
||||
set imap_keepalive = 300
|
||||
set mail_check = 60
|
||||
|
||||
# SMTP
|
||||
set smtp_url = "smtp://dustinswan@smtp.gmail.com:587/"
|
||||
set smtp_pass = $my_pw_personal
|
||||
set send_charset = "utf-8"
|
||||
|
||||
set mailcap_path = ~/.mutt/mailcap
|
||||
|
||||
# Edit headers
|
||||
#set edit_headers = yes
|
||||
#unset use_from
|
||||
#unset use_domain
|
||||
#unset user_agent
|
||||
#unmy_hdr *
|
||||
|
||||
# Sorting
|
||||
set sort = threads
|
||||
set sort_aux = reverse-last-date-received
|
||||
|
||||
# Sidebar
|
||||
set sidebar_delim = ' │'
|
||||
set sidebar_visible = yes
|
||||
set sidebar_width = 24
|
||||
#color sidebar_new color221 color233
|
||||
|
||||
bind index <down> sidebar-next
|
||||
bind index <up> sidebar-prev
|
||||
bind index <right> sidebar-open
|
||||
|
||||
# Status Bar
|
||||
#set status_chars = " *&A"
|
||||
#set status_format = "---[ Folder: %f ]---[%r%n messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]---%>-%?p?( %p postponed )?---""
|
||||
|
||||
# Fucking html mail
|
||||
auto_view text/html
|
||||
alternative_order text/plain text/enriched text/html
|
||||
|
||||
# Colors
|
||||
source ~/.mutt/mutt-colors-solarized-dark-256.muttrc
|
@ -1,21 +0,0 @@
|
||||
source "gpg -dq ~/.my-pwds.gpg |"
|
||||
|
||||
set imap_user = dustinswan@gmail.com
|
||||
|
||||
set imap_pass = $my_pw_personal
|
||||
|
||||
set folder = imaps://imap.gmail.com/
|
||||
|
||||
set spoolfile = +INBOX
|
||||
|
||||
set imap_check_subscribed
|
||||
|
||||
set header_cache = ~/.mutt/hcache
|
||||
|
||||
set postponed = +[Gmail]/Drafts
|
||||
|
||||
unset imap_passive
|
||||
|
||||
set imap_keepalive = 300
|
||||
|
||||
set mail_check = 120
|
@ -0,0 +1,3 @@
|
||||
xrandr --newmode "2560x1440_60.00" 312.25 2560 2752 3024 3488 1440 1443 1448 1493 -hsync +vsync
|
||||
xrandr --addmode Virtual1 2560x1440_60.00
|
||||
xrandr --output Virtual1 --mode 2560x1440_60.00
|
Loading…
Reference in New Issue