madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

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.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

improve vim folding
[etc/awesome.git] / .config / awesome / rc.lua
1 -- {{{ Imports
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 -- }}}
15
16 -- {{{ Error handling
17 -- Check if awesome encountered an error during startup and fell back to
18 -- another config (This code will only ever execute for the fallback config)
19 if awesome.startup_errors then
20     naughty.notify({ preset = naughty.config.presets.critical,
21                      title = "Oops, there were errors during startup!",
22                      text = awesome.startup_errors })
23 end
24
25 -- Handle runtime errors after startup
26 do
27     local in_error = false
28     awesome.connect_signal("debug::error", function (err)
29         -- Make sure we don't go into an endless error loop
30         if in_error then return end
31         in_error = true
32
33         naughty.notify({ preset = naughty.config.presets.critical,
34                          title = "Oops, an error happened!",
35                          text = tostring(err) })
36         in_error = false
37     end)
38 end
39 -- }}}
40
41 -- {{{ Variable definitions
42 -- Themes define colours, icons, and wallpapers
43 beautiful.init(awful.util.get_themes_dir() .. "default/theme.lua")
44
45 -- This is used later as the default terminal and editor to run.
46 terminal = "x-terminal-emulator"
47 editor = "sensible-editor"
48 editor_cmd = terminal .. " -e " .. editor
49
50 -- Default modkey.
51 -- Usually, Mod4 is the key with a logo between Control and Alt.
52 -- If you do not like this or do not have such a key,
53 -- I suggest you to remap Mod4 to another key using xmodmap or other tools.
54 -- However, you can use another modifier like Mod1, but it may interact with others.
55 modkey = "Mod4"
56 cmdkey = "Mod3"
57
58 -- Table of layouts to cover with awful.layout.inc, order matters.
59 awful.layout.layouts = {
60     awful.layout.suit.fair,
61     awful.layout.suit.tile,
62     -- awful.layout.suit.tile.left,
63     -- awful.layout.suit.tile.bottom,
64     awful.layout.suit.tile.top,
65     -- awful.layout.suit.spiral,
66     -- awful.layout.suit.spiral.dwindle,
67     awful.layout.suit.max,
68     awful.layout.suit.max.fullscreen,
69     -- awful.layout.suit.magnifier,
70     -- awful.layout.suit.corner.nw,
71     -- awful.layout.suit.corner.ne,
72     -- awful.layout.suit.corner.sw,
73     -- awful.layout.suit.corner.se,
74     awful.layout.suit.floating,
75 }
76
77 layout_default = awful.layout.layouts[1]
78 layout_tiled = awful.layout.layouts[2]
79 layout_maximised = awful.layout.layouts[4]
80 layout_floating = awful.layout.layouts[5]
81 -- }}}
82
83 -- {{{ Helper functions
84 local function client_menu_toggle_fn()
85     local instance = nil
86
87     return function ()
88         if instance and instance.wibox.visible then
89             instance:hide()
90             instance = nil
91         else
92             instance = awful.menu.clients({ theme = { width = 250 } })
93         end
94     end
95 end
96 -- }}}
97
98 -- {{{ Menu
99 -- Create a launcher widget and a main menu
100 myawesomemenu = {
101    { "hotkeys", function() return false, hotkeys_popup.show_help end},
102    { "manual", terminal .. " -e man awesome" },
103    { "edit config", editor_cmd .. " " .. awesome.conffile },
104    { "restart", awesome.restart },
105    { "quit", awesome.quit }
106 }
107
108 mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
109                                     { "open terminal", terminal }
110                                   }
111                         })
112
113 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
114                                      menu = mymainmenu })
115 -- }}}
116
117 -- {{{ Menubar configuration
118 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
119 -- }}}
120
121 -- {{{ Wibox
122 -- Create a textclock widget
123 mytextclock = wibox.widget.textclock("%a %d %b %H:%M:%S", 1)
124
125 -- Keyboard map indicator and switcher
126 mykeyboardlayout = awful.widget.keyboardlayout()
127
128 -- Create a wibox for each screen and add it
129 mywibox = {}
130 mypromptbox = {}
131 mylayoutbox = {}
132 mytaglist = {}
133 mytaglist.buttons = awful.util.table.join(
134                     awful.button({ }, 1, function(t) t:view_only() end),
135                     awful.button({ modkey }, 1, function(t)
136                                               if client.focus then
137                                                   client.focus:move_to_tag(t)
138                                               end
139                                           end),
140                     awful.button({ }, 3, awful.tag.viewtoggle),
141                     awful.button({ modkey }, 3, function(t)
142                                               if client.focus then
143                                                   client.focus:toggle_tag(t)
144                                               end
145                                           end),
146                     awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
147                     awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
148                 )
149
150 mytasklist = {}
151 mytasklist.buttons = awful.util.table.join(
152                      awful.button({ }, 1, function (c)
153                                               if c == client.focus then
154                                                   c.minimized = true
155                                               else
156                                                   -- Without this, the following
157                                                   -- :isvisible() makes no sense
158                                                   c.minimized = false
159                                                   if not c:isvisible() and c.first_tag then
160                                                       c.first_tag:view_only()
161                                                   end
162                                                   -- This will also un-minimize
163                                                   -- the client, if needed
164                                                   client.focus = c
165                                                   c:raise()
166                                               end
167                                           end),
168                      awful.button({ }, 3, client_menu_toggle_fn()),
169                      awful.button({ }, 4, function ()
170                                               awful.client.focus.byidx(1)
171                                           end),
172                      awful.button({ }, 5, function ()
173                                               awful.client.focus.byidx(-1)
174                                           end))
175 -- }}}
176
177 -- {{{ Tags
178
179 awful.screen.connect_for_each_screen(function(s)
180     -- Wallpaper
181     --DISABLED--if beautiful.wallpaper then
182     --DISABLED--    local wallpaper = beautiful.wallpaper
183     --DISABLED--    -- If wallpaper is a function, call it with the screen
184     --DISABLED--    if type(wallpaper) == "function" then
185     --DISABLED--        wallpaper = wallpaper(s)
186     --DISABLED--    end
187     --DISABLED--    gears.wallpaper.maximized(wallpaper, s, true)
188     --DISABLED--end
189
190     -- Each screen has its own tag table.
191     tags = awful.tag.new({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, layout_default)
192     tags[7].layout = layout_maximised
193     tags[8].layout = layout_maximised
194     tags[9].layout = layout_maximised
195     tags[1].selected = true
196
197     -- Create a promptbox for each screen
198     mypromptbox[s] = awful.widget.prompt()
199     -- Create an imagebox widget which will contains an icon indicating which layout we're using.
200     -- We need one layoutbox per screen.
201     mylayoutbox[s] = awful.widget.layoutbox(s)
202     mylayoutbox[s]:buttons(awful.util.table.join(
203                            awful.button({ }, 1, function () awful.layout.inc( 1) end),
204                            awful.button({ }, 3, function () awful.layout.inc(-1) end),
205                            awful.button({ }, 4, function () awful.layout.inc( 1) end),
206                            awful.button({ }, 5, function () awful.layout.inc(-1) end)))
207     -- Create a taglist widget
208     mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)
209
210     -- Create a tasklist widget
211     mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
212
213     -- Create the wibox
214     mywibox[s] = awful.wibar({ position = "top", screen = s })
215
216     -- Add widgets to the wibox
217     mywibox[s]:setup {
218         layout = wibox.layout.align.horizontal,
219         { -- Left widgets
220             layout = wibox.layout.fixed.horizontal,
221             -- mylauncher,
222             mytaglist[s],
223             mypromptbox[s],
224         },
225         mytasklist[s], -- Middle widget
226         { -- Right widgets
227             layout = wibox.layout.fixed.horizontal,
228             mykeyboardlayout,
229             wibox.widget.systray(),
230             mytextclock,
231             mylayoutbox[s],
232         },
233     }
234 end)
235 -- }}}
236
237 -- {{{ Mouse bindings
238 root.buttons(awful.util.table.join(
239     awful.button({ }, 3, function () mymainmenu:toggle() end),
240     awful.button({ }, 4, awful.tag.viewnext),
241     awful.button({ }, 5, awful.tag.viewprev)
242 ))
243 -- }}}
244
245 -- {{{ Key bindings
246 globalkeys = awful.util.table.join(
247     awful.key({ modkey,           }, "s",      hotkeys_popup.show_help,
248               {description="show help", group="awesome"}),
249     awful.key({ modkey,           }, "Left",   awful.tag.viewprev,
250               {description = "view previous", group = "tag"}),
251     awful.key({ modkey,           }, "Right",  awful.tag.viewnext,
252               {description = "view next", group = "tag"}),
253     awful.key({ modkey,           }, "Escape", awful.tag.history.restore,
254               {description = "go back", group = "tag"}),
255
256     awful.key({ modkey,           }, "j",
257         function ()
258             awful.client.focus.byidx( 1)
259         end,
260         {description = "focus next by index", group = "client"}
261     ),
262     awful.key({ modkey,           }, "k",
263         function ()
264             awful.client.focus.byidx(-1)
265         end,
266         {description = "focus previous by index", group = "client"}
267     ),
268     awful.key({ modkey,           }, "w", function () mymainmenu:show() end,
269               {description = "show main menu", group = "awesome"}),
270
271     -- Layout manipulation
272     awful.key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx(  1)    end,
273               {description = "swap with next client by index", group = "client"}),
274     awful.key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx( -1)    end,
275               {description = "swap with previous client by index", group = "client"}),
276     awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
277               {description = "focus the next screen", group = "screen"}),
278     awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
279               {description = "focus the previous screen", group = "screen"}),
280     awful.key({ modkey,           }, "u", awful.client.urgent.jumpto,
281               {description = "jump to urgent client", group = "client"}),
282     awful.key({ modkey,           }, "Tab",
283         function ()
284             awful.client.focus.history.previous()
285             if client.focus then
286                 client.focus:raise()
287             end
288         end,
289         {description = "go back", group = "client"}),
290
291     -- Standard program
292     awful.key({ modkey,           }, "Return", function () awful.spawn(terminal) end,
293               {description = "open a terminal", group = "launcher"}),
294     awful.key({ modkey, "Control" }, "r", awesome.restart,
295               {description = "reload awesome", group = "awesome"}),
296     awful.key({ modkey, "Shift"   }, "q", awesome.quit,
297               {description = "quit awesome", group = "awesome"}),
298
299     awful.key({ modkey,           }, "l",     function () awful.tag.incmwfact( 0.05)          end,
300               {description = "increase master width factor", group = "layout"}),
301     awful.key({ modkey,           }, "h",     function () awful.tag.incmwfact(-0.05)          end,
302               {description = "decrease master width factor", group = "layout"}),
303     awful.key({ modkey, "Shift"   }, "h",     function () awful.tag.incnmaster( 1, nil, true) end,
304               {description = "increase the number of master clients", group = "layout"}),
305     awful.key({ modkey, "Shift"   }, "l",     function () awful.tag.incnmaster(-1, nil, true) end,
306               {description = "decrease the number of master clients", group = "layout"}),
307     awful.key({ modkey, "Control" }, "h",     function () awful.tag.incncol( 1, nil, true)    end,
308               {description = "increase the number of columns", group = "layout"}),
309     awful.key({ modkey, "Control" }, "l",     function () awful.tag.incncol(-1, nil, true)    end,
310               {description = "decrease the number of columns", group = "layout"}),
311     awful.key({ modkey,           }, "space", function () awful.layout.inc( 1)                end,
312               {description = "select next", group = "layout"}),
313     awful.key({ modkey, "Shift"   }, "space", function () awful.layout.inc(-1)                end,
314               {description = "select previous", group = "layout"}),
315
316     awful.key({ modkey, "Control" }, "n",
317               function ()
318                   local c = awful.client.restore()
319                   -- Focus restored client
320                   if c then
321                       client.focus = c
322                       c:raise()
323                   end
324               end,
325               {description = "restore minimized", group = "client"}),
326
327     -- Prompt
328     awful.key({ modkey },            "r",     function () mypromptbox[awful.screen.focused()]:run() end,
329               {description = "run prompt", group = "launcher"}),
330
331     awful.key({ modkey }, "x",
332               function ()
333                   awful.prompt.run({ prompt = "Run Lua code: " },
334                   mypromptbox[awful.screen.focused()].widget,
335                   awful.util.eval, nil,
336                   awful.util.get_cache_dir() .. "/history_eval")
337               end,
338               {description = "lua execute prompt", group = "awesome"}),
339     -- Menubar
340     awful.key({ modkey }, "p", function() menubar.show() end,
341               {description = "show the menubar", group = "launcher"})
342 )
343
344 clientkeys = awful.util.table.join(
345     awful.key({ modkey,           }, "f",
346         function (c)
347             c.fullscreen = not c.fullscreen
348             c:raise()
349         end,
350         {description = "toggle fullscreen", group = "client"}),
351     awful.key({ modkey, "Shift"   }, "c",      function (c) c:kill()                         end,
352               {description = "close", group = "client"}),
353     awful.key({ modkey, "Control" }, "space",  awful.client.floating.toggle                     ,
354               {description = "toggle floating", group = "client"}),
355     awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
356               {description = "move to master", group = "client"}),
357     awful.key({ modkey,           }, "o",      function (c) c:move_to_screen()               end,
358               {description = "move to screen", group = "client"}),
359     awful.key({ modkey,           }, "t",      function (c) c.ontop = not c.ontop            end,
360               {description = "toggle keep on top", group = "client"}),
361     awful.key({ modkey,           }, "n",
362         function (c)
363             -- The client currently has the input focus, so it cannot be
364             -- minimized, since minimized clients can't have the focus.
365             c.minimized = true
366         end ,
367         {description = "minimize", group = "client"}),
368     awful.key({ modkey,           }, "m",
369         function (c)
370             c.maximized = not c.maximized
371             c:raise()
372         end ,
373         {description = "maximize", group = "client"})
374 )
375
376 -- Bind all key numbers to tags.
377 -- Be careful: we use keycodes to make it works on any keyboard layout.
378 -- This should map on the top row of your keyboard, usually 1 to 9.
379 for i = 1, 9 do
380     globalkeys = awful.util.table.join(globalkeys,
381         -- View tag only.
382         awful.key({ modkey }, "#" .. i + 9,
383                   function ()
384                         local screen = awful.screen.focused()
385                         local tag = screen.tags[i]
386                         if tag then
387                            tag:view_only()
388                         end
389                   end,
390                   {description = "view tag #"..i, group = "tag"}),
391         -- Toggle tag.
392         awful.key({ modkey, "Control" }, "#" .. i + 9,
393                   function ()
394                       local screen = awful.screen.focused()
395                       local tag = screen.tags[i]
396                       if tag then
397                          awful.tag.viewtoggle(tag)
398                       end
399                   end,
400                   {description = "toggle tag #" .. i, group = "tag"}),
401         -- Move client to tag.
402         awful.key({ modkey, "Shift" }, "#" .. i + 9,
403                   function ()
404                       if client.focus then
405                           local tag = client.focus.screen.tags[i]
406                           if tag then
407                               client.focus:move_to_tag(tag)
408                           end
409                      end
410                   end,
411                   {description = "move focused client to tag #"..i, group = "tag"}),
412         -- Toggle tag on focused client.
413         awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
414                   function ()
415                       if client.focus then
416                           local tag = client.focus.screen.tags[i]
417                           if tag then
418                               client.focus:toggle_tag(tag)
419                           end
420                       end
421                   end,
422                   {description = "toggle focused client on tag #" .. i, group = "tag"})
423     )
424 end
425
426 clientbuttons = awful.util.table.join(
427     awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
428     awful.button({ modkey }, 1, awful.mouse.client.move),
429     awful.button({ modkey }, 3, awful.mouse.client.resize))
430
431 -- Set keys
432 root.keys(globalkeys)
433 -- }}}
434
435 -- {{{ Rules
436 -- Rules to apply to new clients (through the "manage" signal).
437 awful.rules.rules = {
438     -- All clients will match this rule.
439     { rule = { },
440       properties = { border_width = beautiful.border_width,
441                      border_color = beautiful.border_normal,
442                      focus = awful.client.focus.filter,
443                      size_hints_honor = false,
444                      raise = true,
445                      keys = clientkeys,
446                      buttons = clientbuttons,
447                      placement = awful.placement.no_overlap+awful.placement.no_offscreen
448      }
449     },
450
451     -- Floating clients.
452     { rule_any = {
453         instance = {
454           "DTA",  -- Firefox addon DownThemAll.
455           "copyq",  -- Includes session name in class.
456         },
457         class = {
458           "Arandr",
459           "Gpick",
460           "Kruler",
461           "MessageWin",  -- kalarm.
462           "Sxiv",
463           "Wpa_gui",
464           "pinentry",
465           "veromix",
466           "xtightvncviewer"},
467
468         name = {
469           "Event Tester",  -- xev.
470         },
471         role = {
472           "AlarmWindow",  -- Thunderbird's calendar.
473           "pop-up",       -- e.g. Google Chrome's (detached) Developer Tools.
474         }
475       }, properties = { floating = true }},
476
477     -- Add titlebars to normal clients and dialogs
478     { rule_any = {type = { "normal", "dialog" }
479       }, properties = { titlebars_enabled = false }
480     },
481
482     -- Set Firefox to always map on the tag named "2" on screen 1.
483     -- { rule = { class = "Firefox" },
484     --   properties = { screen = 1, tag = "2" } },
485 }
486 -- }}}
487
488 -- {{{ Signals
489 -- Signal function to execute when a new client appears.
490 client.connect_signal("manage", function (c)
491     -- Set the windows at the slave,
492     -- i.e. put it at the end of others instead of setting it master.
493     -- if not awesome.startup then awful.client.setslave(c) end
494
495     if awesome.startup and
496       not c.size_hints.user_position
497       and not c.size_hints.program_position then
498         -- Prevent clients from being unreachable after screen count changes.
499         awful.placement.no_offscreen(c)
500     end
501 end)
502
503 -- Add a titlebar if titlebars_enabled is set to true in the rules.
504 client.connect_signal("request::titlebars", function(c)
505     -- buttons for the titlebar
506     local buttons = awful.util.table.join(
507         awful.button({ }, 1, function()
508             client.focus = c
509             c:raise()
510             awful.mouse.client.move(c)
511         end),
512         awful.button({ }, 3, function()
513             client.focus = c
514             c:raise()
515             awful.mouse.client.resize(c)
516         end)
517     )
518
519     awful.titlebar(c) : setup {
520         { -- Left
521             awful.titlebar.widget.iconwidget(c),
522             buttons = buttons,
523             layout  = wibox.layout.fixed.horizontal
524         },
525         { -- Middle
526             { -- Title
527                 align  = "center",
528                 widget = awful.titlebar.widget.titlewidget(c)
529             },
530             buttons = buttons,
531             layout  = wibox.layout.flex.horizontal
532         },
533         { -- Right
534             awful.titlebar.widget.floatingbutton (c),
535             awful.titlebar.widget.maximizedbutton(c),
536             awful.titlebar.widget.stickybutton   (c),
537             awful.titlebar.widget.ontopbutton    (c),
538             awful.titlebar.widget.closebutton    (c),
539             layout = wibox.layout.fixed.horizontal()
540         },
541         layout = wibox.layout.align.horizontal
542     }
543 end)
544
545 -- Enable sloppy focus
546 client.connect_signal("mouse::enter", function(c)
547     if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
548         and awful.client.focus.filter(c) then
549         client.focus = c
550     end
551 end)
552
553 client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
554 client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
555 -- }}}
556
557 -- vim:ft=lua:sw=4:sts=4:ts=4:et