dotfiles/awesome/init.fnl
2021-12-06 06:07:34 -06:00

713 lines
38 KiB
Fennel

;; Standard awesome library|#
(local gears (require "gears"))
(local awful (require "awful"))
(require "awful.autofocus")
;; Widget and layout library
(local wibox (require "wibox"))
;; Theme handling library
(local beautiful (require "beautiful"))
(local xresources (require "beautiful.xresources"))
;; Notification library
(local naughty (require "naughty"))
(local menubar (require "menubar"))
;; Enable hotkeys help widget for VIM and other apps
;; when client with a matching name is opened:
(local hotkeys_popup (require "awful.hotkeys_popup"))
(require "awful.hotkeys_popup.keys")
(local dpi xresources.apply_dpi)
(local ruled (require "ruled"))
;; my splits
(local clientrules (require "rules"))
(local keybindings (require "keybindings"))
(local notifications (require "notifications"))
;; Error handling
;; Check if awesome encountered an error during startup and fall back to
;; another config (This code will only ever execute for the fallback config)
(when awesome.startup_errors
(naughty.notify {:preset naughty.config.presets.critical
:title "Oops, there were errors during startup!"
:text awesome.startup_errors}))
;; Handle runtime errors after startup
(do
(var in_error false)
(awesome.connect_signal "debug::error" (fn [err]
;; Make sure we don't go into an endless error loop
(when (not in_error)
(set in_error true)
(naughty.notify {:preset naughty.config.presets.critical
:title "Oops, an error happened!"
:text (tostring err)})
(set in_error false)))))
;; Variable definitions
;; Themes define colours, icons, font and wallpapers.
(beautiful.init "/home/chris/.config/awesome/theme.lua")
;; Import the bling modules and layouts
(local bling (require "bling"))
;; (local awestore (require "awestore"))
(set naughty.config.defaults.position "bottom_middle")
(set naughty.config.defaults.margin 10)
(set naughty.config.defaults.border_width 0)
(set naughty.config.defaults.hover_timeout 5)
(set naughty.config.defaults.max_width (dpi 500))
;; {
;; :rule { }
;; :properties {
;; :border-width 0
;; :border_color "#000000"
;; :opacity 0.9
;; :shape gears.shape.rounded_rect}}
;; This is used later as the default terminal and editor to run.
(var terminal "alacritty")
(var editor (or (os.getenv "EDITOR") "emacsclient"))
(var editor_cmd (.. terminal " -e " editor))
;; (lambda battery-capacity (awful.spawn.easy_async "cat /sys/class/power_supply/BAT*/capacity"))
;; Default modkey.
;; Usually, Mod4 is the key with a logo between Control and Alt.
;; If you do not like this or do not have such a key,
;; I suggest you to remap Mod4 to another key using xmodmap or other tools.
;; However, you can use another modifier like Mod1, but it may interact with others.
(var modkey "Mod4")
(local shift "Shift")
(local ctrl "Control")
(local alt "Mod1")
;; Set hostname so that we can utilize specific features on different machines
(awful.spawn.easy_async "cat /etc/hostname" (fn [ stdout stderr reason exit_code ]
(if (= "syl\n" stdout)
(global laptop true)
(global laptop false))))
(local laptop true)
;; Table of layouts to cover with awful.layout.inc, order matters.
(set awful.layout.layouts [
awful.layout.suit.tile
bling.layout.mstab
bling.layout.centered
awful.layout.suit.floating
;; awful.layout.suit.tile.left
;; awful.layout.suit.tile.bottom
;; awful.layout.suit.tile.top
;; awful.layout.suit.fair
;; awful.layout.suit.fair.horizontal
;; awful.layout.suit.spiral
;; awful.layout.suit.spiral.dwindle
awful.layout.suit.max
;; awful.layout.suit.max.fullscreen
awful.layout.suit.magnifier
;; awful.layout.suit.corner.nw
;; awful.layout.suit.corner.ne
;; awful.layout.suit.corner.sw
;; awful.layout.suit.corner.se
])
;; Menu
;; Create a launcher widget and a main menu
(global myawesomemenu [
[ "hotkeys" (fn [] (hotkeys_popup.show_help nil (awful.screen.focused))) ]
[ "manual" (.. terminal " -e man awesome") ]
[ "edit config" (.. editor_cmd " " awesome.conffile) ]
[ "restart" awesome.restart ]
[ "quit" (fn [] (awesome.quit)) ]])
(global mymainmenu (awful.menu {:items [
[ "awesome" myawesomemenu beautiful.awesome_icon ]
[ "open terminal" terminal ]]}))
(global mylauncher (awful.widget.launcher {:image beautiful.awesome_icon
:menu mymainmenu }))
;; Menubar configuration
(set menubar.utils.terminal terminal) ;; Set the terminal for applications that require it
;; Keyboard map indicator and switcher
(global mykeyboardlayout (awful.widget.keyboardlayout))
;; Wibar
;; Create a textclock widget
(global mytextclock (wibox.widget.textclock))
;; Create a wibox for each screen and add it
(local taglist_buttons
(gears.table.join
(awful.button [] 1 (fn [t] (: t :view_only)))
(awful.button [ modkey ] 1 (fn [t] (when client.focus (: client.focus :move_to_tag t))))
(awful.button [] 3 awful.tag.viewtoggle)
(awful.button [ modkey ] 3 (fn [t] (when client.focus (: client.focus :toggle_tag t))))
(awful.button [] 4 (fn [t] (awful.tag.viewnext t.screen)))
(awful.button [] 5 (fn [t] (awful.tag.viewprev t.screen)))))
(local tasklist_buttons
(gears.table.join
(awful.button [] 1 (fn [c]
(if (= c client.focus)
(set c.minimized true)
(: c :emit_signal
"request::activate"
"tasklist"
{:raise true}
))))
(awful.button [] 3 (fn [] (awful.menu.client_list {:theme {:width 250 }})))
(awful.button [] 4 (fn [] (awful.client.focus.byidx 1)))
(awful.button [] 5 (fn [] (awful.client.focus.byidx -1)))))
(awful.screen.connect_for_each_screen
(fn [s]
;; Each screen has its own tag table.
(awful.tag [ "  " "  " "  " "  " ] s (. awful.layout.layouts 1))
;; Make buffers on all sides so that tiled clients aren't pushed to edges
(set s.padding (dpi 10))
;; Create a promptbox for each screen
(set s.mypromptbox (awful.widget.prompt))
;; Create an imagebox widget which will contain an icon indicating which layout we're using.
;; We need one layoutbox per screen.
(set s.mylayoutbox (awful.widget.layoutbox s))
(: s.mylayoutbox :buttons (gears.table.join
(awful.button [] 1 (fn [] (awful.layout.inc 1 s awful.layout.layouts)))
(awful.button [] 3 (fn [] (awful.layout.inc -1 s)))
(awful.button [] 4 (fn [] (awful.layout.inc 1 s)))
(awful.button [] 5 (fn [] (awful.layout.inc -1 s)))))
;; Create a taglist widget
(set s.mytaglist (awful.widget.taglist {
:screen s
:filter awful.widget.taglist.filter.all
:buttons taglist_buttons
:style {
:bg_focus beautiful.bg_focus
:fg_focus beautiful.base01
:fg_occupied beautiful.base0B
:bg_occupied beautiful.bg
:bg_empty beautiful.bg
}
:layout {
:spacing (dpi 5)
:spacing_widget {
:valign "center"
:halign "center"
:widget wibox.container.place
}
:layout wibox.layout.flex.horizontal
}
}))
;; (set s.mytaglistbg ( {
;; 1 {
;; s.mytaglist
;; }
;; :widget wibox.container.background
;; :shape gears.shape.rounded_bar
;; :bg beautiful.bg_normal
;; }))
;; Create a tasklist widget
(set s.mytasklist (awful.widget.tasklist {
:screen s
:filter awful.widget.tasklist.filter.focused
:buttons tasklist_buttons
:style {
:border_width 0
:shape gears.shape.rounded_bar
:bg_focus beautiful.transparent
:fg_focus beautiful.fg_normal
}
:layout {
:spacing (dpi 20)
:spacing_widget {
1 {
:forced_width (dpi 5)
:forced_height (dpi 20)
:widget wibox.widget.separator
}
:valign "center"
:halign "center"
:widget wibox.container.place
}
:layout wibox.layout.flex.horizontal
}
:widget_template { 1 {
1 {
1 {
1 {
1 {
:id "icon_role"
:widget wibox.widget.imagebox
}
:left (dpi 10)
:right (dpi 10)
:top (dpi 10)
:bottom (dpi 10)
:widget wibox.container.margin
:layout wibox.layout.align.horizontal
}
2 {
:id "text_role"
:widget wibox.widget.textbox
}
:layout wibox.layout.align.horizontal
}
:left (dpi 10)
:right (dpi 10)
:widget wibox.container.margin
:layout wibox.layout.align.horizontal
}
:id "background_role"
:widget wibox.container.background
}
:widget wibox.container.margin
:left (dpi 10)
:right (dpi 1)
:top (dpi 5)
:bottom (dpi 5)
}
}))
(set s.myminimizedtasklist (awful.widget.tasklist {
:screen s
:filter awful.widget.tasklist.filter.minimizedcurrenttags
:buttons tasklist_buttons
:style {
:border_width 0
:shape gears.shape.rounded_bar
}
:layout {
:spacing (dpi 20)
:spacing_widget {
1 {
:forced_width (dpi 5)
:forced_height (dpi 20)
:widget wibox.widget.separator
}
:valign "center"
:halign "center"
:widget wibox.container.place
}
:layout wibox.layout.flex.horizontal
}
:widget_template {
1 {
1 {
1 {
1 {
:id "icon_role"
:widget wibox.widget.imagebox
}
:margins 2
:widget wibox.container.margin
}
2 {
:id "text_role"
:widget wibox.widget.textbox
}
:layout wibox.layout.align.horizontal
}
:left (dpi 10)
:right (dpi 10)
:widget wibox.container.margin
}
:id "background_role"
:widget wibox.container.background
}
}))
(set s.mytextclock { 1 { 1 (wibox.widget {
:layout wibox.layout.fixed.horizontal
1 {
:format "<b> %a %b %d, %l:%M %p </b>"
:widget wibox.widget.textclock}})
:widget wibox.container.margin
:left 10
:right 10}
:widget wibox.container.background
:shape gears.shape.rounded_bar
:bg beautiful.transparent
:fg beautiful.base0B})
(set s.myemptywidget (wibox.widget { ;; an empty widget for spacing things out
:text ""
:align ""
:valign ""
:widget wibox.widget.textbox}))
(set s.temptext (awful.widget.watch "cat /sys/class/thermal/thermal_zone3/temp" 10))
(set s.tempicon (wibox.widget.textbox " "))
(set s.tempspace (wibox.widget.textbox " "))
(set s.tempwidget (wibox.widget {
1 s.tempicon
2 s.temptext
3 s.tempspace
:layout wibox.layout.fixed.horizontal}))
(set s.volumetext (awful.widget.watch "pamixer --get-volume-human" 0.5))
(set s.mictext (awful.widget.watch "pamixer --default-source --get-volume-human" 1))
(set s.volumeicon (wibox.widget.textbox " "))
(set s.micicon (wibox.widget.textbox " "))
(set s.volumespace (wibox.widget.textbox " "))
(set s.volumewidget { 1 { 1 { 1 (wibox.widget {
1 s.volumeicon
2 s.volumetext
3 s.volumespace
4 s.micicon
5 s.mictext
6 s.volumespace
:layout wibox.layout.fixed.horizontal
})
:widget wibox.container.margin
:left (dpi 5)}
:widget wibox.container.background
:shape gears.shape.rounded_bar
:bg beautiful.transparent
:fg beautiful.base09}
:widget wibox.container.margin
:right (dpi 5)})
(set s.batterytext (awful.widget.watch "cat /sys/class/power_supply/BAT1/capacity" 30))
(set s.batterytext2 (awful.widget.watch "cat /sys/class/power_supply/BAT2/capacity" 30))
(set s.batteryicon (wibox.widget.textbox " "))
(set s.batteryspace (wibox.widget.textbox " "))
(set s.batterywidget { 1 { 1 { 1 (wibox.widget {
1 s.batteryicon
2 s.batterytext
3 s.batteryspace
:layout wibox.layout.fixed.horizontal})
:widget wibox.container.margin
:left (dpi 5)}
:widget wibox.container.background
:shape gears.shape.rounded_bar
:bg beautiful.transparent
:fg beautiful.base0C}
:widget wibox.container.margin
:right (dpi 5)})
(set s.cputext (awful.widget.watch "cpu" 5))
(set s.cpuicon (wibox.widget.textbox " "))
(set s.cpuspace (wibox.widget.textbox " "))
(set s.cpuwidget { 1 { 1 { 1 (wibox.widget {
1 s.cpuicon
2 s.cputext
3 s.cpuspace
:layout wibox.layout.fixed.horizontal
})
:widget wibox.container.margin
:left (dpi 5)}
:widget wibox.container.background
:shape gears.shape.rounded_bar
:bg beautiful.transparent
:fg beautiful.base0A}
:widget wibox.container.margin
:right (dpi 5)})
(set s.memtext (awful.widget.watch "mem" 2))
(set s.memicon (wibox.widget.textbox " "))
(set s.memspace (wibox.widget.textbox " "))
(set s.memwidget { 1 { 1 { 1 (wibox.widget {
1 s.memicon
2 s.memtext
3 s.memspace
:layout wibox.layout.fixed.horizontal
})
:widget wibox.container.margin
:left (dpi 5)}
:widget wibox.container.background
:shape gears.shape.rounded_bar
:bg beautiful.transparent
:fg beautiful.base0E}
:widget wibox.container.margin
:right (dpi 5)})
(set s.nettext (awful.widget.watch "netwidget" 10))
(set s.neticon (wibox.widget.textbox " "))
(set s.netspace (wibox.widget.textbox " "))
(set s.netwidget { 1 { 1 { 1 (wibox.widget {
;; 1 s.neticon
2 s.nettext
3 s.netspace
:layout wibox.layout.fixed.horizontal
})
:widget wibox.container.margin
:left (dpi 5)}
:widget wibox.container.background
:shape gears.shape.rounded_bar
:bg beautiful.transparent
:fg beautiful.base08}
:widget wibox.container.margin
:right (dpi 5)})
(set s.mailtext (awful.widget.watch "muunread" 360))
(set s.mailicon (wibox.widget.textbox " "))
(set s.mailspace (wibox.widget.textbox " "))
(set s.mailwidget { 1 { 1 { 1 (wibox.widget {
1 s.mailicon
2 s.mailtext
3 s.mailspace
:layout wibox.layout.fixed.horizontal
})
:widget wibox.container.margin
:left (dpi 5)}
:widget wibox.container.background
:shape gears.shape.rounded_bar
:bg beautiful.transparent
:fg beautiful.base0D}
:widget wibox.container.margin
:right (dpi 5)})
(set s.wttrtext (awful.widget.watch "wttr" 1200))
(set s.wttrspace (wibox.widget.textbox " "))
(set s.wttrwidget { 1 { 1 { 1 (wibox.widget {
1 s.wttrtext
2 s.wttrspace
:layout wibox.layout.fixed.horizontal
:fg beautiful.base0B
})
:widget wibox.container.margin
:left (dpi 9)}
:widget wibox.container.background
:shape gears.shape.rounded_bar
:bg beautiful.transparent
:fg beautiful.base0C}
:widget wibox.container.margin
:right (dpi 10)})
(set s.mysystray { 1 { 1 { 1 (wibox.widget.systray)
:widget wibox.container.margin
:right (dpi 2)
:top (dpi 5)
:bottom (dpi 5)
:left (dpi 2)}
:widget wibox.container.background
:shape gears.shape.rounded_bar
:opacity 0.7
:bg beautiful.transparent
:fg beautiful.base0C}
:widget wibox.container.margin
:right (dpi 10)})
(set s.myrightwidgets {
1 {
:layout wibox.layout.fixed.horizontal
1 s.netwidget
2 s.mailwidget
3 s.memwidget
4 s.cpuwidget
5 s.volumewidget
6 (if laptop s.batterywidget s.myemptywidget)
7 (if (= s.index 1) s.mysystray)
8 s.mylayoutbox
}
:widget wibox.container.margin
:top (dpi 1)
:bottom (dpi 1)
})
(local yoffset (dpi 45)) ;; variables to be used for placing the wibox
(local xoffset (dpi 26))
;; Create the wibox
(set s.mywibox (wibox {;; since we are using a wibox we have a lot we need to set
;; as opposed to what we normally need to do with a wibar
:position "bottom"
:x (+ s.geometry.x xoffset)
:y (- s.geometry.height yoffset)
:height (dpi 33)
:width (- s.geometry.width (* xoffset 2))
:ontop false
:stretch false
:type "dock"
:shape gears.shape.rounded_bar
:bg beautiful.bg_normal
:fg beautiful.fg_normal
:opacity 0.9
:screen s }))
(: s.mywibox :struts { :bottom (dpi 40) })
;; Add widgets to the wibox
(: s.mywibox :setup {
:layout wibox.layout.align.horizontal
:expand "outside"
1 { ;; Left widgets
1 {
:layout wibox.layout.align.horizontal
1 s.mytaglist
2 s.mytasklist ;; Middle widget
3 s.myemptywidget
}
:left (dpi 10)
:right (dpi 10)
:widget wibox.container.margin
}
2 s.mytextclock :fg beautiful.base0B
3 { ;; Right widgets
1 {
:layout wibox.layout.align.horizontal
1 s.myemptywidget
2 {
1 s.myminimizedtasklist
:left (dpi 10)
:right (dpi 20)
:widget wibox.container.margin
}
3 s.myrightwidgets
}
:left (dpi 10)
:right (dpi 10)
:widget wibox.container.margin
}
})
(set s.mywibox.visible true) ;; this is needed to ensure the raw wibox is shown. Wibar normally does this
))
;; Mouse bindings
(root.buttons (gears.table.join
(awful.button [ ] 3 (fn [] (: mymainmenu :toggle)))
(awful.button [ ] 4 awful.tag.viewnext)
(awful.button [ ] 5 awful.tag.viewprev)))
(client.connect_signal "request::default_keybindings"
(fn []
(awful.keyboard.append_client_keybindings [
(awful.key [modkey] "c" (fn [c] (: c :kill))
{:description "close" :group "client"})
(awful.key [ modkey ] "f" (fn [c] (set c.fullscreen (not c.fullscreen)) (: c :raise))
{:description "toggle fullscreen" :group "client"})
(awful.key [ modkey ctrl ] "space" awful.client.floating.toggle
{:description "toggle floating" :group "client"})
(awful.key [ modkey ctrl ] "Return" (fn [c] (: c :swap (awful.client.getmaster)))
{:description "move to master" :group "client"})
(awful.key [ modkey ] "o" (fn [c] (: c :move_to_screen))
{:description "move to screen" :group "client"})
(awful.key [ modkey ] "t" (fn [c] (set c.ontop (not c.ontop)))
{:description "toggle keep on top" :group "client"})
(awful.key [ modkey ] "n" (fn [c]
;; The client currently has the input focus, so it cannot be
;; minimized, since minimized clients can't have the focus.
(set c.minimized true))
{:description "minimize" :group "client"})
(awful.key [ modkey ] "m" (fn [c] (set c.maximized (not c.maximized)) (: c :raise))
{:description "(un)maximize" :group "client"})
(awful.key [ modkey ctrl ] "m" (fn [c] (set c.maximized_vertical (not c.maximized_vertical)) (: c :raise))
{:description "(un)maximize vertically" :group "client"})
(awful.key [modkey shift ] "m" (fn [c] (set c.maximized_horizontal (not c.maximized_horizontal)) (: c :raise))
{:description "(un)maximize horizontally" :group "client"})]
)))
(client.connect_signal "request::default_mousebindings"
(fn []
(awful.mouse.append_client_mousebindings [
(awful.button [] 1 (fn [c] (: c :activate {:context "mouse_click"})))
(awful.button [modkey] 1 (fn [c] (: c :activate {:context "mouse_click" :action "mouse_move"})))
(awful.button [modkey] 3 (fn [c] (: c :activate {:context "mouse_click" :action "mouse_resize"})))
])))
;; Set keys
(root.keys keybindings.globalkeys)
;; Rules
(ruled.client.append_rules clientrules)
(ruled.notification.connect_signal
"request::rules"
(fn []
(ruled.notification.append_rules notifications)))
;; Signals
;; Signal function to execute when a new client appears.
(client.connect_signal
"manage"
(fn [c]
;; Set the windows at the slave,
;; i.e. put it at the end of others instead of setting it master.
(when (not awesome.startup) (awful.client.setslave c))
(when (and awesome.startup
(not c.size_hints.user_position)
(not c.size_hints.program_position))
;; Prevent clients from being unreachable after screen count changes.
(awful.placement.no_offscreen c))
;; MPV wasn't centering right
(when (= c.class "mpv") (awful.placement.centered c))
(when (= c.class "imv") (awful.placement.centered c))
(when (= c.class "Sxiv") (awful.placement.centered c))
(when (= c.name "Display Window") (set c.fullscreen true))
(awful.client.focus.byidx 1)
;; Rounded windows done right
(when (and (not c.fullscreen) (not (= c.name "Display Window")))
(set c.shape (fn [cr w h]
(gears.shape.rounded_rect cr w h (dpi 15)))))
(: c :activate [])))
(client.connect_signal "property::maximized"
(fn [c]
(let [s c.screen]
(set s.mywibox (wibox {;; since we are using a wibox we have a lot we need to set
;; as opposed to what we normally need to do with a wibar
:position "bottom"
:x 0
:y s.geometry.height
:height (dpi 33)
:width s.geometry.width
:ontop false
:stretch false
:type "dock"
:shape gears.shape.rectangle
:bg beautiful.bg_normal
:fg beautiful.fg_normal
:opacity 0.9})))))
;; make fullscreen clients no longer rounded windows
(client.connect_signal "property::fullscreen"
(fn [c]
(set c.shape (fn [cr w h]
(gears.shape.rectangle cr w h)))))
(client.connect_signal "focus" (fn [c] (set c.border_color beautiful.border_focus)))
(client.connect_signal "unfocus" (fn [c] (set c.border_color beautiful.border_normal)))
(client.connect_signal "request::manage" (fn [c] (if c.floating (set c.placement (+ awful.placement.centered awful.placement.no_offscreen)))))
(awful.screen.focus 1)
(awful.spawn.once "picom --experimental-backend")
(awful.spawn.once "/usr/lib/polkit-kde-authentication-agent-1")
(awful.spawn.once "feh --bg-fill /home/chris/Pictures/wallpapers/tech.jpg")
(awful.spawn.once "caffeine")
(awful.spawn.once "bluetoothctl power on")
(awful.spawn.once "nextcloud --background")
(awful.spawn.once "rbw-agent")
(awful.spawn.once "killall jellyfin-mpv-shim && jellyfin-mpv-shim")
(awful.spawn.once "xset r rate 220 90")
(awful.spawn.once "/usr/lib/kdeconnectd")
(awful.spawn.once "autorandr -c")
(awful.spawn.once "nm-applet")
(awful.spawn.once "xcape -e 'Super_L=Super_L|Control_L|Escape'")
(awful.spawn.once "xcape -e 'Alt_L=Super_L|W'")
;; (awful.spawn.once "latte-dock")