All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
2 -- Standard awesome library
3 local gears = require("gears")
4 local awful = require("awful")
5 require("awful.autofocus")
6 -- Widget and layout library
7 local wibox = require("wibox")
8 -- Theme handling library
9 local beautiful = require("beautiful")
10 -- Notification library
11 local naughty = require("naughty")
12 local menubar = require("menubar")
13 local hotkeys_popup = require("awful.hotkeys_popup").widget
14 local lain = require("lain")
15 local dkjson = require("lain.util").dkjson
16 local math = require("math")
17 local freedesktop = require("freedesktop")
21 -- Check if awesome encountered an error during startup and fell back to
22 -- another config (This code will only ever execute for the fallback config)
23 if awesome.startup_errors then
24 naughty.notify({ preset = naughty.config.presets.critical,
25 title = "Oops, there were errors during startup!",
26 text = awesome.startup_errors })
29 -- Handle runtime errors after startup
31 local in_error = false
32 awesome.connect_signal("debug::error", function (err)
33 -- Make sure we don't go into an endless error loop
34 if in_error then return end
37 naughty.notify({ preset = naughty.config.presets.critical,
38 title = "Oops, an error happened!",
39 text = tostring(err) })
45 -- {{{ Variable definitions
46 -- Themes define colours, icons, and wallpapers
47 beautiful.init(awful.util.get_themes_dir() .. "default/theme.lua")
49 -- This is used later as the default terminal and editor to run.
50 terminal = "x-terminal-emulator"
51 editor = "sensible-editor"
52 editor_cmd = terminal .. " -e " .. editor
55 -- Usually, Mod4 is the key with a logo between Control and Alt.
56 -- If you do not like this or do not have such a key,
57 -- I suggest you to remap Mod4 to another key using xmodmap or other tools.
58 -- However, you can use another modifier like Mod1, but it may interact with others.
62 -- Table of layouts to cover with awful.layout.inc, order matters.
63 awful.layout.layouts = {
64 awful.layout.suit.fair,
65 awful.layout.suit.tile,
66 -- awful.layout.suit.tile.left,
67 -- awful.layout.suit.tile.bottom,
68 awful.layout.suit.tile.top,
69 -- awful.layout.suit.spiral,
70 -- awful.layout.suit.spiral.dwindle,
71 awful.layout.suit.max,
72 -- awful.layout.suit.max.fullscreen,
73 -- awful.layout.suit.magnifier,
74 -- awful.layout.suit.corner.nw,
75 -- awful.layout.suit.corner.ne,
76 -- awful.layout.suit.corner.sw,
77 -- awful.layout.suit.corner.se,
78 awful.layout.suit.floating,
81 layout_default = awful.layout.layouts[1]
82 layout_tiled = awful.layout.layouts[2]
83 layout_maximised = awful.layout.layouts[4]
84 layout_floating = awful.layout.layouts[5]
87 -- {{{ Helper functions
88 local function client_menu_toggle_fn()
92 if instance and instance.wibox.visible then
96 instance = awful.menu.clients({ theme = { width = 250 } })
101 local function sorted_pairs(t, f)
103 for n in pairs(t) do table.insert(a, n) end
105 local i = 0 -- iterator variable
106 local iter = function () -- iterator function
108 if a[i] == nil then return nil
109 else return a[i], t[a[i]]
115 local function print_table(tbl, indent)
116 if not indent then indent = 0 end
117 for k, v in pairs(tbl) do
118 formatting = string.rep(" ", indent) .. k .. ": "
119 if type(v) == "table" then
121 print_table(v, indent+1)
123 print(formatting .. tostring(v))
128 local lain_bat = lain.widget.bat({
129 batteries = {"BAT0", "BAT1"},
130 settings = function()
132 if bat_now.status == "Charging" then delim = "↑"
133 elseif bat_now.status == "Unknown" then delim = "٭" end
134 widget:set_text(bat_now.perc .. "% " .. delim .. " " .. bat_now.time)
138 local function poloniex_price(output, pair, prec)
139 local xc, pos, err = dkjson.decode(output, 1, nil)
140 if not prec then prec = 4 end
141 val = (xc and xc[pair]["last"]) or 0
142 val = math.floor(val*10^prec+0.5)/10^prec
143 return (not err and val) or "n/a"
146 local eth_widget = lain.widget.watch({
147 cmd = "curl -m5 -s 'https://poloniex.com/public?command=returnTicker'",
149 settings = function()
150 widget:set_text(poloniex_price(output, 'BTC_ETH') .. " Ƀ/Ξ")
154 local function coindesk_price(output, base, prec)
155 local xc, pos, err = dkjson.decode(output, 1, nil)
156 if not prec then prec = 4 end
157 val = (xc and xc["bpi"][base]["rate_float"]) or 0
158 val = math.floor(val*10^prec+0.5)/10^prec
159 return (not err and val) or "n/a"
162 local btc_widget = lain.widget.watch({
163 cmd = "curl -m5 -Ls 'https://api.coindesk.com/v1/bpi/currentprice/EUR.json'",
165 settings = function()
166 widget:set_text(coindesk_price(output, "EUR", 2) .. " €/Ƀ")
173 -- Create a launcher widget and a main menu
175 { "hotkeys", function() return false, hotkeys_popup.show_help end},
176 { "manual", terminal .. " -e man awesome" },
177 { "edit config", editor_cmd .. " " .. awesome.conffile },
178 { "restart", awesome.restart },
179 { "quit", awesome.quit }
182 mymainmenu = freedesktop.menu.build({
184 { "awesome", myawesomemenu, beautiful.awesome_icon },
185 { "terminal", terminal },
191 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
195 -- {{{ Menubar configuration
196 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
200 local spacer = wibox.widget.textbox()
201 spacer:set_text(' | ')
202 -- Create a textclock widget
203 mytextclock = wibox.widget.textclock("%a %d %b %H:%M:%S", 1)
205 -- Create a wibox for each screen and add it
210 mytaglist.buttons = awful.util.table.join(
211 awful.button({ }, 1, function(t) t:view_only() end),
212 awful.button({ modkey }, 1, function(t)
214 client.focus:move_to_tag(t)
217 awful.button({ }, 3, awful.tag.viewtoggle),
218 awful.button({ modkey }, 3, function(t)
220 client.focus:toggle_tag(t)
223 awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
224 awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
228 mytasklist.buttons = awful.util.table.join(
229 awful.button({ }, 1, function (c)
230 if c == client.focus then
231 -- I don't like click-minimising
232 -- c.minimized = true
234 -- Without this, the following
235 -- :isvisible() makes no sense
237 if not c:isvisible() and c.first_tag then
238 c.first_tag:view_only()
240 -- This will also un-minimize
241 -- the client, if needed
246 awful.button({ }, 3, client_menu_toggle_fn()),
247 awful.button({ }, 4, function ()
248 awful.client.focus.byidx(1)
250 awful.button({ }, 5, function ()
251 awful.client.focus.byidx(-1)
258 tags.config["main"] = {
259 t1 = { layout = layout_default, selected = true },
260 t2 = { layout = layout_default },
261 t3 = { layout = layout_tiled },
262 t4 = { layout = layout_tiled },
263 t5 = { layout = layout_tiled },
264 t6 = { layout = layout_floating },
265 t7 = { layout = layout_maximised },
266 t8 = { layout = layout_maximised },
267 t9 = { layout = layout_maximised },
269 tags.config["aux"] = {
270 t1 = { layout = layout_default, selected = true },
271 t2 = { layout = layout_default },
272 t3 = { layout = layout_tiled },
273 t4 = { layout = layout_floating },
274 t5 = { layout = layout_floating },
275 t6 = { layout = layout_floating },
276 t7 = { layout = layout_floating },
277 t8 = { layout = layout_floating },
278 t9 = { layout = layout_maximised },
282 screentags[1] = tags.config["main"]
283 if screen.count() == 2 then -- aux screen is on the right
284 screentags[2] = tags.config["aux"]
285 elseif screen.count() == 3 then -- main screen is still #1 in the middle
286 screentags[2] = tags.config["aux"]
287 screentags[3] = tags.config["aux"]
290 awful.screen.connect_for_each_screen(function(s)
292 --DISABLED--if beautiful.wallpaper then
293 --DISABLED-- local wallpaper = beautiful.wallpaper
294 --DISABLED-- -- If wallpaper is a function, call it with the screen
295 --DISABLED-- if type(wallpaper) == "function" then
296 --DISABLED-- wallpaper = wallpaper(s)
298 --DISABLED-- gears.wallpaper.maximized(wallpaper, s, true)
301 if not tags[s.index] then
304 for n,p in sorted_pairs(screentags[s.index]) do
306 n = string.sub(n, 2) -- remove leading 't' needed for syntax in table
307 table.insert(tags[s.index], awful.tag.add(n, p))
310 -- Create a promptbox for each screen
311 mypromptbox[s] = awful.widget.prompt()
312 -- Create an imagebox widget which will contains an icon indicating which layout we're using.
313 -- We need one layoutbox per screen.
314 mylayoutbox[s] = awful.widget.layoutbox(s)
315 mylayoutbox[s]:buttons(awful.util.table.join(
316 awful.button({ }, 1, function () awful.layout.inc( 1) end),
317 awful.button({ }, 3, function () awful.layout.inc(-1) end),
318 awful.button({ }, 4, function () awful.layout.inc( 1) end),
319 awful.button({ }, 5, function () awful.layout.inc(-1) end)))
320 -- Create a taglist widget
321 mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)
323 -- Create a tasklist widget
324 mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
327 mywibox[s] = awful.wibar({ position = "top", screen = s })
329 -- Add widgets to the wibox
331 layout = wibox.layout.align.horizontal,
333 layout = wibox.layout.fixed.horizontal,
338 mytasklist[s], -- Middle widget
340 layout = wibox.layout.fixed.horizontal,
342 wibox.widget.systray(),
354 -- {{{ Mouse bindings
355 root.buttons(awful.util.table.join(
356 awful.button({ }, 3, function () mymainmenu:toggle() end),
357 awful.button({ }, 4, awful.tag.viewnext),
358 awful.button({ }, 5, awful.tag.viewprev)
363 globalkeys = awful.util.table.join(
364 awful.key({ modkey, }, "s", hotkeys_popup.show_help,
365 {description="show help", group="awesome"}),
366 awful.key({ modkey, }, "Left", awful.tag.viewprev,
367 {description = "view previous", group = "tag"}),
368 awful.key({ modkey, }, "Right", awful.tag.viewnext,
369 {description = "view next", group = "tag"}),
370 awful.key({ modkey, }, "Escape", awful.tag.history.restore,
371 {description = "go back", group = "tag"}),
373 awful.key({ modkey, }, "k",
375 awful.client.focus.byidx( 1)
377 {description = "focus next by index", group = "client"}
379 awful.key({ modkey, }, "j",
381 awful.client.focus.byidx(-1)
383 {description = "focus previous by index", group = "client"}
385 awful.key({ modkey, }, "w", function () mymainmenu:show() end,
386 {description = "show main menu", group = "awesome"}),
388 -- Layout manipulation
389 awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( 1) end,
390 {description = "swap with next client by index", group = "client"}),
391 awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( -1) end,
392 {description = "swap with previous client by index", group = "client"}),
393 awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end,
394 {description = "focus the next screen", group = "screen"}),
395 awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end,
396 {description = "focus the previous screen", group = "screen"}),
397 awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
398 {description = "jump to urgent client", group = "client"}),
399 awful.key({ modkey, }, "Tab",
401 awful.client.focus.history.previous()
406 {description = "go back", group = "client"}),
409 awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
410 {description = "open a terminal", group = "launcher"}),
411 awful.key({ modkey, "Control" }, "r", awesome.restart,
412 {description = "reload awesome", group = "awesome"}),
413 awful.key({ modkey, "Shift" }, "q", awesome.quit,
414 {description = "quit awesome", group = "awesome"}),
416 awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
417 {description = "increase master width factor", group = "layout"}),
418 awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
419 {description = "decrease master width factor", group = "layout"}),
420 awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
421 {description = "increase the number of master clients", group = "layout"}),
422 awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
423 {description = "decrease the number of master clients", group = "layout"}),
424 awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
425 {description = "increase the number of columns", group = "layout"}),
426 awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
427 {description = "decrease the number of columns", group = "layout"}),
428 awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
429 {description = "select next", group = "layout"}),
430 awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
431 {description = "select previous", group = "layout"}),
433 awful.key({ modkey, "Control" }, "n",
435 local c = awful.client.restore()
436 -- Focus restored client
442 {description = "restore minimized", group = "client"}),
445 awful.key({ modkey }, "r", function () mypromptbox[awful.screen.focused()]:run() end,
446 {description = "run prompt", group = "launcher"}),
448 awful.key({ modkey }, "x",
450 awful.prompt.run({ prompt = "Run Lua code: " },
451 mypromptbox[awful.screen.focused()].widget,
452 awful.util.eval, nil,
453 awful.util.get_cache_dir() .. "/history_eval")
455 {description = "lua execute prompt", group = "awesome"}),
457 awful.key({ modkey }, "p", function() menubar.show() end,
458 {description = "show the menubar", group = "launcher"})
461 clientkeys = awful.util.table.join(
462 awful.key({ modkey, }, "f",
464 c.fullscreen = not c.fullscreen
467 {description = "toggle fullscreen", group = "client"}),
468 awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
469 {description = "close", group = "client"}),
470 awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
471 {description = "toggle floating", group = "client"}),
472 awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
473 {description = "move to master", group = "client"}),
474 awful.key({ modkey, }, "o", function (c) c:move_to_screen() end,
475 {description = "move to screen", group = "client"}),
476 awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
477 {description = "toggle keep on top", group = "client"}),
478 awful.key({ modkey, }, "n",
480 -- The client currently has the input focus, so it cannot be
481 -- minimized, since minimized clients can't have the focus.
484 {description = "minimize", group = "client"}),
485 awful.key({ modkey, }, "m",
487 c.maximized = not c.maximized
488 c.maximized_horizontal = false
489 c.maximized_vertical = false
492 {description = "maximize", group = "client"})
495 -- Bind all key numbers to tags.
496 -- Be careful: we use keycodes to make it works on any keyboard layout.
497 -- This should map on the top row of your keyboard, usually 1 to 9.
499 globalkeys = awful.util.table.join(globalkeys,
501 awful.key({ modkey }, "#" .. i + 9,
503 local screen = awful.screen.focused()
504 local tag = screen.tags[i]
509 {description = "view tag #"..i, group = "tag"}),
511 awful.key({ modkey, "Control" }, "#" .. i + 9,
513 local screen = awful.screen.focused()
514 local tag = screen.tags[i]
516 awful.tag.viewtoggle(tag)
519 {description = "toggle tag #" .. i, group = "tag"}),
520 -- Move client to tag.
521 awful.key({ modkey, "Shift" }, "#" .. i + 9,
524 local tag = client.focus.screen.tags[i]
526 client.focus:move_to_tag(tag)
530 {description = "move focused client to tag #"..i, group = "tag"}),
531 -- Toggle tag on focused client.
532 awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
535 local tag = client.focus.screen.tags[i]
537 client.focus:toggle_tag(tag)
541 {description = "toggle focused client on tag #" .. i, group = "tag"})
545 clientbuttons = awful.util.table.join(
546 awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
547 awful.button({ modkey }, 1, awful.mouse.client.move),
548 awful.button({ modkey }, 3, awful.mouse.client.resize))
551 globalkeys = awful.util.table.join(globalkeys,
552 awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end),
553 awful.key({ cmdkey }, "m", function () awful.spawn("chromium --enable-remote-extensions") end),
554 awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end),
555 awful.key({ cmdkey }, "c", function () awful.spawn("thunderbird") end),
556 awful.key({ cmdkey }, "r", function () mypromptbox[mouse.screen]:run() end),
557 awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end),
558 awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end),
559 awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end),
560 awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end),
561 awful.key({ cmdkey }, "i", function () awful.spawn(terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh -4 -- irc-host tmux new -As irc irssi") end),
562 awful.key({ cmdkey }, "x", function () awful.spawn.with_shell("/sbin/start-stop-daemon --start --background --exec /usr/bin/xscreensaver -- -no-capture-stderr; sleep 2; xscreensaver-command -lock") end),
563 awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end),
566 awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end),
567 awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
568 awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end),
569 awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
570 awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end),
571 awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
572 awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end),
573 awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end),
574 awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end),
575 awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end),
576 awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end),
577 awful.key(nil, "XF86Display", function () awful.spawn("") end),
578 awful.key(nil, "XF86WLAN", function () awful.spawn("") end),
579 awful.key(nil, "XF86Tools", function () awful.spawn("") end),
580 awful.key(nil, "XF86Search", function () awful.spawn("") end),
581 awful.key(nil, "XF86LaunchA", function () awful.spawn("") end),
582 awful.key(nil, "XF86Explorer", function () awful.spawn("") end)
586 root.keys(globalkeys)
590 -- Rules to apply to new clients (through the "manage" signal).
592 local function move_to_tag(s, t)
594 c:move_to_tag(tags[s][t])
598 awful.rules.rules = {
599 -- All clients will match this rule.
601 properties = { border_width = beautiful.border_width,
602 border_color = beautiful.border_normal,
603 focus = awful.client.focus.filter,
606 buttons = clientbuttons,
607 screen = awful.screen.preferred,
608 placement = awful.placement.no_overlap+awful.placement.no_offscreen,
613 -- Add titlebars to normal clients and dialogs
614 --DISABLED-- { rule_any = {type = { "normal", "dialog" }
615 --DISABLED-- }, properties = { titlebars_enabled = true }
618 { rule = { type = "dialog" },
619 properties = { floating = true,
620 placement = awful.placement.centered
624 { rule = { class = "URxvt" },
627 size_hints_honor = false
629 { rule = { class = "URxvt", instance = "irc" },
633 callback = move_to_tag(screen.count(), screen.count() == 1 and 2 or 1)
635 { rule = { class = "Firefox", instance = "Navigator" },
639 callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
641 { rule = { class = "Firefox-esr", instance = "Navigator" },
645 callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
647 { rule = { class = "Thunderbird", instance = "Mail" },
651 callback = move_to_tag(screen.count() == 1 and 1 or 2, 8)
653 { rule = { class = "Chromium", instance = "chromium" },
657 callback = move_to_tag(screen.count() == 1 and 1 or 2, 9)
659 { rule = { class = "Gscan2pdf" },
663 callback = move_to_tag(1, 5)
665 { rule = { name = "gscan2pdf .*" },
670 { rule = { class = "Thunar", type = "normal" },
675 { rule = { class = "MuPDF", instance = "mupdf" },
680 { rule = { class = "Pinentry", instance = "pinentry" },
685 { rule = { class = "Gxmessage" },
694 -- Signal function to execute when a new client appears.
695 client.connect_signal("manage", function (c)
696 -- Set the windows at the slave,
697 -- i.e. put it at the end of others instead of setting it master.
698 if not awesome.startup then awful.client.setslave(c) end
700 if awesome.startup and
701 not c.size_hints.user_position
702 and not c.size_hints.program_position then
703 -- Prevent clients from being unreachable after screen count changes.
704 awful.placement.no_offscreen(c)
707 c.maximized_horizontal = false
708 c.maximized_vertical = false
711 -- Add a titlebar if titlebars_enabled is set to true in the rules.
712 client.connect_signal("request::titlebars", function(c)
713 -- buttons for the titlebar
714 local buttons = awful.util.table.join(
715 awful.button({ }, 1, function()
718 awful.mouse.client.move(c)
720 awful.button({ }, 3, function()
723 awful.mouse.client.resize(c)
727 awful.titlebar(c) : setup {
729 awful.titlebar.widget.iconwidget(c),
731 layout = wibox.layout.fixed.horizontal
736 widget = awful.titlebar.widget.titlewidget(c)
739 layout = wibox.layout.flex.horizontal
742 awful.titlebar.widget.floatingbutton (c),
743 awful.titlebar.widget.maximizedbutton(c),
744 awful.titlebar.widget.stickybutton (c),
745 awful.titlebar.widget.ontopbutton (c),
746 awful.titlebar.widget.closebutton (c),
747 layout = wibox.layout.fixed.horizontal()
749 layout = wibox.layout.align.horizontal
753 -- Enable sloppy focus
754 client.connect_signal("mouse::enter", function(c)
755 if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
756 and awful.client.focus.filter(c) then
761 client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
762 client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
764 awful.ewmh.add_activate_filter(function(c, context, hints)
765 if context == "ewmh" and (c.class == "Firefox-esr" or c.class == "Firefox") then return false end
768 -- vim:ft=lua:sw=4:sts=4:ts=4:et