summaryrefslogtreecommitdiff
path: root/desktop-x11
diff options
context:
space:
mode:
authorMarcelo Lira <mlira@acumera.com>2025-03-07 00:41:38 -0300
committerMarcelo Lira <mlira@acumera.com>2025-03-19 20:35:19 -0300
commit7343a15f123c78d7c29ff7a189798de689869026 (patch)
tree462f4fbe3f17ee36c3adad2bc57531e2f8f371a7 /desktop-x11
Initial commit.HEADmaster
Diffstat (limited to 'desktop-x11')
-rwxr-xr-xdesktop-x11/.config/bspwm/bspwmrc134
-rw-r--r--desktop-x11/.config/polybar/base.ini73
-rw-r--r--desktop-x11/.config/polybar/colors.ini35
-rw-r--r--desktop-x11/.config/polybar/config.ini49
-rwxr-xr-xdesktop-x11/.config/polybar/launch.sh45
-rw-r--r--desktop-x11/.config/polybar/modules.ini354
-rw-r--r--desktop-x11/.config/sxhkd/sxhkdrc353
-rwxr-xr-xdesktop-x11/.local/bin/rofi-pass868
8 files changed, 1911 insertions, 0 deletions
diff --git a/desktop-x11/.config/bspwm/bspwmrc b/desktop-x11/.config/bspwm/bspwmrc
new file mode 100755
index 0000000..1c662f4
--- /dev/null
+++ b/desktop-x11/.config/bspwm/bspwmrc
@@ -0,0 +1,134 @@
+#! /bin/sh
+
+# set -xv
+# exec 2>>/tmp/bspwm.log
+
+pgrep -x sxhkd > /dev/null || sxhkd &
+
+# setxkbmap -rules evdev -model pc105 -layout ck61 -variant ck61 -option caps:escape
+# setxkbmap -option caps:escape
+# xmodmap $HOME/.Xmodmap
+
+# My monitors:
+# DP-2-2
+# HDMI-2
+# eDP-1
+CONNECTED_MONITORS=`xrandr -q | grep -w connected | cut -d ' ' -f1`
+MONITORS_COUNT=`echo "$CONNECTED_MONITORS" | wc -l`
+
+# Network Interfaces for Polybar modules
+NETWORK_INTERFACES=`nmcli -t device | grep -v bridge`
+ETHERNET_INTERFACES=`echo "$NETWORK_INTERFACES" | grep ":ethernet:"`
+ETHERNET_COUNT=`echo "$ETHERNET_INTERFACES" | wc -l`
+ETHER_IFACE=
+if [[ "$ETHERNET_COUNT" == "1" ]]; then
+ ETHER_IFACE=`echo "$ETHERNET_INTERFACES" | cut -d ':' -f1`
+else
+ ETHER_IFACE=`echo "$ETHERNET_INTERFACES" | grep ":connected" | cut -d ':' -f1`
+fi
+WIFI_INTERFACES=`echo "$NETWORK_INTERFACES" | grep ":wifi:"`
+WIFI_COUNT=`echo "$WIFI_INTERFACES" | wc -l`
+WIFI_IFACE=
+if [[ "$WIFI_COUNT" == "1" ]]; then
+ WIFI_IFACE=`echo "$WIFI_INTERFACES" | cut -d ':' -f1`
+else
+ WIFI_IFACE=`echo "$WIFI_INTERFACES" | grep ":connected" | cut -d ':' -f1`
+fi
+
+killall polybar
+xrandr --output eDP-1 --mode 1920x1080
+
+if [ "$MONITORS_COUNT" = "1" ]; then
+ bspc monitor eDP-1 -d I II III IV V VI VII VIII IX X
+ # PRIMARY_MONITOR="eDP-1" WIFI_IFACE="wlp4s0" polybar primary-monitor &
+ PRIMARY_MONITOR="eDP-1" ETHER_IFACE="$ETHER_IFACE" WIFI_IFACE="$WIFI_IFACE" polybar primary-monitor &
+else
+ EXTERNAL_MONITOR=`echo "$CONNECTED_MONITORS" | grep -v "eDP-1" | head -n1`
+ if [ "$EXTERNAL_MONITOR" = "DP-2-1" ] || [ "$EXTERNAL_MONITOR" = "DP-2-2" ]; then
+ EXTERNAL_MONITOR_RESOLUTION="2560x1080"
+ # xrandr --output $EXTERNAL_MONITOR --primary --mode 2560x1080 --left-of eDP-1
+ # bspc monitor eDP-1 -d IX X
+ # bspc monitor $EXTERNAL_MONITOR -d I II III IV V VI VII VIII
+ else
+ EXTERNAL_MONITOR_RESOLUTION="1920x1080"
+ # xrandr --output $EXTERNAL_MONITOR --primary --mode 1920x1080 --left-of eDP-1
+ # bspc monitor eDP-1 -d I II
+ # bspc monitor $EXTERNAL_MONITOR -d III IV V VI VII VIII IX X
+ fi
+ xrandr --output $EXTERNAL_MONITOR --primary --mode $EXTERNAL_MONITOR_RESOLUTION --left-of eDP-1
+ bspc monitor eDP-1 -d IX X
+ bspc monitor $EXTERNAL_MONITOR -d I II III IV V VI VII VIII
+ SECONDARY_MONITOR="eDP-1" polybar secondary-monitor &
+ PRIMARY_MONITOR="$EXTERNAL_MONITOR" ETHER_IFACE="$ETHER_IFACE" WIFI_IFACE="$WIFI_IFACE" polybar primary-monitor &
+fi
+
+bspc config border_width 1
+bspc config window_gap 3
+
+bspc config split_ratio 0.52 # 0.6
+bspc config borderless_monocle false # true
+bspc config gapless_monocle true
+
+bspc config focus_follows_pointer true
+bspc config pointer_follows_focus true
+bspc config pointer_follows_monitor true
+
+# Border colors
+# Original
+# bspc config normal_border_color "#484848"
+# bspc config focused_border_color "#21BA45"
+# bspc config active_border_color "#BA9521"
+# bspc config presel_feedback_color "#E2FF20"
+
+# Vault Tec
+bspc config normal_border_color "#345985"
+bspc config focused_border_color "#FDF070"
+bspc config active_border_color "#5C835E"
+bspc config presel_feedback_color "#A63C45"
+
+# xrdb ${XDG_CONFIG_HOME:-$HOME/.config}/Xresources
+pgrep -x picom > /dev/null || picom &
+pgrep -x unclutter > /dev/null || unclutter &
+pgrep -x dunst > /dev/null || dunst &
+pgrep -x nm-applet > /dev/null || nm-applet &
+# /usr/bin/gnome-keyring-daemon --start --components=ssh
+xset r rate 300 50
+
+feh --bg-fill $HOME/Dropbox/Images/wallpapers/dore-christ-leaving-the-praetorium.jpeg
+# wal -i $HOME/Dropbox/Images/wallpapers/dore-christ-leaving-the-praetorium.jpeg >/dev/null 2>&1
+
+# bspc rule -a Gimp desktop='^8' state=floating follow=on
+# bspc rule -a Chromium desktop='^2'
+# bspc rule -a mplayer2 state=floating
+# bspc rule -a Kupfer.py focus=on
+# bspc rule -a Screenkey manage=off
+
+bspc rule -a Floating state=floating center=true follow=on
+
+bspc rule -a Arandr state=floating
+bspc rule -a Blueman-manager state=floating
+bspc rule -a Cheese state=floating center=true follow=on
+bspc rule -a Clocks state=floating center=true follow=on
+bspc rule -a Eog state=floating center=true follow=on
+bspc rule -a Gitg state=floating center=true follow=on
+bspc rule -a Gitk state=floating center=true follow=on
+bspc rule -a Gnome-calculator state=floating center=true follow=on
+bspc rule -a Gnome-calendar state=floating center=true follow=on
+bspc rule -a Gnome-control-center state=floating center=true follow=on
+bspc rule -a Gnome-screenshot state=floating center=true follow=on
+bspc rule -a Gnome-todo state=floating center=true follow=on
+bspc rule -a Gnome-tweaks state=floating center=true follow=on
+bspc rule -a MuPDF state=floating center=true follow=on
+bspc rule -a Pavucontrol state=floating center=true follow=on
+bspc rule -a Qemu-system-i386 state=floating center=true follow=on
+bspc rule -a Qemu-system-x86_64 state=floating center=true follow=on
+bspc rule -a Signal state=floating
+bspc rule -a SimpleScreenRecorder state=floating center=true follow=on
+bspc rule -a Surf state=floating center=true follow=on
+bspc rule -a Sxiv state=floating center=true follow=on
+bspc rule -a mpv state=floating center=true follow=on
+bspc rule -a "Org.gnome.Characters:*:*" state=floating center=true follow=on
+bspc rule -a "Gpick:*:*" state=floating center=true follow=on
+bspc rule -a "*:*:Picture-in-Picture" state=floating follow=on
+bspc rule -a "*:*:Network Connections" state=floating follow=on
+bspc rule -a gnome-calculator state=floating center=true follow=on
diff --git a/desktop-x11/.config/polybar/base.ini b/desktop-x11/.config/polybar/base.ini
new file mode 100644
index 0000000..807104b
--- /dev/null
+++ b/desktop-x11/.config/polybar/base.ini
@@ -0,0 +1,73 @@
+;==========================================================
+;
+; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗
+; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗
+; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝
+; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗
+; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║
+; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
+;
+;==========================================================
+
+[settings]
+; Reload upon receiving XCB_RANDR_SCREEN_CHANGE_NOTIFY events
+screenchange-reload = true
+pseudo-transparency = false
+
+; Compositing operators
+; @see: https://www.cairographics.org/manual/cairo-cairo-t.html#cairo-operator-t
+compositing-background = source
+compositing-foreground = over
+compositing-overline = over
+compositing-underline = over
+compositing-border = over
+
+; Define fallback values used by all module formats
+; format-foreground =
+; format-background =
+; format-underline =
+; format-overline =
+; format-spacing =
+; format-padding =
+; format-margin =
+; format-offset =
+
+[global/wm]
+margin-top = 0
+margin-bottom = 0
+
+[bar/base]
+enable-ipc = true
+
+background = ${colors.background}
+foreground = ${colors.foreground}
+
+font-0 = RobotoMono Nerd Font:style=Medium,Regular:size=8:antialias=true;2
+font-1 = FontAwesome:style=Regular:size=8:antialias=true;1
+font-2 = Symbola:style=Regular:size=8:antialias=true;1
+font-3 = fixed:pixelsize=0;0
+
+width = 100%
+height = 18
+fixed-center = false
+bottom = false
+
+line-size = 2
+line-color = #f00
+
+border-size = 0
+border-color = #00000000
+
+padding-left = 0
+padding-right = 0
+
+module-margin-left = 0
+module-margin-right = 1
+
+scroll-up = i3wm-wsprev
+scroll-down = i3wm-wsnext
+
+cursor-click = pointer
+cursor-scroll = ns-resize
+
+override-redirect = false
diff --git a/desktop-x11/.config/polybar/colors.ini b/desktop-x11/.config/polybar/colors.ini
new file mode 100644
index 0000000..d768194
--- /dev/null
+++ b/desktop-x11/.config/polybar/colors.ini
@@ -0,0 +1,35 @@
+;==========================================================
+;
+; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗
+; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗
+; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝
+; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗
+; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║
+; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
+;
+;==========================================================
+
+[colors]
+background = ${xrdb:color0:#cc222222}
+background-alt = #444444
+foreground = ${xrdb:color7:#dfdfdf}
+foreground-alt = #555555
+
+primary = #ffb52a
+secondary = #e60053
+alert = #bd2c40
+
+module-label-foreground = #000000
+module-label-background = #0a6cf5
+module-value-foreground = #000000
+module-value-background = #d0d0d0d0
+
+module-value-intensity-1 = #55aa55
+module-value-intensity-2 = #557755
+module-value-intensity-3 = #f5a70a
+module-value-intensity-4 = #ff5555
+
+module-value-negative-foreground = #7C7772
+module-value-negative-background = #C1BAAD
+
+; vim:ft=dosini
diff --git a/desktop-x11/.config/polybar/config.ini b/desktop-x11/.config/polybar/config.ini
new file mode 100644
index 0000000..82a92fc
--- /dev/null
+++ b/desktop-x11/.config/polybar/config.ini
@@ -0,0 +1,49 @@
+;==========================================================
+;
+; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗
+; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗
+; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝
+; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗
+; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║
+; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
+;
+;==========================================================
+
+include-file = ./colors.ini
+include-file = ./base.ini
+include-file = ./modules.ini
+
+[bar/primary-monitor]
+inherit = bar/base
+
+monitor = ${env:PRIMARY_MONITOR}
+
+modules-left = ewmh
+modules-center = xwindow
+modules-right = cpu temperature fs-root fs-storage network-iface-1 network-iface-2 vpn calendar
+
+tray-position = right
+tray-padding = 4
+tray-foreground = ${root.foreground}
+tray-background = ${root.background}
+
+[bar/secondary-monitor]
+inherit = bar/base
+
+monitor = ${env:SECONDARY_MONITOR}
+
+bottom = true
+
+modules-left = ewmh
+; modules-center = mpd
+modules-right = battery pulseaudio xkeyboard
+
+[module/network-iface-1]
+inherit = module/network-eth
+interface = ${env:ETHER_IFACE}
+
+[module/network-iface-2]
+inherit = module/network-wifi
+interface = ${env:WIFI_IFACE}
+
+; vim:ft=dosini
diff --git a/desktop-x11/.config/polybar/launch.sh b/desktop-x11/.config/polybar/launch.sh
new file mode 100755
index 0000000..0704e24
--- /dev/null
+++ b/desktop-x11/.config/polybar/launch.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+# Terminate already running bar instances
+killall -q polybar
+
+# Wait until the processes have been shut down
+while pgrep -x polybar >/dev/null; do sleep 1; done
+
+host=$(hostname)
+
+# My monitors:
+# DP-2-2
+# HDMI-2
+# eDP-1
+LAPTOP_BUILT_IN_MONITOR="eDP-1"
+
+NETWORK_INTERFACES=`nmcli -t device | grep -v bridge`
+
+ETHERNET_INTERFACES=`echo "$NETWORK_INTERFACES" | grep ":ethernet:"`
+ETHERNET_COUNT=`echo "$ETHERNET_INTERFACES" | wc -l`
+ETHER_IFACE=
+if [[ "$ETHERNET_COUNT" == "1" ]]; then
+ ETHER_IFACE=`echo "$ETHERNET_INTERFACES" | cut -d ':' -f1`
+else
+ ETHER_IFACE=`echo "$ETHERNET_INTERFACES" | grep ":connected" | cut -d ':' -f1`
+fi
+
+WIFI_INTERFACES=`echo "$NETWORK_INTERFACES" | grep ":wifi:"`
+WIFI_COUNT=`echo "$WIFI_INTERFACES" | wc -l`
+WIFI_IFACE=
+if [[ "$WIFI_COUNT" == "1" ]]; then
+ WIFI_IFACE=`echo "$WIFI_INTERFACES" | cut -d ':' -f1`
+else
+ WIFI_IFACE=`echo "$WIFI_INTERFACES" | grep ":connected" | cut -d ':' -f1`
+fi
+
+# Launch polybar
+CONNECTED_MONITORS=`xrandr -q | grep -w connected | cut -d ' ' -f1`
+MONITORS_COUNT=`echo "$CONNECTED_MONITORS" | wc -l`
+if [[ "$MONITORS_COUNT" == "1" ]]; then
+ PRIMARY_MONITOR="$CONNECTED_MONITORS" ETHER_IFACE="$ETHER_IFACE" WIFI_IFACE="$WIFI_IFACE" polybar primary-monitor &
+else
+ PRIMARY_MONITOR=`echo "$CONNECTED_MONITORS" | grep -v "$LAPTOP_BUILT_IN_MONITOR" | head -n1` ETHER_IFACE="$ETHER_IFACE" WIFI_IFACE="$WIFI_IFACE" polybar primary-monitor &
+ SECONDARY_MONITOR="$LAPTOP_BUILT_IN_MONITOR" polybar secondary-monitor &
+fi
diff --git a/desktop-x11/.config/polybar/modules.ini b/desktop-x11/.config/polybar/modules.ini
new file mode 100644
index 0000000..c3b2d0e
--- /dev/null
+++ b/desktop-x11/.config/polybar/modules.ini
@@ -0,0 +1,354 @@
+;==========================================================
+;
+; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗
+; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗
+; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝
+; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗
+; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║
+; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
+;
+;==========================================================
+
+; Internal modules ------------------------------------------------------------
+
+[module/date]
+type = internal/date
+interval = 5
+time = %H:%M
+format-prefix-foreground = ${colors.foreground-alt}
+format-underline = #0a6cf5
+
+label = %time%
+
+[module/xwindow]
+type = internal/xwindow
+label = %title:0:30:...%
+
+[module/xkeyboard]
+type = internal/xkeyboard
+blacklist-0 = num lock
+
+format-prefix = " ⌨ "
+format-prefix-foreground = ${colors.module-label-foreground}
+format-prefix-background = #219ebc
+format-foreground = ${colors.module-value-foreground}
+format-background = ${colors.module-value-background}
+
+label-layout = " %layout% "
+
+label-indicator-padding = 2
+label-indicator-margin = 1
+label-indicator-background = ${colors.secondary}
+label-indicator-underline = ${colors.secondary}
+
+click-left = ~/.local/bin/fix-keyboard
+
+[fs-base]
+type = internal/fs
+interval = 25
+
+format-unmounted-prefix = ${self.format-mounted-prefix}
+format-unmounted-prefix-foreground = ${self.format-mounted-prefix-foreground}
+format-unmounted-prefix-background = ${self.format-mounted-prefix-background}
+
+label-mounted = " %percentage_free%% free · %free% "
+label-mounted-foreground = ${colors.module-value-foreground}
+label-mounted-background = ${colors.module-value-background}
+
+label-unmounted = " absent "
+label-unmounted-foreground = ${colors.module-value-negative-foreground}
+label-unmounted-background = ${colors.module-value-negative-background}
+
+[module/fs-root]
+inherit = fs-base
+mount-0 = /
+format-mounted-prefix = "  Root "
+format-mounted-prefix-foreground = #005500
+format-mounted-prefix-background = #b0e000
+
+[module/fs-storage]
+inherit = fs-base
+mount-0 = /home/setanta/storage
+format-mounted-prefix = "  External "
+format-mounted-prefix-foreground = #b7f6b9
+format-mounted-prefix-background = #347D39
+
+[module/ewmh]
+type = internal/xworkspaces
+
+pin-workspaces = true
+enable-click = true
+enable-scroll = true
+reverse-scroll = true
+
+format = <label-state>
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; Default: %icon% %name%
+label-active = %name%
+label-active-foreground = ${colors.primary}
+label-active-background = #625233
+
+label-occupied = %name%
+label-occupied-foreground = ${colors.foreground}
+label-occupied-background = ${colors.background-alt}
+
+label-urgent = %name%
+label-urgent-foreground = #ff3a03
+label-urgent-background = #743021
+
+label-font = 2.5
+
+label-active-padding = 1
+label-urgent-padding = 1
+label-occupied-padding = 1
+label-empty-padding = 1
+
+[module/cpu]
+type = internal/cpu
+interval = 5
+format = "<label> <ramp-coreload> "
+format-prefix = "  CPU "
+format-prefix-foreground = #7b0000
+format-prefix-background = #fe8700
+format-foreground = ${colors.module-value-foreground}
+format-background = ${colors.module-value-background}
+label = " %percentage:2%% "
+ramp-coreload-spacing = 2
+ramp-coreload-0 = "%{O-12}%{F#999}▁"
+ramp-coreload-1 = "%{O-12}%{F#977}▂"
+ramp-coreload-2 = "%{O-12}%{F#955}▃"
+ramp-coreload-3 = "%{O-12}%{F#931}▄"
+ramp-coreload-4 = "%{O-12}%{F#900}▅"
+ramp-coreload-5 = "%{O-12}%{F#B00}▆"
+ramp-coreload-6 = "%{O-12}%{F#D00}▇"
+ramp-coreload-7 = "%{O-12}%{F#F00}█"
+
+[module/memory]
+type = internal/memory
+interval = 5
+format = "<label> <bar-used> "
+format-prefix = " Mem "
+format-prefix-foreground = ${colors.module-label-foreground}
+format-prefix-background = #a1c181
+label = " %percentage_used%% "
+format-foreground = ${colors.module-value-foreground}
+format-background = ${colors.module-value-background}
+
+bar-used-indicator =
+bar-used-width = 8
+bar-used-foreground-0 = ${module-value-intensity-1}
+bar-used-foreground-1 = ${module-value-intensity-2}
+bar-used-foreground-2 = ${module-value-intensity-3}
+bar-used-foreground-3 = ${module-value-intensity-4}
+
+bar-used-fill = ▐
+bar-used-empty = ▐
+bar-used-empty-foreground = #444444
+
+ramp-used-0 = ▁
+ramp-used-1 = ▂
+ramp-used-2 = ▃
+ramp-used-3 = ▄
+ramp-used-4 = ▅
+ramp-used-5 = ▆
+ramp-used-6 = ▇
+ramp-used-7 = █
+
+ramp-free-0 = ▁
+ramp-free-1 = ▂
+ramp-free-2 = ▃
+ramp-free-3 = ▄
+ramp-free-4 = ▅
+ramp-free-5 = ▆
+ramp-free-6 = ▇
+ramp-free-7 = █
+
+[network-base]
+type = internal/network
+unknown-as-up = true
+label-connected = "%{B#E7FFE7}%{F#4E8049} ↓%downspeed:8% %{B#FFE6E8}%{F#80494C} ↑%upspeed:8% %{B- F-}"
+format-connected = <label-connected>
+format-connected-foreground = ${colors.module-value-foreground}
+format-connected-background = ${colors.module-value-background}
+label-disconnected = " offline "
+label-disconnected-foreground = ${colors.module-value-negative-foreground}
+label-disconnected-background = ${colors.module-value-negative-background}
+format-disconnected = <label-disconnected>
+format-disconnected-prefix = ${self.format-connected-prefix}
+format-disconnected-prefix-foreground = ${self.format-connected-prefix-foreground}
+format-disconnected-prefix-background = ${self.format-connected-prefix-background}
+
+[module/network-eth]
+inherit = network-base
+format-connected-prefix = " 🖧 Eth "
+format-connected-prefix-foreground = #71CDFF
+format-connected-prefix-background = #3F76BB
+
+; FIXME: I don't know why, but inheritance is not working for wifi
+[module/network-wifi]
+type = internal/network
+unknown-as-up = ${network-base.unknown-as-up}
+label-connected = ${network-base.label-connected}
+format-connected = ${network-base.format-connected}
+; inherit = network-base
+format-connected-prefix = " 📡 Wifi "
+format-connected-prefix-foreground = #DBA3FF
+format-connected-prefix-background = #8E69CA
+format-connected-foreground = ${network-base.format-connected-foreground}
+format-connected-background = ${network-base.format-connected-background}
+
+label-disconnected = " offline "
+label-disconnected-foreground = ${colors.module-value-negative-foreground}
+label-disconnected-background = ${colors.module-value-negative-background}
+format-disconnected = <label-disconnected>
+format-disconnected-prefix = ${self.format-connected-prefix}
+format-disconnected-prefix-foreground = ${self.format-connected-prefix-foreground}
+format-disconnected-prefix-background = ${self.format-connected-prefix-background}
+
+[module/pulseaudio]
+type = internal/pulseaudio
+
+format-volume = <label-volume> <bar-volume>
+label-volume = " ♫ VOL %percentage%% "
+label-volume-foreground = ${colors.module-label-foreground}
+label-volume-background = #d0a0d0
+label-muted = " ♫ muted "
+label-muted-foreground = #666
+bar-volume-width = 8
+bar-volume-foreground-0 = ${colors.module-value-intensity-1}
+bar-volume-foreground-1 = ${colors.module-value-intensity-1}
+bar-volume-foreground-2 = ${colors.module-value-intensity-2}
+bar-volume-foreground-3 = ${colors.module-value-intensity-2}
+bar-volume-foreground-4 = ${colors.module-value-intensity-3}
+bar-volume-foreground-5 = ${colors.module-value-intensity-3}
+bar-volume-foreground-6 = ${colors.module-value-intensity-4}
+
+bar-volume-gradient = false
+bar-volume-indicator = |
+bar-volume-indicator-font = 3
+bar-volume-fill = ─
+bar-volume-fill-font = 3
+bar-volume-empty = ─
+bar-volume-empty-font = 3
+
+[module/temperature]
+type = internal/temperature
+thermal-zone = 0
+warn-temperature = 60
+
+; format-prefix = " 🌡Temp "
+format-prefix = " Temp "
+format = <label><ramp>
+format-prefix-foreground = #3f4a47
+format-prefix-background = #88b1b1
+format-foreground = ${colors.module-value-foreground}
+format-background = ${colors.module-value-background}
+
+format-warn-prefix = " 🌡Temp "
+format-warn = <label-warn><ramp>
+format-warn-prefix-foreground = ${colors.module-value-foreground}
+format-warn-prefix-background = ${self.format-prefix-background}
+
+label = " %temperature-c% "
+; label-foreground = ${colors.module-label-foreground}
+; label-background = ${colors.module-label-background}
+label-foreground = ${colors.module-value-foreground}
+label-background = ${colors.module-value-background}
+
+label-warn = " %temperature-c% "
+label-warn-foreground = ${colors.module-value-foreground}
+label-warn-background = ${colors.module-value-background}
+
+ramp-0 = " ➊ "
+ramp-1 = " ➋ "
+ramp-2 = " ➌ "
+ramp-background = ${colors.module-value-background}
+ramp-0-foreground = ${colors.module-value-intensity-1}
+ramp-1-foreground = ${colors.module-value-intensity-3}
+ramp-2-foreground = ${colors.module-value-intensity-4}
+
+[module/battery]
+type = internal/battery
+full-at = 99
+low-at = 5
+battery = BAT0
+adapter = ADP1
+poll-interval = 5
+time-format = %H:%M
+format-charging = <animation-charging> <label-charging>
+format-discharging = <ramp-capacity> <label-discharging>
+label-charging = Charging %percentage%%
+label-discharging = Discharging %percentage%%
+label-full = " ⚡ Fully charged "
+label-full-foreground = #1a1a1a
+label-full-background = #ffff00
+label-low = BATTERY LOW
+ramp-capacity-0 = 
+ramp-capacity-1 = 
+ramp-capacity-2 = 
+ramp-capacity-3 = 
+ramp-capacity-4 = 
+bar-capacity-width = 10
+animation-charging-0 = 
+animation-charging-1 = 
+animation-charging-2 = 
+animation-charging-3 = 
+animation-charging-4 = 
+; Framerate in milliseconds
+animation-charging-framerate = 750
+animation-discharging-0 = 
+animation-discharging-1 = 
+animation-discharging-2 = 
+animation-discharging-3 = 
+animation-discharging-4 = 
+; Framerate in milliseconds
+animation-discharging-framerate = 500
+animation-low-0 = !
+animation-low-1 =
+animation-low-framerate = 200
+
+; [module/mpd]
+; type = internal/mpd
+;
+; host = 127.0.0.1
+; port = 6600
+; interval = 2
+; format-online = <label-time> <label-song>
+; label-song = %artist% - %title%
+; label-offline = 🎜 mpd is offline
+
+; Custom modules --------------------------------------------------------------
+
+[module/calendar]
+type = custom/script
+exec = ~/.local/bin/clock
+interval = 5
+tail = true
+format-prefix = " 📆 "
+format-prefix-foreground = #e3e7ce
+format-prefix-background = #076678
+format-foreground = ${colors.module-value-foreground}
+format-background = ${colors.module-value-background}
+click-left = BLOCK_BUTTON=1 ~/.local/bin/clock
+click-middle = BLOCK_BUTTON=2 ~/.local/bin/clock
+click-right = BLOCK_BUTTON=3 ~/.local/bin/clock
+
+[module/vpn]
+type = custom/script
+exec = ~/.local/bin/vpn
+interval = 25
+tail = true
+format-prefix = " ♜ VPN "
+format-prefix-foreground = #BE492A
+format-prefix-background = #f99256
+format-foreground = ${colors.module-value-foreground}
+format-background = ${colors.module-value-background}
+click-left = BLOCK_BUTTON=1 ~/.local/bin/vpn
+click-middle = BLOCK_BUTTON=2 ~/.local/bin/vpn
+click-right = BLOCK_BUTTON=3 ~/.local/bin/vpn
+
+; vim:ft=dosini
diff --git a/desktop-x11/.config/sxhkd/sxhkdrc b/desktop-x11/.config/sxhkd/sxhkdrc
new file mode 100644
index 0000000..f993ab5
--- /dev/null
+++ b/desktop-x11/.config/sxhkd/sxhkdrc
@@ -0,0 +1,353 @@
+# make sxhkd reload its configuration files:
+super + Escape
+ dunstctl set-paused true ; i3lock -tfi ~/Dropbox/Images/wallpapers/stmichael.png ; dunstctl set-paused false
+
+# make sxhkd reload its configuration files:
+super + ctrl + Escape
+ pkill -usr1 -x sxhkd; dunstify 'sxhkd' 'Reloaded config'
+
+#
+# Gaps
+#
+super + {_,shift + }equal
+ bspc config -d focused window_gap $(($(bspc config -d focused window_gap) + {2,10}))
+
+super + {_,shift + }minus
+ bspc config -d focused window_gap $(($(bspc config -d focused window_gap) - {2,10}))
+
+# Terminal
+super + Return
+ alacritty -e tmux
+
+super + shift + Return
+ alacritty
+
+super + ctrl + Return
+ alacritty --class Floating
+
+super + e
+ st -z 14
+ # alacritty --class Floating --option 'font.size=24.0' --option 'window.dimensions={columns=100,lines=20}' --command vim ~/scratchpad
+
+super + shift + e
+ st -z 14 -e tmux
+
+super + control + e
+ st -c Floating -z 16
+
+ # alacritty --class Floating --option 'font.size=24.0' --option 'window.dimensions={columns=100,lines=20}' --command vim --clean ~/scratchpad
+
+# Settings
+super + shift + s
+ pavucontrol
+
+# program launcher
+super + @space
+ rofi -show drun -window-thumbnail -window-format "\{w\} \{t\}"
+
+super + shift + @space
+ rofi -show run -window-thumbnail -window-format "\{w\} \{t\}"
+
+super + ctrl + @space
+ rofi -show window -window-thumbnail -window-format "\{w\} \{t\}" -window-command "bspc node \{window\} -d newest -f"
+
+super + i
+ rofi -show filebrowser -theme dark-grid
+
+super + ctrl + i
+ rofi -filebrowser-directory $HOME/Pictures/Screenshots -show filebrowser -show filebrowser -theme dark-grid
+
+super + p
+ rofi-pass --last-used -lines 12
+
+# Notifications
+
+# Redisplay last message(s).
+ctrl + grave
+ dunstctl history-pop
+
+# Close notification.
+ctrl + shift + grave
+ dunstctl close
+
+# Close all notifications.
+ctrl + shift + alt + grave
+ dunstctl close-all
+
+# Context menu.
+ctrl + shift + period
+ dunstctl context
+
+# start a web browser
+super + o
+ /usr/bin/librewolf -P personal
+
+super + ctrl + o
+ /usr/bin/librewolf -P work
+
+super + alt + o
+ bspc rule -a '*:*' -o state=floating ; /usr/bin/librewolf -P personal
+
+super + shift + p
+ bspc rule -a '*:*' -o state=floating ; /usr/bin/librewolf --private-window
+
+# super + alt + b
+# ~/.local/bin/rofi-buku2
+ # rofi-buku -show
+
+# start a file browser
+super + n
+ /usr/bin/nautilus
+
+super + shift + n
+ ~/.config/regolith/bin/open-dirs.sh
+
+super + shift + i
+ catfish ~/storage/Downloads/images --name Floating
+
+# Audio Controls
+{shift + XF86AudioLowerVolume, super + less}
+ ~/.local/bin/volume-control down
+
+{shift + XF86AudioRaiseVolume, super + greater}
+ ~/.local/bin/volume-control up
+
+XF86AudioLowerVolume
+ ~/.local/bin/volume-control down-a-bit
+
+XF86AudioRaiseVolume
+ ~/.local/bin/volume-control up-a-bit
+
+{XF86AudioMute, super + shift + m}
+ ~/.local/bin/volume-control mute
+ # ~/.local/bin/volume-control medium
+
+super + shift + less
+ ~/.local/bin/volume-control quiet
+
+super + shift + greater
+ ~/.local/bin/volume-control max
+
+# Music Player Daemon controls
+super + ctrl + p
+ song-control toggle
+ # dunstify --urgency normal --timeout 2000 --icon multimedia-player --hints=string:x-dunst-stack-tag:song "$(mpc toggle | head -n2)"
+
+super + ctrl + less
+ song-control prev
+ # dunstify --urgency normal --timeout 2000 --icon multimedia-player --hints=string:x-dunst-stack-tag:song "$(mpc prev | head -n1)"
+
+super + ctrl + greater
+ song-control next
+ # dunstify --urgency normal --timeout 2000 --icon multimedia-player --hints=string:x-dunst-stack-tag:song "$(mpc next | head -n1)"
+
+# bspwm hotkeys
+#
+
+# quit/restart bspwm
+super + shift + r
+ [ $(printf "Yes\nNo" | rofi -dmenu -i -p "Restart BSPWM") = "Yes" ] && bspc wm -r
+
+super + q
+ rofi -show session-menu -modi "session-menu:/home/setanta/.local/bin/rofi-power-menu"
+ # [ $(printf "Yes\nNo" | rofi -dmenu -i -p "Logout") = "Yes" ] && bspc quit
+
+# close and kill
+super + {_,shift + }w
+ bspc node -{c,k}
+
+# alternate between the tiled and monocle layout
+super + m
+ bspc desktop -l next
+
+super + alt + n
+ bsp-layout next | head -n1 | xargs dunstify
+
+super + alt + p
+ bsp-layout previous | head -n1 | xargs dunstify
+
+super + alt + t
+ bsp-layout set tall | head -n1 | xargs dunstify
+
+super + alt + shift + t
+ bsp-layout set tiled | head -n1 | xargs dunstify
+
+# send the newest marked node to the newest preselected node
+super + y
+ bspc node newest.marked.local -n newest.!automatic.local
+
+# swap the current node and the biggest window
+super + g
+ bspc node -s biggest.window
+
+#
+# state/flags
+#
+
+# set the window state
+super + {t,shift + t,s,f}
+ bspc node -t {tiled,pseudo_tiled,floating,fullscreen}
+
+# set the node flags
+super + ctrl + {m,x,y,z}
+ bspc node -g {marked,locked,sticky,private}
+
+#
+# focus/swap
+#
+
+# focus the node in the given direction
+super + {_,shift + }{h,j,k,l}
+ bspc node -{f,s} {west,south,north,east}
+super + {_,shift + }{Left,Down,Up,Right}
+ bspc node -{f,s} {west,south,north,east}
+
+# focus the node for the given path jump
+# super + {p,b,comma,period}
+# bspc node -f @{parent,brother,first,second}
+
+# focus the next/previous window in the current desktop
+# super + {_,shift + }c
+# bspc node -f {next,prev}.local.!hidden.window
+super + comma
+ bspc node -f prev.local.!hidden.window
+super + period
+ bspc node -f next.local.!hidden.window
+
+# focus the next/previous desktop in the current monitor
+super + {Prior,Next}
+ bspc desktop -f {prev,next}.local.occupied
+
+super + ctrl + {Prior,Next}
+ bspc desktop -f {prev,next}.local
+
+super + bracket{left,right}
+ bspc desktop -f {prev,next}.local.occupied
+
+super + ctrl + bracket{left,right}
+ bspc desktop -f {prev,next}.local
+
+# focus the last node/desktop
+super + {Tab,grave}
+ bspc {node,desktop} -f last
+
+# focus the older or newer node in the focus history
+super + {o,i}
+ bspc wm -h off; \
+ bspc node {older,newer} -f; \
+ bspc wm -h on
+
+# focus or send to the given desktop
+super + {_,shift + }{1-9,0}
+ bspc {desktop -f,node -d} '^{1-9,10}'
+
+super + alt + {1-9,0}
+ bspc node -d '^{1-9,10}' --follow
+
+#
+# preselect
+#
+
+# preselect the direction
+super + ctrl + shift + {h,j,k,l}
+ bspc node -p {west,south,north,east}
+
+# preselect the ratio
+super + ctrl + {1-9}
+ bspc node -o 0.{1-9}
+
+# cancel the preselection for the focused node
+# super + ctrl + space
+# bspc node -p cancel
+
+# cancel the preselection for the focused desktop
+# super + ctrl + shift + space
+super + alt + space
+ bspc query -N -d | xargs -I id -n 1 bspc node id -p cancel
+
+#
+# move/resize
+#
+
+# move a floating window
+super + ctrl + {Left,Down,Up,Right}
+ bspc node -v {-20 0,0 20,0 -20,20 0}
+
+super + ctrl + {h,j,k,l}
+ bspc node -v {-20 0,0 20,0 -20,20 0}
+
+# expand/contract a window
+# super + control + shift + {h,j,k,l}
+# bspc node -z {left -20 0 || bspc node -z right -20 0, \
+# bottom 0 20 || bspc node -z top 0 20,\
+# top 0 -20 || bspc node -z bottom 0 -20,\
+# right 20 0 || bspc node -z left 20 0}
+
+super + control + shift + {Left,Down,Up,Right}
+ bspc node -z {left -20 0 || bspc node -z right -20 0, \
+ bottom 0 20 || bspc node -z top 0 20,\
+ top 0 -20 || bspc node -z bottom 0 -20,\
+ right 20 0 || bspc node -z left 20 0}
+
+# expand a window by moving one of its side outward
+super + alt + {h,j,k,l}
+ bspc node -z {left -20 0,bottom 0 20,top 0 -20,right 20 0}
+
+super + alt + {Left,Down,Up,Right}
+ bspc node -z {left -20 0,bottom 0 20,top 0 -20,right 20 0}
+
+# contract a window by moving one of its side inward
+super + alt + shift + {h,j,k,l}
+ bspc node -z {right -20 0,top 0 20,bottom 0 -20,left 20 0}
+
+super + alt + shift + {Left,Down,Up,Right}
+ bspc node -z {right -20 0,top 0 20,bottom 0 -20,left 20 0}
+
+#
+# Prayers
+#
+super + shift + o
+ sxiv -bsf ~/Dropbox/Images/prayers/ -g 1700x1010
+
+super + shift + z
+ sxiv -bsf ~/Nextcloud/Images/imgs-ca-from-gdrive/Rosary-2/ -g 1430x1044
+
+#
+# Calendar & Clock
+#
+
+super + c
+ ~/.local/bin/mycal
+
+super + shift + c
+ ~/.local/bin/mytime
+
+#
+# Screenshots
+#
+
+# Select area to capture
+Print
+ SCREENSHOT_FILE=$HOME/Pictures/Screenshots/Screenshot_$(date +%Y%b%d-%H%M%S).png ; \
+ maim -s $SCREENSHOT_FILE && \
+ xclip -selection clipboard -t image/png -i ~/Pictures/Screenshots/`ls -1 -t ~/Pictures/Screenshots | head -1` && \
+ add_recent_file $SCREENSHOT_FILE && \
+ if [ "$(dunstify 'Screenshot taken.' --action='show,Show Image' --action='dismiss,Dismiss' -I $SCREENSHOT_FILE)" = "show" ]; then sxiv $SCREENSHOT_FILE; fi;
+
+# Capture the whole screen
+shift + Print
+ SCREENSHOT_FILE=$HOME/Pictures/Screenshots/Screenshot_$(date +%Y%b%d-%H%M%S).png ; \
+ maim $SCREENSHOT_FILE && \
+ xclip -selection clipboard -t image/png -i ~/Pictures/Screenshots/`ls -1 -t ~/Pictures/Screenshots | head -1` && \
+ add_recent_file $SCREENSHOT_FILE && \
+ if [ "$(dunstify 'Screenshot taken.' --action='show,Show Image' --action='dismiss,Dismiss' -I $SCREENSHOT_FILE)" = "show" ]; then sxiv $SCREENSHOT_FILE; fi;
+
+# Capture focused window
+alt + Print
+ SCREENSHOT_FILE=$HOME/Pictures/Screenshots/Screenshot_$(date +%Y%b%d-%H%M%S).png ; \
+ maim -i $(xdotool getactivewindow) $SCREENSHOT_FILE && \
+ xclip -selection clipboard -t image/png -i ~/Pictures/Screenshots/`ls -1 -t ~/Pictures/Screenshots | head -1` && \
+ add_recent_file $SCREENSHOT_FILE && \
+ if [ "$(dunstify 'Screenshot taken.' --action='show,Show Image' --action='dismiss,Dismiss' -I $SCREENSHOT_FILE)" = "show" ]; then sxiv $SCREENSHOT_FILE; fi;
+
+# vim:ft=bash
diff --git a/desktop-x11/.local/bin/rofi-pass b/desktop-x11/.local/bin/rofi-pass
new file mode 100755
index 0000000..8d38cfc
--- /dev/null
+++ b/desktop-x11/.local/bin/rofi-pass
@@ -0,0 +1,868 @@
+#!/usr/bin/env bash
+
+# rofi-pass
+# (c) 2015 Rasmus Steinke <rasi@xssn.at>
+basecommand="$0"
+
+# set default settings
+_rofi () {
+ rofi -no-auto-select -i "$@"
+}
+
+_pwgen () {
+ pwgen -y "$@"
+}
+
+_image_viewer () {
+ feh -
+}
+
+# We expect to find these fields in pass(1)'s output
+URL_field='url'
+USERNAME_field='user'
+AUTOTYPE_field='autotype'
+OTPmethod_field='otp_method'
+
+default_autotype="user :tab pass"
+delay=2
+wait=0.2
+xdotool_delay=12
+default_do='menu' # menu, copyPass, typeUser, typePass, copyUser, copyUrl, viewEntry, typeMenu, actionMenu, copyMenu, openUrl
+auto_enter='false'
+notify='false'
+help_color=""
+clip=primary
+clip_clear=45
+default_user="${ROFI_PASS_DEFAULT_USER-$(whoami)}"
+default_user2=john_doe
+password_length=12
+fix_layout=false
+
+# default shortcuts
+autotype="Alt+1"
+type_user="Alt+2"
+type_pass="Alt+3"
+open_url="Alt+4"
+copy_name="Alt+u"
+copy_url="Alt+l"
+copy_pass="Alt+p"
+show="Alt+o"
+copy_menu="Alt+c"
+action_menu="Alt+a"
+type_menu="Alt+t"
+help="Alt+h"
+switch="Alt+x"
+insert_pass="Alt+n"
+qrcode="Alt+q"
+previous_root="Shift+Left"
+next_root="Shift+Right"
+
+# Safe permissions
+umask 077
+
+has_qrencode() {
+ command -v qrencode >/dev/null 2>&1
+}
+
+# get all password files and create an array
+list_passwords() {
+ cd "${root}" || exit
+ pw_list=(**/*.gpg)
+ printf '%s\n' "${pw_list[@]%.gpg}" | sort -n
+
+}
+
+doClip () {
+ case "$clip" in
+ "primary") xclip ;;
+ "clipboard") xclip -selection clipboard;;
+ "both") xclip; xclip -o | xclip -selection clipboard;;
+ esac
+}
+
+checkIfPass () {
+ printf '%s\n' "${root}: $selected_password" >| "$HOME/.cache/rofi-pass/last_used"
+}
+
+
+autopass () {
+ x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
+ xset r off
+
+ rm -f "$HOME/.cache/rofi-pass/last_used"
+ printf '%s\n' "${root}: $selected_password" > "$HOME/.cache/rofi-pass/last_used"
+ for word in ${stuff["$AUTOTYPE_field"]}; do
+ case "$word" in
+ ":tab") xdotool key Tab;;
+ ":space") xdotool key space;;
+ ":delay") sleep "${delay}";;
+ ":enter") xdotool key Return;;
+ ":otp") printf '%s' "$(generateOTP)" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -;;
+ "pass") printf '%s' "${password}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -;;
+ "path") printf '%s' "${selected_password}" | rev | cut -d'/' -f1 | rev | xdotool type --clearmodifiers --file -;;
+ *) printf '%s' "${stuff[${word}]}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -;;
+ esac
+ done
+
+ if [[ ${auto_enter} == "true" ]]; then
+ xdotool key Return
+ fi
+
+ xset r "$x_repeat_enabled"
+ unset x_repeat_enabled
+ clearUp
+}
+
+generateQrCode() {
+ has_qrencode
+
+ if [[ $? -eq "1" ]]; then
+ printf '%s\n' "qrencode not found" | _rofi -dmenu
+ exit_code=$?
+ if [[ $exit_code -eq "1" ]]; then
+ exit
+ else
+ "${basecommand}"
+ fi
+ fi
+
+ checkIfPass
+ pass "$selected_password" | head -n 1 | qrencode -d 300 -v 8 -l H -o - | _image_viewer
+ if [[ $? -eq "1" ]]; then
+ printf '%s\n' "" | _rofi -dmenu -mesg "Image viewer not defined or cannot read from pipe"
+ exit_value=$?
+ if [[ $exit_value -eq "1" ]]; then
+ exit
+ else
+ "${basecommand}"
+ fi
+ fi
+ clearUp
+}
+
+openURL () {
+ checkIfPass
+ $BROWSER "$(PASSWORD_STORE_DIR="${root}" pass "$selected_password" | grep "${URL_field}: " | gawk '{sub(/:/,"")}{print $2}1' | head -1)"; exit;
+ clearUp
+}
+
+typeUser () {
+ checkIfPass
+
+ x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
+ xset r off
+
+ printf '%s' "${stuff[${USERNAME_field}]}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -
+
+ xset r "$x_repeat_enabled"
+ unset x_repeat_enabled
+
+ clearUp
+}
+
+typePass () {
+ checkIfPass
+
+ x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
+ xset r off
+
+ printf '%s' "${password}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -
+
+ if [[ $notify == "true" ]]; then
+ if [[ "${stuff[notify]}" == "false" ]]; then
+ :
+ else
+ notify-send "rofi-pass" "finished typing password";
+ fi
+ elif [[ $notify == "false" ]]; then
+ if [[ "${stuff[notify]}" == "true" ]]; then
+ notify-send "rofi-pass" "finished typing password";
+ else
+ :
+ fi
+ fi
+
+ xset r "$x_repeat_enabled"
+ unset x_repeat_enabled
+ clearUp
+}
+
+typeField () {
+ checkIfPass
+ local to_type
+
+ x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
+ xset r off
+
+ case $typefield in
+ "OTP") to_type="$(generateOTP)" ;;
+ *) to_type="${stuff[${typefield}]}" ;;
+ esac
+
+ printf '%s' "$to_type" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -
+
+ xset r "$x_repeat_enabled"
+ unset x_repeat_enabled
+ unset to_type
+
+ clearUp
+}
+
+generateOTP () {
+ checkIfPass
+
+ # First, we check if there is a non-conventional OTP command in the pass file
+ if PASSWORD_STORE_DIR="${root}" pass "$selected_password" | grep -q "${OTPmethod_field}: "; then
+ # We execute the commands after otp_method: AS-IS
+ bash -c "$(PASSWORD_STORE_DIR="${root}" pass "$selected_password" | grep "${OTPmethod_field}: " | cut -d' ' -f2-)"
+ else
+ # If there is no method defined, fallback to pass-otp
+ PASSWORD_STORE_DIR="${root}" pass otp "$selected_password"
+ fi
+
+ clearUp
+}
+
+copyUser () {
+ checkIfPass
+ printf '%s' "${stuff[${USERNAME_field}]}" | doClip
+ clearUp
+}
+
+copyField () {
+ checkIfPass
+ printf '%s' "${stuff[${copyfield}]}" | doClip
+ clearUp
+}
+
+copyURL () {
+ checkIfPass
+ printf '%s' "${stuff[${URL_field}]}" | doClip
+ clearUp
+}
+
+copyPass () {
+ checkIfPass
+ printf '%s' "$password" | doClip
+ if [[ $notify == "true" ]]; then
+ notify-send "rofi-pass" "Copied Password\\nClearing in $clip_clear seconds"
+ fi
+
+ if [[ $notify == "true" ]]; then
+ (sleep $clip_clear; printf '%s' "" | xclip; printf '%s' "" | xclip -selection clipboard | notify-send "rofi-pass" "Clipboard cleared") &
+ elif [[ $notify == "false" ]]; then
+ (sleep $clip_clear; printf '%s' "" | xclip; printf '%s' "" | xclip -selection clipboard) &
+ fi
+}
+
+viewEntry () {
+ checkIfPass
+ showEntry "${selected_password}"
+}
+
+generatePass () {
+ askmenu_content=(
+ "Yes"
+ "No")
+
+ askGenMenu=$(printf '%s\n' "${askmenu_content[@]}" | _rofi -dmenu -p "Generate new Password for ${selected_password}? > ")
+ askgen_exit=$?
+
+ if [[ $askgen_exit -eq 1 ]]; then
+ exit
+ fi
+ if [[ $askGenMenu == "Yes" ]]; then
+ true
+ elif [[ $askGenMenu == "No" ]]; then
+ actionMenu
+ fi
+
+ checkIfPass
+
+ symbols_content=(
+ "0 Cancel"
+ "1 Yes"
+ "2 No")
+
+ symbols=$(printf '%s\n' "${symbols_content[@]}" | _rofi -dmenu -p "Use Symbols? > ")
+ symbols_val=$?
+
+ if [[ $symbols_val -eq 1 ]]; then
+ exit
+ fi
+ if [[ $symbols == "0 Cancel" ]]; then
+ mainMenu;
+ elif [[ $symbols == "1 Yes" ]]; then
+ symbols="";
+ elif [[ $symbols == "2 No" ]]; then
+ symbols="-n";
+ fi
+
+ HELP="<span color='$help_color'>Enter Number or hit Enter to use default length</span>"
+ length=$(printf '%s' "" | _rofi -dmenu -mesg "${HELP}" -p "Password length? (Default: ${password_length}) > ")
+ length_exit=$?
+
+ if [[ $length_exit -eq 1 ]]; then
+ exit
+ fi
+ if [[ $length == "" ]]; then
+ PASSWORD_STORE_DIR="${root}" pass generate ${symbols} -i "$selected_password" "${password_length}" > /dev/null;
+ else
+ PASSWORD_STORE_DIR="${root}" pass generate ${symbols} -i "$selected_password" "${length}" > /dev/null;
+ fi
+}
+
+# main Menu
+mainMenu () {
+ if [[ $1 == "--bmarks" ]]; then
+ selected_password="$(list_passwords 2>/dev/null \
+ | _rofi -mesg "Bookmarks Mode. ${switch} to switch" \
+ -dmenu \
+ -kb-custom-10 "${switch}" \
+ -select "$entry" \
+ -p "rofi-pass > ")"
+
+ rofi_exit=$?
+
+ if [[ $rofi_exit -eq 1 ]]; then
+ exit
+ elif [[ $rofi_exit -eq 19 ]]; then
+ ${basecommand}
+ elif [[ $rofi_exit -eq 0 ]]; then
+ openURL
+ fi
+ else
+ unset selected_password
+
+ args=( -dmenu
+ -kb-custom-1 "${autotype}"
+ -kb-custom-2 "${type_user}"
+ -kb-custom-3 "${type_pass}"
+ -kb-custom-4 "${open_url}"
+ -kb-custom-5 "${copy_name}"
+ -kb-custom-6 "${copy_pass}"
+ -kb-custom-7 "${show}"
+ -kb-custom-8 "${copy_url}"
+ -kb-custom-9 "${type_menu}"
+ -kb-custom-10 "${previous_root}"
+ -kb-custom-11 "${next_root}"
+ -kb-custom-14 "${action_menu}"
+ -kb-custom-15 "${copy_menu}"
+ -kb-custom-16 "${help}"
+ -kb-custom-17 "${switch}"
+ -kb-custom-18 "${insert_pass}"
+ -kb-custom-19 "${qrcode}")
+ args+=(-kb-mode-previous "" # These keyboard shortcut options are needed, because
+ -kb-mode-next "" # Shift+<Left|Right> are otherwise taken by rofi.
+ -select "$entry"
+ -p "󱕵")
+
+ if [[ ${#roots[@]} -gt "1" || $custom_root == "true" ]]; then
+ args+=(-mesg "PW Store: ${root}")
+ fi
+
+ selected_password="$(list_passwords 2>/dev/null | _rofi "${args[@]}")"
+
+ rofi_exit=$?
+ if [[ $rofi_exit -eq 1 ]]; then
+ exit
+ fi
+
+ # Actions based on exit code, which do not need the entry.
+ # The exit code for -kb-custom-X is X+9.
+ case "${rofi_exit}" in
+ 19) roots_index=$(( (roots_index-1+roots_length) % roots_length)); root=${roots[$roots_index]}; mainMenu; return;;
+ 20) roots_index=$(( (roots_index+1) % roots_length)); root=${roots[$roots_index]}; mainMenu; return;;
+ 25) helpMenu; return;;
+ 26) ${basecommand} --bmarks; return;;
+ esac
+
+ mapfile -t password_temp < <(PASSWORD_STORE_DIR="${root}" pass show "$selected_password")
+ password=${password_temp[0]}
+
+ if [[ ${password} == "#FILE="* ]]; then
+ pass_file="${password#*=}"
+ mapfile -t password_temp2 < <(PASSWORD_STORE_DIR="${root}" pass show "${pass_file}")
+ password=${password_temp2[0]}
+ fi
+
+ fields=$(printf '%s\n' "${password_temp[@]:1}" | awk '$1 ~ /:$/ || /otpauth:\/\// {$1=$1;print}')
+ declare -A stuff
+ stuff["pass"]=${password}
+
+ if [[ -n $fields ]]; then
+ while read -r LINE; do
+ unset _id _val
+ case "$LINE" in
+ "otpauth://"*|"${OTPmethod_field}"*)
+ _id="OTP"
+ _val=""
+ ;;
+ *)
+ _id="${LINE%%: *}"
+ _val="${LINE#* }"
+ ;;
+ esac
+
+ if [[ -n "$_id" ]]; then
+ stuff["${_id}"]=${_val}
+ fi
+ done < <(printf '%s\n' "${fields}")
+
+ if test "${stuff['autotype']+autotype}"; then
+ :
+ else
+ stuff["autotype"]="${USERNAME_field} :tab pass"
+ fi
+ fi
+ fi
+
+ if [[ -z "${stuff["${AUTOTYPE_field}"]}" ]]; then
+ if [[ -n $default_autotype ]]; then
+ stuff["${AUTOTYPE_field}"]="${default_autotype}"
+ fi
+ fi
+ if [[ -z "${stuff["${USERNAME_field}"]}" ]]; then
+ if [[ -n $default_user ]]; then
+ if [[ "$default_user" == ":filename" ]]; then
+ stuff["${USERNAME_field}"]="$(basename $selected_password)"
+ else
+ stuff["${USERNAME_field}"]="${default_user}"
+ fi
+ fi
+ fi
+ pass_content="$(for key in "${!stuff[@]}"; do printf '%s\n' "${key}: ${stuff[$key]}"; done)"
+
+ # actions based on keypresses
+ # The exit code for -kb-custom-X is X+9.
+ case "${rofi_exit}" in
+ 0) typeMenu;;
+ 10) sleep $wait; autopass;;
+ 11) sleep $wait; typeUser;;
+ 12) sleep $wait; typePass;;
+ 13) openURL;;
+ 14) copyUser;;
+ 15) copyPass;;
+ 16) viewEntry;;
+ 17) copyURL;;
+ 18) default_do="menu" typeMenu;;
+ 23) actionMenu;;
+ 24) copyMenu;;
+ 27) insertPass;;
+ 28) generateQrCode;;
+ esac
+ clearUp
+}
+
+
+clearUp () {
+ password=''
+ selected_password=''
+ unset stuff
+ unset password
+ unset selected_password
+ unset password_temp
+ unset stuff
+}
+
+helpMenu () {
+ printf '%s' "${autotype}: Autotype
+${type_user}: Type Username
+${type_pass}: Type Password
+${qrcode}: Generate and display qrcode
+---
+${copy_name}: Copy Username
+${copy_pass}: Copy Password
+${copy_url}: Copy URL
+${open_url}: Open URL
+${copy_menu}: Copy Custom Field
+---
+${action_menu}: Edit, Move, Delete, Re-generate Submenu
+${show}: Show Password File
+${insert_pass}: Insert new Pass Entry
+${switch}: Switch Pass/Bookmark Mode
+---
+${previous_root}: Switch to previous password store (--root)
+${next_root}: Switch to next password store (--root)
+ " | _rofi -dmenu -mesg "Hint: All hotkeys are configurable in config file" -p "Help > "
+ help_val=$?
+
+ if [[ $help_val -eq 1 ]]; then
+ exit;
+ else
+ unset helptext; mainMenu;
+ fi
+}
+
+
+typeMenu () {
+ if [[ -n $default_do ]]; then
+ if [[ $default_do == "menu" ]]; then
+ checkIfPass
+ local -a keys=("${!stuff[@]}")
+ keys=("${keys[@]/$AUTOTYPE_field}")
+ typefield=$({ printf '%s' "${AUTOTYPE_field}" ; printf '%s\n' "${keys[@]}" | sort; } | _rofi -dmenu -p "Choose Field to type > ")
+ typefield_exit=$?
+ if [[ $typefield_exit -eq 1 ]]; then
+ exit
+ fi
+ case "$typefield" in
+ '') exit;;
+ 'pass') sleep $wait; typePass;;
+ "${AUTOTYPE_field}") sleep $wait; autopass;;
+ *) sleep $wait; typeField
+ esac
+ clearUp
+ elif [[ $default_do == "${AUTOTYPE_field}" ]]; then
+ sleep $wait; autopass
+ else
+ ${default_do}
+ fi
+ fi
+}
+
+copyMenu () {
+ checkIfPass
+ copyfield=$(printf '%s\n' "${!stuff[@]}" | sort | _rofi -dmenu -p "Choose Field to copy > ")
+ val=$?
+ if [[ $val -eq 1 ]]; then
+ exit;
+ fi
+ if [[ $copyfield == "pass" ]]; then
+ copyPass;
+ else
+ copyField
+ fi
+ clearUp
+}
+
+actionMenu () {
+ checkIfPass
+ action_content=("< Return"
+ "---"
+ "1 Move Password File"
+ "2 Copy Password File"
+ "3 Delete Password File"
+ "4 Edit Password File"
+ "5 Generate New Password")
+
+ action=$(printf '%s\n' "${action_content[@]}" | _rofi -dmenu -p "Choose Action > ")
+ if [[ ${action} == "1 Move Password File" ]]; then
+ manageEntry move;
+ elif [[ ${action} == "3 Delete Password File" ]]; then
+ manageEntry delete;
+ elif [[ ${action} == "2 Copy Password File" ]]; then
+ manageEntry copy;
+ elif [[ ${action} == "4 Edit Password File" ]]; then
+ manageEntry edit;
+ elif [[ ${action} == "5 Generate New Password" ]]; then
+ generatePass;
+ elif [[ ${action} == "< Return" ]]; then
+ mainMenu;
+ elif [[ ${action} == "" ]]; then
+ exit
+ fi
+}
+
+showEntry () {
+ if [[ -z $pass_content ]]; then
+ pass_temp=$(PASSWORD_STORE_DIR="${root}" pass show "$selected_password")
+ password="${pass_temp%%$'\n'*}"
+ pass_key_value=$(printf '%s\n' "${pass_temp}" | tail -n+2 | grep ': ')
+ declare -A stuff
+
+ while read -r LINE; do
+ _id="${LINE%%: *}"
+ _val="${LINE#* }"
+ stuff["${_id}"]=${_val}
+ done < <(printf '%s\n' "${pass_key_value}")
+
+ stuff["pass"]=${password}
+
+ if test "${stuff['autotype']+autotype}"; then
+ :
+ else
+ stuff["autotype"]="${USERNAME_field} :tab pass"
+ fi
+
+ pass_content="$(for key in "${!stuff[@]}"; do printf '%s\n' "${key}: ${stuff[$key]}"; done)"
+ fi
+
+ bla_content=("< Return"
+ "${pass_content}")
+
+ bla=$(printf '%s\n' "${bla_content[@]}" | _rofi -dmenu -mesg "Enter: Copy entry to clipboard" -p "> ")
+ rofi_exit=$?
+
+ word=$(printf '%s' "$bla" | gawk -F': ' '{print $1}')
+
+ if [[ ${rofi_exit} -eq 1 ]]; then
+ exit
+ elif [[ ${rofi_exit} -eq 0 ]]; then
+ if [[ ${bla} == "< Return" ]]; then
+ mainMenu
+ else
+ if [[ -z $(printf '%s' "${stuff[${word}]}") ]]; then
+ printf '%s' "$word" | doClip
+ else
+ printf '%s' "${stuff[${word}]}" | doClip
+ fi
+ if [[ $notify == "true" ]]; then
+ notify-send "rofi-pass" "Copied Password\\nClearing in $clip_clear seconds"
+ fi
+ if [[ $notify == "true" ]]; then
+ (sleep $clip_clear; printf '%s' "" | xclip; printf '%s' "" | xclip -selection clipboard | notify-send "rofi-pass" "Clipboard cleared") &
+ elif [[ $notify == "false" ]]; then
+ (sleep $clip_clear; printf '%s' "" | xclip; printf '%s' "" | xclip -selection clipboard) &
+ fi
+ exit
+ fi
+ fi
+ exit
+ unset stuff
+ unset password
+ unset selected_password
+ unset password_temp
+ unset stuff
+ exit
+}
+
+manageEntry () {
+ if [[ "$1" == "edit" ]]; then
+ EDITOR=$EDITOR PASSWORD_STORE_DIR="${root}" pass edit "${selected_password}"
+ mainMenu
+ elif [[ $1 == "move" ]]; then
+ cd "${root}" || exit
+ group_array=(*/)
+ group=$(printf '%s\n' "${group_array[@]%/}" | _rofi -dmenu -p "Choose Group > ")
+ if [[ $group == "" ]]; then
+ exit
+ fi
+ PASSWORD_STORE_DIR="${root}" pass mv "$selected_password" "${group}"
+ mainMenu
+ elif [[ $1 == "copy" ]]; then
+ cd "${root}" || exit
+ group_array=(*/)
+ group=$(printf '%s\n' "${group_array[@]%/}" | _rofi -dmenu -p "Choose Group > ")
+ if [[ $group == "" ]]; then
+ exit
+ else
+ new_name="$(listgpg | _rofi -dmenu -format 'f' -mesg "Copying to same Group. Please enter a name for the new entry" -p "> ")"
+ fi
+ PASSWORD_STORE_DIR="${root}" pass cp "$selected_password" "${group}/${new_name}"
+ mainMenu
+ elif [[ "$1" == "delete" ]]; then
+ HELP="<span color='$help_color'>Selected entry: ${selected_password}</span>"
+ ask_content=("Yes"
+ "No")
+ ask=$(printf '%s\n' "${ask_content[@]}" | _rofi -mesg "${HELP}" -dmenu -p "Are You Sure? > ")
+ if [[ "$ask" == "Yes" ]]; then
+ PASSWORD_STORE_DIR="${root}" pass rm --force "${selected_password}"
+ elif [[ "$ask" == "No" ]]; then
+ mainMenu
+ elif [[ -z "$ask" ]]; then
+ exit
+ fi
+ else
+ mainMenu
+ fi
+}
+
+listgpg () {
+ pw_list=(**/*.gpg)
+ printf '%s\n' "${pw_list[@]}" | sort -n
+}
+
+insertPass () {
+ url=$(xclip --selection clipboard -o)
+
+ if [[ "${url:0:4}" == "http" ]]; then
+ domain_name="$(printf '%s\n' "${url}" | awk -F / '{l=split($3,a,"."); print (a[l-1]=="com"?a[l-2] OFS:X) a[l-1] OFS a[l]}' OFS=".")"
+ help_content="Domain: ${domain_name}
+ Type name, make sure it is unique"
+ else
+ help_content="Hint: Copy URL to clipboard before calling this menu.
+ Type name, make sure it is unique"
+ fi
+
+ cd "${root}" || exit
+ group_array=(*/)
+ grouplist=$(printf '%s\n' "${group_array[@]%/}")
+ name="$(listgpg | _rofi -dmenu -format 'f' -filter "${domain_name}" -mesg "${help_content}" -p "> ")"
+ val=$?
+
+ if [[ $val -eq 1 ]]; then
+ exit
+ fi
+
+ user_content=("${default_user2}"
+ "${USER}"
+ "${default_user}")
+
+ user=$(printf '%s\n' "${user_content[@]}" | _rofi -dmenu -mesg "Chose Username or type" -p "> ")
+ val=$?
+
+ if [[ $val -eq 1 ]]; then
+ exit
+ fi
+
+ group_content=("No Group"
+ "---"
+ "${grouplist}")
+
+ group=$(printf '%s\n' "${group_content[@]}" | _rofi -dmenu -p "Choose Group > ")
+ val=$?
+
+ if [[ $val -eq 1 ]]; then
+ exit
+ fi
+
+ pw=$(printf '%s' "Generate" | _rofi -dmenu -password -p "Password > " -mesg "Type Password or hit Enter to generate one")
+
+ if [[ $pw == "Generate" ]]; then
+ pw=$(_pwgen "${password_length}")
+ fi
+
+ clear
+
+ if [[ "$group" == "No Group" ]]; then
+ if [[ $url == http* ]]; then
+ pass_content=("${pw}"
+ "---"
+ "${USERNAME_field}: ${user}"
+ "${URL_field}: ${url}")
+ printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${name}" > /dev/null && PASSWORD_STORE_DIR="${root}" pass edit "${name}"
+ else
+ pass_content=("${pw}"
+ "---"
+ "${USERNAME_field}: ${user}")
+ printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${name}" > /dev/null && PASSWORD_STORE_DIR="${root}" pass edit "${name}"
+ fi
+ else
+ if [[ $url == http* ]]; then
+ pass_content=("${pw}"
+ "---"
+ "${USERNAME_field}: ${user}"
+ "${URL_field}: ${url}")
+ printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${group}/${name}" > /dev/null && PASSWORD_STORE_DIR="${root}" pass edit "${group}/${name}"
+ else
+ pass_content=("${pw}"
+ "---"
+ "${USERNAME_field}: ${user}")
+ printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${group}/${name}" > /dev/null
+ if [[ $edit_new_pass == "true" ]]; then
+ PASSWORD_STORE_DIR="${root}" pass edit "${group}/${name}"
+ fi
+ fi
+ fi
+}
+
+help_msg () {
+ cat <<'EOF'
+ Usage:
+ rofi-pass [command]
+
+ Commands:
+ --insert insert new entry to password store
+ --root set custom root directories (colon separated)
+ --last-used highlight last used item
+ --show-last show details of last used Entry
+ --bmarks start in bookmarks mode
+
+ rofi-pass version 1.5.3
+EOF
+}
+
+get_config_file () {
+ configs=("$ROFI_PASS_CONFIG"
+ "$HOME/.config/rofi-pass/config"
+ "/etc/rofi-pass.conf")
+
+ # return the first config file with a valid path
+ for config in "${configs[@]}"; do
+ # '! -z' is needed in case ROFI_PASS_CONFIG is not set
+ if [[ ! -z "${config}" && -f "${config}" ]]; then
+ printf "%s" "$config"
+ return
+ fi
+ done
+}
+
+main () {
+ # enable extended globbing
+ shopt -s nullglob globstar
+
+ # load config file
+ config_file="$(get_config_file)"
+ [[ ! -z "$config_file" ]] && source "$config_file"
+
+ # create tmp dir
+ if [[ ! -d "$HOME/.cache/rofi-pass" ]]; then
+ mkdir "$HOME/.cache/rofi-pass"
+ fi
+
+ # fix keyboard layout if enabled in config
+ if [[ $fix_layout == "true" ]]; then
+ layout_cmd
+ fi
+
+ # set help color
+ if [[ $help_color == "" ]]; then
+ help_color=$(rofi -dump-xresources | grep 'rofi.color.normal' | gawk -F ',' '/,/{gsub(/ /, "", $2); print $2}')
+ fi
+
+ # check for BROWSER variable, use xdg-open as fallback
+ if [[ -z $BROWSER ]]; then
+ export BROWSER=xdg-open
+ fi
+
+ # check if alternative root directory was given on commandline
+ if [[ -r "$HOME/.cache/rofi-pass/last_used" ]] && [[ $1 == "--last-used" || $1 == "--show-last" ]]; then
+ roots=("$(awk -F ': ' '{ print $1 }' "$HOME/.cache/rofi-pass/last_used")")
+ elif [[ -n "$2" && "$1" == "--root" ]]; then
+ custom_root=true; IFS=: read -r -a roots <<< "$2"
+ elif [[ -n $root ]]; then
+ custom_root=true; IFS=: read -r -a roots <<< "${root}"
+ elif [[ -n ${PASSWORD_STORE_DIR} ]]; then
+ roots=("${PASSWORD_STORE_DIR}")
+ else
+ roots=("$HOME/.password-store")
+ fi
+ roots_index=0
+ roots_length=${#roots[@]}
+ export root=${roots[$roots_index]}
+ export PASSWORD_STORE_DIR="${root}"
+ case $1 in
+ --insert)
+ insertPass
+ ;;
+ --root)
+ mainMenu
+ ;;
+ --help)
+ help_msg
+ ;;
+ --last-used)
+ if [[ -r "$HOME/.cache/rofi-pass/last_used" ]]; then
+ entry="$(awk -F ': ' '{ print $2 }' "$HOME/.cache/rofi-pass/last_used")"
+ fi
+ mainMenu
+ ;;
+ --show-last)
+ if [[ -r "$HOME/.cache/rofi-pass/last_used" ]]; then
+ selected_password="$(awk -F ': ' '{ print $2 }' "$HOME/.cache/rofi-pass/last_used")" viewEntry
+ else
+ mainMenu
+ fi
+ ;;
+ --bmarks)
+ mainMenu --bmarks;
+ ;;
+ *)
+ mainMenu
+ ;;
+ esac
+}
+
+main "$@"
+