Compare commits
56 Commits
71308fd9d5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| cf44651f85 | |||
| 7161892da7 | |||
| 06815e7bc6 | |||
| cfe932bf4a | |||
| e44618391b | |||
| d55a8a4d0d | |||
| 79b9ddf5f6 | |||
| 61b96b3f38 | |||
| 364e7c94a2 | |||
| 00ef3b6217 | |||
| 58c5211d19 | |||
| 49d6627ee1 | |||
| e80d9d797c | |||
| 817831838d | |||
| 2343a00f2b | |||
| 7217d016ea | |||
| 261400a636 | |||
| 2f024495b4 | |||
| 1056c63bca | |||
| 2dac598a95 | |||
| de82e55696 | |||
| 2ca642aef3 | |||
| ec47a1ef95 | |||
| 4d1c411870 | |||
| 83acf4ce98 | |||
| 4ac47e3300 | |||
| 47d093f95f | |||
| 408440ad18 | |||
| baacfff7c4 | |||
| 6a603a5c9b | |||
| bbc5492534 | |||
| 1127019300 | |||
| 65a39a7cd6 | |||
| 9320af98a3 | |||
| 66d886c4e6 | |||
| 098e16e000 | |||
| bf27d4565e | |||
| 593b961a51 | |||
| feaca0be5a | |||
| 74b1584e0d | |||
| 241e988813 | |||
| 4f60bf3a7f | |||
| c32e875762 | |||
| e0686e8adf | |||
| 41007302d4 | |||
| ab65bc3406 | |||
| 7e09c1d742 | |||
| 20d31ef694 | |||
| 00d4b17125 | |||
| a279fc4923 | |||
| 06b1f4fb40 | |||
| 792ba347e5 | |||
| 790c931bcb | |||
| 78d8ef68f6 | |||
| 6a62232f0e | |||
| 7ced7d04de |
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
[bell]
|
[bell]
|
||||||
animation = "EaseOutSine"
|
animation = "EaseOutSine"
|
||||||
color = "0x9a7c9d"
|
color = "0x9a7c9d"
|
||||||
@@ -43,19 +44,19 @@ render_timer = false
|
|||||||
size = 9
|
size = 9
|
||||||
|
|
||||||
[font.bold]
|
[font.bold]
|
||||||
family = "JetBrainsMono Nerd Font"
|
family = "JetBrains Mono"
|
||||||
style = "Bold"
|
style = "Bold"
|
||||||
|
|
||||||
[font.bold_italic]
|
[font.bold_italic]
|
||||||
family = "JetBrainsMono Nerd Font"
|
family = "JetBrains Mono"
|
||||||
style = "Semibold Italic"
|
style = "Semibold Italic"
|
||||||
|
|
||||||
[font.italic]
|
[font.italic]
|
||||||
family = "JetBrainsMono Nerd Font"
|
family = "JetBrains Mono"
|
||||||
style = "Italic"
|
style = "Italic"
|
||||||
|
|
||||||
[font.normal]
|
[font.normal]
|
||||||
family = "JetBrainsMono Nerd Font"
|
family = "JetBrains Mono"
|
||||||
style = "Regular"
|
style = "Regular"
|
||||||
|
|
||||||
[window]
|
[window]
|
||||||
@@ -64,5 +65,5 @@ dynamic_title = true
|
|||||||
opacity = 0.8
|
opacity = 0.8
|
||||||
title = "Terminal"
|
title = "Terminal"
|
||||||
|
|
||||||
[general]
|
[terminal]
|
||||||
working_directory = "/home/ezri"
|
#shell = { program = "/usr/bin/systemd-run", args = [ "--user", "--scope", "--slice=app-shell.slice", "--property=PartOf=alacritty.service", "--property=After=alacritty.service", "-S", "-q"]}
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
working_directory = "/home/ezri"
|
|
||||||
|
|
||||||
[bell]
|
|
||||||
animation = "EaseOutSine"
|
|
||||||
color = "0x9a7c9d"
|
|
||||||
duration = 200
|
|
||||||
|
|
||||||
[colors]
|
|
||||||
draw_bold_text_with_bright_colors = false
|
|
||||||
|
|
||||||
[colors.bright]
|
|
||||||
black = "0x3f3242"
|
|
||||||
blue = "0x7587a6"
|
|
||||||
cyan = "0xafc4db"
|
|
||||||
green = "0x8f9d6a"
|
|
||||||
magenta = "0x9b859d"
|
|
||||||
red = "0xcf6a4c"
|
|
||||||
white = "0xffffff"
|
|
||||||
yellow = "0xf9ee98"
|
|
||||||
|
|
||||||
[colors.normal]
|
|
||||||
black = "0x2d272f"
|
|
||||||
blue = "0x7587a6"
|
|
||||||
cyan = "0xafc4db"
|
|
||||||
green = "0x8f9d6a"
|
|
||||||
magenta = "0x9b859d"
|
|
||||||
red = "0xcf6a4c"
|
|
||||||
white = "0xa7a7a7"
|
|
||||||
yellow = "0xf9ee98"
|
|
||||||
|
|
||||||
[colors.primary]
|
|
||||||
background = "0x1e1e1e"
|
|
||||||
foreground = "0x9a7c9d"
|
|
||||||
|
|
||||||
[cursor.style]
|
|
||||||
blinking = "Always"
|
|
||||||
shape = "underline"
|
|
||||||
|
|
||||||
[debug]
|
|
||||||
highlight_damage = false
|
|
||||||
render_timer = false
|
|
||||||
|
|
||||||
[font]
|
|
||||||
size = 12
|
|
||||||
|
|
||||||
[font.bold]
|
|
||||||
family = "JetBrainsMono Nerd Font"
|
|
||||||
style = "Bold"
|
|
||||||
|
|
||||||
[font.bold_italic]
|
|
||||||
family = "JetBrainsMono Nerd Font"
|
|
||||||
style = "Semibold Italic"
|
|
||||||
|
|
||||||
[font.italic]
|
|
||||||
family = "JetBrainsMono Nerd Font"
|
|
||||||
style = "Italic"
|
|
||||||
|
|
||||||
[font.normal]
|
|
||||||
family = "JetBrainsMono Nerd Font"
|
|
||||||
style = "Regular"
|
|
||||||
|
|
||||||
[window]
|
|
||||||
dynamic_padding = true
|
|
||||||
dynamic_title = true
|
|
||||||
opacity = 0.98
|
|
||||||
title = "Terminal"
|
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"BACKGROUND_COLOR": "#202225",
|
"BACKGROUND_COLOR": "#121214",
|
||||||
"IS_MAXIMIZED": true,
|
"IS_MAXIMIZED": false,
|
||||||
"IS_MINIMIZED": false,
|
"IS_MINIMIZED": false,
|
||||||
"MINIMIZE_TO_TRAY": false,
|
"MINIMIZE_TO_TRAY": false,
|
||||||
"OPEN_ON_STARTUP": false,
|
"OPEN_ON_STARTUP": false,
|
||||||
"WINDOW_BOUNDS": {
|
"WINDOW_BOUNDS": {
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"width": 1688,
|
"width": 2328,
|
||||||
"height": 1022
|
"height": 1382
|
||||||
},
|
},
|
||||||
"DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING": true,
|
"DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING": true,
|
||||||
"SKIP_HOST_UPDATE": true,
|
"SKIP_HOST_UPDATE": true,
|
||||||
|
|||||||
2
.config/eww/.gitignore
vendored
Normal file
2
.config/eww/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
__pycache__/
|
||||||
|
/displaytime
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
$wallpaper: #1e1e1e;
|
$wallpaper: #1e1e1e;
|
||||||
$foreground: #9a7c9d;
|
$foreground: #966e9b;
|
||||||
|
|
||||||
$bg0: #2d272f;
|
$bg0: #2d272f;
|
||||||
$bg1: #3f3242;
|
$bg1: #3f3242;
|
||||||
|
|
||||||
$red: #cf6a4c;
|
$red: #b36152;
|
||||||
$green: #8f9d6a;
|
$green: #a1ae50;
|
||||||
$yellow: #f9ee98;
|
$yellow: #f9ee98;
|
||||||
$blue: #7587a6;
|
$blue: #7d7ca5;
|
||||||
$magenta: #9b859d;
|
$magenta: #9b859d;
|
||||||
$cyan: #afc4db;
|
$cyan: #afc4db;
|
||||||
$white: #a7a7a7;
|
$white: #a7a7a7;
|
||||||
|
|||||||
@@ -10,29 +10,54 @@
|
|||||||
|
|
||||||
.root {
|
.root {
|
||||||
color: $foreground;
|
color: $foreground;
|
||||||
font-family: "Source Code Pro";
|
font-family: "Armstrong";
|
||||||
font-size: 9pt;
|
font-size: 9pt;
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(30, 30, 30, 0.7);
|
||||||
|
padding: 10px;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
|
||||||
|
&:not(.focused) {
|
||||||
|
border-color: $bg0;
|
||||||
|
}
|
||||||
|
&.focused {
|
||||||
|
border-color: $foreground;
|
||||||
|
}
|
||||||
|
|
||||||
// Probably needs to change
|
// Probably needs to change
|
||||||
&.bar {
|
&.bar {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.side {
|
&.bottombar {
|
||||||
|
margin: 10px;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.left-side {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
margin-top: 20px;
|
margin-top: 39px;
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
|
margin-bottom: 39px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right-side {
|
||||||
|
margin: 10px;
|
||||||
|
margin-top: 39px;
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-bottom: 39px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.bg {
|
&.bg {
|
||||||
background-color: $bg0;
|
background-color: $bg0;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.outline {
|
.outline {
|
||||||
border: 1px solid $bg1;
|
border: 1px solid $bg1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nebula {
|
.nebula {
|
||||||
@@ -65,7 +90,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.gauge-gutter {
|
.gauge-gutter {
|
||||||
color: $bg0;
|
color: rgba(30, 30, 30, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
@@ -73,13 +98,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.invisible {
|
.invisible {
|
||||||
color: $wallpaper;
|
color: rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.highlight {
|
.highlight {
|
||||||
color: $red;
|
color: $red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.timezone {
|
||||||
|
color: $red;
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.offline {
|
.offline {
|
||||||
color: $bg1;
|
color: $bg1;
|
||||||
}
|
}
|
||||||
@@ -100,8 +130,19 @@
|
|||||||
background-color: $wallpaper;
|
background-color: $wallpaper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mpris module
|
||||||
|
|
||||||
|
.mpris--miniplayer-album {
|
||||||
|
border-radius: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
// sway module
|
// sway module
|
||||||
|
|
||||||
|
.sway--root.sway--vertical {
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.sway--ws {
|
.sway--ws {
|
||||||
color: $bg1;
|
color: $bg1;
|
||||||
|
|
||||||
@@ -140,3 +181,24 @@
|
|||||||
.clock--date {
|
.clock--date {
|
||||||
font-size: 9pt;
|
font-size: 9pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
menu {
|
||||||
|
padding: 3px;
|
||||||
|
background-color: $bg0;
|
||||||
|
font-family: "Armstrong";
|
||||||
|
border: 1px solid $foreground;
|
||||||
|
|
||||||
|
menuitem {
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
border-bottom: 1px solid $bg1;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitem:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitem:hover {
|
||||||
|
background-color: $bg1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
118
.config/eww/eww.yuck
Normal file
118
.config/eww/eww.yuck
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
;; -*-lisp-*- Include modules
|
||||||
|
(include "./modules/workspaces.yuck")
|
||||||
|
(include "./modules/clock.yuck")
|
||||||
|
(include "./modules/system.yuck")
|
||||||
|
(include "./modules/network.yuck")
|
||||||
|
(include "./modules/volume.yuck")
|
||||||
|
(include "./modules/aggietime.yuck")
|
||||||
|
(include "./modules/timer.yuck")
|
||||||
|
(include "./modules/mpris.yuck")
|
||||||
|
|
||||||
|
(defvar power--state "normal")
|
||||||
|
|
||||||
|
(include "./windows.yuck")
|
||||||
|
|
||||||
|
(defwindow desktop-leftbar [group]
|
||||||
|
:geometry (geometry :width "100%"
|
||||||
|
:height "36px"
|
||||||
|
:anchor "top center")
|
||||||
|
:exclusive true
|
||||||
|
:focusable false
|
||||||
|
:stacking "bg"
|
||||||
|
(centerbox :orientation "h"
|
||||||
|
:class "bar root ${sway--data.visible[group].focused ? 'focused' : ''}"
|
||||||
|
(hostname-leftalign)
|
||||||
|
''
|
||||||
|
(ws-group-rightalign :workspace-group {group})))
|
||||||
|
|
||||||
|
(defwindow desktop-mainbar [group]
|
||||||
|
:geometry (geometry :width "100%"
|
||||||
|
:height "36px"
|
||||||
|
:anchor "top center")
|
||||||
|
:exclusive true
|
||||||
|
:focusable false
|
||||||
|
:stacking "bg"
|
||||||
|
(centerbox :orientation "h"
|
||||||
|
:class "bar root ${sway--data.visible[group].focused ? 'focused' : ''}"
|
||||||
|
(ws-group-leftalign :workspace-group {group})
|
||||||
|
(hostname-centeralign)
|
||||||
|
(desktop-details-rightalign)))
|
||||||
|
|
||||||
|
(defwindow desktop-rightbar [group]
|
||||||
|
:geometry (geometry :width "100%"
|
||||||
|
:height "36px"
|
||||||
|
:anchor "top center")
|
||||||
|
:exclusive true
|
||||||
|
:focusable false
|
||||||
|
:stacking "bg"
|
||||||
|
(centerbox :orientation "h"
|
||||||
|
:class "bar root ${sway--data.visible[group].focused ? 'focused' : ''}"
|
||||||
|
(ws-group-leftalign :workspace-group {group})
|
||||||
|
''
|
||||||
|
(hostname-rightalign)))
|
||||||
|
|
||||||
|
(defwindow sidebar [group side]
|
||||||
|
:geometry (geometry :width "200px"
|
||||||
|
:height "100%"
|
||||||
|
:anchor "${side} center")
|
||||||
|
:exclusive true
|
||||||
|
:focusable false
|
||||||
|
:stacking "bg"
|
||||||
|
(centerbox :orientation "v"
|
||||||
|
;; :class "root ${side}-side ${sway--data.visible[group].focused ? 'focused' : ''}"
|
||||||
|
(system-sidebar :group {group}
|
||||||
|
:side {side})
|
||||||
|
""
|
||||||
|
""
|
||||||
|
))
|
||||||
|
|
||||||
|
(defwindow user-sidebar [group side]
|
||||||
|
:geometry (geometry :width "200px"
|
||||||
|
:height "100%"
|
||||||
|
:anchor "${side} center")
|
||||||
|
:exclusive true
|
||||||
|
:focusable false
|
||||||
|
:stacking "bg"
|
||||||
|
(user-sidebar :orientation {side}))
|
||||||
|
|
||||||
|
|
||||||
|
(defwindow laptopbar [group battery]
|
||||||
|
:geometry (geometry :width "100%"
|
||||||
|
:height "36px"
|
||||||
|
:anchor "top center")
|
||||||
|
:exclusive true
|
||||||
|
:focusable false
|
||||||
|
:stacking "bg"
|
||||||
|
(centerbox :orientation "h"
|
||||||
|
:class "laptop bar root ${sway--data.visible[group].focused ? 'focused' : ''}"
|
||||||
|
(hostname-and-workspace-leftalign :workspace-group {group})
|
||||||
|
""
|
||||||
|
(laptop-details-rightalign :battery {battery} )))
|
||||||
|
|
||||||
|
(defwindow laptopsidebar [group battery side]
|
||||||
|
:geometry (geometry :width "35px"
|
||||||
|
:height "100%"
|
||||||
|
:anchor "${side} center")
|
||||||
|
:exclusive true
|
||||||
|
:focusable false
|
||||||
|
:stacking "bg"
|
||||||
|
(centerbox :orientation "v"
|
||||||
|
(laptop-sidebar-top :group {group}
|
||||||
|
:side {side})
|
||||||
|
""
|
||||||
|
(laptop-sidebar-bottom :group {group}
|
||||||
|
:side {side}
|
||||||
|
:battery {battery})))
|
||||||
|
|
||||||
|
(defwindow vertical-bottombar [group]
|
||||||
|
:geometry (geometry :width "100%"
|
||||||
|
:height "65px"
|
||||||
|
:anchor "bottom center")
|
||||||
|
:exclusive true
|
||||||
|
:focusable false
|
||||||
|
:stacking "bg"
|
||||||
|
(centerbox :orientation "h"
|
||||||
|
:class "bottombar root ${sway--data.visible[group].focused ? 'focused' : ''}"
|
||||||
|
(date)
|
||||||
|
(big-clock)
|
||||||
|
(horizontal-minigauges-rightalign)))
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
;; -*-lisp-*- Include modules
|
|
||||||
(include "./modules/workspaces.yuck")
|
|
||||||
(include "./modules/clock.yuck")
|
|
||||||
(include "./modules/system.yuck")
|
|
||||||
(include "./modules/network.yuck")
|
|
||||||
(include "./modules/volume.yuck")
|
|
||||||
(include "./modules/aggietime.yuck")
|
|
||||||
(include "./modules/timer.yuck")
|
|
||||||
(include "./modules/mpris.yuck")
|
|
||||||
|
|
||||||
(include "./windows.yuck")
|
|
||||||
|
|
||||||
(defwindow leftbar
|
|
||||||
:monitor 2
|
|
||||||
:geometry (geometry :width "100%"
|
|
||||||
:height "36px"
|
|
||||||
:anchor "top center")
|
|
||||||
:exclusive true
|
|
||||||
:focusable false
|
|
||||||
:stacking "fg"
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:class "bar root"
|
|
||||||
(normandy-leftbar--left)
|
|
||||||
"" ;;(normandy-leftbar--center)
|
|
||||||
(normandy-leftbar--right)))
|
|
||||||
|
|
||||||
(defwindow rightbar
|
|
||||||
:monitor 1
|
|
||||||
:geometry (geometry :width "100%"
|
|
||||||
:height "26px"
|
|
||||||
:anchor "top center")
|
|
||||||
:exclusive true
|
|
||||||
:focusable false
|
|
||||||
:stacking "fg"
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:class "bar root"
|
|
||||||
(normandy-rightbar--left)
|
|
||||||
"" ;;(normandy-rightbar--center)
|
|
||||||
(normandy-rightbar--right)))
|
|
||||||
|
|
||||||
(defwindow centerbar
|
|
||||||
:monitor 0
|
|
||||||
:geometry (geometry :width "100%"
|
|
||||||
:height "26px"
|
|
||||||
:anchor "top center")
|
|
||||||
:exclusive true
|
|
||||||
:focusable false
|
|
||||||
:stacking "fg"
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:class "bar root"
|
|
||||||
(normandy-centerbar--left)
|
|
||||||
(normandy-centerbar--center)
|
|
||||||
(normandy-centerbar--right)))
|
|
||||||
|
|
||||||
(defwindow sidebar
|
|
||||||
:monitor 2
|
|
||||||
:geometry (geometry :width "210px"
|
|
||||||
:height "1044px"
|
|
||||||
:anchor "left bottom")
|
|
||||||
:exclusive true
|
|
||||||
:focusable false
|
|
||||||
:stacking "fg"
|
|
||||||
(normandy-sidebar))
|
|
||||||
|
|
||||||
(defwindow sidebar2
|
|
||||||
:monitor 1
|
|
||||||
:geometry (geometry :width "210px"
|
|
||||||
:height "1044px"
|
|
||||||
:anchor "right bottom")
|
|
||||||
:exclusive true
|
|
||||||
:focusable false
|
|
||||||
:stacking "fg"
|
|
||||||
(normandy-sidebar))
|
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
;; -*-lisp-*- Include modules
|
|
||||||
(include "./modules/workspaces.yuck")
|
|
||||||
(include "./modules/clock.yuck")
|
|
||||||
(include "./modules/system.yuck")
|
|
||||||
(include "./modules/network.yuck")
|
|
||||||
(include "./modules/volume.yuck")
|
|
||||||
(include "./modules/aggietime.yuck")
|
|
||||||
(include "./modules/timer.yuck")
|
|
||||||
(include "./modules/mpris.yuck")
|
|
||||||
|
|
||||||
(defvar power--state "normal")
|
|
||||||
|
|
||||||
(include "./windows.yuck")
|
|
||||||
|
|
||||||
(defwindow builtinbar
|
|
||||||
:monitor 0
|
|
||||||
:geometry (geometry :width "100%"
|
|
||||||
:height "36px"
|
|
||||||
:anchor "top center")
|
|
||||||
:exclusive true
|
|
||||||
:focusable false
|
|
||||||
:stacking "fg"
|
|
||||||
(centerbox :orientation "h" :class "bar root ${power--state == 'critical' ? 'reservepower' : ''}"
|
|
||||||
(rocinante-builtinbar--left)
|
|
||||||
(rocinante-builtinbar--center)
|
|
||||||
(rocinante-builtinbar--right)))
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
;; -*-lisp-*- Include modules
|
|
||||||
(include "./modules/workspaces.yuck")
|
|
||||||
(include "./modules/clock.yuck")
|
|
||||||
(include "./modules/system.yuck")
|
|
||||||
(include "./modules/network.yuck")
|
|
||||||
(include "./modules/volume.yuck")
|
|
||||||
(include "./modules/aggietime.yuck")
|
|
||||||
(include "./modules/timer.yuck")
|
|
||||||
(include "./modules/mpris.yuck")
|
|
||||||
|
|
||||||
(include "./windows.yuck")
|
|
||||||
|
|
||||||
(defwindow leftbar
|
|
||||||
:monitor 1
|
|
||||||
:geometry (geometry :width "100%"
|
|
||||||
:height "36px"
|
|
||||||
:anchor "top center")
|
|
||||||
:exclusive true
|
|
||||||
:focusable false
|
|
||||||
:stacking "fg"
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:class "bar root"
|
|
||||||
(tycho-leftbar--left)
|
|
||||||
(tycho-leftbar--center)
|
|
||||||
(tycho-leftbar--right)))
|
|
||||||
|
|
||||||
(defwindow centerbar
|
|
||||||
:monitor 0
|
|
||||||
:geometry (geometry :width "100%"
|
|
||||||
:height "26px"
|
|
||||||
:anchor "top center")
|
|
||||||
:exclusive true
|
|
||||||
:focusable false
|
|
||||||
:stacking "fg"
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:class "bar root"
|
|
||||||
(tycho-centerbar--left)
|
|
||||||
(tycho-centerbar--center)
|
|
||||||
(tycho-centerbar--right)))
|
|
||||||
|
|
||||||
(defwindow rightbar
|
|
||||||
:monitor 2
|
|
||||||
:geometry (geometry :width "1440px"
|
|
||||||
:height "36px"
|
|
||||||
:anchor "top center")
|
|
||||||
:exclusive true
|
|
||||||
:focusable false
|
|
||||||
:stacking "fg"
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:class "bar root"
|
|
||||||
(tycho-rightbar--left)
|
|
||||||
(tycho-rightbar--center)
|
|
||||||
(tycho-rightbar--right)))
|
|
||||||
|
|
||||||
(defwindow sidebar
|
|
||||||
:monitor 1
|
|
||||||
:geometry (geometry :width "200px"
|
|
||||||
:height "100%"
|
|
||||||
:anchor "left center")
|
|
||||||
:exclusive true
|
|
||||||
:focusable false
|
|
||||||
:stacking "fg"
|
|
||||||
(tycho-sidebar))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defwindow network-status
|
|
||||||
:monitor 0
|
|
||||||
:geometry (geometry :width "200px"
|
|
||||||
:height "0px"
|
|
||||||
:x "300px"
|
|
||||||
:y "0px"
|
|
||||||
:anchor "top right")
|
|
||||||
:exclusive false
|
|
||||||
:focusable false
|
|
||||||
:stacking "overlay"
|
|
||||||
(box :orientation "v"
|
|
||||||
:class "bar root bg outline"
|
|
||||||
:visible {network--show-details}
|
|
||||||
(network-detail)))
|
|
||||||
|
|
||||||
@@ -8,14 +8,95 @@
|
|||||||
(box :class "module text"
|
(box :class "module text"
|
||||||
:spacing 0
|
:spacing 0
|
||||||
:orientation "v"
|
:orientation "v"
|
||||||
(label :class "special"
|
(box :orientation "h"
|
||||||
:text "${clock--data.hour}:${clock--data.minute}:${clock--data.second}")
|
:spacing -5
|
||||||
(label :text "${clock--data.year}-${clock--data.month}-${clock--data.day}")))
|
:space-evenly true
|
||||||
|
:class "special"
|
||||||
|
"${formattime(clock--data.stamp, '%H', clock--data.tz)}"
|
||||||
|
":"
|
||||||
|
"${formattime(clock--data.stamp, '%M', clock--data.tz)}"
|
||||||
|
":"
|
||||||
|
"${formattime(clock--data.stamp, '%S', clock--data.tz)}"
|
||||||
|
)
|
||||||
|
(label :text {formattime(clock--data.stamp, "%Y-%m-%d", clock--data.tz)})))
|
||||||
|
|
||||||
|
|
||||||
|
(defwidget mission-clock []
|
||||||
|
(box :class "module text"
|
||||||
|
:spacing 0
|
||||||
|
:orientation "v"
|
||||||
|
:halign "center"
|
||||||
|
:valign "center"
|
||||||
|
:visible {clock--data.timer.active}
|
||||||
|
(box :orientation "h"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 5
|
||||||
|
:valign "center"
|
||||||
|
:halign "center"
|
||||||
|
(label :text 'T'
|
||||||
|
:class "special")
|
||||||
|
(label :text {clock--data.timer.started ? "+" : "-"}
|
||||||
|
:class {clock--data.timer.started ? "green" : "highlight"})
|
||||||
|
(label :text {clock--data.timer.timer}
|
||||||
|
:class "special"))
|
||||||
|
(label :text '${clock--data.timer.title} ${clock--data.timer.prefix}')))
|
||||||
|
|
||||||
|
(defwidget big-clock []
|
||||||
|
(centerbox :class "bigger nebula"
|
||||||
|
:space-evenly false
|
||||||
|
:halign "center"
|
||||||
|
:valign "center"
|
||||||
|
:width 100
|
||||||
|
:orientation "h"
|
||||||
|
(box :halign "start" {formattime(clock--data.stamp, "%H", clock--data.tz)})
|
||||||
|
(box :halign "center" ":")
|
||||||
|
(box :halign "end" {formattime(clock--data.stamp, "%M", clock--data.tz)})))
|
||||||
|
|
||||||
|
|
||||||
|
(defwidget date []
|
||||||
|
(box :class "nebula module text"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:halign "start"
|
||||||
|
:valign "center"
|
||||||
|
:orientation "h"
|
||||||
|
(label :text {formattime(clock--data.stamp, "%A", clock--data.tz)}
|
||||||
|
:class "medium"
|
||||||
|
:valign "center")
|
||||||
|
(label :text {formattime(clock--data.stamp, "%B %d", clock--data.tz)}
|
||||||
|
:class "special"
|
||||||
|
:valign "center")))
|
||||||
|
|
||||||
|
|
||||||
|
(defwidget side-mission-clock []
|
||||||
|
(box :class "module text"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 5
|
||||||
|
:halign "start"
|
||||||
|
:valign "center"
|
||||||
|
:visible {clock--data.timer.active}
|
||||||
|
:width 200
|
||||||
|
:orientation "v"
|
||||||
|
(label :class "big nebula special"
|
||||||
|
:text {clock--data.timer.title})
|
||||||
|
(label :class "nebula"
|
||||||
|
:text {clock--data.timer.prefix})
|
||||||
|
(box :class "nebula"
|
||||||
|
:spacing 5
|
||||||
|
:halign "center"
|
||||||
|
:space-evenly false
|
||||||
|
(label :text "T")
|
||||||
|
(label :class {clock--data.timer.started ? "green" : "highlight"}
|
||||||
|
:text {clock--data.timer.started ? "+" : "-"})
|
||||||
|
|
||||||
|
(label :class "nebula"
|
||||||
|
:text {clock--data.timer.timer}))))
|
||||||
|
|
||||||
(defwidget sideclock []
|
(defwidget sideclock []
|
||||||
(button :onclick "echo -n $(date +%Y-%d-%m) | wl-copy"
|
(button :onclick "echo -n $(date +%Y-%d-%m) | wl-copy && eww update clock--show=date && sleep 2 && eww update clock--show=clock"
|
||||||
:onrightclick "echo -n $(date +%s) | wl-copy && eww update clock--show=unixtime && sleep 2 && eww update clock--show=clock"
|
:onrightclick "echo -n $(date +%s) | wl-copy && eww update clock--show=unixtime && sleep 2 && eww update clock--show=clock"
|
||||||
(overlay
|
(overlay
|
||||||
(box :class "module text nebula"
|
(box :class "module text"
|
||||||
:spacing 0
|
:spacing 0
|
||||||
:space-evenly false
|
:space-evenly false
|
||||||
:orientation "v"
|
:orientation "v"
|
||||||
@@ -24,12 +105,17 @@
|
|||||||
:width 150
|
:width 150
|
||||||
:halign "center"
|
:halign "center"
|
||||||
:orientation "h"
|
:orientation "h"
|
||||||
(box :halign "start" "${clock--data.hour}")
|
(box :halign "start" {formattime(clock--data.stamp, "%H", clock--data.tz)})
|
||||||
(box :halign "center" ":")
|
(box :halign "center" ":")
|
||||||
(box :halign "end" "${clock--data.minute}"))
|
(box :halign "end" {formattime(clock--data.stamp, "%M", clock--data.tz)}))
|
||||||
(label :text "${clock--data.dow}"
|
(label :text {formattime(clock--data.stamp, "%A", clock--data.tz)}
|
||||||
:class "special")
|
:class "special nebula")
|
||||||
(label :text "${clock--data.month_name} ${clock--data.day}"))
|
(label :text {formattime(clock--data.stamp, "%B %d", clock--data.tz)}
|
||||||
|
:class "nebula")
|
||||||
|
(label :text {clock--data.tz}
|
||||||
|
:class "highlight timezone"
|
||||||
|
:visible {clock--data.tz-source != "system"})
|
||||||
|
)
|
||||||
(box
|
(box
|
||||||
:height 100
|
:height 100
|
||||||
(revealer :transition "crossfade"
|
(revealer :transition "crossfade"
|
||||||
|
|||||||
@@ -1,29 +1,64 @@
|
|||||||
;; -*-lisp-*-
|
;; -*-lisp-*-
|
||||||
(deflisten mpris--data :initial "{}"
|
(deflisten mpris--data :initial "{}"
|
||||||
`~/.config/eww/scripts/mpris.py`)
|
`~/.config/eww/scripts/mpris2.py`)
|
||||||
|
|
||||||
(defwidget mpris2
|
(defwidget mpris2
|
||||||
[]
|
[]
|
||||||
|
(button :onclick "astal-mpris --player '${mpris--data.active_player}' play-pause"
|
||||||
(box :class "module text"
|
(box :class "module text"
|
||||||
:spacing 0
|
:spacing 0
|
||||||
:orientation "v"
|
:orientation "v"
|
||||||
(label :class {mpris--data.playing ? "special" : "offline"}
|
(box :spacing 5
|
||||||
:visible {mpris--data.running}
|
:space-evenly false
|
||||||
:text "${mpris--data.title} by ${mpris--data.artist}")
|
:halign "center"
|
||||||
|
:orientation "h"
|
||||||
|
:visible {mpris--data.running}
|
||||||
|
:class {mpris--data.playing ? "special" : "offline"}
|
||||||
|
{mpris--data.title}
|
||||||
|
"--"
|
||||||
|
(box :space-evenly false
|
||||||
|
:orientation "h"
|
||||||
|
{mpris--data.position_minutes}
|
||||||
|
":"
|
||||||
|
{mpris--data.position_seconds}
|
||||||
|
(box :space-evenly false
|
||||||
|
:orientation "h"
|
||||||
|
:visible {mpris--data.length > 0}
|
||||||
|
"/"
|
||||||
|
{mpris--data.length_minutes}
|
||||||
|
":"
|
||||||
|
{mpris--data.length_seconds}))
|
||||||
|
)
|
||||||
(label :class "offline"
|
(label :class "offline"
|
||||||
:visible {!mpris--data.running}
|
:visible {!mpris--data.running}
|
||||||
:text "player offline")
|
:text "player offline")
|
||||||
(label :visible {mpris--data.running}
|
(label :visible {mpris--data.running}
|
||||||
:text "now playing from ${mpris--data.album}")
|
:text "now playing from ${mpris--data.album}")
|
||||||
(label :visible {!mpris--data.running}
|
(label :visible {!mpris--data.running}
|
||||||
:text "player offline")))
|
:text "player offline"))))
|
||||||
|
|
||||||
|
|
||||||
(defwidget mpris-miniplayer []
|
(defwidget mpris-miniplayer []
|
||||||
(box :class "miniplayer"
|
(box :class "miniplayer"
|
||||||
:orientation "v"
|
:orientation "v"
|
||||||
|
:space-evenly false
|
||||||
:spacing 10
|
:spacing 10
|
||||||
(image :path {mpris--data.album_art}
|
(label :class "nebula medium special"
|
||||||
:image-width 100
|
:text "Music")
|
||||||
:image-height 100)
|
(box :orientation "v"
|
||||||
(label)))
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:visible {mpris--data.running}
|
||||||
|
(image :path {mpris--data.album_art}
|
||||||
|
:class "mpris--miniplayer-album"
|
||||||
|
:image-width 150
|
||||||
|
:image-height 150)
|
||||||
|
(box :orientation "v"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 5
|
||||||
|
(label :text {mpris--data.title}
|
||||||
|
:class "large special")
|
||||||
|
(label :text {mpris--data.artist})))
|
||||||
|
(label :class "nebula offline"
|
||||||
|
:visible {!mpris--data.running}
|
||||||
|
:text "Offline")))
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
;; -*-lisp-*-
|
;; -*-lisp-*-
|
||||||
(deflisten network--data
|
(deflisten network--data
|
||||||
`~/.config/eww/scripts/network.py`)
|
`~/.config/eww/scripts/network.py`)
|
||||||
|
|
||||||
|
(defvar nebula-armstrong-alignment "-3px")
|
||||||
|
|
||||||
(defvar network--show-details false)
|
(defvar network--show-details false)
|
||||||
|
|
||||||
@@ -48,27 +50,12 @@
|
|||||||
:halign "start"
|
:halign "start"
|
||||||
:space-evenly false
|
:space-evenly false
|
||||||
:spacing 0
|
:spacing 0
|
||||||
(label :class "offline"
|
(label :class "highlight"
|
||||||
:visible {network--data
|
:visible {!device.online}
|
||||||
["network"]
|
:text "offline")
|
||||||
[device]
|
(label :class "special"
|
||||||
["offline"]
|
:visible {device.online}
|
||||||
}
|
:text {network--data.wifi.ssid})))
|
||||||
:text "offline")
|
|
||||||
(label :visible {network--data
|
|
||||||
["network"]
|
|
||||||
[device]
|
|
||||||
["connecting"]
|
|
||||||
}
|
|
||||||
:class "highlight"
|
|
||||||
:text "connecting...")
|
|
||||||
(label :visible {network--data
|
|
||||||
["network"]
|
|
||||||
[device]
|
|
||||||
["online"]
|
|
||||||
}
|
|
||||||
:class "special"
|
|
||||||
:text "${network--data['wifi']['ssid']}")))
|
|
||||||
|
|
||||||
(defwidget network--lan
|
(defwidget network--lan
|
||||||
[device]
|
[device]
|
||||||
@@ -76,11 +63,11 @@
|
|||||||
:halign "start"
|
:halign "start"
|
||||||
:space-evenly false
|
:space-evenly false
|
||||||
:spacing 0
|
:spacing 0
|
||||||
(label :class "offline"
|
(label :class "highlight"
|
||||||
:visible {!device.online}
|
:visible {!device.online}
|
||||||
:text "offline")
|
:text "offline")
|
||||||
(label :visible {device.online}
|
(label :visible {device.online}
|
||||||
:class {network--data.last_update.unix < clock--data.unix - 30 ? "highlight" : "special"}
|
:class {network--data.last_update.unix < clock--data.stamp - 30 ? "highlight" : "special"}
|
||||||
:text "${device.addresses[0].address}/${device.addresses[0].prefixlen}")))
|
:text "${device.addresses[0].address}/${device.addresses[0].prefixlen}")))
|
||||||
|
|
||||||
(defwidget network--secure
|
(defwidget network--secure
|
||||||
@@ -127,9 +114,28 @@
|
|||||||
:halign "center"
|
:halign "center"
|
||||||
:space-evenly false
|
:space-evenly false
|
||||||
:spacing 10
|
:spacing 10
|
||||||
(network--lan :device {network--data.default_interface}))
|
(network--lan :device {network--data.default_interface}
|
||||||
|
:visible {!network--data.wifi.default}))
|
||||||
"communications")))
|
"communications")))
|
||||||
|
|
||||||
|
(defwidget wifi []
|
||||||
|
(box :orientation "v"
|
||||||
|
:halign "start"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 0
|
||||||
|
:visible {network--data != ''}
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "center"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
(label :class "offline"
|
||||||
|
:text "offline"
|
||||||
|
:visible {!network--data.wifi.connected})
|
||||||
|
(label :class "special"
|
||||||
|
:text {network--data.wifi.ssid}
|
||||||
|
:visible {network--data.wifi.connected}))
|
||||||
|
"wireless"))
|
||||||
|
|
||||||
(defwidget network--public-ip
|
(defwidget network--public-ip
|
||||||
[]
|
[]
|
||||||
(centerbox :orientation "h"
|
(centerbox :orientation "h"
|
||||||
@@ -231,7 +237,7 @@
|
|||||||
(box :halign "end"
|
(box :halign "end"
|
||||||
:spacing 0
|
:spacing 0
|
||||||
:space-evenly false
|
:space-evenly false
|
||||||
(label :class {network--data.last_update.unix < clock--data.unix - 30 ? "highlight" : "special"}
|
(label :class {network--data.last_update.unix < clock--data.stamp - 30 ? "highlight" : "special"}
|
||||||
:text "${network--data.last_update.month}-${network--data.last_update.day} ${network--data.last_update.hour}:${network--data.last_update.minute}:${network--data.last_update.second}")))
|
:text "${network--data.last_update.month}-${network--data.last_update.day} ${network--data.last_update.hour}:${network--data.last_update.minute}:${network--data.last_update.second}")))
|
||||||
))
|
))
|
||||||
|
|
||||||
@@ -265,46 +271,56 @@
|
|||||||
:spacing 10
|
:spacing 10
|
||||||
:width 200
|
:width 200
|
||||||
:space-evenly false
|
:space-evenly false
|
||||||
(box :halign "start"
|
(transform :translate-y {network--data.have_default_route ? nebula-armstrong-alignment : "0px"}
|
||||||
:class "nebula"
|
|
||||||
"Route On:")
|
|
||||||
""
|
|
||||||
(box :halign "end"
|
|
||||||
(label :text "No Route"
|
|
||||||
:class "highlight"
|
|
||||||
:visible {network--data.online && !network--data.have_default_route})
|
|
||||||
(label :text "${network--data.default_route}"
|
|
||||||
:class "special"
|
|
||||||
:visible {network--data.online && network--data.have_default_route})))
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:spacing 10
|
|
||||||
:width 200
|
|
||||||
:space-evenly false
|
|
||||||
(box :halign "start"
|
(box :halign "start"
|
||||||
:valign "start"
|
:valign "start"
|
||||||
:class "nebula"
|
:class "nebula"
|
||||||
"Address:")
|
"Route On:"))
|
||||||
""
|
""
|
||||||
(box :halign "end"
|
(box :halign "end"
|
||||||
:orientation "v"
|
(label :text "No Route"
|
||||||
(label :text "${network--data.default_interface.addresses[0].address}"
|
:class "nebula highlight"
|
||||||
:class "special")
|
:visible {!network--data.have_default_route})
|
||||||
(label :text "/${network--data.default_interface.addresses[0].prefixlen}"
|
(label :text "${network--data.default_route}"
|
||||||
:halign "end"
|
:class "special"
|
||||||
:class "special")))
|
:visible {network--data.have_default_route})))
|
||||||
(centerbox :orientation "h"
|
(centerbox :orientation "h"
|
||||||
:halign "start"
|
:halign "start"
|
||||||
:spacing 10
|
:spacing 10
|
||||||
:width 200
|
:width 200
|
||||||
:space-evenly false
|
:space-evenly false
|
||||||
|
(transform :translate-y {network--data.online ? nebula-armstrong-alignment : "0px"}
|
||||||
(box :halign "start"
|
(box :halign "start"
|
||||||
|
:valign "start"
|
||||||
:class "nebula"
|
:class "nebula"
|
||||||
"Public IP:")
|
"Address:"))
|
||||||
|
""
|
||||||
|
(box :halign "end"
|
||||||
|
:valign "end"
|
||||||
|
:orientation "v"
|
||||||
|
(label :text "${network--data.default_interface.addresses[0].address}"
|
||||||
|
:class "special"
|
||||||
|
:visible {network--data.online})
|
||||||
|
(label :text "offline"
|
||||||
|
:class "nebula highlight"
|
||||||
|
:visible {!network--data.online})
|
||||||
|
(label :text "/${network--data.default_interface.addresses[0].prefixlen}"
|
||||||
|
:halign "end"
|
||||||
|
:class "special"
|
||||||
|
:visible {network--data.online})))
|
||||||
|
(centerbox :orientation "h"
|
||||||
|
:halign "start"
|
||||||
|
:spacing 10
|
||||||
|
:width 200
|
||||||
|
:space-evenly false
|
||||||
|
(transform :translate-y {network--data.have_public_ip ? nebula-armstrong-alignment : "0px"}
|
||||||
|
(box :halign "start"
|
||||||
|
:class "nebula"
|
||||||
|
"Public IP:"))
|
||||||
""
|
""
|
||||||
(box :halign "end"
|
(box :halign "end"
|
||||||
(label :text "Offline"
|
(label :text "Offline"
|
||||||
:class "highlight"
|
:class "nebula highlight"
|
||||||
:visible {!network--data.have_public_ip})
|
:visible {!network--data.have_public_ip})
|
||||||
(label :text {network--data.public_ip.ip}
|
(label :text {network--data.public_ip.ip}
|
||||||
:class "special"
|
:class "special"
|
||||||
@@ -314,9 +330,10 @@
|
|||||||
:spacing 10
|
:spacing 10
|
||||||
:width 200
|
:width 200
|
||||||
:space-evenly false
|
:space-evenly false
|
||||||
(box :halign "start"
|
(transform :translate-y {network--data.have_gateway ? nebula-armstrong-alignment : "0px"}
|
||||||
:class "nebula"
|
(box :halign "start"
|
||||||
"Gateway:")
|
:class "nebula"
|
||||||
|
"Gateway:"))
|
||||||
""
|
""
|
||||||
(box :halign "end"
|
(box :halign "end"
|
||||||
(label :text "Error"
|
(label :text "Error"
|
||||||
@@ -325,6 +342,23 @@
|
|||||||
(label :text {network--data.gateway}
|
(label :text {network--data.gateway}
|
||||||
:class "special"
|
:class "special"
|
||||||
:visible {network--data.have_gateway})))
|
:visible {network--data.have_gateway})))
|
||||||
|
(centerbox :orientation "h"
|
||||||
|
:halign "start"
|
||||||
|
:spacing 10
|
||||||
|
:width 200
|
||||||
|
:space-evenly false
|
||||||
|
(transform :translate-y {network--data.wifi.connected ? nebula-armstrong-alignment : "0px"}
|
||||||
|
(box :halign "start"
|
||||||
|
:class "nebula"
|
||||||
|
"Wireless:"))
|
||||||
|
""
|
||||||
|
(box :halign "end"
|
||||||
|
(label :text "offline"
|
||||||
|
:class "offline nebula"
|
||||||
|
:visible {!network--data.wifi.connected})
|
||||||
|
(label :text {network--data.wifi.ssid}
|
||||||
|
:class "special"
|
||||||
|
:visible {network--data.wifi.connected})))
|
||||||
(centerbox :orientation "h"
|
(centerbox :orientation "h"
|
||||||
:halign "start"
|
:halign "start"
|
||||||
:class "nebula"
|
:class "nebula"
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
(deflisten network--data
|
|
||||||
`~/.config/eww/scripts/network.py`)
|
|
||||||
|
|
||||||
(defwidget network--wlan [device]
|
|
||||||
(box :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 0
|
|
||||||
(label :class "offline"
|
|
||||||
:visible {network--data["network"][device]["offline"]}
|
|
||||||
:text "offline")
|
|
||||||
(label :visible {network--data["network"][device]["connecting"]}
|
|
||||||
:class "highlight"
|
|
||||||
:text "connecting...")
|
|
||||||
(label :visible {network--data["network"][device]["online"]}
|
|
||||||
:class "special"
|
|
||||||
:text "${network--data['wifi']['ssid']}")))
|
|
||||||
|
|
||||||
(defwidget network--lan [device]
|
|
||||||
(box :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 0
|
|
||||||
(label :class "offline"
|
|
||||||
:visible {network--data["network"][device]["offline"]}
|
|
||||||
:text "offline")
|
|
||||||
(label :visible {network--data["network"][device]["connecting"]}
|
|
||||||
:class "highlight"
|
|
||||||
:text "connecting...")
|
|
||||||
(label :visible {network--data["network"][device]["online"] && !network--data.network[device].connecting}
|
|
||||||
:class "special"
|
|
||||||
:text "${network--data['network'][device]['ip4_addr']}/${network--data['network'][device]['ip4_prefix']}")))
|
|
||||||
|
|
||||||
(defwidget network--proxy-vpn [device ?required]
|
|
||||||
(box :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 0
|
|
||||||
:visible {network--data["network"][device]["exists"] || required}
|
|
||||||
(label :class "highlight"
|
|
||||||
:text "- insecure"
|
|
||||||
:visible {! network--data["network"][device]["exists"]})
|
|
||||||
(label :class "green"
|
|
||||||
:text "- secured"
|
|
||||||
:visible {network--data["network"][device]["exists"]})))
|
|
||||||
|
|
||||||
(defwidget proxy-network [device]
|
|
||||||
(box :orientation "v"
|
|
||||||
:halign "start"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 0
|
|
||||||
(label :class "green"
|
|
||||||
:text "connected"
|
|
||||||
:visible {network--data.network[device].exists})
|
|
||||||
(label :class "offline"
|
|
||||||
:text "offline"
|
|
||||||
:visible {!network--data.network[device].exists})
|
|
||||||
"proxy vpn"))
|
|
||||||
|
|
||||||
(defwidget vpn-network []
|
|
||||||
(box :orientation "v"
|
|
||||||
:halign "start"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 0
|
|
||||||
(label :class "highlight"
|
|
||||||
:text "offline"
|
|
||||||
:visible {! network--data["network"]["ezrinet"]["exists"] || ! network--data["connected"]})
|
|
||||||
(label :class "green"
|
|
||||||
:text "connected"
|
|
||||||
:visible {network--data["network"]["ezrinet"]["exists"] && network--data["connected"]})
|
|
||||||
"personal network"))
|
|
||||||
|
|
||||||
(defwidget network []
|
|
||||||
(box :orientation "v"
|
|
||||||
:halign "start"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 0
|
|
||||||
(box :orientation "h"
|
|
||||||
:halign "center"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 10
|
|
||||||
(network--lan :device "insight")
|
|
||||||
(network--proxy-vpn :device "wg-mullvad" :required {!network--data.trusted}))
|
|
||||||
"communications"))
|
|
||||||
|
|
||||||
(defwidget network-sidebar-details []
|
|
||||||
(box :orientation "v"
|
|
||||||
:halign "start"
|
|
||||||
:class "module"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 5
|
|
||||||
:width 200
|
|
||||||
(box :orientation "h"
|
|
||||||
:halign "center"
|
|
||||||
:class "nebula"
|
|
||||||
:spacing 10
|
|
||||||
:space-evenly false
|
|
||||||
(label :text "Comms"
|
|
||||||
:class "medium special"))
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:class "nebula"
|
|
||||||
:spacing 10
|
|
||||||
:width 200
|
|
||||||
:space-evenly false
|
|
||||||
(box :halign "start"
|
|
||||||
"Status:")
|
|
||||||
""
|
|
||||||
(box :halign "end"
|
|
||||||
(label :text "Online"
|
|
||||||
:class "green"
|
|
||||||
:visible {network--data.connected})
|
|
||||||
(label :text "Offline"
|
|
||||||
:class "highlight"
|
|
||||||
:visible {!network--data.connected})))
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:class "nebula"
|
|
||||||
:spacing 10
|
|
||||||
:width 200
|
|
||||||
:space-evenly false
|
|
||||||
(box :halign "start"
|
|
||||||
"VPN:")
|
|
||||||
""
|
|
||||||
(box :halign "end"
|
|
||||||
(label :text "Connected"
|
|
||||||
:class "green"
|
|
||||||
:visible {network--data.network.ezrinet.online && network--data.connected})
|
|
||||||
(label :text "Offline"
|
|
||||||
:class "highlight"
|
|
||||||
:visible {!network--data.network.ezrinet.exists})))
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:class "nebula"
|
|
||||||
:spacing 10
|
|
||||||
:width 200
|
|
||||||
:space-evenly false
|
|
||||||
(box :halign "start"
|
|
||||||
"Proxy:")
|
|
||||||
""
|
|
||||||
(box :halign "end"
|
|
||||||
(label :text "Connected"
|
|
||||||
:class "green"
|
|
||||||
:visible {network--data.network.wg-mullvad.online})
|
|
||||||
(label :text "Offline"
|
|
||||||
:class "highlight"
|
|
||||||
:visible {!network--data.network.wg-mullvad.exists})))
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:class "nebula"
|
|
||||||
:spacing 10
|
|
||||||
:width 200
|
|
||||||
:space-evenly false
|
|
||||||
(box :halign "start"
|
|
||||||
"Wi-Fi:")
|
|
||||||
""
|
|
||||||
(box :halign "end"
|
|
||||||
(label :text {network--data.wifi.ssid}
|
|
||||||
:limit-width 12
|
|
||||||
:class "green"
|
|
||||||
:visible {network--data.wifi.connected})
|
|
||||||
(label :text "Offline"
|
|
||||||
:class "offline"
|
|
||||||
:visible {!network--data.wifi.connected})))
|
|
||||||
(centerbox :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:spacing 10
|
|
||||||
:width 200
|
|
||||||
:class "nebula"
|
|
||||||
:space-evenly false
|
|
||||||
(box :valign "start"
|
|
||||||
:halign "start"
|
|
||||||
"Addrs:")
|
|
||||||
""
|
|
||||||
(box :valign "start"
|
|
||||||
:halign "end"
|
|
||||||
:visible {network--data.connected}
|
|
||||||
:orientation "v"
|
|
||||||
(for addr in {network--data.ip4_addrs}
|
|
||||||
(box :class "special"
|
|
||||||
:halign "end"
|
|
||||||
{addr}))
|
|
||||||
(box :visible {!network--data.connected}
|
|
||||||
:class "offline"
|
|
||||||
"none")))
|
|
||||||
;; (box :orientation "h"
|
|
||||||
;; :halign "start"
|
|
||||||
;; :class "nebula"
|
|
||||||
;; :spacing 10
|
|
||||||
;; :space-evenly false
|
|
||||||
;; (label :text "Addr:")
|
|
||||||
;; (label :text {network--data.network[device].ip4_addr}
|
|
||||||
;; :class "medium special"))))
|
|
||||||
))
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
;; -*-lisp-*-
|
|
||||||
(deflisten network--data
|
|
||||||
`~/.config/eww/scripts/network.py`)
|
|
||||||
|
|
||||||
(defwidget network--wlan [device]
|
|
||||||
(box :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 10
|
|
||||||
(label :class "offline"
|
|
||||||
:visible {network--data["network"][device]["offline"]}
|
|
||||||
:text "offline")
|
|
||||||
(label :visible {network--data["network"][device]["connecting"]}
|
|
||||||
:class "highlight"
|
|
||||||
:text "connecting...")
|
|
||||||
(label :visible {network--data["network"][device]["online"] && !network--data.network[device].connecting}
|
|
||||||
:class "special"
|
|
||||||
:text "${network--data['wifi']['ssid']}")
|
|
||||||
(label :visible {!network--data.connection.internet && network--data.network[device].online}
|
|
||||||
:class "highlight"
|
|
||||||
:text "- no internet"
|
|
||||||
)))
|
|
||||||
|
|
||||||
(defwidget network--lan [device]
|
|
||||||
(box :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 0
|
|
||||||
(label :class "offline"
|
|
||||||
:visible {network--data["network"][device]["offline"]}
|
|
||||||
:text "offline")
|
|
||||||
(label :visible {network--data["network"][device]["connecting"]}
|
|
||||||
:class "highlight"
|
|
||||||
:text "connecting...")
|
|
||||||
(label :visible {network--data["network"][device]["online"] && !network--data.network[device].connecting}
|
|
||||||
:class "special"
|
|
||||||
:text "${network--data['network'][device]['ip4_addr']}/${network--data['network'][device]['ip4_prefix']}")))
|
|
||||||
|
|
||||||
(defwidget network--proxy-vpn [device ?required]
|
|
||||||
(box :orientation "h"
|
|
||||||
:halign "start"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 0
|
|
||||||
:visible {network--data.connection.internet && (network--data["network"][device]["exists"] || required)}
|
|
||||||
(label :class "highlight"
|
|
||||||
:text "- insecure"
|
|
||||||
:visible {! network--data["network"][device]["exists"]})
|
|
||||||
(label :class "green"
|
|
||||||
:text "- secured"
|
|
||||||
:visible {network--data["network"][device]["exists"]})))
|
|
||||||
|
|
||||||
(defwidget vpn-network []
|
|
||||||
(box :orientation "v"
|
|
||||||
:halign "start"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 0
|
|
||||||
(label :class "highlight"
|
|
||||||
:text "offline"
|
|
||||||
:visible {!network--data.connection.ezrinet})
|
|
||||||
(label :class "green"
|
|
||||||
:text "connected"
|
|
||||||
:visible {network--data.connection.ezrinet})
|
|
||||||
"personal network"))
|
|
||||||
|
|
||||||
(defwidget network []
|
|
||||||
(box :orientation "v"
|
|
||||||
:halign "start"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 0
|
|
||||||
(box :orientation "h"
|
|
||||||
:halign "center"
|
|
||||||
:space-evenly false
|
|
||||||
:spacing 10
|
|
||||||
(network--wlan :device "wlan0")
|
|
||||||
(network--proxy-vpn :device "wg-mullvad" :required {!network--data.trusted}))
|
|
||||||
"communications"))
|
|
||||||
|
|
||||||
@@ -12,6 +12,22 @@
|
|||||||
:text "${EWW_BATTERY[battery].capacity}%")
|
:text "${EWW_BATTERY[battery].capacity}%")
|
||||||
(label :text "${EWW_BATTERY[battery].status == 'Charging' || EWW_BATTERY[battery].status == 'Full' ? 'external' : 'internal'} power")))
|
(label :text "${EWW_BATTERY[battery].status == 'Charging' || EWW_BATTERY[battery].status == 'Full' ? 'external' : 'internal'} power")))
|
||||||
|
|
||||||
|
(defwidget system-battery-gauge-small [battery]
|
||||||
|
(box :orientation "v"
|
||||||
|
:halign "center"
|
||||||
|
:width 35
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
:class ""
|
||||||
|
(label :text "PWR"
|
||||||
|
:class "special")
|
||||||
|
(box :halign "center"
|
||||||
|
(overlay
|
||||||
|
(system--small-gauge :value {EWW_BATTERY[battery].capacity}
|
||||||
|
:threshold 25
|
||||||
|
:invert-threshold true
|
||||||
|
:green {EWW_BATTERY[battery].status == "Charging" || EWW_BATTERY[battery].capacity == 100})))))
|
||||||
|
|
||||||
(defwidget system-name []
|
(defwidget system-name []
|
||||||
(label :halign "center"
|
(label :halign "center"
|
||||||
:valign "center"
|
:valign "center"
|
||||||
@@ -56,7 +72,7 @@
|
|||||||
:text "${round(system--data.memory.used / 1024 / 1024 / 1024, 2)} / ${round(system--data.memory.total / 1024 / 1024 / 1024, 2)} GiB")
|
:text "${round(system--data.memory.used / 1024 / 1024 / 1024, 2)} / ${round(system--data.memory.total / 1024 / 1024 / 1024, 2)} GiB")
|
||||||
(label :text "system memory")))
|
(label :text "system memory")))
|
||||||
|
|
||||||
(defwidget system--gauge [value ?threshold]
|
(defwidget system--gauge [value ?threshold ?green]
|
||||||
(overlay :width 80
|
(overlay :width 80
|
||||||
:height 80
|
:height 80
|
||||||
(circular-progress :value 75
|
(circular-progress :value 75
|
||||||
@@ -68,6 +84,18 @@
|
|||||||
:start-at 37.5
|
:start-at 37.5
|
||||||
:thickness 2)))
|
:thickness 2)))
|
||||||
|
|
||||||
|
(defwidget system--small-gauge [value ?threshold ?green ?invert-threshold]
|
||||||
|
(overlay :width 30
|
||||||
|
:height 30
|
||||||
|
(circular-progress :value 75
|
||||||
|
:class "gauge-gutter"
|
||||||
|
:start-at 37.5
|
||||||
|
:thickness 2)
|
||||||
|
(circular-progress :value {value * 0.75}
|
||||||
|
:class 'gauge ${(green ?: false) ? "green" : (((invert-threshold ?: false) ? (value < (threshold ?: 20)) : (value > (threshold ?: 80))) ? "highlight" : "")}'
|
||||||
|
:start-at 37.5
|
||||||
|
:thickness 2)))
|
||||||
|
|
||||||
(defwidget cpu-mem-gauges []
|
(defwidget cpu-mem-gauges []
|
||||||
(box :orientation "v"
|
(box :orientation "v"
|
||||||
:space-evenly false
|
:space-evenly false
|
||||||
@@ -121,7 +149,40 @@
|
|||||||
(transform
|
(transform
|
||||||
:translate-y "3px"
|
:translate-y "3px"
|
||||||
(label :text "%"
|
(label :text "%"
|
||||||
:class "offline"))))))))
|
:class "offline"))))))))
|
||||||
|
|
||||||
|
(defwidget system--memory-gauge-small [?invert]
|
||||||
|
(box :orientation "v"
|
||||||
|
:halign "center"
|
||||||
|
:width 35
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
:class ""
|
||||||
|
(label :text "MEM"
|
||||||
|
:visible {!(invert ?: false)}
|
||||||
|
:class "special")
|
||||||
|
(box :halign "center"
|
||||||
|
(overlay
|
||||||
|
(system--small-gauge :value {system--data.memory.percent})))
|
||||||
|
(label :text "MEM"
|
||||||
|
:visible {invert ?: false}
|
||||||
|
:class "special")))
|
||||||
|
|
||||||
|
(defwidget system--swap-gauge-small [?invert]
|
||||||
|
(box :orientation "v"
|
||||||
|
:halign "center"
|
||||||
|
:width 35
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
:class ""
|
||||||
|
(label :text "SWAP"
|
||||||
|
:visible {!(invert ?: false)}
|
||||||
|
:class "special")
|
||||||
|
(box :halign "center"
|
||||||
|
(system--small-gauge :value {system--data.swap.percent}))
|
||||||
|
(label :text "SWAP"
|
||||||
|
:visible {invert ?: false}
|
||||||
|
:class "special")))
|
||||||
|
|
||||||
(defwidget system--cpu-gauge []
|
(defwidget system--cpu-gauge []
|
||||||
(box :orientation "v"
|
(box :orientation "v"
|
||||||
@@ -151,6 +212,24 @@
|
|||||||
:class "offline"))))))
|
:class "offline"))))))
|
||||||
))
|
))
|
||||||
|
|
||||||
|
(defwidget system--cpu-gauge-small [?invert]
|
||||||
|
(box :orientation "v"
|
||||||
|
:halign "center"
|
||||||
|
:width 35
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
:class ""
|
||||||
|
(label :text "CPU"
|
||||||
|
:visible {!(invert ?: false)}
|
||||||
|
:class "special")
|
||||||
|
(box :halign "center"
|
||||||
|
(overlay
|
||||||
|
(system--small-gauge :value {system--data.cpu.avg}
|
||||||
|
:threshold 80)))
|
||||||
|
(label :text "CPU"
|
||||||
|
:visible {(invert ?: false)}
|
||||||
|
:class "special")))
|
||||||
|
|
||||||
(defwidget system--gpu-gauge []
|
(defwidget system--gpu-gauge []
|
||||||
(box :orientation "v"
|
(box :orientation "v"
|
||||||
:halign "start"
|
:halign "start"
|
||||||
@@ -176,7 +255,24 @@
|
|||||||
(transform
|
(transform
|
||||||
:translate-y "3px"
|
:translate-y "3px"
|
||||||
(label :text "%"
|
(label :text "%"
|
||||||
:class "offline"))))))))
|
:class "offline"))))))))
|
||||||
|
|
||||||
|
(defwidget system--gpu-gauge-small [?invert]
|
||||||
|
(box :orientation "v"
|
||||||
|
:halign "center"
|
||||||
|
:width 35
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
:class ""
|
||||||
|
(label :text "GPU"
|
||||||
|
:visible {!(invert ?: false)}
|
||||||
|
:class "special")
|
||||||
|
(box :halign "center"
|
||||||
|
(overlay
|
||||||
|
(system--small-gauge :value {system--data.gpu.load * 100})))
|
||||||
|
(label :text "GPU"
|
||||||
|
:visible {invert ?: false}
|
||||||
|
:class "special")))
|
||||||
|
|
||||||
(defwidget system--vram-gauge []
|
(defwidget system--vram-gauge []
|
||||||
(box :orientation "v"
|
(box :orientation "v"
|
||||||
@@ -203,7 +299,24 @@
|
|||||||
(transform
|
(transform
|
||||||
:translate-y "3px"
|
:translate-y "3px"
|
||||||
(label :text "%"
|
(label :text "%"
|
||||||
:class "offline"))))))))
|
:class "offline"))))))))
|
||||||
|
|
||||||
|
(defwidget system--vram-gauge-small [?invert]
|
||||||
|
(box :orientation "v"
|
||||||
|
:halign "center"
|
||||||
|
:width 35
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
:class ""
|
||||||
|
(label :text "VMEM"
|
||||||
|
:visible {!(invert ?: false)}
|
||||||
|
:class "special")
|
||||||
|
(box :halign "center"
|
||||||
|
(overlay
|
||||||
|
(system--small-gauge :value {system--data.gpu.memory * 100})))
|
||||||
|
(label :text "VMEM"
|
||||||
|
:visible {invert ?: false}
|
||||||
|
:class "special")))
|
||||||
|
|
||||||
|
|
||||||
(defwidget system--gauge-generic [value value-fmt big-text little-text ?subscript ?threshold]
|
(defwidget system--gauge-generic [value value-fmt big-text little-text ?subscript ?threshold]
|
||||||
@@ -248,3 +361,4 @@
|
|||||||
:class "big nebula")
|
:class "big nebula")
|
||||||
(label :text {little-text}
|
(label :text {little-text}
|
||||||
:class "nebula special")))))
|
:class "nebula special")))))
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
;; -*-lisp-*-
|
;; -*-lisp-*-
|
||||||
(deflisten volume--data
|
(deflisten volume--data
|
||||||
`~/.config/eww/scripts/volume.py`)
|
`~/.config/eww/scripts/volume2.py`)
|
||||||
|
|
||||||
(defwidget volume-h []
|
(defwidget volume-h []
|
||||||
(box :orientation "h"
|
(box :orientation "h"
|
||||||
@@ -27,3 +27,90 @@
|
|||||||
(label :class {volume--data.input.mute ? "offline" : "special"}
|
(label :class {volume--data.input.mute ? "offline" : "special"}
|
||||||
:text "${volume--data.input.volume}%"))
|
:text "${volume--data.input.volume}%"))
|
||||||
"audio system"))
|
"audio system"))
|
||||||
|
|
||||||
|
(defwidget volume-small-gauge [?invert]
|
||||||
|
(box :orientation "v"
|
||||||
|
:halign "center"
|
||||||
|
:width 35
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
:class ""
|
||||||
|
(label :text "VOL"
|
||||||
|
:visible {!(invert ?: false)}
|
||||||
|
:class "special")
|
||||||
|
(overlay :width 30
|
||||||
|
:height 30
|
||||||
|
(circular-progress :value {75 / 2.05}
|
||||||
|
:class "gauge-gutter"
|
||||||
|
:start-at 37.5
|
||||||
|
:thickness 2)
|
||||||
|
(circular-progress :value {75 / 2.05}
|
||||||
|
:class "gauge-gutter"
|
||||||
|
:start-at 12.5
|
||||||
|
:clockwise false
|
||||||
|
:thickness 2)
|
||||||
|
(circular-progress :value {volume--data.output.mute ? 0 : min(volume--data.output.volume * 0.75 / 2.05, 75 / 2.05)}
|
||||||
|
:class 'gauge ${volume--data.output.mute ? "green" : volume--data.output.volume > 100 ? "highlight" : ""}'
|
||||||
|
:start-at 37.5
|
||||||
|
:thickness 2)
|
||||||
|
(circular-progress :value {volume--data.input.mute ? 0 : min(volume--data.input.volume * 0.75 / 2.05, 75 / 2.05)}
|
||||||
|
:class 'gauge ${volume--data.input.mute ? "green" : volume--data.input.volume > 100 ? "highlight" : ""}'
|
||||||
|
:start-at 12.5
|
||||||
|
:clockwise false
|
||||||
|
:thickness 2))
|
||||||
|
(label :text "VOL"
|
||||||
|
:visible {invert ?: false}
|
||||||
|
:class "special")))
|
||||||
|
|
||||||
|
(defwidget volume--gauge [io]
|
||||||
|
(box :orientation "v"
|
||||||
|
:halign {io == "in" ? "start" : "end"}
|
||||||
|
:width 95
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
:class "nebula"
|
||||||
|
(label :text {io})
|
||||||
|
(box :halign "center"
|
||||||
|
(overlay
|
||||||
|
(system--gauge :value {volume--data["${io}put"].volume}
|
||||||
|
:threshold {volume--data["${io}put"].mute ? 0 : 100})
|
||||||
|
(transform :translate-y "-2px"
|
||||||
|
(box
|
||||||
|
(box :halign "center"
|
||||||
|
:valign "center"
|
||||||
|
:orientation "h"
|
||||||
|
:space-evenly false
|
||||||
|
:visible {!volume--data["${io}put"].mute}
|
||||||
|
(label :text "%"
|
||||||
|
:class "invisible")
|
||||||
|
(label :text {volume--data["${io}put"].volume}
|
||||||
|
:class "special")
|
||||||
|
(label :text "%"
|
||||||
|
:class "offline"))
|
||||||
|
(box :halign "center"
|
||||||
|
:valign "center"
|
||||||
|
:orientation "h"
|
||||||
|
:space-evenly false
|
||||||
|
:visible {volume--data["${io}put"].mute}
|
||||||
|
(label :text "mute"
|
||||||
|
:class "offline"))
|
||||||
|
))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defwidget volume-gauges []
|
||||||
|
(box :orientation "v"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
:width 200
|
||||||
|
:halign "start"
|
||||||
|
:class "nebula"
|
||||||
|
(label :class "medium special"
|
||||||
|
:text "Audio")
|
||||||
|
(box :orientation "h"
|
||||||
|
:space-evenly false
|
||||||
|
:width 200
|
||||||
|
:halign "start"
|
||||||
|
:spacing 10
|
||||||
|
(volume--gauge :io "out")
|
||||||
|
(volume--gauge :io "in"))
|
||||||
|
))
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
:start-at 0
|
:start-at 0
|
||||||
:clockwise true
|
:clockwise true
|
||||||
:width 16
|
:width 16
|
||||||
|
:height 16
|
||||||
:thickness 1
|
:thickness 1
|
||||||
(box :class 'fill' ))))
|
(box :class 'fill' ))))
|
||||||
|
|
||||||
@@ -68,6 +69,17 @@
|
|||||||
(for workspace in {sway--data.ws[sway--data.context ?: "personal"][group]}
|
(for workspace in {sway--data.ws[sway--data.context ?: "personal"][group]}
|
||||||
(sway--workspace :ws workspace))))
|
(sway--workspace :ws workspace))))
|
||||||
|
|
||||||
|
(defwidget sway-workspaces-vertical [group]
|
||||||
|
(box :orientation "v"
|
||||||
|
:valign "start"
|
||||||
|
:halign "center"
|
||||||
|
:visible {sway--data != ''}
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 5
|
||||||
|
:class "sway--root sway--vertical"
|
||||||
|
(for workspace in {sway--data.ws[sway--data.context ?: "personal"][group]}
|
||||||
|
(sway--workspace :ws workspace))))
|
||||||
|
|
||||||
(defwidget hypr-workspaces [group]
|
(defwidget hypr-workspaces [group]
|
||||||
(box :orientation "h"
|
(box :orientation "h"
|
||||||
:halign "start"
|
:halign "start"
|
||||||
|
|||||||
@@ -8,17 +8,109 @@ Used instead of the `date` command in order to avoid spawning a new process ever
|
|||||||
import datetime
|
import datetime
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
import asyncio
|
||||||
|
from asyncinotify import Inotify, Mask
|
||||||
|
from pathlib import Path
|
||||||
|
from json import load, dump
|
||||||
|
|
||||||
|
|
||||||
def get_date():
|
def refresh_tz():
|
||||||
"""Return the current date as a JSON object string."""
|
"""Reload the timezone."""
|
||||||
return datetime.datetime.now().strftime(
|
tz_file = Path("~/.config/eww/displaytime").expanduser()
|
||||||
'{"hour": "%H", "minute": "%M", "second": "%S", "day": "%d", "month": "%m", "year": "%Y", "dow": "%A","month_name": "%B", "unix": %s}'
|
source = "user"
|
||||||
)
|
if not tz_file.exists():
|
||||||
|
tz_file = Path("/etc/localtime")
|
||||||
|
source = "system"
|
||||||
|
if tz_file.exists():
|
||||||
|
tz = str(tz_file.resolve().relative_to("/usr/share/zoneinfo"))
|
||||||
|
else:
|
||||||
|
tz = "Etc/UTC"
|
||||||
|
source = "static"
|
||||||
|
return tz, source
|
||||||
|
|
||||||
|
|
||||||
|
def refresh_timer():
|
||||||
|
"""Reload the timer."""
|
||||||
|
|
||||||
|
timer_file = Path("~/.config/eww/timer.json").expanduser()
|
||||||
|
if timer_file.exists() and timer_file.is_file():
|
||||||
|
with timer_file.open("r") as f:
|
||||||
|
return load(f)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
timezone, source = refresh_tz()
|
||||||
|
timer = refresh_timer()
|
||||||
|
|
||||||
|
|
||||||
|
def format_timer():
|
||||||
|
"""Format the timer delta."""
|
||||||
|
|
||||||
|
if timer is None:
|
||||||
|
return {"active": False, "error": False, "reason": "no timer"}
|
||||||
|
|
||||||
|
startstamp = timer.get("start")
|
||||||
|
if startstamp is None:
|
||||||
|
return {"active": False, "error": True, "reason": "no start"}
|
||||||
|
start = datetime.datetime.fromtimestamp(startstamp)
|
||||||
|
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
if (stopstamp := timer.get("stop")) is not None:
|
||||||
|
stop = datetime.datetime.fromtimestamp(stopstamp)
|
||||||
|
if stop < now:
|
||||||
|
return {"active": False, "error": False, "reason": f"stopped at {stop}"}
|
||||||
|
|
||||||
|
delta_sec = (now - start).total_seconds()
|
||||||
|
started = True
|
||||||
|
if delta_sec < 0:
|
||||||
|
started = False
|
||||||
|
delta = datetime.timedelta(seconds=int(abs(delta_sec)))
|
||||||
|
else:
|
||||||
|
delta = datetime.timedelta(seconds=int(delta_sec))
|
||||||
|
days = delta.days
|
||||||
|
remainder = datetime.timedelta(seconds=delta.total_seconds() - (days * 24 * 3600))
|
||||||
|
|
||||||
|
return {
|
||||||
|
"active": True,
|
||||||
|
"error": False,
|
||||||
|
"prefix": timer.get("prefix", "MET"),
|
||||||
|
"title": timer.get("title", "timer"),
|
||||||
|
"started": started,
|
||||||
|
"timer": f"{days}d {str(remainder)}",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
"""Print loop."""
|
||||||
|
asyncio.ensure_future(asyncio.create_task(monitor()))
|
||||||
|
while True:
|
||||||
|
dump(
|
||||||
|
{
|
||||||
|
"stamp": int(datetime.datetime.now().timestamp()),
|
||||||
|
"tz": timezone,
|
||||||
|
"tz-source": source,
|
||||||
|
"timer": format_timer(),
|
||||||
|
},
|
||||||
|
sys.stdout,
|
||||||
|
)
|
||||||
|
sys.stdout.write("\n")
|
||||||
|
sys.stdout.flush()
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
|
|
||||||
|
|
||||||
|
async def monitor():
|
||||||
|
"""Timezone monitor loop."""
|
||||||
|
global timezone, source, timer
|
||||||
|
with Inotify() as inotify:
|
||||||
|
inotify.add_watch(
|
||||||
|
Path("~/.config/eww").expanduser(),
|
||||||
|
Mask.CREATE | Mask.DELETE | Mask.MODIFY,
|
||||||
|
)
|
||||||
|
inotify.add_watch(Path("/etc"), Mask.CREATE | Mask.DELETE)
|
||||||
|
async for event in inotify:
|
||||||
|
timezone, source = refresh_tz()
|
||||||
|
timer = refresh_timer()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
while True:
|
asyncio.run(main())
|
||||||
print(get_date())
|
|
||||||
sys.stdout.flush()
|
|
||||||
time.sleep(0.5)
|
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ except:
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
from gi.repository import Playerctl, GLib
|
from gi.repository import Playerctl, GLib
|
||||||
|
from gi.events import GLibEventLoopPolicy
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
asyncio.set_event_loop_policy(GLibEventLoopPolicy())
|
||||||
|
|
||||||
title_maxlen = 40
|
title_maxlen = 40
|
||||||
title_end_at = ["(", "-"]
|
title_end_at = ["(", "-"]
|
||||||
@@ -56,8 +60,8 @@ class StatusDisplay:
|
|||||||
def show(self):
|
def show(self):
|
||||||
self._init_player()
|
self._init_player()
|
||||||
|
|
||||||
main = GLib.MainLoop()
|
loop = asyncio.get_event_loop()
|
||||||
main.run()
|
loop.run_forever()
|
||||||
|
|
||||||
def _get_status(self, playing=None):
|
def _get_status(self, playing=None):
|
||||||
if self._player:
|
if self._player:
|
||||||
|
|||||||
150
.config/eww/scripts/mpris2.py
Executable file
150
.config/eww/scripts/mpris2.py
Executable file
@@ -0,0 +1,150 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from gi.repository import AstalMpris as Mpris, Gio
|
||||||
|
from gi.events import GLibEventLoopPolicy
|
||||||
|
import json
|
||||||
|
import asyncio
|
||||||
|
import sys
|
||||||
|
|
||||||
|
PRIORITY_PLAYERS = {"Feishin"}
|
||||||
|
|
||||||
|
# Override the reported album if the URL is in this dict
|
||||||
|
URL_ALBUM_OVERRIDES = {
|
||||||
|
"https://distantworlds3.space/radio/": "Distant Radio",
|
||||||
|
"https://radio.distantworlds3.space/listen/distant_radio/distantradio.mp3": "Distant Radio",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class MprisMonitor(Gio.Application):
|
||||||
|
"""MPRIS monitor application."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.mpris = Mpris.Mpris.new()
|
||||||
|
self.players: dict[str, Mpris.Player] = {} # type: ignore[annotation-unchecked]
|
||||||
|
self.display_player: Mpris.Player | None = None # type: ignore[annotation-unchecked]
|
||||||
|
|
||||||
|
def connect_player(self, mpris: Mpris.Mpris, player: Mpris.Player):
|
||||||
|
"""Connect a new player."""
|
||||||
|
self.players[player.props.bus_name] = player
|
||||||
|
if self.display_player is None:
|
||||||
|
self.display_player = player
|
||||||
|
|
||||||
|
elif (
|
||||||
|
player.props.identity in PRIORITY_PLAYERS
|
||||||
|
and self.display_player.props.identity not in PRIORITY_PLAYERS
|
||||||
|
):
|
||||||
|
self.display_player = player
|
||||||
|
|
||||||
|
player.connect("notify", self.on_status_update)
|
||||||
|
|
||||||
|
def disconnect_player(self, mpris: Mpris.Mpris, player: Mpris.Player):
|
||||||
|
"""Disconnect a closed player."""
|
||||||
|
print(f"player disconnected: {player.props.bus_name}", file=sys.stderr)
|
||||||
|
existing_player = self.players.get(player.props.bus_name)
|
||||||
|
self.players = {
|
||||||
|
key: val for key, val in self.players.items() if val is not existing_player
|
||||||
|
}
|
||||||
|
if existing_player is self.display_player:
|
||||||
|
self.display_player = None
|
||||||
|
for player in self.players.values():
|
||||||
|
if not self.display_player:
|
||||||
|
self.display_player = player
|
||||||
|
elif (
|
||||||
|
self.display_player.props.identity not in PRIORITY_PLAYERS
|
||||||
|
and player.props.identity in PRIORITY_PLAYERS
|
||||||
|
):
|
||||||
|
self.display_player = player
|
||||||
|
|
||||||
|
if existing_player is not None:
|
||||||
|
existing_player.disconnect_by_func(self.on_status_update)
|
||||||
|
del existing_player
|
||||||
|
|
||||||
|
self.output_status()
|
||||||
|
|
||||||
|
def do_activate(self):
|
||||||
|
"""Activate the application."""
|
||||||
|
self.mpris.connect("player-added", self.connect_player)
|
||||||
|
self.mpris.connect("player-closed", self.disconnect_player)
|
||||||
|
for player in self.mpris.get_players():
|
||||||
|
self.connect_player(self.mpris, player)
|
||||||
|
self.output_status()
|
||||||
|
self.hold()
|
||||||
|
|
||||||
|
def on_status_update(self, player: Mpris.Player, *args):
|
||||||
|
"""Perform status update tasks."""
|
||||||
|
if (
|
||||||
|
player.props.identity in PRIORITY_PLAYERS
|
||||||
|
and player.props.playback_status == Mpris.PlaybackStatus.PLAYING
|
||||||
|
):
|
||||||
|
self.display_player = player
|
||||||
|
elif (
|
||||||
|
player.props.playback_status == Mpris.PlaybackStatus.PLAYING
|
||||||
|
and self.display_player != Mpris.PlaybackStatus.PLAYING
|
||||||
|
):
|
||||||
|
self.display_player = player
|
||||||
|
self.output_status()
|
||||||
|
|
||||||
|
def output_status(self):
|
||||||
|
"""Print the status of the currently active player, or an offline status if no active player exists."""
|
||||||
|
if self.display_player is not None:
|
||||||
|
self.print_player_status(self.display_player)
|
||||||
|
else:
|
||||||
|
self.print_offline_status()
|
||||||
|
|
||||||
|
def print_player_status(self, player: Mpris.Player):
|
||||||
|
"""Print a player's status."""
|
||||||
|
print(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"running": player.props.available
|
||||||
|
and player.props.playback_status != Mpris.PlaybackStatus.STOPPED,
|
||||||
|
"playing": player.props.playback_status
|
||||||
|
== Mpris.PlaybackStatus.PLAYING,
|
||||||
|
"title": player.props.title,
|
||||||
|
"artist": player.props.artist,
|
||||||
|
"album": URL_ALBUM_OVERRIDES.get(
|
||||||
|
player.props.metadata.unpack().get("xesam:url", ""),
|
||||||
|
player.props.album,
|
||||||
|
),
|
||||||
|
"album_artist": player.props.album_artist,
|
||||||
|
"position": player.props.position,
|
||||||
|
"position_minutes": int((player.props.position) // 60),
|
||||||
|
"position_seconds": f"{int((player.props.position + 0) % 60):02}",
|
||||||
|
"length": player.props.length,
|
||||||
|
"length_minutes": int((player.props.length + 0) // 60),
|
||||||
|
"length_seconds": f"{int((player.props.length + 0) % 60):02}",
|
||||||
|
"active_player": player.props.identity,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def print_offline_status(self):
|
||||||
|
"""Print an offline status for when we have no players."""
|
||||||
|
print(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"running": False,
|
||||||
|
"playing": False,
|
||||||
|
"title": None,
|
||||||
|
"artist": None,
|
||||||
|
"album": None,
|
||||||
|
"album_artist": None,
|
||||||
|
"position": None,
|
||||||
|
"position_minutes": None,
|
||||||
|
"position_seconds": None,
|
||||||
|
"length": None,
|
||||||
|
"length_minutes": None,
|
||||||
|
"length_seconds": None,
|
||||||
|
"active_player": "",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.set_event_loop_policy(GLibEventLoopPolicy())
|
||||||
|
app = MprisMonitor()
|
||||||
|
app.run()
|
||||||
@@ -92,7 +92,7 @@ class Interface:
|
|||||||
def get_first_hop() -> IPAddress | None:
|
def get_first_hop() -> IPAddress | None:
|
||||||
"""Get the first network hop."""
|
"""Get the first network hop."""
|
||||||
# Use ping to get the first hop
|
# Use ping to get the first hop
|
||||||
cmd = ["/usr/bin/ping", "-c1", "-W0.3", "-t1", "1.1.1.1"]
|
cmd = ["ping", "-c1", "-W0.3", "-t1", "1.1.1.1"]
|
||||||
result = run(cmd, stdout=PIPE, stderr=PIPE)
|
result = run(cmd, stdout=PIPE, stderr=PIPE)
|
||||||
try:
|
try:
|
||||||
ip = IPAddress(result.stdout.decode("utf-8").split("\n")[1].split()[1])
|
ip = IPAddress(result.stdout.decode("utf-8").split("\n")[1].split()[1])
|
||||||
@@ -121,6 +121,16 @@ def get_gateways():
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def get_ssid():
|
||||||
|
|
||||||
|
cmd = ["iwgetid", "-r"]
|
||||||
|
result = run(cmd, stdout=PIPE, stderr=PIPE)
|
||||||
|
if result.returncode == 0:
|
||||||
|
return result.stdout.decode("utf-8").strip()
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def interface_status(interface: str, gw):
|
def interface_status(interface: str, gw):
|
||||||
"""Get the status of an interface."""
|
"""Get the status of an interface."""
|
||||||
try:
|
try:
|
||||||
@@ -145,14 +155,14 @@ def interface_status(interface: str, gw):
|
|||||||
|
|
||||||
|
|
||||||
def ping(host: IPAddress) -> bool:
|
def ping(host: IPAddress) -> bool:
|
||||||
cmd = ["/usr/bin/ping", "-c1", "-w1", str(host)]
|
cmd = ["ping", "-c1", "-w1", str(host)]
|
||||||
result = run(cmd, stdout=DEVNULL, stderr=DEVNULL)
|
result = run(cmd, stdout=DEVNULL, stderr=DEVNULL)
|
||||||
return result.returncode == 0
|
return result.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
def get_public_ip():
|
def get_public_ip():
|
||||||
"""Get the public IP address."""
|
"""Get the public IP address."""
|
||||||
cmd = ["/usr/bin/curl", "-s", "https://ipinfo.io"]
|
cmd = ["curl", "-s", "https://ipinfo.io"]
|
||||||
result = run(cmd, stdout=PIPE, stderr=PIPE)
|
result = run(cmd, stdout=PIPE, stderr=PIPE)
|
||||||
try:
|
try:
|
||||||
data = json.loads(result.stdout.decode("utf-8"))
|
data = json.loads(result.stdout.decode("utf-8"))
|
||||||
@@ -171,7 +181,7 @@ def get_public_ip():
|
|||||||
|
|
||||||
def get_default_route():
|
def get_default_route():
|
||||||
"""Get the default route."""
|
"""Get the default route."""
|
||||||
cmd = ["/usr/bin/ip", "route", "show", "default"]
|
cmd = ["ip", "route", "get", "1.1.1.1"]
|
||||||
result = run(cmd, stdout=PIPE, stderr=PIPE)
|
result = run(cmd, stdout=PIPE, stderr=PIPE)
|
||||||
try:
|
try:
|
||||||
# Get first line (might have multiple gateway routes)
|
# Get first line (might have multiple gateway routes)
|
||||||
@@ -197,21 +207,6 @@ def format_time(time: datetime) -> dict[str, str | int]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# system_bus = dbus.SystemBus()
|
|
||||||
# networkd = system_bus.get_object(
|
|
||||||
# "org.freedesktop.network1", "/org/freedesktop/network1"
|
|
||||||
# )
|
|
||||||
# manager = dbus.Interface(networkd, "org.freedesktop.network1.Manager")
|
|
||||||
|
|
||||||
|
|
||||||
# def get_dbus_interfaces():
|
|
||||||
# for iface in INTERFACES_TO_WATCH:
|
|
||||||
# dbus_object = system_bus.get_object(
|
|
||||||
# "org.freedesktop.network1", manager.GetLinkByName(iface)
|
|
||||||
# )
|
|
||||||
# dbus_interface = dbus.Interface(dbus_object, "org.freedesktop.network1.Link")
|
|
||||||
# yield dbus_interface
|
|
||||||
|
|
||||||
runtime_dir = os.environ.get("XDG_RUNTIME_DIR", "/tmp")
|
runtime_dir = os.environ.get("XDG_RUNTIME_DIR", "/tmp")
|
||||||
|
|
||||||
|
|
||||||
@@ -284,6 +279,12 @@ while True:
|
|||||||
|
|
||||||
default_route_iface_data = interface_status(default_route, gw)
|
default_route_iface_data = interface_status(default_route, gw)
|
||||||
|
|
||||||
|
ssid = get_ssid()
|
||||||
|
if ssid is None:
|
||||||
|
wifi_connected = False
|
||||||
|
else:
|
||||||
|
wifi_connected = True
|
||||||
|
|
||||||
print(
|
print(
|
||||||
json.dumps(
|
json.dumps(
|
||||||
{
|
{
|
||||||
@@ -297,6 +298,11 @@ while True:
|
|||||||
"have_default_route": default_route is not None,
|
"have_default_route": default_route is not None,
|
||||||
"gateway": str(hop),
|
"gateway": str(hop),
|
||||||
"have_gateway": hop is not None,
|
"have_gateway": hop is not None,
|
||||||
|
"wifi": {
|
||||||
|
"ssid": ssid,
|
||||||
|
"connected": wifi_connected,
|
||||||
|
"default": default_route == "wlan0",
|
||||||
|
},
|
||||||
"last_update": format_time(datetime.now()),
|
"last_update": format_time(datetime.now()),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import json
|
|
||||||
import sys
|
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
TRUSTED_NETWORKS = ['honnouji', 'honnouji_2.4']
|
|
||||||
|
|
||||||
def wifi():
|
|
||||||
ssid_cmd = subprocess.run(['iwgetid', '-r'], capture_output = True)
|
|
||||||
if ssid_cmd.returncode != 0:
|
|
||||||
return {"connected": False, "ssid": None}
|
|
||||||
return {"connected": True, "ssid": ssid_cmd.stdout.decode('utf-8').strip()}
|
|
||||||
|
|
||||||
def netdev(device: str):
|
|
||||||
ip_cmd = subprocess.run(['ip', '-j', 'addr', 'show', device], capture_output = True)
|
|
||||||
if ip_cmd.returncode != 0:
|
|
||||||
sys.stderr.write(ip_cmd.stdout.decode('utf-8'))
|
|
||||||
return {"exists": False, "online": False}
|
|
||||||
ip_data = json.loads(ip_cmd.stdout.decode('utf-8'))[0]
|
|
||||||
ip4_addr = ""
|
|
||||||
ip4_prefix_length = 24
|
|
||||||
addr4_info = list(filter(lambda addr: addr.get("family") == "inet", ip_data["addr_info"]))
|
|
||||||
if len(addr4_info) >= 1:
|
|
||||||
ip4_addr = addr4_info[0]["local"]
|
|
||||||
ip4_prefix_length = addr4_info[0]["prefixlen"]
|
|
||||||
online = ip_data["operstate"] == "UP" or ip4_addr != ""
|
|
||||||
connecting = ip_data["operstate"] != "DOWN" and (ip4_addr == "" or not online)
|
|
||||||
return {
|
|
||||||
"exists": True,
|
|
||||||
"online": online,
|
|
||||||
"connecting": connecting,
|
|
||||||
"offline": not online and not connecting,
|
|
||||||
"ip4_addr": ip4_addr,
|
|
||||||
"ip4_prefix": ip4_prefix_length
|
|
||||||
}
|
|
||||||
|
|
||||||
def trusted(ssid: str | None):
|
|
||||||
# Don't throw up an "INSECURE" alert when offline
|
|
||||||
if not ssid:
|
|
||||||
return True
|
|
||||||
return ssid in TRUSTED_NETWORKS
|
|
||||||
|
|
||||||
while True:
|
|
||||||
insight = netdev('insight')
|
|
||||||
wlan0 = netdev('wlan0')
|
|
||||||
wifi_data = wifi()
|
|
||||||
connected = insight['exists'] and insight['online'] or wifi_data['connected']
|
|
||||||
networks = {
|
|
||||||
"insight": insight,
|
|
||||||
"wlan0": netdev("wlan0"),
|
|
||||||
"ezrinet": netdev("ezrinet"),
|
|
||||||
"wg-mullvad": netdev("wg-mullvad"),
|
|
||||||
}
|
|
||||||
result = {
|
|
||||||
'connected': connected,
|
|
||||||
"network": networks,
|
|
||||||
'wifi': wifi_data,
|
|
||||||
"trusted": True,
|
|
||||||
"ip4_addrs": [ network.get('ip4_addr') for network in networks.values() if network.get('ip4_addr', "") != "" ]
|
|
||||||
}
|
|
||||||
print(json.dumps(result), flush=True)
|
|
||||||
sleep(1)
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import json
|
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
TRUSTED_NETWORKS = ['gayer people']
|
|
||||||
|
|
||||||
def wifi():
|
|
||||||
ssid_cmd = subprocess.run(['iwgetid', '-r'], capture_output = True)
|
|
||||||
if ssid_cmd.returncode != 0:
|
|
||||||
return {"connected": False, "ssid": None}
|
|
||||||
ssid = ssid_cmd.stdout.decode('utf-8').strip()
|
|
||||||
ssid = ssid if len(ssid) <= 15 else f"{ssid[:14]}…"
|
|
||||||
return {"connected": True, "ssid": ssid}
|
|
||||||
|
|
||||||
def netdev(device: str):
|
|
||||||
ip_cmd = subprocess.run(['ip', '-j', 'addr', 'show', device], capture_output = True)
|
|
||||||
if ip_cmd.returncode != 0:
|
|
||||||
return {"exists": False}
|
|
||||||
ip_data = json.loads(ip_cmd.stdout.decode('utf-8'))[0]
|
|
||||||
online = ip_data["operstate"] == "UP"
|
|
||||||
ip4_addr = ""
|
|
||||||
ip4_prefix_length = 24
|
|
||||||
addr4_info = list(filter(lambda addr: addr.get("family") == "inet", ip_data["addr_info"]))
|
|
||||||
if len(addr4_info) >= 1:
|
|
||||||
ip4_addr = addr4_info[0]["local"]
|
|
||||||
ip4_prefix_length = addr4_info[0]["prefixlen"]
|
|
||||||
connecting = ip_data["operstate"] != "DOWN" and (ip4_addr == "" or not online)
|
|
||||||
return {
|
|
||||||
"exists": True,
|
|
||||||
"online": online,
|
|
||||||
"connecting": connecting,
|
|
||||||
"offline": not online and not connecting,
|
|
||||||
"ip4_addr": ip4_addr,
|
|
||||||
"ip4_prefix": ip4_prefix_length
|
|
||||||
}
|
|
||||||
|
|
||||||
def trusted(ssid: str | None):
|
|
||||||
# Don't throw up an "INSECURE" alert when offline
|
|
||||||
if not ssid:
|
|
||||||
return True
|
|
||||||
return ssid in TRUSTED_NETWORKS
|
|
||||||
|
|
||||||
def ping(host: str):
|
|
||||||
ping_cmd = subprocess.Popen(['/usr/bin/ping', '-c1', '-W2', host], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
||||||
return ping_cmd
|
|
||||||
|
|
||||||
counter = 0
|
|
||||||
ezrinet_last = False
|
|
||||||
internet_last = False
|
|
||||||
ezrinet_ping = None
|
|
||||||
internet_ping = None
|
|
||||||
|
|
||||||
while True:
|
|
||||||
if counter == 0:
|
|
||||||
ezrinet_ping = ping('10.242.3.1')
|
|
||||||
internet_ping = ping('1.1.1.1')
|
|
||||||
if ezrinet_ping.poll() is not None:
|
|
||||||
ezrinet_last = ezrinet_ping.returncode == 0
|
|
||||||
if internet_ping.poll() is not None:
|
|
||||||
internet_last = internet_ping.returncode == 0
|
|
||||||
wifi_data = wifi()
|
|
||||||
result = {
|
|
||||||
"wifi": wifi_data,
|
|
||||||
"network": {
|
|
||||||
"wlan0": netdev("wlan0"),
|
|
||||||
"ezrinet": netdev("ezrinet"),
|
|
||||||
"wg-mullvad": netdev("mullvad"),
|
|
||||||
},
|
|
||||||
"connection": {
|
|
||||||
"ezrinet": ezrinet_last,
|
|
||||||
"internet": internet_last
|
|
||||||
},
|
|
||||||
"trusted": trusted(wifi_data.get("ssid", None))
|
|
||||||
}
|
|
||||||
print(json.dumps(result), flush=True)
|
|
||||||
counter += 1
|
|
||||||
# Send pings every 10 seconds
|
|
||||||
counter %= 3
|
|
||||||
sleep(1)
|
|
||||||
397
.config/eww/scripts/network2.py
Executable file
397
.config/eww/scripts/network2.py
Executable file
@@ -0,0 +1,397 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Asynchronous network monitoring script, reports current state every 5 seconds."""
|
||||||
|
|
||||||
|
from ipaddress import (
|
||||||
|
IPv4Address as IPAddress,
|
||||||
|
IPv4Network as IPNetwork,
|
||||||
|
IPv4Interface as IPInterface,
|
||||||
|
AddressValueError,
|
||||||
|
)
|
||||||
|
from dbus_fast.aio import MessageBus
|
||||||
|
from dbus_fast import Variant, BusType
|
||||||
|
import re
|
||||||
|
import asyncio
|
||||||
|
from subprocess import PIPE
|
||||||
|
import functools
|
||||||
|
import sys
|
||||||
|
from typing import Any, Self, Callable, Awaitable
|
||||||
|
import aiohttp
|
||||||
|
import datetime
|
||||||
|
import json
|
||||||
|
import socket
|
||||||
|
from vpn_manager.api.manager import VPNManager, VPNConnection
|
||||||
|
|
||||||
|
|
||||||
|
class PingableIPAddress(IPAddress):
|
||||||
|
"""IPv4 address with a ping function."""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs) -> None:
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.reachable: bool | None = None
|
||||||
|
|
||||||
|
async def ping(self) -> tuple[bool, float | None]:
|
||||||
|
"""
|
||||||
|
Ping this IP address.
|
||||||
|
|
||||||
|
Returns a tuple of [success, ping time in ms]
|
||||||
|
"""
|
||||||
|
proc = await asyncio.create_subprocess_exec(
|
||||||
|
"ping", "-c1", "-w1", "-n", str(self), stdout=PIPE
|
||||||
|
)
|
||||||
|
stdout, stderr = await proc.communicate()
|
||||||
|
|
||||||
|
_match = re.search(
|
||||||
|
r"icmp_seq=1 ttl=[0-9]+ time=([0-9]+\.?[0-9]*) ms", stdout.decode("utf-8")
|
||||||
|
)
|
||||||
|
if _match is None:
|
||||||
|
self.reachable = False
|
||||||
|
return (False, None)
|
||||||
|
else:
|
||||||
|
self.reachable = True
|
||||||
|
return (True, float(_match.group(1)))
|
||||||
|
|
||||||
|
|
||||||
|
class Netdata:
|
||||||
|
"""Container for netdata."""
|
||||||
|
|
||||||
|
monitor_ips = {
|
||||||
|
"ezrinet": PingableIPAddress("10.242.3.1"),
|
||||||
|
"internet": PingableIPAddress("1.1.1.1"),
|
||||||
|
}
|
||||||
|
|
||||||
|
ssids: list[str] | None = None
|
||||||
|
public_ip: IPAddress | None = None
|
||||||
|
public_ip_meta: dict[str, str] | None = None
|
||||||
|
last_ip_pull = datetime.datetime.fromtimestamp(0)
|
||||||
|
|
||||||
|
gateway: PingableIPAddress | None = None
|
||||||
|
route_on: str | None = None
|
||||||
|
net_state: str | None = None
|
||||||
|
|
||||||
|
vpns: dict[str, bool] = {}
|
||||||
|
|
||||||
|
interfaces: dict[str, Any] = {}
|
||||||
|
|
||||||
|
|
||||||
|
INTERFACE_IGNORE_PATTERN = re.compile(r"^vb-|^vz-|^virbr[0-9]+|^lo$")
|
||||||
|
|
||||||
|
[
|
||||||
|
re.compile(r"^vb-"),
|
||||||
|
re.compile(r"^vz-"),
|
||||||
|
re.compile(r"^virbr[0-9]+"),
|
||||||
|
re.compile(r"^lo$"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def timer(interval: float, initial_delay: float = 0):
|
||||||
|
"""Decorate a function or coroutine to run it on the given interval."""
|
||||||
|
|
||||||
|
def decorator(func):
|
||||||
|
|
||||||
|
async def do_interval():
|
||||||
|
try:
|
||||||
|
await asyncio.sleep(initial_delay)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
await func()
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
await asyncio.sleep(interval)
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
return
|
||||||
|
|
||||||
|
def start():
|
||||||
|
loop = asyncio.get_running_loop()
|
||||||
|
if "_timer_task" in func.__dict__:
|
||||||
|
raise Exception("Timer is already running.")
|
||||||
|
func.__dict__["_timer_task"] = loop.create_task(do_interval())
|
||||||
|
|
||||||
|
func.__dict__["start"] = start
|
||||||
|
return func
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
async def ping(address: IPAddress) -> tuple[bool, float | None]:
|
||||||
|
"""Ping a host and return a tuple of [success, ping time]."""
|
||||||
|
proc = await asyncio.create_subprocess_exec(
|
||||||
|
"ping", "-c1", "-w1", "-n", str(address), stdout=PIPE
|
||||||
|
)
|
||||||
|
stdout, stderr = await proc.communicate()
|
||||||
|
|
||||||
|
_match = re.search(
|
||||||
|
r"icmp_seq=1 ttl=[0-9]+ time=([0-9]+\.?[0-9]*) ms", stdout.decode("utf-8")
|
||||||
|
)
|
||||||
|
if _match is None:
|
||||||
|
return (False, None)
|
||||||
|
else:
|
||||||
|
return (True, float(_match.group(1)))
|
||||||
|
|
||||||
|
|
||||||
|
class Poller:
|
||||||
|
"""Poller."""
|
||||||
|
|
||||||
|
def __init__(self, freq: int, startup_delay: int = 0):
|
||||||
|
self._freq = freq
|
||||||
|
self._startup_delay = startup_delay
|
||||||
|
self._coros = []
|
||||||
|
self._task: asyncio.Task | None = None
|
||||||
|
self._after_poll = lambda context: None
|
||||||
|
self._setup = lambda context: None
|
||||||
|
self._context: dict[str, Any] = {}
|
||||||
|
|
||||||
|
def poll(
|
||||||
|
self, func: Callable[[asyncio.TaskGroup, dict[str, Any]], Awaitable[None]]
|
||||||
|
) -> Callable[[asyncio.TaskGroup], Awaitable[None]]:
|
||||||
|
"""Decorate a coroutine function to be polled."""
|
||||||
|
|
||||||
|
# suppress the exceptions, logging them but otherwise ignoring them.
|
||||||
|
async def suppressor(*args):
|
||||||
|
try:
|
||||||
|
await func(*args)
|
||||||
|
except (KeyboardInterrupt, SystemExit, asyncio.CancelledError):
|
||||||
|
print(
|
||||||
|
f"Poller {func.__name__} cancelled or aborted.",
|
||||||
|
file=sys.stderr,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
except BaseException as e:
|
||||||
|
print(
|
||||||
|
f"Poller {func.__name__} raised an exception:",
|
||||||
|
e,
|
||||||
|
file=sys.stderr,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
self._coros.append(suppressor)
|
||||||
|
|
||||||
|
def after_poll(
|
||||||
|
self, func: Callable[[dict[str, Any]], None]
|
||||||
|
) -> Callable[[dict[str, Any]], None]:
|
||||||
|
"""
|
||||||
|
Decorate a function to run after each poll cycle (after all pollers are done).
|
||||||
|
|
||||||
|
Should not be a coroutine function, and should not execute any blocking I/O or long-running
|
||||||
|
tasks.
|
||||||
|
"""
|
||||||
|
self._after_poll = func
|
||||||
|
return func
|
||||||
|
|
||||||
|
def setup(
|
||||||
|
self, func: Callable[[dict[str, Any]], None]
|
||||||
|
) -> Callable[[dict[str, Any]], None]:
|
||||||
|
"""
|
||||||
|
Decorate a function to run before the poll cycle starts to set up the context.
|
||||||
|
|
||||||
|
This can be a coroutine.
|
||||||
|
"""
|
||||||
|
self._setup = func
|
||||||
|
return func
|
||||||
|
|
||||||
|
async def start(self):
|
||||||
|
"""Execute polling in a loop."""
|
||||||
|
try:
|
||||||
|
await asyncio.sleep(self._startup_delay)
|
||||||
|
if asyncio.iscoroutinefunction(self._setup):
|
||||||
|
await self._setup(self._context)
|
||||||
|
else:
|
||||||
|
self._setup(self._context)
|
||||||
|
while True:
|
||||||
|
start = datetime.datetime.now()
|
||||||
|
try:
|
||||||
|
async with asyncio.timeout(self._freq):
|
||||||
|
async with asyncio.TaskGroup() as tg:
|
||||||
|
for coro in self._coros:
|
||||||
|
tg.create_task(coro(tg, self._context))
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
print(
|
||||||
|
"Warning: poll took too long! Not all data will be updated!",
|
||||||
|
file=sys.stderr,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
self._after_poll(self._context)
|
||||||
|
end = datetime.datetime.now()
|
||||||
|
await asyncio.sleep(self._freq - (start - end).total_seconds())
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
mainloop = Poller(5)
|
||||||
|
|
||||||
|
|
||||||
|
@mainloop.poll
|
||||||
|
async def ping_checks(tg: asyncio.TaskGroup, context: dict[str, Any]):
|
||||||
|
"""Recurring ping checks for configured IP addresses."""
|
||||||
|
for ip in Netdata.monitor_ips.values():
|
||||||
|
tg.create_task(ip.ping())
|
||||||
|
|
||||||
|
|
||||||
|
@mainloop.poll
|
||||||
|
async def firsthop_check(tg: asyncio.TaskGroup, context: dict[str, Any]):
|
||||||
|
"""Recurring firsthop check."""
|
||||||
|
# Targeted IP doesn't matter, since TTL is 1
|
||||||
|
proc = await asyncio.create_subprocess_exec(
|
||||||
|
"ping", "-c1", "-W1", "-t1", "1.1.1.1", stdout=PIPE
|
||||||
|
)
|
||||||
|
stdout, stderr = await proc.communicate()
|
||||||
|
try:
|
||||||
|
ip = IPAddress(stdout.decode("utf-8").split("\n")[1].split()[1])
|
||||||
|
Netdata.gateway = ip
|
||||||
|
except (IndexError, AddressValueError):
|
||||||
|
# No firsthop
|
||||||
|
Netdata.gateway = None
|
||||||
|
|
||||||
|
|
||||||
|
@mainloop.poll
|
||||||
|
async def route_check(tg: asyncio.TaskGroup, context: dict[str, Any]):
|
||||||
|
"""Recurring route check."""
|
||||||
|
proc = await asyncio.create_subprocess_exec(
|
||||||
|
"ip", "route", "show", "default", stdout=PIPE
|
||||||
|
)
|
||||||
|
stdout, stderr = await proc.communicate()
|
||||||
|
try:
|
||||||
|
# First line
|
||||||
|
line = stdout.decode("utf-8").splitlines()[0]
|
||||||
|
# Get the link name
|
||||||
|
link = re.search(r"dev\s+(\S+)", line).group(1)
|
||||||
|
Netdata.route_on = link
|
||||||
|
except:
|
||||||
|
Netdata.route_on = None
|
||||||
|
|
||||||
|
|
||||||
|
@mainloop.poll
|
||||||
|
async def public_ip(tg: asyncio.TaskGroup, context: dict[str, Any]):
|
||||||
|
"""Recurring public IP retriever."""
|
||||||
|
# Only query for public IP if it's been at least 1 hour since the last query or our gateway has changed.
|
||||||
|
refresh = False
|
||||||
|
if Netdata.public_ip is None:
|
||||||
|
refresh = True
|
||||||
|
print("no public IP data, fetching", file=sys.stderr, flush=True)
|
||||||
|
if context.get("last_gateway") != Netdata.gateway:
|
||||||
|
refresh = True
|
||||||
|
print("gateway changed, refreshing public IP", file=sys.stderr, flush=True)
|
||||||
|
if Netdata.last_ip_pull < datetime.datetime.now() - datetime.timedelta(hours=1):
|
||||||
|
refresh = True
|
||||||
|
print(
|
||||||
|
f"last public IP pull was at {Netdata.last_ip_pull.isoformat()}, refreshing",
|
||||||
|
file=sys.stderr,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
if refresh:
|
||||||
|
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get("https://ipinfo.io/json") as response:
|
||||||
|
data: dict[str, str] = await response.json()
|
||||||
|
Netdata.public_ip_meta = data
|
||||||
|
Netdata.public_ip = IPAddress(data["ip"])
|
||||||
|
Netdata.last_ip_pull = datetime.datetime.now()
|
||||||
|
context["last_gateway"] = Netdata.gateway
|
||||||
|
|
||||||
|
|
||||||
|
@mainloop.setup
|
||||||
|
async def setup_dbus(context: dict[str, Any]) -> MessageBus:
|
||||||
|
"""Set up the D-Bus connections."""
|
||||||
|
bus = await MessageBus(bus_type=BusType.SYSTEM).connect()
|
||||||
|
context["system_bus"] = bus
|
||||||
|
intro = await bus.introspect(
|
||||||
|
"org.freedesktop.network1", "/org/freedesktop/network1"
|
||||||
|
)
|
||||||
|
context["network_manager"] = bus.get_proxy_object(
|
||||||
|
"org.freedesktop.network1", "/org/freedesktop/network1", intro
|
||||||
|
)
|
||||||
|
context["network_manager_iface"] = context["network_manager"].get_interface(
|
||||||
|
"org.freedesktop.network1.Manager"
|
||||||
|
)
|
||||||
|
context["network_manager_props"] = context["network_manager"].get_interface(
|
||||||
|
"org.freedesktop.DBus.Properties"
|
||||||
|
)
|
||||||
|
context["vpn_manager"] = VPNManager(allow_interactive_authorization=True, bus=bus)
|
||||||
|
|
||||||
|
|
||||||
|
@mainloop.poll
|
||||||
|
async def global_netstate(tg: asyncio.TaskGroup, context: dict[str, Any]):
|
||||||
|
"""Recurring global netstate retriever."""
|
||||||
|
manager = context["network_manager_iface"]
|
||||||
|
Netdata.net_state = await manager.get_operational_state()
|
||||||
|
|
||||||
|
|
||||||
|
@mainloop.poll
|
||||||
|
async def interface_status(tg: asyncio.TaskGroup, context: dict[str, Any]):
|
||||||
|
"""Recurring interface stats generator."""
|
||||||
|
# Set up D-Bus connection if it's not there already
|
||||||
|
bus: MessageBus = context["system_bus"]
|
||||||
|
manager = context["network_manager_iface"]
|
||||||
|
descr = json.loads(await manager.call_describe())
|
||||||
|
ifaces = [
|
||||||
|
{
|
||||||
|
**iface,
|
||||||
|
"Addresses": [
|
||||||
|
IPInterface(
|
||||||
|
f"{'.'.join(str(octet) for octet in addr['Address'])}/{addr['PrefixLength']}"
|
||||||
|
)
|
||||||
|
for addr in iface.get("Addresses", [])
|
||||||
|
if addr["Family"] == socket.AF_INET
|
||||||
|
],
|
||||||
|
}
|
||||||
|
for iface in descr["Interfaces"]
|
||||||
|
if not INTERFACE_IGNORE_PATTERN.match(iface["Name"])
|
||||||
|
]
|
||||||
|
wlans = [iface for iface in ifaces if iface["Type"] == "wlan"]
|
||||||
|
Netdata.ssids = [wlan["SSID"] for wlan in wlans if "SSID" in wlan]
|
||||||
|
Netdata.interfaces = {
|
||||||
|
iface["Name"]: {
|
||||||
|
"type": iface["Type"],
|
||||||
|
"state": iface["OnlineState"],
|
||||||
|
"addresses": [str(addr) for addr in iface["Addresses"]],
|
||||||
|
}
|
||||||
|
for iface in ifaces
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def get_vpn_conn(conn: VPNConnection):
|
||||||
|
"""Populate data for a VPN connection."""
|
||||||
|
Netdata.vpns[conn._name] = await conn.is_connected()
|
||||||
|
|
||||||
|
|
||||||
|
@mainloop.poll
|
||||||
|
async def vpn_status(tg: asyncio.TaskGroup, context: dict[str, Any]):
|
||||||
|
"""Recurring VPN stats generator."""
|
||||||
|
manager: VPNManager = context["vpn_manager"]
|
||||||
|
connections = await manager.get_connections()
|
||||||
|
Netdata.vpns = {}
|
||||||
|
for connection in connections:
|
||||||
|
tg.create_task(get_vpn_conn(connection))
|
||||||
|
|
||||||
|
|
||||||
|
@mainloop.after_poll
|
||||||
|
def output_data(context: dict[str, Any]):
|
||||||
|
"""Print the data to stdout."""
|
||||||
|
routable = False
|
||||||
|
for iface in Netdata.interfaces.values():
|
||||||
|
if iface["type"] in {"wlan", "ether"} and iface["state"] == "online":
|
||||||
|
routable = True
|
||||||
|
break
|
||||||
|
json.dump(
|
||||||
|
{
|
||||||
|
"routable": routable,
|
||||||
|
"ssids": Netdata.ssids,
|
||||||
|
"ping_status": {
|
||||||
|
key: value.reachable for key, value in Netdata.monitor_ips.items()
|
||||||
|
},
|
||||||
|
"gateway": str(Netdata.gateway) if Netdata.gateway else None,
|
||||||
|
"route_on": Netdata.route_on,
|
||||||
|
"public_ip": Netdata.public_ip_meta,
|
||||||
|
"operational_state": Netdata.net_state,
|
||||||
|
"vpn_state": Netdata.vpns,
|
||||||
|
"interfaces": Netdata.interfaces,
|
||||||
|
},
|
||||||
|
sys.stdout,
|
||||||
|
)
|
||||||
|
sys.stdout.write("\n")
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(mainloop.start())
|
||||||
93
.config/eww/scripts/polkitagent.py
Executable file
93
.config/eww/scripts/polkitagent.py
Executable file
@@ -0,0 +1,93 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""Polkit agent."""
|
||||||
|
import json
|
||||||
|
import gi
|
||||||
|
from gi.repository import Gtk, GLib, Gdk
|
||||||
|
from gi.events import GLibEventLoopPolicy
|
||||||
|
import asyncio
|
||||||
|
from asyncio import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
policy = GLibEventLoopPolicy()
|
||||||
|
asyncio.set_event_loop_policy(policy)
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
|
|
||||||
|
class AuthHandler(Gtk.Application):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(application_id="dev.ezri.PolkitAuthHandler")
|
||||||
|
GLib.set_application_name("Polkit Auth Handler")
|
||||||
|
sasscmd = loop.run_until_complete(
|
||||||
|
asyncio.create_subprocess_shell(
|
||||||
|
"sass ~/.config/eww/eww.scss -I ~/.config/eww", stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
css = loop.run_until_complete(sasscmd.stdout.read())
|
||||||
|
self.style_provider = Gtk.CssProvider()
|
||||||
|
self.style_provider.load_from_string(css.decode("utf-8"))
|
||||||
|
Gtk.StyleContext.add_provider_for_display(
|
||||||
|
Gdk.Display.get_default(),
|
||||||
|
self.style_provider,
|
||||||
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def handle_input(self):
|
||||||
|
reader = asyncio.StreamReader()
|
||||||
|
protocol = asyncio.StreamReaderProtocol(reader)
|
||||||
|
await loop.connect_read_pipe(lambda: protocol, sys.stdin)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
line = await reader.readline()
|
||||||
|
except:
|
||||||
|
break
|
||||||
|
decoded = json.loads(line.decode("utf-8"))
|
||||||
|
if decoded["action"] == "request password":
|
||||||
|
self.message_label.set_label(
|
||||||
|
decoded.get("polkit action", decoded)["message"]
|
||||||
|
)
|
||||||
|
self.prompt_label.set_label(decoded.get("prompt", "Password:"))
|
||||||
|
self.password_field.set_editable(True)
|
||||||
|
elif decoded["action"] == "authorization response":
|
||||||
|
if decoded["authorized"]:
|
||||||
|
break
|
||||||
|
|
||||||
|
def send_response(self, password_field):
|
||||||
|
password_field.set_editable(False)
|
||||||
|
password = password_field.get_text()
|
||||||
|
print(json.dumps({"action": "authenticate", "password": password}), flush=True)
|
||||||
|
|
||||||
|
def do_activate(self):
|
||||||
|
window = Gtk.ApplicationWindow(
|
||||||
|
application=self,
|
||||||
|
title="Password prompt",
|
||||||
|
css_classes=["root", "darkbg"],
|
||||||
|
default_width=600,
|
||||||
|
default_height=350,
|
||||||
|
)
|
||||||
|
# window.get_style_context().add_provider(self.style_provider, 801)
|
||||||
|
box = Gtk.Box(
|
||||||
|
spacing=20, homogeneous=False, orientation=Gtk.Orientation.VERTICAL
|
||||||
|
)
|
||||||
|
window.set_child(box)
|
||||||
|
box.append(
|
||||||
|
Gtk.Label(label="Authentication Required", css_classes=["nebula", "big"])
|
||||||
|
)
|
||||||
|
self.message_label = Gtk.Label(css_classes=["paragraph"])
|
||||||
|
box.append(self.message_label)
|
||||||
|
pwbox = Gtk.Box(
|
||||||
|
spacing=5, homogeneous=False, orientation=Gtk.Orientation.HORIZONTAL
|
||||||
|
)
|
||||||
|
self.prompt_label = Gtk.Label()
|
||||||
|
pwbox.append(self.prompt_label)
|
||||||
|
self.password_field = Gtk.PasswordEntry(hexpand=True)
|
||||||
|
pwbox.append(self.password_field)
|
||||||
|
self.password_field.connect("activate", self.send_response)
|
||||||
|
box.append(pwbox)
|
||||||
|
window.present()
|
||||||
|
loop.create_task(self.handle_input())
|
||||||
|
|
||||||
|
|
||||||
|
app = AuthHandler()
|
||||||
|
exit_status = app.run()
|
||||||
|
sys.exit(exit_status)
|
||||||
@@ -100,7 +100,7 @@ while True:
|
|||||||
"sensors": {chip: sensor(chip) for chip in sensor_list},
|
"sensors": {chip: sensor(chip) for chip in sensor_list},
|
||||||
"memory": memory(),
|
"memory": memory(),
|
||||||
"swap": swap(),
|
"swap": swap(),
|
||||||
"reboot": reboot(),
|
# "reboot": reboot(),
|
||||||
"hostname": machine_info.get("PRETTY_HOSTNAME"),
|
"hostname": machine_info.get("PRETTY_HOSTNAME"),
|
||||||
}
|
}
|
||||||
print(json.dumps(result), flush=True)
|
print(json.dumps(result), flush=True)
|
||||||
|
|||||||
@@ -1,56 +1,51 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
# This script prints the time remaining for the current timer
|
# Produces a mission timer based on the start time stored in the ~/.config/eww/timer.json file.
|
||||||
# as stored in the file ~/.timer as a binary unix timestamp.
|
# This file should have an object with three fields: "start", containing the start time as an integer
|
||||||
|
# Unix timestamp in second resolution, "title", containing the title to be presented beneath the timer,
|
||||||
|
# and "prefix", containing a string to render in front of the timer (such as "MET")
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import datetime
|
import datetime
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import asyncio
|
||||||
|
from asyncinotify import Inotify, Mask
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
# Get the time stored in the file ~/.timer
|
|
||||||
try:
|
|
||||||
with open("/home/ezri/.timer", "br") as f:
|
|
||||||
timer = f.read()
|
|
||||||
except FileNotFoundError:
|
|
||||||
print("It's Time!", flush=True)
|
|
||||||
exit()
|
|
||||||
|
|
||||||
# Convert the binary unix timestamp to a datetime object
|
def refresh_timer():
|
||||||
timer = datetime.datetime.fromtimestamp(int.from_bytes(timer, "big"))
|
"""Reload the timer."""
|
||||||
|
|
||||||
while True:
|
timer_file = Path("~/.config/eww/timer.json")
|
||||||
# Get the current time
|
if timer_file.exists() and timer_file.is_file():
|
||||||
now = datetime.datetime.now()
|
with timer_file.open("r") as f:
|
||||||
|
return json.load(f)
|
||||||
|
return None
|
||||||
|
|
||||||
# Calculate the time remaining
|
|
||||||
remaining = timer - now
|
|
||||||
|
|
||||||
# If the timer has already expired, delete the file and exit
|
timer = refresh_timer()
|
||||||
if remaining.total_seconds() <= 0:
|
|
||||||
import os
|
|
||||||
|
|
||||||
os.remove("/home/ezri/.timer")
|
|
||||||
print("Timer expired.")
|
|
||||||
|
|
||||||
# Print the time remaining in the format "D days, HH:MM:SS"
|
async def main():
|
||||||
if remaining.days == 0:
|
"""Print loop."""
|
||||||
print(
|
asyncio.ensure_future(asyncio.create_task(monitor()))
|
||||||
"{} hours {:02d}:{:02d}".format(
|
while True:
|
||||||
remaining.seconds // 3600,
|
if timer is None:
|
||||||
remaining.seconds % 3600 // 60,
|
json.dump({"active": False}, sys.stdout)
|
||||||
remaining.seconds % 60,
|
else:
|
||||||
),
|
start = timer.get("start", 0)
|
||||||
flush=True,
|
now = datetime.datetime.now()
|
||||||
)
|
if now < start:
|
||||||
else:
|
started = True
|
||||||
print(
|
else:
|
||||||
"{} days, {:02d}:{:02d}:{:02d}".format(
|
started = False
|
||||||
remaining.days,
|
json.dump(
|
||||||
remaining.seconds // 3600,
|
{
|
||||||
remaining.seconds % 3600 // 60,
|
"active": True,
|
||||||
remaining.seconds % 60,
|
"stamp": timer.get("start", 0),
|
||||||
),
|
"title": timer.get("title", "timer"),
|
||||||
flush=True,
|
"prefix": timer.get("prefix", "MET"),
|
||||||
)
|
},
|
||||||
|
sys.stdout,
|
||||||
# Wait half a second before printing the time again
|
)
|
||||||
time.sleep(1)
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import json
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
async def get_values(pulse):
|
async def get_values(pulse):
|
||||||
sink = None
|
sink = None
|
||||||
try:
|
try:
|
||||||
@@ -18,27 +19,27 @@ async def get_values(pulse):
|
|||||||
os.execv(sys.argv[0], sys.argv)
|
os.execv(sys.argv[0], sys.argv)
|
||||||
sink_result = {
|
sink_result = {
|
||||||
"mute": sink.mute == 1,
|
"mute": sink.mute == 1,
|
||||||
"volume": f"{int(sink.volume.value_flat * 100):2}"
|
"volume": int(sink.volume.value_flat * 100 + 0.5),
|
||||||
}
|
}
|
||||||
source_result = {
|
source_result = {
|
||||||
"mute": source.mute == 1,
|
"mute": source.mute == 1,
|
||||||
"volume": f"{int(source.volume.value_flat * 100):2}"
|
"volume": int(source.volume.value_flat * 100 + 0.5),
|
||||||
}
|
|
||||||
result = {
|
|
||||||
"output": sink_result,
|
|
||||||
"input": source_result
|
|
||||||
}
|
}
|
||||||
|
result = {"output": sink_result, "input": source_result}
|
||||||
print(json.dumps(result), flush=True)
|
print(json.dumps(result), flush=True)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
async def listen():
|
async def listen():
|
||||||
async with pulsectl_asyncio.PulseAsync("volume-monitor") as pulse:
|
async with pulsectl_asyncio.PulseAsync("volume-monitor") as pulse:
|
||||||
await get_values(pulse)
|
await get_values(pulse)
|
||||||
async for _ in pulse.subscribe_events('all'):
|
async for _ in pulse.subscribe_events("all"):
|
||||||
await get_values(pulse)
|
await get_values(pulse)
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
listen_task = asyncio.create_task(listen())
|
listen_task = asyncio.create_task(listen())
|
||||||
|
loop = asyncio.get_running_loop()
|
||||||
|
|
||||||
for sig in (signal.SIGTERM, signal.SIGHUP, signal.SIGINT):
|
for sig in (signal.SIGTERM, signal.SIGHUP, signal.SIGINT):
|
||||||
loop.add_signal_handler(sig, listen_task.cancel)
|
loop.add_signal_handler(sig, listen_task.cancel)
|
||||||
@@ -46,5 +47,5 @@ async def main():
|
|||||||
with suppress(asyncio.CancelledError):
|
with suppress(asyncio.CancelledError):
|
||||||
await listen_task
|
await listen_task
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
loop.run_until_complete(main())
|
asyncio.run(main())
|
||||||
|
|||||||
139
.config/eww/scripts/volume2.py
Executable file
139
.config/eww/scripts/volume2.py
Executable file
@@ -0,0 +1,139 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from gi import require_version
|
||||||
|
|
||||||
|
require_version("AstalWp", "0.1")
|
||||||
|
from gi.repository import AstalWp as Wp, Gio, GObject
|
||||||
|
from gi.events import GLibEventLoopPolicy
|
||||||
|
import json
|
||||||
|
import asyncio
|
||||||
|
import sys
|
||||||
|
from typing import Any, Literal
|
||||||
|
from enum import IntEnum
|
||||||
|
import signal
|
||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
class EndpointBinding:
|
||||||
|
"""Collection of connection IDs for an audio endpoint."""
|
||||||
|
|
||||||
|
def __init__(self, endpoint: Wp.Endpoint, callback):
|
||||||
|
self.callback = callback
|
||||||
|
self.volume_binding = endpoint.connect_after(
|
||||||
|
"notify::volume", self._volume_callback
|
||||||
|
)
|
||||||
|
self.mute_binding = endpoint.connect_after("notify::mute", callback)
|
||||||
|
self.id = endpoint.props.id
|
||||||
|
self.endpoint = endpoint
|
||||||
|
|
||||||
|
def hash(self) -> int:
|
||||||
|
return self.volume_binding + (self.mute_binding << 32)
|
||||||
|
|
||||||
|
def _volume_callback(self, endpoint, param):
|
||||||
|
if round(endpoint.props.volume * 100) > 100:
|
||||||
|
self.endpoint.set_volume(1)
|
||||||
|
else:
|
||||||
|
self.callback(endpoint, param)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
"""Object cleanup."""
|
||||||
|
self.endpoint.disconnect_by_func(self.callback)
|
||||||
|
self.endpoint.disconnect_by_func(self._volume_callback)
|
||||||
|
|
||||||
|
|
||||||
|
class AudioController(Gio.Application):
|
||||||
|
"""Audio controller application."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.wp = Wp.get_default()
|
||||||
|
self.bindings = dict[int, EndpointBinding]()
|
||||||
|
|
||||||
|
def do_activate(self):
|
||||||
|
self.wp.connect("ready", self._on_ready)
|
||||||
|
self.hold()
|
||||||
|
loop = asyncio.get_running_loop()
|
||||||
|
for sig in (signal.SIGTERM, signal.SIGHUP, signal.SIGINT):
|
||||||
|
loop.add_signal_handler(sig, self.release)
|
||||||
|
|
||||||
|
def _on_ready(self, wp: Wp.Wp):
|
||||||
|
self.audio = self.wp.get_audio()
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
# this is a set-default call, so lets do that.
|
||||||
|
self.set_default(sys.argv[1], " ".join(sys.argv[2:]))
|
||||||
|
else:
|
||||||
|
self.audio.connect("microphone-added", self._device_added)
|
||||||
|
self.audio.connect("speaker-added", self._device_added)
|
||||||
|
self.audio.connect("microphone-removed", self._device_removed)
|
||||||
|
self.audio.connect("speaker-removed", self._device_removed)
|
||||||
|
|
||||||
|
for mic in self.audio.props.microphones:
|
||||||
|
self.bindings[mic.props.id] = EndpointBinding(mic, self._dump_info)
|
||||||
|
for sink in self.audio.props.speakers:
|
||||||
|
self.bindings[sink.props.id] = EndpointBinding(sink, self._dump_info)
|
||||||
|
|
||||||
|
self._dump_info()
|
||||||
|
|
||||||
|
def set_default(self, dir: Literal["in"] | Literal["out"], description: str):
|
||||||
|
"""Set the default source or sink."""
|
||||||
|
if dir == "in":
|
||||||
|
arr: list[Wp.Endpoint] = self.audio.get_microphones()
|
||||||
|
else:
|
||||||
|
arr = self.audio.get_speakers()
|
||||||
|
|
||||||
|
for dev in arr:
|
||||||
|
if dev.get_description() == description:
|
||||||
|
dev.set_is_default(True)
|
||||||
|
break
|
||||||
|
|
||||||
|
self.release()
|
||||||
|
|
||||||
|
def _device_added(self, audio: Wp.Audio, device: Wp.Endpoint):
|
||||||
|
self.bindings[device.props.id] = EndpointBinding(device, self._dump_info)
|
||||||
|
self._dump_info()
|
||||||
|
|
||||||
|
def _device_removed(self, audio: Wp.Audio, device: Wp.Endpoint):
|
||||||
|
try:
|
||||||
|
del self.bindings[device.props.id]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
self._dump_info()
|
||||||
|
|
||||||
|
def _dump_info(self, *args):
|
||||||
|
asyncio.ensure_future(self._do_dump())
|
||||||
|
|
||||||
|
async def _do_dump(self):
|
||||||
|
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
|
||||||
|
json.dump(
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
mic.get_description() for mic in self.audio.get_microphones()
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
sink.get_description() for sink in self.audio.get_speakers()
|
||||||
|
],
|
||||||
|
"input": {
|
||||||
|
"volume": round(
|
||||||
|
self.audio.get_default_microphone().get_volume() * 100
|
||||||
|
),
|
||||||
|
"mute": self.audio.get_default_microphone().get_mute(),
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"volume": round(
|
||||||
|
self.audio.get_default_speaker().get_volume() * 100
|
||||||
|
),
|
||||||
|
"mute": self.audio.get_default_speaker().get_mute(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sys.stdout,
|
||||||
|
)
|
||||||
|
print()
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.set_event_loop_policy(GLibEventLoopPolicy())
|
||||||
|
app = AudioController()
|
||||||
|
app.run()
|
||||||
5
.config/eww/timer.json
Normal file
5
.config/eww/timer.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"title": "DW3",
|
||||||
|
"prefix": "expedition clock",
|
||||||
|
"start": 1768759200
|
||||||
|
}
|
||||||
@@ -2,6 +2,157 @@
|
|||||||
;; Top-Level Module Definitions ;;
|
;; Top-Level Module Definitions ;;
|
||||||
;;;; ;;;;
|
;;;; ;;;;
|
||||||
|
|
||||||
|
;;; ;;;
|
||||||
|
;; Generic Windows ;;
|
||||||
|
;;; ;;;
|
||||||
|
|
||||||
|
(defwidget system-sidebar [group side]
|
||||||
|
(box :orientation "v"
|
||||||
|
:valign "start"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "root ${side}-side ${sway--data.visible[group].focused ? 'focused' : ''}"
|
||||||
|
(sideclock)
|
||||||
|
(side-mission-clock)
|
||||||
|
(network-sidebar-details)
|
||||||
|
(system-gauges)
|
||||||
|
(volume-gauges)))
|
||||||
|
|
||||||
|
(defwidget user-sidebar [orientation]
|
||||||
|
(box :orientation "v"
|
||||||
|
:valign "start"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "root ${orientation}-side"
|
||||||
|
(sideclock)
|
||||||
|
(mpris-miniplayer)
|
||||||
|
(volume-gauges)))
|
||||||
|
|
||||||
|
(defwidget minigauges-bottomalign [battery]
|
||||||
|
(box :orientation "v"
|
||||||
|
:valign "end"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
(system--cpu-gauge-small)
|
||||||
|
(system--memory-gauge-small)
|
||||||
|
(system--swap-gauge-small)
|
||||||
|
(system--gpu-gauge-small)
|
||||||
|
(system--vram-gauge-small)
|
||||||
|
(volume-small-gauge)
|
||||||
|
(system-battery-gauge-small :battery {battery})))
|
||||||
|
|
||||||
|
|
||||||
|
(defwidget laptop-sidebar-top [group side]
|
||||||
|
(box :orientation "v"
|
||||||
|
:valign "start"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
:class "root ${side}-side ${sway--data.visible[group].focused ? 'focused' : ''}"
|
||||||
|
(sway-workspaces-vertical :group {group})))
|
||||||
|
|
||||||
|
(defwidget laptop-sidebar-bottom [group side battery]
|
||||||
|
(box :orientation "v"
|
||||||
|
:valign "start"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 10
|
||||||
|
:class "root ${side}-side ${sway--data.visible[group].focused ? 'focused' : ''}"
|
||||||
|
(minigauges-bottomalign :battery {battery})))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(defwidget ws-group-rightalign [workspace-group]
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "end"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "rightbox"
|
||||||
|
(sway-workspace :group {workspace-group})
|
||||||
|
(sway-workspaces :group {workspace-group})))
|
||||||
|
|
||||||
|
(defwidget ws-group-leftalign [workspace-group]
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "start"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "leftbox"
|
||||||
|
(sway-workspaces :group {workspace-group})
|
||||||
|
(sway-workspace :group {workspace-group})))
|
||||||
|
|
||||||
|
|
||||||
|
(defwidget desktop-details-rightalign []
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "end"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "rightbox"
|
||||||
|
(mpris2)
|
||||||
|
(mission-clock)
|
||||||
|
(vpn-network)
|
||||||
|
(network)
|
||||||
|
(wifi)
|
||||||
|
(system-memory)
|
||||||
|
(system-cpu-avg)
|
||||||
|
(clock)))
|
||||||
|
|
||||||
|
(defwidget hostname-centeralign []
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "center"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "centerbox"
|
||||||
|
(system-name)))
|
||||||
|
|
||||||
|
(defwidget hostname-leftalign []
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "start"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "leftbox"
|
||||||
|
(system-name)))
|
||||||
|
|
||||||
|
(defwidget hostname-rightalign []
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "end"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "rightbox"
|
||||||
|
(system-name)))
|
||||||
|
|
||||||
|
(defwidget hostname-and-workspace-leftalign [workspace-group]
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "start"
|
||||||
|
:valign "center"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "leftbox"
|
||||||
|
(transform :translate-y "-2px"
|
||||||
|
(system-name))
|
||||||
|
(sway-workspace :group {workspace-group})))
|
||||||
|
|
||||||
|
(defwidget laptop-details-rightalign [?battery]
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "end"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "rightbox"
|
||||||
|
(mpris2)
|
||||||
|
(vpn-network)
|
||||||
|
(network)
|
||||||
|
(wifi)
|
||||||
|
(clock)))
|
||||||
|
|
||||||
|
(defwidget horizontal-minigauges-rightalign []
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "end"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "rightbox"
|
||||||
|
(system--cpu-gauge-small :invert {false})
|
||||||
|
(system--memory-gauge-small :invert {false})
|
||||||
|
(system--swap-gauge-small :invert {false})
|
||||||
|
(system--gpu-gauge-small :invert {false})
|
||||||
|
(system--vram-gauge-small :invert {false})
|
||||||
|
(volume-small-gauge :invert {false})))
|
||||||
|
|
||||||
;;; ;;;
|
;;; ;;;
|
||||||
;; Bars for Rocinante ;;
|
;; Bars for Rocinante ;;
|
||||||
@@ -36,6 +187,32 @@
|
|||||||
(audio)
|
(audio)
|
||||||
(clock)))
|
(clock)))
|
||||||
|
|
||||||
|
(defwidget rocinante-externalbar--left []
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "start"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "leftbox"
|
||||||
|
(system-name)))
|
||||||
|
|
||||||
|
(defwidget rocinante-externalbar--center []
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "center"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "centerbox"))
|
||||||
|
|
||||||
|
(defwidget rocinante-externalbar--right []
|
||||||
|
(box :orientation "h"
|
||||||
|
:halign "end"
|
||||||
|
:space-evenly false
|
||||||
|
:spacing 20
|
||||||
|
:class "rightbox"
|
||||||
|
(vpn-network)
|
||||||
|
(network)
|
||||||
|
(system-battery :battery "BAT1")
|
||||||
|
(audio)
|
||||||
|
(clock)))
|
||||||
|
|
||||||
;;; ;;;
|
;;; ;;;
|
||||||
;; Bars for S.S.V. Normandy ;;
|
;; Bars for S.S.V. Normandy ;;
|
||||||
|
|||||||
3
.config/git/ignore
Normal file
3
.config/git/ignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Never include pycache directories or pyc files
|
||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Beware! This file is rewritten by htop when settings are changed in the interface.
|
# Beware! This file is rewritten by htop when settings are changed in the interface.
|
||||||
# The parser is also very primitive, and not human-friendly.
|
# The parser is also very primitive, and not human-friendly.
|
||||||
htop_version=3.3.0
|
htop_version=3.4.1-3.4.1
|
||||||
config_reader_min_version=3
|
config_reader_min_version=3
|
||||||
fields=0 48 17 18 38 39 40 2 46 47 49 1
|
fields=0 48 17 18 38 39 40 2 46 47 49 1
|
||||||
hide_kernel_threads=1
|
hide_kernel_threads=1
|
||||||
@@ -21,12 +21,13 @@ strip_exe_from_cmdline=1
|
|||||||
show_merged_command=0
|
show_merged_command=0
|
||||||
header_margin=1
|
header_margin=1
|
||||||
screen_tabs=1
|
screen_tabs=1
|
||||||
detailed_cpu_time=0
|
detailed_cpu_time=1
|
||||||
cpu_count_from_one=0
|
cpu_count_from_one=0
|
||||||
show_cpu_usage=1
|
show_cpu_usage=1
|
||||||
show_cpu_frequency=0
|
show_cpu_frequency=0
|
||||||
show_cpu_temperature=1
|
show_cpu_temperature=1
|
||||||
degree_fahrenheit=0
|
degree_fahrenheit=0
|
||||||
|
show_cached_memory=1
|
||||||
update_process_names=0
|
update_process_names=0
|
||||||
account_guest_in_cpu_meter=0
|
account_guest_in_cpu_meter=0
|
||||||
color_scheme=0
|
color_scheme=0
|
||||||
@@ -38,20 +39,20 @@ column_meters_0=Hostname Blank Tasks LoadAverage Uptime Clock
|
|||||||
column_meter_modes_0=2 2 2 2 2 2
|
column_meter_modes_0=2 2 2 2 2 2
|
||||||
column_meters_1=AllCPUs2 Blank MemorySwap
|
column_meters_1=AllCPUs2 Blank MemorySwap
|
||||||
column_meter_modes_1=1 2 1
|
column_meter_modes_1=1 2 1
|
||||||
tree_view=1
|
tree_view=0
|
||||||
sort_key=0
|
sort_key=46
|
||||||
tree_sort_key=0
|
tree_sort_key=46
|
||||||
sort_direction=1
|
sort_direction=-1
|
||||||
tree_sort_direction=1
|
tree_sort_direction=-1
|
||||||
tree_view_always_by_pid=0
|
tree_view_always_by_pid=0
|
||||||
all_branches_collapsed=0
|
all_branches_collapsed=0
|
||||||
screen:Main=PID USER PRIORITY NICE M_VIRT M_RESIDENT M_SHARE STATE PERCENT_CPU PERCENT_MEM TIME Command
|
screen:Main=PID USER PRIORITY NICE M_VIRT M_RESIDENT M_SHARE STATE PERCENT_CPU PERCENT_MEM TIME Command
|
||||||
.sort_key=PID
|
.sort_key=PERCENT_CPU
|
||||||
.tree_sort_key=PID
|
.tree_sort_key=PERCENT_CPU
|
||||||
.tree_view_always_by_pid=0
|
.tree_view_always_by_pid=0
|
||||||
.tree_view=1
|
.tree_view=0
|
||||||
.sort_direction=1
|
.sort_direction=-1
|
||||||
.tree_sort_direction=1
|
.tree_sort_direction=-1
|
||||||
.all_branches_collapsed=0
|
.all_branches_collapsed=0
|
||||||
screen:I/O=PID USER IO_PRIORITY IO_RATE IO_READ_RATE IO_WRITE_RATE PERCENT_SWAP_DELAY PERCENT_IO_DELAY Command
|
screen:I/O=PID USER IO_PRIORITY IO_RATE IO_READ_RATE IO_WRITE_RATE PERCENT_SWAP_DELAY PERCENT_IO_DELAY Command
|
||||||
.sort_key=IO_RATE
|
.sort_key=IO_RATE
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ certifi
|
|||||||
charset-normalizer
|
charset-normalizer
|
||||||
dbus-python
|
dbus-python
|
||||||
decorator
|
decorator
|
||||||
|
exceptiongroup
|
||||||
executing
|
executing
|
||||||
i3ipc
|
i3ipc
|
||||||
idna
|
idna
|
||||||
@@ -14,10 +15,13 @@ netifaces
|
|||||||
parso
|
parso
|
||||||
pexpect
|
pexpect
|
||||||
pickleshare
|
pickleshare
|
||||||
prompt-toolkit
|
prompt_toolkit
|
||||||
psutil
|
psutil
|
||||||
ptyprocess
|
ptyprocess
|
||||||
pure-eval
|
pulsectl
|
||||||
|
pulsectl-asyncio
|
||||||
|
pure_eval
|
||||||
|
pyamdgpuinfo
|
||||||
pycairo
|
pycairo
|
||||||
Pygments
|
Pygments
|
||||||
PyGObject
|
PyGObject
|
||||||
@@ -28,5 +32,6 @@ six
|
|||||||
stack-data
|
stack-data
|
||||||
traitlets
|
traitlets
|
||||||
trparse
|
trparse
|
||||||
|
typing_extensions
|
||||||
urllib3
|
urllib3
|
||||||
wcwidth
|
wcwidth
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
Host gitea
|
Host gitea
|
||||||
Hostname git.ezri.dev
|
Hostname git.ezri.dev
|
||||||
User git
|
User git
|
||||||
|
ControlPersist no
|
||||||
|
|
||||||
Host github
|
Host github
|
||||||
Hostname github.com
|
Hostname github.com
|
||||||
User git
|
User git
|
||||||
ControlPersist no
|
ControlPersist no
|
||||||
|
|||||||
@@ -22,17 +22,6 @@ set $colorprimary '#815986'
|
|||||||
set $colorbackground '#2d272f'
|
set $colorbackground '#2d272f'
|
||||||
set $colorwallpaper '#1e1e1e'
|
set $colorwallpaper '#1e1e1e'
|
||||||
|
|
||||||
## ##
|
|
||||||
# Configure displays and workspaces #
|
|
||||||
## ##
|
|
||||||
|
|
||||||
## Set Background
|
|
||||||
output * bg '#1e1e1e' solid_color
|
|
||||||
|
|
||||||
## Include Device-Specific Configs
|
|
||||||
#include display-arrangement.conf
|
|
||||||
#include workspace-arrangement.conf
|
|
||||||
|
|
||||||
### ###
|
### ###
|
||||||
# Window Management Keybinds #
|
# Window Management Keybinds #
|
||||||
### ###
|
### ###
|
||||||
@@ -75,6 +64,13 @@ bindsym {
|
|||||||
$mod+0 exec busctl --user call dev.ezri.sway /ContextManager dev.ezri.sway.ContextManager FocusWorkspace y 10
|
$mod+0 exec busctl --user call dev.ezri.sway /ContextManager dev.ezri.sway.ContextManager FocusWorkspace y 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindgesture {
|
||||||
|
swipe:3:left exec busctl --user call dev.ezri.sway /ContextManager dev.ezri.sway.ContextManager FocusNextWorkspace
|
||||||
|
swipe:4:left exec busctl --user call dev.ezri.sway /ContextManager dev.ezri.sway.ContextManager FocusNextWorkspace
|
||||||
|
swipe:3:right exec busctl --user call dev.ezri.sway /ContextManager dev.ezri.sway.ContextManager FocusPreviousWorkspace
|
||||||
|
swipe:4:right exec busctl --user call dev.ezri.sway /ContextManager dev.ezri.sway.ContextManager FocusPreviousWorkspace
|
||||||
|
}
|
||||||
|
|
||||||
## Window Reassignment Keybinds
|
## Window Reassignment Keybinds
|
||||||
bindsym {
|
bindsym {
|
||||||
$mod+Shift+1 exec busctl --user call dev.ezri.sway /ContextManager dev.ezri.sway.ContextManager MoveContainer y 1
|
$mod+Shift+1 exec busctl --user call dev.ezri.sway /ContextManager dev.ezri.sway.ContextManager MoveContainer y 1
|
||||||
@@ -199,6 +195,12 @@ for_window [floating] border normal 1
|
|||||||
## Thunderbird New.* windows should float
|
## Thunderbird New.* windows should float
|
||||||
for_window [app_id="thunderbird" title="(New|Write)"] floating enable
|
for_window [app_id="thunderbird" title="(New|Write)"] floating enable
|
||||||
|
|
||||||
|
## Bitwarden extension windows should float by default
|
||||||
|
for_window [app_id="firefox" title="Extension: \(Bitwarden Password Manager\)"] floating enable
|
||||||
|
|
||||||
|
## Kwallet popup prompts should float
|
||||||
|
for_window [app_id="rg.kde.kwalletd6"] floating enable
|
||||||
|
|
||||||
### ###
|
### ###
|
||||||
# Application Keybinds #
|
# Application Keybinds #
|
||||||
### ###
|
### ###
|
||||||
@@ -207,19 +209,23 @@ for_window [app_id="thunderbird" title="(New|Write)"] floating enable
|
|||||||
bindsym $mod+Shift+r reload
|
bindsym $mod+Shift+r reload
|
||||||
|
|
||||||
## Default Application Launcher
|
## Default Application Launcher
|
||||||
bindsym $mod+Return exec default-application-launcher
|
bindsym $mod+Return exec ~/.local/lib/voidshell/default-application-launcher
|
||||||
|
|
||||||
## Terminal Launcher
|
## Terminal Launcher
|
||||||
bindsym $mod+Shift+Return exec alacritty msg create-window || alacritty
|
bindsym $mod+Shift+Return exec alacritty msg create-window || alacritty
|
||||||
|
|
||||||
## Program Menu
|
## Program Menu
|
||||||
bindsym $mod+d exec wofi --show drun
|
bindsym $mod+d exec systemd-run --user --scope --slice=app-sway.slice --unit=app-sway-wofilaunch-$RANDOM.scope -- wofi --show drun
|
||||||
|
|
||||||
## Media Controls
|
## Media Controls
|
||||||
bindsym --locked {
|
bindsym --locked {
|
||||||
XF86AudioPlay exec playerctl play-pause
|
XF86AudioPlay exec playerctl play-pause
|
||||||
XF86AudioNext exec playerctl next
|
XF86AudioNext exec playerctl next
|
||||||
XF86AudioPrev exec playerctl previous
|
XF86AudioPrev exec playerctl previous
|
||||||
|
|
||||||
|
XF86AudioRaiseVolume exec wpctl set-volume @DEFAULT_SINK@ 5%+
|
||||||
|
XF86AudioLowerVolume exec wpctl set-volume @DEFAULT_SINK@ 5%-
|
||||||
|
XF86AudioMute exec wpctl set-mute @DEFAULT_SINK@ toggle
|
||||||
}
|
}
|
||||||
|
|
||||||
## Screen Locking
|
## Screen Locking
|
||||||
@@ -247,14 +253,7 @@ include input.conf
|
|||||||
# Service Management #
|
# Service Management #
|
||||||
### ###
|
### ###
|
||||||
|
|
||||||
## Import Environment Variables
|
exec exec ~/.local/lib/voidshell/sway-session-manager setup
|
||||||
exec_always XDG_CURRENT_DESKTOP=sway {
|
|
||||||
systemctl --user import-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP PATH ASDF_DATA_DIR
|
|
||||||
dbus-update-activation-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP PATH ASDF_DATA_DIR
|
|
||||||
}
|
|
||||||
|
|
||||||
## Start Session Target
|
|
||||||
exec_always systemctl --user start sway-session.target
|
|
||||||
|
|
||||||
### ###
|
### ###
|
||||||
# Generic Local Configuration #
|
# Generic Local Configuration #
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
### -*-conf-space-*- ###
|
|
||||||
# S.S.V. Normandy Display Config #
|
|
||||||
### ###
|
|
||||||
|
|
||||||
set $leftdisplay 'HDMI-A-1'
|
|
||||||
set $centerdisplay 'DP-1'
|
|
||||||
set $rightdisplay 'DP-2'
|
|
||||||
|
|
||||||
output {
|
|
||||||
$leftdisplay pos 0 220 mode --custom 1920x1080@75Hz
|
|
||||||
$centerdisplay pos 1920 0 mode 2560x1440@165Hz
|
|
||||||
$rightdisplay pos 4480 230 mode --custom 1920x1080@75Hz
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
### -*-conf-space-*- ###
|
|
||||||
# Rocinante Display Config #
|
|
||||||
### ###
|
|
||||||
|
|
||||||
set $display eDP-1
|
|
||||||
|
|
||||||
output $display scale 1 pos 0 1080
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
### -*-conf-space-*- ###
|
|
||||||
# Tycho Station Display Config #
|
|
||||||
### ###
|
|
||||||
|
|
||||||
set $leftdisplay "HP Inc. HP Z27n G2 6CM0151FHY"
|
|
||||||
set $centerdisplay "Hewlett Packard HP S340c CN490508SQ"
|
|
||||||
set $rightdisplay "HP Inc. HP Z27n G2 6CM0151FD4"
|
|
||||||
|
|
||||||
output {
|
|
||||||
$leftdisplay pos 0 450 mode 2560x1440@60Hz
|
|
||||||
$leftdisplay bg ~/Images/Wallpaper.png center
|
|
||||||
$centerdisplay pos 2560 450 mode 3440x1440 transform 0
|
|
||||||
$centerdisplay bg ~/Images/Wallpaper.png center
|
|
||||||
$rightdisplay pos 6000 0 mode 2560x1440@60Hz transform 90
|
|
||||||
$rightdisplay bg ~/Images/Sidepaper.png center
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#-*-conf-space-*-
|
|
||||||
|
|
||||||
exec_always gsettings set org.gnome.desktop.interface text-scaling-factor 1.25
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
font pango:JetBrainsMono Nerd Font 12
|
|
||||||
42
.config/sway/outputs.json
Normal file
42
.config/sway/outputs.json
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"zariman-builtin": {
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"mode": "2560x1600",
|
||||||
|
"refresh": 165,
|
||||||
|
"color_profile": "icc /usr/share/color/icc/colord/BOE_CQ_______NE160QDM_NZ6.icm"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"work-left": {
|
||||||
|
"make": "Acer Technologies",
|
||||||
|
"model": "XV271U M3",
|
||||||
|
"serial": "1322131231233",
|
||||||
|
"eww_windows": {},
|
||||||
|
"options": {
|
||||||
|
"mode": "2560x1440",
|
||||||
|
"refresh": 120
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"work-right": {
|
||||||
|
"make": "Acer Technologies",
|
||||||
|
"model": "XV271U M3",
|
||||||
|
"serial": "1431038964205",
|
||||||
|
"options": {
|
||||||
|
"mode": "2560x1440",
|
||||||
|
"refresh": 120
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"work-center": {
|
||||||
|
"make": "Dell Inc.",
|
||||||
|
"model": "DELL U3818DW",
|
||||||
|
"serial": "97F8P9350W0L",
|
||||||
|
"options": {
|
||||||
|
"mode": "3840x1600"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
# -*-conf-*-
|
# -*-conf-*-
|
||||||
|
|
||||||
timeout 10 'pgrep swaylock &> /dev/null && swaymsg output "*" power off' resume 'pgrep swaylock &> /dev/null && swaymsg output "*" power on'
|
timeout 10 'systemctl --user start screens-off.target &> /dev/null' resume 'systemctl --user stop screens-off.target'
|
||||||
lock ~/.local/bin/screenlock
|
lock 'systemctl --user start screenlock.service'
|
||||||
before-sleep 'loginctl lock-session'
|
before-sleep 'systemctl --user start screenlock.service'
|
||||||
unlock 'pkill -SIGUSR1 swaylock'
|
unlock 'systemctl --user stop screenlock.service'
|
||||||
idlehint 600
|
timeout 600 'systemctl --user start idle.target' resume 'systemctl --user stop idle.target'
|
||||||
|
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
### -*-conf-space-*- ###
|
|
||||||
# Dual-Monitor Workspace Settings #
|
|
||||||
### ###
|
|
||||||
|
|
||||||
# This file defines the workspaces and creates the keybinds to switch
|
|
||||||
# between them and move containers around between them. This version
|
|
||||||
# is for dual-monitor systems. The host-specific display-arrangement.conf
|
|
||||||
# file should declare the $leftdisplay and $rightdisplay variables used
|
|
||||||
# here.
|
|
||||||
|
|
||||||
workspace {
|
|
||||||
# Left monitor workspaces
|
|
||||||
1 output $leftdisplay
|
|
||||||
2 output $leftdisplay
|
|
||||||
3 output $leftdisplay
|
|
||||||
4 output $leftdisplay
|
|
||||||
5 output $leftdisplay
|
|
||||||
6 output $leftdisplay
|
|
||||||
7 output $leftdisplay
|
|
||||||
8 output $leftdisplay
|
|
||||||
9 output $leftdisplay
|
|
||||||
10 output $leftdisplay
|
|
||||||
|
|
||||||
# Right monitor workspaces
|
|
||||||
11 output $rightdisplay
|
|
||||||
12 output $rightdisplay
|
|
||||||
13 output $rightdisplay
|
|
||||||
14 output $rightdisplay
|
|
||||||
15 output $rightdisplay
|
|
||||||
16 output $rightdisplay
|
|
||||||
17 output $rightdisplay
|
|
||||||
18 output $rightdisplay
|
|
||||||
19 output $rightdisplay
|
|
||||||
20 output $rightdisplay
|
|
||||||
}
|
|
||||||
|
|
||||||
## Workspace Switching Keybinds
|
|
||||||
bindsym {
|
|
||||||
$mod+1 exec swaymsg workspace $(sway-find-workspace 1 )
|
|
||||||
$mod+2 exec swaymsg workspace $(sway-find-workspace 2 )
|
|
||||||
$mod+3 exec swaymsg workspace $(sway-find-workspace 3 )
|
|
||||||
$mod+4 exec swaymsg workspace $(sway-find-workspace 4 )
|
|
||||||
$mod+5 exec swaymsg workspace $(sway-find-workspace 5 )
|
|
||||||
$mod+6 exec swaymsg workspace $(sway-find-workspace 6 )
|
|
||||||
$mod+7 exec swaymsg workspace $(sway-find-workspace 7 )
|
|
||||||
$mod+8 exec swaymsg workspace $(sway-find-workspace 8 )
|
|
||||||
$mod+9 exec swaymsg workspace $(sway-find-workspace 9 )
|
|
||||||
$mod+0 exec swaymsg workspace $(sway-find-workspace 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
## Window Reassignment Keybinds
|
|
||||||
bindsym {
|
|
||||||
$mod+Shift+1 exec swaymsg move container to workspace $(sway-find-workspace 1 )
|
|
||||||
$mod+Shift+2 exec swaymsg move container to workspace $(sway-find-workspace 2 )
|
|
||||||
$mod+Shift+3 exec swaymsg move container to workspace $(sway-find-workspace 3 )
|
|
||||||
$mod+Shift+4 exec swaymsg move container to workspace $(sway-find-workspace 4 )
|
|
||||||
$mod+Shift+5 exec swaymsg move container to workspace $(sway-find-workspace 5 )
|
|
||||||
$mod+Shift+6 exec swaymsg move container to workspace $(sway-find-workspace 6 )
|
|
||||||
$mod+Shift+7 exec swaymsg move container to workspace $(sway-find-workspace 7 )
|
|
||||||
$mod+Shift+8 exec swaymsg move container to workspace $(sway-find-workspace 8 )
|
|
||||||
$mod+Shift+9 exec swaymsg move container to workspace $(sway-find-workspace 9 )
|
|
||||||
$mod+Shift+0 exec swaymsg move container to workspace $(sway-find-workspace 10)
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
### -*-conf-space-*- ###
|
|
||||||
# Single-Monitor Workspace Settings #
|
|
||||||
### ###
|
|
||||||
|
|
||||||
# This file defines the workspaces and creates the keybinds to switch
|
|
||||||
# between them and move containers around between them. This version
|
|
||||||
# is for dual-monitor systems. The host-specific display-arrangement.conf
|
|
||||||
# file should declare the $display variable used here.
|
|
||||||
|
|
||||||
workspace {
|
|
||||||
1 output $display
|
|
||||||
2 output $display
|
|
||||||
3 output $display
|
|
||||||
4 output $display
|
|
||||||
5 output $display
|
|
||||||
6 output $display
|
|
||||||
7 output DP-1 DP-2 DP-3 DP-4 $display
|
|
||||||
8 output $display
|
|
||||||
9 output $display
|
|
||||||
10 output $display
|
|
||||||
}
|
|
||||||
|
|
||||||
## Workspace Switching Keybinds
|
|
||||||
bindsym {
|
|
||||||
$mod+1 exec swaymsg workspace 1
|
|
||||||
$mod+2 exec swaymsg workspace 2
|
|
||||||
$mod+3 exec swaymsg workspace 3
|
|
||||||
$mod+4 exec swaymsg workspace 4
|
|
||||||
$mod+5 exec swaymsg workspace 5
|
|
||||||
$mod+6 exec swaymsg workspace 6
|
|
||||||
$mod+7 exec swaymsg workspace 7
|
|
||||||
$mod+8 exec swaymsg workspace 8
|
|
||||||
$mod+9 exec swaymsg workspace 9
|
|
||||||
$mod+0 exec swaymsg workspace 10
|
|
||||||
}
|
|
||||||
|
|
||||||
## Window Reassignment Keybinds
|
|
||||||
bindsym {
|
|
||||||
$mod+Shift+1 exec swaymsg move container to workspace 1
|
|
||||||
$mod+Shift+2 exec swaymsg move container to workspace 2
|
|
||||||
$mod+Shift+3 exec swaymsg move container to workspace 3
|
|
||||||
$mod+Shift+4 exec swaymsg move container to workspace 4
|
|
||||||
$mod+Shift+5 exec swaymsg move container to workspace 5
|
|
||||||
$mod+Shift+6 exec swaymsg move container to workspace 6
|
|
||||||
$mod+Shift+7 exec swaymsg move container to workspace 7
|
|
||||||
$mod+Shift+8 exec swaymsg move container to workspace 8
|
|
||||||
$mod+Shift+9 exec swaymsg move container to workspace 9
|
|
||||||
$mod+Shift+0 exec swaymsg move container to workspace 10
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
### -*-conf-space-*- ###
|
|
||||||
# Tie Fighter Workspace Settings #
|
|
||||||
### ###
|
|
||||||
|
|
||||||
# This file defines the workspaces and creates the keybinds to switch
|
|
||||||
# between them and move containers around between them. This version
|
|
||||||
# is for "tie-fighter" systems (one horizontal central display flanked
|
|
||||||
# by two vertical displays). The host-specific display-arrangement.conf
|
|
||||||
# file should declare the $leftdisplay, $centerdisplay, and $rightdisplay
|
|
||||||
# variables used here.
|
|
||||||
|
|
||||||
workspace {
|
|
||||||
# Left monitor workspaces
|
|
||||||
1 output $leftdisplay
|
|
||||||
2 output $leftdisplay
|
|
||||||
3 output $leftdisplay
|
|
||||||
4 output $leftdisplay
|
|
||||||
5 output $leftdisplay
|
|
||||||
|
|
||||||
# Center monitor workspaces
|
|
||||||
6 output $centerdisplay
|
|
||||||
7 output $centerdisplay
|
|
||||||
8 output $centerdisplay
|
|
||||||
9 output $centerdisplay
|
|
||||||
10 output $centerdisplay
|
|
||||||
11 output $centerdisplay
|
|
||||||
12 output $centerdisplay
|
|
||||||
13 output $centerdisplay
|
|
||||||
14 output $centerdisplay
|
|
||||||
15 output $centerdisplay
|
|
||||||
|
|
||||||
# Right monitor workspaces
|
|
||||||
16 output $rightdisplay
|
|
||||||
17 output $rightdisplay
|
|
||||||
18 output $rightdisplay
|
|
||||||
19 output $rightdisplay
|
|
||||||
20 output $rightdisplay
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
### -*-conf-space-*- ###
|
|
||||||
# Dual-Monitor Workspace Settings #
|
|
||||||
### ###
|
|
||||||
|
|
||||||
# This file defines the workspaces and creates the keybinds to switch
|
|
||||||
# between them and move containers around between them. This version
|
|
||||||
# is for dual-monitor systems. The host-specific display-arrangement.conf
|
|
||||||
# file should declare the $leftdisplay and $rightdisplay variables used
|
|
||||||
# here.
|
|
||||||
|
|
||||||
workspace {
|
|
||||||
# Left monitor workspaces
|
|
||||||
1 output $leftdisplay
|
|
||||||
2 output $leftdisplay
|
|
||||||
3 output $leftdisplay
|
|
||||||
4 output $leftdisplay
|
|
||||||
5 output $leftdisplay
|
|
||||||
6 output $leftdisplay
|
|
||||||
7 output $leftdisplay
|
|
||||||
8 output $leftdisplay
|
|
||||||
9 output $leftdisplay
|
|
||||||
10 output $leftdisplay
|
|
||||||
|
|
||||||
# Center monitor workspaces
|
|
||||||
11 output $centerdisplay
|
|
||||||
12 output $centerdisplay
|
|
||||||
13 output $centerdisplay
|
|
||||||
14 output $centerdisplay
|
|
||||||
15 output $centerdisplay
|
|
||||||
16 output $centerdisplay
|
|
||||||
17 output $centerdisplay
|
|
||||||
18 output $centerdisplay
|
|
||||||
19 output $centerdisplay
|
|
||||||
20 output $centerdisplay
|
|
||||||
|
|
||||||
# Right monitor workspaces
|
|
||||||
21 output $rightdisplay
|
|
||||||
22 output $rightdisplay
|
|
||||||
23 output $rightdisplay
|
|
||||||
24 output $rightdisplay
|
|
||||||
25 output $rightdisplay
|
|
||||||
26 output $rightdisplay
|
|
||||||
27 output $rightdisplay
|
|
||||||
28 output $rightdisplay
|
|
||||||
29 output $rightdisplay
|
|
||||||
30 output $rightdisplay
|
|
||||||
}
|
|
||||||
|
|
||||||
## Workspace Switching Keybinds
|
|
||||||
bindsym {
|
|
||||||
$mod+1 exec swaymsg workspace $(sway-find-workspace 1 )
|
|
||||||
$mod+2 exec swaymsg workspace $(sway-find-workspace 2 )
|
|
||||||
$mod+3 exec swaymsg workspace $(sway-find-workspace 3 )
|
|
||||||
$mod+4 exec swaymsg workspace $(sway-find-workspace 4 )
|
|
||||||
$mod+5 exec swaymsg workspace $(sway-find-workspace 5 )
|
|
||||||
$mod+6 exec swaymsg workspace $(sway-find-workspace 6 )
|
|
||||||
$mod+7 exec swaymsg workspace $(sway-find-workspace 7 )
|
|
||||||
$mod+8 exec swaymsg workspace $(sway-find-workspace 8 )
|
|
||||||
$mod+9 exec swaymsg workspace $(sway-find-workspace 9 )
|
|
||||||
$mod+0 exec swaymsg workspace $(sway-find-workspace 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
## Window Reassignment Keybinds
|
|
||||||
bindsym {
|
|
||||||
$mod+Shift+1 exec swaymsg move container to workspace $(sway-find-workspace 1 )
|
|
||||||
$mod+Shift+2 exec swaymsg move container to workspace $(sway-find-workspace 2 )
|
|
||||||
$mod+Shift+3 exec swaymsg move container to workspace $(sway-find-workspace 3 )
|
|
||||||
$mod+Shift+4 exec swaymsg move container to workspace $(sway-find-workspace 4 )
|
|
||||||
$mod+Shift+5 exec swaymsg move container to workspace $(sway-find-workspace 5 )
|
|
||||||
$mod+Shift+6 exec swaymsg move container to workspace $(sway-find-workspace 6 )
|
|
||||||
$mod+Shift+7 exec swaymsg move container to workspace $(sway-find-workspace 7 )
|
|
||||||
$mod+Shift+8 exec swaymsg move container to workspace $(sway-find-workspace 8 )
|
|
||||||
$mod+Shift+9 exec swaymsg move container to workspace $(sway-find-workspace 9 )
|
|
||||||
$mod+Shift+0 exec swaymsg move container to workspace $(sway-find-workspace 10)
|
|
||||||
}
|
|
||||||
408
.config/sway/workspaces.json##hostname.ezri-laptop
Normal file
408
.config/sway/workspaces.json##hostname.ezri-laptop
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
{
|
||||||
|
"default_context": "personal-portable",
|
||||||
|
"workspaces": [
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"name": "console",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"name": "code",
|
||||||
|
"exec": "emacsclient",
|
||||||
|
"args": ["-nc"],
|
||||||
|
"program_name": "emacsclient"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 3,
|
||||||
|
"name": "internet",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"environ": {},
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 4,
|
||||||
|
"name": "project",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 5,
|
||||||
|
"name": "discord",
|
||||||
|
"exec": "vesktop",
|
||||||
|
"comms": true,
|
||||||
|
"program_name": "discord"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 6,
|
||||||
|
"name": "console",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 7,
|
||||||
|
"name": "code",
|
||||||
|
"exec": "emacsclient",
|
||||||
|
"args": ["-nc"],
|
||||||
|
"program_name": "emacsclient"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 8,
|
||||||
|
"name": "internet",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 9,
|
||||||
|
"name": "project",
|
||||||
|
"exec": "firefox-developer-edition",
|
||||||
|
"args": ["-start-debugger-server", "--new-window"],
|
||||||
|
"program_name": "firefox-developer-edition"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 10,
|
||||||
|
"name": "server management",
|
||||||
|
"exec": "virt-manager",
|
||||||
|
"program_name": "virt-manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 11,
|
||||||
|
"name": "password management",
|
||||||
|
"exec": "bitwarden-desktop",
|
||||||
|
"program_name": "bitwarden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 12,
|
||||||
|
"name": "video",
|
||||||
|
"exec": "jellyfinmediaplayer",
|
||||||
|
"program_name": "jellyfinmediaplayer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 13,
|
||||||
|
"name": "comms",
|
||||||
|
"exec": "firefoxpwa",
|
||||||
|
"args": ["site", "launch", "01K233XSC3TE6CM7ZQZ1X303JX", "--protocol"],
|
||||||
|
"forking": true,
|
||||||
|
"program_name": "zoom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 14,
|
||||||
|
"name": "mail",
|
||||||
|
"exec": "thunderbird",
|
||||||
|
"program_name": "thunderbird",
|
||||||
|
"environ": {
|
||||||
|
"MOZ_ENABLE_WAYLAND": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 15,
|
||||||
|
"name": "config",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 16,
|
||||||
|
"name": "console",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 17,
|
||||||
|
"name": "code",
|
||||||
|
"exec": "emacsclient",
|
||||||
|
"args": ["-nc"],
|
||||||
|
"program_name": "emacsclient"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 18,
|
||||||
|
"name": "music",
|
||||||
|
"exec": "feishin-electron",
|
||||||
|
"program_name": "feishin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 19,
|
||||||
|
"name": "internet",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 20,
|
||||||
|
"name": "slack",
|
||||||
|
"exec": "slack",
|
||||||
|
"comms": true,
|
||||||
|
"program_name": "slack",
|
||||||
|
"args": [
|
||||||
|
"--enable-features=UseOzonePlatform",
|
||||||
|
"--ozone-platform=wayland",
|
||||||
|
"--enable-gpu-rasterization"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 21,
|
||||||
|
"name": "livestream",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 22,
|
||||||
|
"name": "encrypted comms",
|
||||||
|
"exec": "signal-desktop",
|
||||||
|
"comms": true,
|
||||||
|
"program_name": "signal",
|
||||||
|
"environ": {
|
||||||
|
"ELECTRON_OZONE_PLATFORM_HINT": "wayland"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 23,
|
||||||
|
"name": "steam",
|
||||||
|
"exec": "steam",
|
||||||
|
"program_name": "steam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 24,
|
||||||
|
"name": "telephony",
|
||||||
|
"exec": "telephony-launcher.sh",
|
||||||
|
"program_name": "telephony"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contexts": {
|
||||||
|
"docked": {
|
||||||
|
"primary": "center",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [0, 1100],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2560x1600@165Hz scale 1.5 color_profile icc /usr/share/color/icc/colord/BOE_CQ_______NE160QDM_NZ6.icm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "Dell Inc.",
|
||||||
|
"model": "DELL U2715H",
|
||||||
|
"serial": "H7YCC64Q0WFL",
|
||||||
|
"group": "left",
|
||||||
|
"position": [1706, 500],
|
||||||
|
"mode": "2560x1440 color_profile icc /usr/share/color/icc/colord/sRGB.icc",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-leftbar": {},
|
||||||
|
"sidebar": {
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "Dell Inc.",
|
||||||
|
"model": "DELL U3818DW",
|
||||||
|
"serial": "97F8P9350W0L",
|
||||||
|
"group": "center",
|
||||||
|
"position": [4266, 500],
|
||||||
|
"mode": "3840x1600 color_profile icc /usr/share/color/icc/colord/sRGB.icc",
|
||||||
|
"eww_windows": ["desktop-mainbar"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "Dell Inc.",
|
||||||
|
"model": "DELL U2722D",
|
||||||
|
"serial": "5X3MGH3",
|
||||||
|
"group": "right",
|
||||||
|
"position": [8106, 0],
|
||||||
|
"mode": "2560x1440 transform 270 color_profile icc /usr/share/color/icc/colord/sRGB.icc",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-rightbar": {},
|
||||||
|
"vertical-bottombar": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [21, 22],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"left": {
|
||||||
|
"workspaces": [6, 2, 3, 13, 5],
|
||||||
|
"reverse": true
|
||||||
|
},
|
||||||
|
"center": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 10, 11, 12, 24, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"workspaces": [16, 17, 19, 18, 20],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"battlestation": {
|
||||||
|
"primary": "center",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"make": "ASUSTek COMPUTER INC",
|
||||||
|
"model": "VG245",
|
||||||
|
"serial": "L7LMQS132447",
|
||||||
|
"group": "left",
|
||||||
|
"position": [0, 200],
|
||||||
|
"mode": "1920x1080@75Hz",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-leftbar": {},
|
||||||
|
"sidebar": {
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "ASUSTek COMPUTER INC",
|
||||||
|
"model": "VG32AQA1A",
|
||||||
|
"serial": "S5LMQS033656",
|
||||||
|
"group": "center",
|
||||||
|
"position": [1920, 0],
|
||||||
|
"mode": "2560x1440@165Hz",
|
||||||
|
"eww_windows": ["desktop-mainbar"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "ASUSTek COMPUTER INC",
|
||||||
|
"model": "VG245",
|
||||||
|
"serial": "L6LMQS065439",
|
||||||
|
"group": "right",
|
||||||
|
"position": [4480, 200],
|
||||||
|
"mode": "1920x1080@75Hz",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-rightbar": {},
|
||||||
|
"sidebar": {
|
||||||
|
"side": "right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [6400, 600],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2560x1600@165Hz scale 1.5 color_profile icc /usr/share/color/icc/colord/BOE_CQ_______NE160QDM_NZ6.icm"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [21, 22],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"left": {
|
||||||
|
"workspaces": [6, 2, 3, 18, 5],
|
||||||
|
"reverse": true
|
||||||
|
},
|
||||||
|
"center": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 10, 11, 12, 24, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"workspaces": [16, 17, 19, 13, 20],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"work-portable": {
|
||||||
|
"primary": "builtin",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [0, 0],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2560x1600@165Hz scale 1.25 color_profile icc /usr/share/color/icc/colord/BOE_CQ_______NE160QDM_NZ6.icm"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 10, 13, 18, 20, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"personal-portable": {
|
||||||
|
"primary": "builtin",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [0, 0],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2560x1600@165Hz scale 1.25 color_profile icc /usr/share/color/icc/colord/BOE_CQ_______NE160QDM_NZ6.icm"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 23, 22, 18, 5, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"spawnpoint": {
|
||||||
|
"primary": "external",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [2560, 0],
|
||||||
|
"eww_windows": ["builtinbar"],
|
||||||
|
"mode": "2560x1600@165Hz scale 1.5 color_profile icc /usr/share/color/icc/colord/BOE_CQ_______NE160QDM_NZ6.icm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "LG Electronics",
|
||||||
|
"model": "LG UltraFine",
|
||||||
|
"serial": "111NTRL2Y030",
|
||||||
|
"group": "external",
|
||||||
|
"position": [0, 0],
|
||||||
|
"eww_windows": ["centerbar"],
|
||||||
|
"mode": "3840x2160@60Hz scale 1.5"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [6, 2, 3, 18, 5],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"external": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 23, 22, 19, 20, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
398
.config/sway/workspaces.json##hostname.razorback
Normal file
398
.config/sway/workspaces.json##hostname.razorback
Normal file
@@ -0,0 +1,398 @@
|
|||||||
|
{
|
||||||
|
"default_context": "personal-portable",
|
||||||
|
"workspaces": [
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"name": "console",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"name": "code",
|
||||||
|
"exec": "emacsclient",
|
||||||
|
"args": ["-nc"],
|
||||||
|
"program_name": "emacsclient"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 3,
|
||||||
|
"name": "documentation",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"environ": {},
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 4,
|
||||||
|
"name": "project",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 5,
|
||||||
|
"name": "discord",
|
||||||
|
"exec": "vesktop",
|
||||||
|
"program_name": "discord"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 6,
|
||||||
|
"name": "console",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 7,
|
||||||
|
"name": "code",
|
||||||
|
"exec": "emacsclient",
|
||||||
|
"args": ["-nc"],
|
||||||
|
"program_name": "emacsclient"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 8,
|
||||||
|
"name": "internet",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 9,
|
||||||
|
"name": "project",
|
||||||
|
"exec": "firefox-developer-edition",
|
||||||
|
"args": ["-start-debugger-server", "--new-window"],
|
||||||
|
"program_name": "firefox-developer-edition"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 10,
|
||||||
|
"name": "server management",
|
||||||
|
"exec": "virt-manager",
|
||||||
|
"program_name": "virt-manager",
|
||||||
|
"systemd": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 11,
|
||||||
|
"name": "password management",
|
||||||
|
"exec": "bitwarden-desktop",
|
||||||
|
"program_name": "bitwarden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 12,
|
||||||
|
"name": "video",
|
||||||
|
"exec": "jellyfinmediaplayer",
|
||||||
|
"program_name": "jellyfinmediaplayer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 13,
|
||||||
|
"name": "comms",
|
||||||
|
"exec": "zoom",
|
||||||
|
"program_name": "zoom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 14,
|
||||||
|
"name": "mail",
|
||||||
|
"exec": "thunderbird",
|
||||||
|
"program_name": "thunderbird",
|
||||||
|
"environ": {
|
||||||
|
"MOZ_ENABLE_WAYLAND": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 15,
|
||||||
|
"name": "config",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 16,
|
||||||
|
"name": "console",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 17,
|
||||||
|
"name": "code",
|
||||||
|
"exec": "emacsclient",
|
||||||
|
"args": ["-nc"],
|
||||||
|
"program_name": "emacsclient"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 18,
|
||||||
|
"name": "music",
|
||||||
|
"exec": "feishin",
|
||||||
|
"program_name": "feishin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 19,
|
||||||
|
"name": "internet",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 20,
|
||||||
|
"name": "slack",
|
||||||
|
"exec": "slack",
|
||||||
|
"program_name": "slack",
|
||||||
|
"args": [
|
||||||
|
"--enable-features=UseOzonePlatform",
|
||||||
|
"--ozone-platform=wayland",
|
||||||
|
"--enable-gpu-rasterization"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 21,
|
||||||
|
"name": "stream",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 22,
|
||||||
|
"name": "encrypted comms",
|
||||||
|
"exec": "signal-desktop",
|
||||||
|
"program_name": "signal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 23,
|
||||||
|
"name": "steam",
|
||||||
|
"exec": "steam",
|
||||||
|
"program_name": "steam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 30,
|
||||||
|
"name": "present 1",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 31,
|
||||||
|
"name": "present 2",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 32,
|
||||||
|
"name": "present 3",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contexts": {
|
||||||
|
"docked": {
|
||||||
|
"primary": "center",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [0, 850],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2256x1504 scale 1.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "Dell Inc.",
|
||||||
|
"model": "DELL U2722D",
|
||||||
|
"serial": "DV3MGH3",
|
||||||
|
"group": "left",
|
||||||
|
"position": [1504, 0],
|
||||||
|
"mode": "2560x1440 color_profile icc /usr/share/color/icc/colord/DCI-P3.icd",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-leftbar": {},
|
||||||
|
"sidebar": {
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "Dell Inc.",
|
||||||
|
"model": "DELL U3818DW",
|
||||||
|
"serial": "97F8P9350W0L",
|
||||||
|
"group": "center",
|
||||||
|
"position": [4064, 0],
|
||||||
|
"mode": "3840x1600",
|
||||||
|
"eww_windows": ["desktop-mainbar"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "Dell Inc.",
|
||||||
|
"model": "DELL U2722D",
|
||||||
|
"serial": "5X3MGH3",
|
||||||
|
"group": "right",
|
||||||
|
"position": [7904, 0],
|
||||||
|
"mode": "2560x1440 color_profile icc /usr/share/color/icc/colord/DCI-P3.icd",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-rightbar": {},
|
||||||
|
"sidebar": {
|
||||||
|
"side": "right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [21, 22],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"left": {
|
||||||
|
"workspaces": [6, 2, 3, 4, 5],
|
||||||
|
"reverse": true
|
||||||
|
},
|
||||||
|
"center": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"workspaces": [16, 17, 19, 18, 20, 13],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"battlestation": {
|
||||||
|
"primary": "center",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [0, 600],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2256x1504 scale 1.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "ASUSTek COMPUTER INC",
|
||||||
|
"model": "VG245",
|
||||||
|
"serial": "L7LMQS132447",
|
||||||
|
"group": "left",
|
||||||
|
"position": [1504, 200],
|
||||||
|
"mode": "1920x1080@75Hz",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-leftbar": {},
|
||||||
|
"sidebar": {
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "ASUSTek COMPUTER INC",
|
||||||
|
"model": "VG32AQA1A",
|
||||||
|
"serial": "S5LMQS033656",
|
||||||
|
"group": "center",
|
||||||
|
"position": [3424, 0],
|
||||||
|
"mode": "2560x1440@165Hz",
|
||||||
|
"eww_windows": ["desktop-mainbar"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "ASUSTek COMPUTER INC",
|
||||||
|
"model": "VG245",
|
||||||
|
"serial": "L6LMQS065439",
|
||||||
|
"group": "right",
|
||||||
|
"position": [5984, 200],
|
||||||
|
"mode": "1920x1080@75Hz",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-rightbar": {},
|
||||||
|
"sidebar": {
|
||||||
|
"side": "right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [21, 20],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"left": {
|
||||||
|
"workspaces": [6, 2, 3, 18, 5],
|
||||||
|
"reverse": true
|
||||||
|
},
|
||||||
|
"center": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"workspaces": [16, 17, 19, 4, 22],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"portable": {
|
||||||
|
"primary": "builtin",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [0, 0],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2256x1504 scale 1.25"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 23, 22, 18, 5, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"primary": "builtin",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [0, 0],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2256x1504 scale 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": ["DP-1", "DP-2", "DP-3", "DP-4"],
|
||||||
|
"group": "presentation",
|
||||||
|
"position": [2256, 0],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 23, 22, 18, 5, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"workspaces": [30, 31, 32],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,76 +1,398 @@
|
|||||||
{
|
{
|
||||||
"default_context": "personal",
|
"default_context": "personal-portable",
|
||||||
"display_ordering": ["builtin"],
|
"workspaces": [
|
||||||
"display_layout": {
|
{
|
||||||
"builtin": "eDP-1"
|
"index": 1,
|
||||||
},
|
"name": "console",
|
||||||
"contexts": {
|
"exec": "console",
|
||||||
"personal": {
|
"program_name": "console"
|
||||||
"builtin": [
|
},
|
||||||
{
|
{
|
||||||
"index": 1,
|
"index": 2,
|
||||||
"name": "terminal",
|
"name": "code",
|
||||||
"exec": "console",
|
"exec": "emacsclient",
|
||||||
"program_name": "console"
|
"args": ["-nc"],
|
||||||
},
|
"program_name": "emacsclient"
|
||||||
{
|
},
|
||||||
"index": 2,
|
{
|
||||||
"name": "code",
|
"index": 3,
|
||||||
"exec": "emacsclient",
|
"name": "documentation",
|
||||||
"args": ["-nc"],
|
"exec": "firefox",
|
||||||
"program_name": "emacsclient"
|
"args": ["--new-window"],
|
||||||
},
|
"environ": {},
|
||||||
{
|
"program_name": "firefox"
|
||||||
"index": 3,
|
},
|
||||||
"name": "internet",
|
{
|
||||||
"exec": "firefox",
|
"index": 4,
|
||||||
"args": ["--new-window"],
|
"name": "project",
|
||||||
"program_name": "firefox"
|
"exec": "firefox",
|
||||||
},
|
"args": ["--new-window"],
|
||||||
{
|
"program_name": "firefox"
|
||||||
"index": 4,
|
},
|
||||||
"name": "project",
|
{
|
||||||
"exec": "firefox",
|
"index": 5,
|
||||||
"args": ["--new-window"],
|
"name": "discord",
|
||||||
"program_name": "firefox"
|
"exec": "vesktop",
|
||||||
},
|
"program_name": "discord"
|
||||||
{
|
},
|
||||||
"index": 5,
|
{
|
||||||
"name": "servers",
|
"index": 6,
|
||||||
"exec": "virt-manager",
|
"name": "console",
|
||||||
"program_name": "virt-manager"
|
"exec": "console",
|
||||||
},
|
"program_name": "console"
|
||||||
{
|
},
|
||||||
"index": 6,
|
{
|
||||||
"name": "steam",
|
"index": 7,
|
||||||
"exec": "steam",
|
"name": "code",
|
||||||
"program_name": "steam"
|
"exec": "emacsclient",
|
||||||
},
|
"args": ["-nc"],
|
||||||
{
|
"program_name": "emacsclient"
|
||||||
"index": 7,
|
},
|
||||||
"name": "media",
|
{
|
||||||
"exec": "jellyfinmediaplayer",
|
"index": 8,
|
||||||
"program_name": "jellyfinmediaplayer"
|
"name": "internet",
|
||||||
},
|
"exec": "firefox",
|
||||||
{
|
"args": ["--new-window"],
|
||||||
"index": 8,
|
"program_name": "firefox"
|
||||||
"name": "real-time comms",
|
},
|
||||||
"exec": "discord",
|
{
|
||||||
"program_name": "discord"
|
"index": 9,
|
||||||
},
|
"name": "project",
|
||||||
{
|
"exec": "firefox-developer-edition",
|
||||||
"index": 9,
|
"args": ["-start-debugger-server", "--new-window"],
|
||||||
"name": "messages",
|
"program_name": "firefox-developer-edition"
|
||||||
"exec": "thunderbird",
|
},
|
||||||
"program_name": "thunderbird"
|
{
|
||||||
},
|
"index": 10,
|
||||||
{
|
"name": "server management",
|
||||||
"index": 10,
|
"exec": "virt-manager",
|
||||||
"name": "config",
|
"program_name": "virt-manager",
|
||||||
"exec": "pavucontrol",
|
"systemd": false
|
||||||
"program_name": "pavucontrol"
|
},
|
||||||
}
|
{
|
||||||
|
"index": 11,
|
||||||
|
"name": "password management",
|
||||||
|
"exec": "bitwarden-desktop",
|
||||||
|
"program_name": "bitwarden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 12,
|
||||||
|
"name": "video",
|
||||||
|
"exec": "jellyfinmediaplayer",
|
||||||
|
"program_name": "jellyfinmediaplayer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 13,
|
||||||
|
"name": "comms",
|
||||||
|
"exec": "zoom",
|
||||||
|
"program_name": "zoom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 14,
|
||||||
|
"name": "mail",
|
||||||
|
"exec": "thunderbird",
|
||||||
|
"program_name": "thunderbird",
|
||||||
|
"environ": {
|
||||||
|
"MOZ_ENABLE_WAYLAND": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 15,
|
||||||
|
"name": "config",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 16,
|
||||||
|
"name": "console",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 17,
|
||||||
|
"name": "code",
|
||||||
|
"exec": "emacsclient",
|
||||||
|
"args": ["-nc"],
|
||||||
|
"program_name": "emacsclient"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 18,
|
||||||
|
"name": "music",
|
||||||
|
"exec": "feishin",
|
||||||
|
"program_name": "feishin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 19,
|
||||||
|
"name": "internet",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 20,
|
||||||
|
"name": "slack",
|
||||||
|
"exec": "slack",
|
||||||
|
"program_name": "slack",
|
||||||
|
"args": [
|
||||||
|
"--enable-features=UseOzonePlatform",
|
||||||
|
"--ozone-platform=wayland",
|
||||||
|
"--enable-gpu-rasterization"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 21,
|
||||||
|
"name": "stream",
|
||||||
|
"exec": "firefox",
|
||||||
|
"args": ["--new-window"],
|
||||||
|
"program_name": "firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 22,
|
||||||
|
"name": "encrypted comms",
|
||||||
|
"exec": "signal-desktop",
|
||||||
|
"program_name": "signal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 23,
|
||||||
|
"name": "steam",
|
||||||
|
"exec": "steam",
|
||||||
|
"program_name": "steam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 30,
|
||||||
|
"name": "present 1",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 31,
|
||||||
|
"name": "present 2",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 32,
|
||||||
|
"name": "present 3",
|
||||||
|
"exec": "console",
|
||||||
|
"program_name": "console"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contexts": {
|
||||||
|
"docked": {
|
||||||
|
"primary": "center",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [0, 850],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2256x1504 scale 1.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "Dell Inc.",
|
||||||
|
"model": "DELL U2722D",
|
||||||
|
"serial": "DV3MGH3",
|
||||||
|
"group": "left",
|
||||||
|
"position": [1504, 0],
|
||||||
|
"mode": "2560x1440 color_profile icc /usr/share/color/icc/colord/DCI-P3.icd",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-leftbar": {},
|
||||||
|
"sidebar": {
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "Dell Inc.",
|
||||||
|
"model": "DELL U3818DW",
|
||||||
|
"serial": "97F8P9350W0L",
|
||||||
|
"group": "center",
|
||||||
|
"position": [4064, 0],
|
||||||
|
"mode": "3840x1600",
|
||||||
|
"eww_windows": ["desktop-mainbar"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "Dell Inc.",
|
||||||
|
"model": "DELL U2722D",
|
||||||
|
"serial": "5X3MGH3",
|
||||||
|
"group": "right",
|
||||||
|
"position": [7904, 0],
|
||||||
|
"mode": "2560x1440 color_profile icc /usr/share/color/icc/colord/DCI-P3.icd",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-rightbar": {},
|
||||||
|
"sidebar": {
|
||||||
|
"side": "right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [21, 22],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"left": {
|
||||||
|
"workspaces": [6, 2, 3, 4, 5],
|
||||||
|
"reverse": true
|
||||||
|
},
|
||||||
|
"center": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"workspaces": [16, 17, 19, 18, 20, 13],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"battlestation": {
|
||||||
|
"primary": "center",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [0, 600],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2256x1504 scale 1.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "ASUSTek COMPUTER INC",
|
||||||
|
"model": "VG245",
|
||||||
|
"serial": "L7LMQS132447",
|
||||||
|
"group": "left",
|
||||||
|
"position": [1504, 200],
|
||||||
|
"mode": "1920x1080@75Hz",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-leftbar": {},
|
||||||
|
"sidebar": {
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "ASUSTek COMPUTER INC",
|
||||||
|
"model": "VG32AQA1A",
|
||||||
|
"serial": "S5LMQS033656",
|
||||||
|
"group": "center",
|
||||||
|
"position": [3424, 0],
|
||||||
|
"mode": "2560x1440@165Hz",
|
||||||
|
"eww_windows": ["desktop-mainbar"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"make": "ASUSTek COMPUTER INC",
|
||||||
|
"model": "VG245",
|
||||||
|
"serial": "L6LMQS065439",
|
||||||
|
"group": "right",
|
||||||
|
"position": [5984, 200],
|
||||||
|
"mode": "1920x1080@75Hz",
|
||||||
|
"eww_windows": {
|
||||||
|
"desktop-rightbar": {},
|
||||||
|
"sidebar": {
|
||||||
|
"side": "right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [21, 20],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"left": {
|
||||||
|
"workspaces": [6, 2, 3, 18, 5],
|
||||||
|
"reverse": true
|
||||||
|
},
|
||||||
|
"center": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"workspaces": [16, 17, 19, 4, 22],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"portable": {
|
||||||
|
"primary": "builtin",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [0, 0],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2256x1504 scale 1.25"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 23, 22, 18, 5, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"primary": "builtin",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"names": ["eDP-1"],
|
||||||
|
"group": "builtin",
|
||||||
|
"position": [0, 0],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
},
|
||||||
|
"laptopsidebar": {
|
||||||
|
"battery": "BAT1",
|
||||||
|
"side": "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "2256x1504 scale 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": ["DP-1", "DP-2", "DP-3", "DP-4"],
|
||||||
|
"group": "presentation",
|
||||||
|
"position": [2256, 0],
|
||||||
|
"eww_windows": {
|
||||||
|
"laptopbar": {
|
||||||
|
"battery": "BAT1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": {
|
||||||
|
"builtin": {
|
||||||
|
"workspaces": [1, 7, 8, 9, 23, 22, 18, 5, 14, 15],
|
||||||
|
"reverse": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"workspaces": [30, 31, 32],
|
||||||
|
"reverse": false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
28
.config/swaylock/config
Normal file
28
.config/swaylock/config
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
font="Source Sans Pro"
|
||||||
|
font-size=15
|
||||||
|
indicator-radius=80
|
||||||
|
indicator-thickness=10
|
||||||
|
inside-color=#1e1e1e
|
||||||
|
inside-clear-color=#1e1e1e
|
||||||
|
inside-caps-lock-color=#1e1e1e
|
||||||
|
inside-ver-color=#1e1e1e
|
||||||
|
inside-wrong-color=#1e1e1e
|
||||||
|
key-hl-color=#815986
|
||||||
|
bs-hl-color=#cf6a4c
|
||||||
|
caps-lock-key-hl-color=#f9ee98
|
||||||
|
caps-lock-bs-hl-color=#cf6a4c
|
||||||
|
ring-color=#815986
|
||||||
|
ring-clear-color=#f9ee98
|
||||||
|
ring-caps-lock-color=#f9ee98
|
||||||
|
ring-ver-color=#815986
|
||||||
|
ring-wrong-color=#cf6a4c
|
||||||
|
line-uses-inside
|
||||||
|
text-color=#815986
|
||||||
|
text-clear-color=#f9ee98
|
||||||
|
text-caps-lock-color=#f9ee98
|
||||||
|
text-ver-color=#815986
|
||||||
|
text-wrong-color=#cf6a4c
|
||||||
|
color=#1e1e1e
|
||||||
|
show-failed-attempts
|
||||||
|
ignore-empty-password
|
||||||
|
indicator-idle-visible
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
"timeout-critical": 0,
|
"timeout-critical": 0,
|
||||||
"fit-to-screen": false,
|
"fit-to-screen": false,
|
||||||
"relative-timestamps": true,
|
"relative-timestamps": true,
|
||||||
"control-center-width": 500,
|
"control-center-width": 800,
|
||||||
"control-center-height": 600,
|
"control-center-height": 600,
|
||||||
"notification-window-width": 500,
|
"notification-window-width": 500,
|
||||||
"keyboard-shortcuts": true,
|
"keyboard-shortcuts": true,
|
||||||
|
|||||||
3
.config/systemd/.gitignore
vendored
Normal file
3
.config/systemd/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/user/*.wants
|
||||||
|
/user/*.requires
|
||||||
|
/user/*.upholds
|
||||||
2
.config/systemd/user.conf
Normal file
2
.config/systemd/user.conf
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[Manager]
|
||||||
|
DefaultEnvironment=ELECTRON_OZONE_PLATFORM_HINT=wayland ORACLE_HOME=/usr
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=AggieTimeD
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStartPre=-/usr/bin/rm /run/user/%U/aggietimed.sock
|
|
||||||
ExecStartPre=/usr/bin/sleep 1
|
|
||||||
ExecStart=/usr/bin/node /usr/bin/aggietimed -d -s /run/user/%U/aggietimed.sock -p echo
|
|
||||||
RestartSec=30
|
|
||||||
Restart=always
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=sway-session.target
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Terminal emulator
|
Description=Terminal emulator
|
||||||
PartOf=sway-session.target
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
ExecStart=alacritty
|
ExecStart=alacritty --daemon --socket=%t/alacritty
|
||||||
Slice=gui.slice
|
ExecStopPost=rm %t/alacritty
|
||||||
|
Slice=app.slice
|
||||||
|
|||||||
2
.config/systemd/user/app-shell.slice
Normal file
2
.config/systemd/user/app-shell.slice
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Command-line shells
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=dunst notification daemon
|
|
||||||
PartOf=sway-session.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=dunst
|
|
||||||
Slice=session.slice
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=sway-session.target
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Emacs text editor
|
|
||||||
Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/
|
|
||||||
PartOf=graphical-session.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=forking
|
|
||||||
ExecStart=/usr/bin/emacs --daemon
|
|
||||||
ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)"
|
|
||||||
Environment=SSH_AUTH_SOCK=/run/user/1000/gnupg/S.gpg-agent.ssh
|
|
||||||
Environment=ASDF_DATA_DIR=/home/ezri/.local/share/asdf-vm
|
|
||||||
Restart=on-failure
|
|
||||||
Slice=session.slice
|
|
||||||
MemoryAccounting=yes
|
|
||||||
# Tide eats memory like crazy, so lets put it on a diet.
|
|
||||||
MemoryHigh=3G
|
|
||||||
MemoryMax=5G
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=graphical-session.target
|
|
||||||
6
.config/systemd/user/emacs.socket
Normal file
6
.config/systemd/user/emacs.socket
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[Socket]
|
||||||
|
ListenStream=%t/emacs/server
|
||||||
|
DirectoryMode=0700
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
||||||
@@ -3,8 +3,12 @@ Description=eww status bars
|
|||||||
PartOf=sway-session.target
|
PartOf=sway-session.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=forking
|
Type=simple
|
||||||
ExecStart=eww daemon
|
ExecSearchPath=%h/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
|
||||||
|
Environment=PATH=%h/.pyenv/shims:%h/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
|
||||||
|
Environment=PYENV_ROOT=%h/.pyenv
|
||||||
|
Environment=PYENV_VERSION=eww-modules
|
||||||
|
ExecStart=eww daemon --no-daemonize
|
||||||
ExecReload=eww reload
|
ExecReload=eww reload
|
||||||
ExecStop=eww kill
|
ExecStop=eww kill
|
||||||
ExecStopPost=sleep 1
|
ExecStopPost=sleep 1
|
||||||
|
|||||||
13
.config/systemd/user/gpg-ssh-auth-sock.service
Normal file
13
.config/systemd/user/gpg-ssh-auth-sock.service
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Ensure the service manager has an SSH agent available -- GnuPG Edition
|
||||||
|
BindsTo=gpg-agent-ssh.socket
|
||||||
|
After=gpg-agent-ssh.socket
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart= systemctl --user set-environment SSH_AUTH_SOCK=%t/gnupg/S.gpg-agent.ssh
|
||||||
|
ExecStop=systemctl --user unset-environment SSH_AUTH_SOCK=%t/gnupg/S.gpg-agent.ssh
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
UpheldBy=gpg-agent-ssh.socket
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Hyprland compositor session
|
|
||||||
Documentation=man:systemd.special
|
|
||||||
BindsTo=graphical-session.target
|
|
||||||
Wants=graphical-session-pre.target
|
|
||||||
After=graphical-session-pre.target
|
|
||||||
Wants=sway-session.target
|
|
||||||
12
.config/systemd/user/idle.target
Normal file
12
.config/systemd/user/idle.target
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Graphical session is idle
|
||||||
|
# Pull in the idle hint sync service
|
||||||
|
Wants=logind-idlehint.service
|
||||||
|
Requisite=graphical-session.target
|
||||||
|
After=screenlock.service
|
||||||
|
# Ensure that when the screen unlocks, the session is also no longer considered idle.
|
||||||
|
StopPropagatedFrom=screenlock.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
# If "enabled", the graphical session will be considered idle while the screen is locked.
|
||||||
|
WantedBy=screenlock.service
|
||||||
@@ -3,7 +3,12 @@ Description=KDE Connect Daemon
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
ExecStart=/usr/lib/kdeconnectd
|
ExecStart=/usr/bin/kdeconnectd
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5s
|
||||||
|
RestartMaxDelaySec=1min
|
||||||
|
RestartSteps=5
|
||||||
|
Slice=session.slice
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=default.target
|
WantedBy=graphical-session.target
|
||||||
|
|||||||
14
.config/systemd/user/logind-idlehint.service
Normal file
14
.config/systemd/user/logind-idlehint.service
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# This unit is pulled in by idle.target, but can be masked if idle hinting is not desired or if another program already provides it.
|
||||||
|
# This service should be preferred to other mechanisms, however, as it provides synchronization between the idle target and the logind
|
||||||
|
# state, which is generally what is desired.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=systemd-logind idle hint synchronization
|
||||||
|
PartOf=idle.target
|
||||||
|
Before=idle.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
ExecStart=busctl call org.freedesktop.login1 /org/freedesktop/login1/session/auto org.freedesktop.login1.Session SetIdleHint b 1
|
||||||
|
ExecStop=busctl call org.freedesktop.login1 /org/freedesktop/login1/session/auto org.freedesktop.login1.Session SetIdleHint b 0
|
||||||
15
.config/systemd/user/logind-lockhint.service
Normal file
15
.config/systemd/user/logind-lockhint.service
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# This unit should be pulled in by a provider of screenlock.service if the service doesn't provide lock hinting support natively.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=systemd-logind lock hint synchronization
|
||||||
|
PartOf=screenlock.service
|
||||||
|
After=screenlock.service
|
||||||
|
StopWhenUnneeded=yes
|
||||||
|
RefuseManualStart=yes
|
||||||
|
RefuseManualStop=yes
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
ExecStart=busctl call org.freedesktop.login1 /org/freedesktop/login1/session/auto org.freedesktop.login1.Session SetLockedHint b 1
|
||||||
|
ExecStop=busctl call org.freedesktop.login1 /org/freedesktop/login1/session/auto org.freedesktop.login1.Session SetLockedHint b 0
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description = PolicyKit authentication agent
|
|
||||||
BindTo=sway-session.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=sway-session.target
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description = Forwarding bluetooth audio controls to MPRIS players
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type = simple
|
|
||||||
ExecStart = /usr/bin/mpris-proxy
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy = graphical@i3.target
|
|
||||||
7
.config/systemd/user/screenlock.target
Normal file
7
.config/systemd/user/screenlock.target
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Screen locked
|
||||||
|
Requires=screenlock.service
|
||||||
|
After=screenlock.service
|
||||||
|
Requisite=graphical-session.target
|
||||||
|
AllowIsolate=yes
|
||||||
|
StopPropagatedFrom=screenlock.service
|
||||||
2
.config/systemd/user/screens-off.target
Normal file
2
.config/systemd/user/screens-off.target
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Displays are turned off
|
||||||
13
.config/systemd/user/suspend-comms-apps.service
Normal file
13
.config/systemd/user/suspend-comms-apps.service
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Suspend comms apps
|
||||||
|
PartOf=idle.target
|
||||||
|
Before=idle.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
ExecStart=bash -c 'echo 1 > /sys/fs/cgroup/user.slice/user-%U.slice/user@%U.service/app.slice/app-comms.slice/cgroup.freeze'
|
||||||
|
ExecStop=bash -c 'echo 0 > /sys/fs/cgroup/user.slice/user-%U.slice/user@%U.service/app.slice/app-comms.slice/cgroup.freeze'
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=idle.target
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description = Sway workspace context manager for dynamic-monitor setups
|
Description=Sway workspace context manager for dynamic-monitor setups
|
||||||
PartOf=sway-session.target
|
PartOf=sway-session.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=dbus
|
Type=dbus
|
||||||
BusName=dev.ezri.sway
|
BusName=dev.ezri.sway
|
||||||
ExecStart=/usr/bin/sway_context_manager
|
ExecSearchPath=
|
||||||
|
ExecSearchPath=%h/.pyenv/shims:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
|
||||||
|
Environment=PATH=%h/.pyenv/shims:%h/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
|
||||||
|
Environment=PYENV_ROOT=%h/.pyenv
|
||||||
|
Environment=PYENV_VERSION=sway
|
||||||
|
ExecStart=sway_context_manager
|
||||||
Slice=session.slice
|
Slice=session.slice
|
||||||
Restart=on-abnormal
|
Restart=on-abnormal
|
||||||
RestartSec=5s
|
RestartSec=5s
|
||||||
|
|||||||
9
.config/systemd/user/sway-env-cleanup.service
Normal file
9
.config/systemd/user/sway-env-cleanup.service
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Clean up sway session enviornment variables from the service manager
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=%h/.local/bin/sway-session-manager.sh
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sway-session-shutdown.target
|
||||||
6
.config/systemd/user/sway-session-pre.target
Normal file
6
.config/systemd/user/sway-session-pre.target
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Sway session services which should run early before the graphical session is brought up
|
||||||
|
Documentation=man:systemd.special(7)
|
||||||
|
Requires=basic.target
|
||||||
|
RefuseManualStart=yes
|
||||||
|
StopWhenUnneeded=yes
|
||||||
4
.config/systemd/user/sway-session-shutdown.target
Normal file
4
.config/systemd/user/sway-session-shutdown.target
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Cleanup tasks for Sway compositor sessions that run after the compositor shuts down
|
||||||
|
RefuseManualStart=yes
|
||||||
|
StopWhenUnneeded=yes
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Sway compositor session
|
Description=Sway compositor session
|
||||||
Documentation=man:systemd.special
|
Documentation=man:systemd.special(7)
|
||||||
BindsTo=graphical-session.target
|
BindsTo=graphical-session.target
|
||||||
Wants=graphical-session-pre.target
|
Wants=sway-session-pre.target
|
||||||
After=graphical-session-pre.target
|
After=sway-session-pre.target
|
||||||
|
Requisite=sway.scope
|
||||||
|
RefuseManualStart=yes
|
||||||
|
StopWhenUnneeded=yes
|
||||||
|
|||||||
13
.config/systemd/user/swaylock.service
Normal file
13
.config/systemd/user/swaylock.service
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Sway screen locker
|
||||||
|
Documentation=man:swaylock(1)
|
||||||
|
Requisite=sway-session.target
|
||||||
|
Wants=logind-lockhint.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=forking
|
||||||
|
ExecStart=swaylock -f
|
||||||
|
KillSignal=SIGUSR1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
Alias=screenlock.service
|
||||||
13
.config/systemd/user/wallpaper.service
Normal file
13
.config/systemd/user/wallpaper.service
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Wallpaper daemon
|
||||||
|
PartOf=sway-session.target
|
||||||
|
Before=sway-session.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify-reload
|
||||||
|
ExecStart=%h/.local/lib/voidshell/background
|
||||||
|
NotifyAccess=all
|
||||||
|
Slice=background.slice
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sway-session.target
|
||||||
8
.config/systemd/user/zsh-.scope.d/resource-limits.conf
Normal file
8
.config/systemd/user/zsh-.scope.d/resource-limits.conf
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[Scope]
|
||||||
|
MemoryAccounting=yes
|
||||||
|
|
||||||
|
CPUQuota=400%
|
||||||
|
MemoryHigh=2G
|
||||||
|
MemoryMax=4G
|
||||||
|
|
||||||
|
TasksMax=100
|
||||||
101
.config/voidshell/README.md
Normal file
101
.config/voidshell/README.md
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# VoidShell Configuration
|
||||||
|
|
||||||
|
VoidShell is configured using a YAML file consisting of multiple top-level objects:
|
||||||
|
|
||||||
|
- `outputs` contains output definitions, which are referenced elsewhere by name
|
||||||
|
- `workspaces` contains worksapce definitions, which are referenced by ID
|
||||||
|
- `layouts` contains information about various output layouts that VoidShell will attempt to load when connected outputs change
|
||||||
|
- `contexts` contains information about a "context", which describes what workspaces should be present on which outputs and in what order, based on the current layout
|
||||||
|
- `config` contains global configuration variables that can be referenced elsewhere in the config file using Python format string syntax (`{var_name}`). Due to limitations with Python's `format` function, this object must be flat, i.e., contain only primitive values.
|
||||||
|
|
||||||
|
Additionally, there is a top-level `import` directive, which takes a list of file paths to other YAML files, allowing composable configuration. Relative paths are interpreted as being from the location of the *main config file*, not the file in which the `import` directive appears. If a listed file does not exist, it is ignored.
|
||||||
|
|
||||||
|
Imports are processed in a depth-first manner.
|
||||||
|
|
||||||
|
Finally, there is a top-level `default-context` directive, which specifies which context VoidShell should start in. If not specified, the first non-`default` context will be used, unless `default` is the only defined context in which case `default` will be used.
|
||||||
|
|
||||||
|
## Output Section
|
||||||
|
|
||||||
|
The `output` section defines the display outputs known to VoidShell. These are physical monitors, identified by various criteria, but should form a one-to-one mapping from the definition to the monitor. This should generally be accomplished by including make, model, and serial number, but for a laptop, the name `eDP-1` will nearly always refer exclusively to the built-in display, making it useful for those laptop panels which do not report a serial number in their EDIDs.
|
||||||
|
|
||||||
|
It consists of a mapping of internal output name to output definition.
|
||||||
|
|
||||||
|
Multiple output sections are concatenated together. If an output is defined twice, the definitions will be merged, with later appearances overwriting duplicate keys, unless stated otherwise.
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
- `criteria`: Match criteria. The following criteria are available, and all must match for the output to be used:
|
||||||
|
- `name`: The name of the output as reported by the compositor. This changes based on what port the monitor is plugged into, and should therefore not be used for any external displays unless absolutely necessary. Can also be a list of names, in which case will match on any of them (OR filter)
|
||||||
|
- `hostname`: The hostname of the computer VoidShell is running on. Can also be a list of hostnames, in which case will match on any of them (OR filter)
|
||||||
|
- `make`: The make of the monitor, reported by EDID
|
||||||
|
- `model`: The model of the monitor, reported by EDID
|
||||||
|
- `serial`: The serial "number" of the monitor, reported by EDID
|
||||||
|
- `modes`: A list of modes which must be available. All modes listed must be available (AND filter). Undefined attributes are ignored (wildcard match).
|
||||||
|
- `width`: The width in pixels
|
||||||
|
- `height`: The height in pixels
|
||||||
|
- `refresh`: The integer refresh rate in millihertz
|
||||||
|
- `picture_aspect_ratio`: The aspect ratio listed in the EDID (not necessarily equal to `width / height`)
|
||||||
|
- `eww-windows`: A list of EWW (ElKowar's Wacky Widgets) windows to open when this output is activated, or an object mapping the name of an EWW window to additional variables to pass when opening the window.
|
||||||
|
- `options`: An object mapping configuration option names to values. When running under Sway, any unrecognized options will simply be added to the configuration command in the form `{option_name} {option_value}`. Duplicate `options` are merged, with later appearances overwriting duplicate keys. All options are optional, with the compositor determining what to do when an option is absent. The following options are understood:
|
||||||
|
- `resolution`: The resolution to set the output to. Must be a defined mode reported by the monitor EDID. Mutually exclusive with `custom-mode`.
|
||||||
|
- `refresh`: The refresh rate in millihertz. Added to `resolution` to produce the final mode line. Must be a defined refresh rate for the resolution. Mutually exclusive with `custom-mode`.
|
||||||
|
- `custom-mode`: The modeline to set the output to. Does not need to be defined by the monitor's EDID. Use with caution. Mutually exclusive with `mode` and `refresh`.
|
||||||
|
- `scale`: The scaling factor of the output.
|
||||||
|
|
||||||
|
## Workspaces Section
|
||||||
|
|
||||||
|
The `workspaces` section defines the workspaces that VoidShell manages. These are implemented using the underlying compositor's workspace system.
|
||||||
|
|
||||||
|
Workspaces have a concept of a "default application", which is the program that will be executed on this workspace when the default application keybind is pressed. These applications are run in their own cgroups, with logs directed to the user journal unless this is overridden.
|
||||||
|
|
||||||
|
It consists of a mapping of workspace IDs to workspace definitions. The IDs are used to relate the definition to a workspace in the compositor.
|
||||||
|
|
||||||
|
Multiple workspace sections are concatenated together. If a workspace ID is defined multiple times, the last definition is used.
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
- `name`: The name of the workspace that is presented to the user
|
||||||
|
- `application`: The default application of the workspace. The name will have `.desktop` added to the end, and a matching file will be searched for in the standard desktop file locations. Mutually exclusive with `exec`, `args`, and `unit`.
|
||||||
|
- `exec`: The default application of the workspace. This is assumed to be an executable in VoidShell's PATH. It should contain only the executable name or a path to the executable. Mutually exclusive with `application` and `unit`.
|
||||||
|
- `args`: The arguments to pass to the command run with `exec`, excluding `argv[0]` (the program name itself). Optional. Mutually exclusive with `application` and `unit`.
|
||||||
|
- `environ`: A key-value mapping of environment variables and their values to set for the process. Mutually exclusive with `unit`.
|
||||||
|
- `unit`: A SystemD user unit to start as the default application of the workspace. Mutually exclusive with all other default application options.
|
||||||
|
- `systemd`: Boolean value indicating whether the default application should be run under SystemD for process control and logging. Defaults to true, and disabling has no effect if the `unit` option is used.
|
||||||
|
- `log-output`: Boolean value indicating whether the default application should be run with its ouptut (stdout/stderr) connected to the user journal (true), or to `/dev/null` (false). Defaults to true, and disabling has no effect if the `unit` option is used.
|
||||||
|
|
||||||
|
## Layouts Section
|
||||||
|
|
||||||
|
The `layouts` section defines the display layouts that VoidShell will attempt to configure. A scoring system is used to determine the best-fit layout for a given set of connected monitors, and the highest-scoring layout will be activated automatically. However, any compatible layout may be manually selected at any time.
|
||||||
|
|
||||||
|
It consists of a mapping of layout names to layout definitions.
|
||||||
|
|
||||||
|
Multiple layout sections are concatenated together. If a layout name is defined multiple times, the last definition is used.
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
A layout object is a key-value mapping specifying the outputs used. The keys provide layout-local generic names for the outputs (e.g. "left" or "right"), which are referenced by contexts to define workspace groups. These objects have the following structure:
|
||||||
|
|
||||||
|
- `required`: Boolean value indicating whether the output must be present to activate the layout. Optional outputs still contribute to score when present, but do not remove the layout from consideration when absent. Defaults to true.
|
||||||
|
- `score`: The score that this output contributes to the layout when matched. Default is based on how the output was matched, detailed in the *Scoring* section.
|
||||||
|
- `position`: The position within the framebuffer to place the output, as a tuple of the form `[x, y]`. Values can be integers, in which case they are used directly, or strings, in which case they are processed as follows:
|
||||||
|
- They are formatted with both the global configuration (set in the `config` section), and an additional value for each previously-defined output equal to its framebuffer resolution (resolution after scaling) in the current dimension.
|
||||||
|
- This allows to create dynamic output positioning formulae
|
||||||
|
- Unmatched optional outputs will have their values here set to 0, so they can be safely used.
|
||||||
|
- They are then evaluated as mathematical expressions, and the result is used as the position.
|
||||||
|
- `outputs`: A list of outputs that can be used in this layout. If multiple listed outputs are connected, an earlier-listed output will be preferred if it is available.
|
||||||
|
- `options`: An options mapping as in an output definition. It is merged the same as other duplicate option sets, and overrides any keys set in the definition. Useful for e.g. layout-dependent scaling.
|
||||||
|
|
||||||
|
## Contexts Section
|
||||||
|
|
||||||
|
The `contexts` section defines the "contexts" that VoidShell can be used in (e.g. personal, work, school). These contexts define the mappings of workspaces to outputs based on layout.
|
||||||
|
|
||||||
|
It consists of a mapping of context names to context definitions.
|
||||||
|
|
||||||
|
Multiple context sections are concatenated together. If a context name is defined multiple times, the definitions will be merged, with duplicate groups being overridden in full by later definitions and configs merged.
|
||||||
|
|
||||||
|
The special context name `default` allows for the configuration of fallback workspace assignments in case a group is present in the current layout but not configured in the current context. This context cannot be marked active unless it is the only context defined.
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
- `config`: A key-value pairing of configuration values local to this context. Values duplicated from the global config override those in the global config.
|
||||||
|
- `groups`: A key-value pairing of group names to workspace lists. These are matched against the layout-specific output names of the current layout, with group names not defined in the layout being ignored. The workspaces are identified by their IDs.
|
||||||
10
.config/voidshell/config.yml
Normal file
10
.config/voidshell/config.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
vars:
|
||||||
|
battery: BAT1
|
||||||
|
slack:
|
||||||
|
team: E080NNY25MX
|
||||||
|
import:
|
||||||
|
- local.yml
|
||||||
|
- outputs.yml
|
||||||
|
- layouts.yml
|
||||||
|
- contexts.yml
|
||||||
|
- workspaces.yml
|
||||||
115
.config/voidshell/contexts.yml
Normal file
115
.config/voidshell/contexts.yml
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
contexts:
|
||||||
|
work:
|
||||||
|
groups:
|
||||||
|
auxiliary:
|
||||||
|
- media-streaming
|
||||||
|
primary:
|
||||||
|
- console-1
|
||||||
|
- code-1
|
||||||
|
- inet-1
|
||||||
|
- proj-1
|
||||||
|
- misc-image-editor
|
||||||
|
- misc-password
|
||||||
|
- docs-2
|
||||||
|
- comms-zoom
|
||||||
|
- comms-mail
|
||||||
|
- misc-audio
|
||||||
|
left-wing:
|
||||||
|
- console-2
|
||||||
|
- code-2
|
||||||
|
- docs-1
|
||||||
|
- comms-signal
|
||||||
|
- comms-discord
|
||||||
|
right-wing:
|
||||||
|
- console-3
|
||||||
|
- code-3
|
||||||
|
- inet-3
|
||||||
|
- media-music
|
||||||
|
- comms-slack
|
||||||
|
builtin:
|
||||||
|
- console-1
|
||||||
|
- code-1
|
||||||
|
- inet-1
|
||||||
|
- proj-1
|
||||||
|
- docs-1
|
||||||
|
- comms-zoom
|
||||||
|
- media-music
|
||||||
|
- comms-slack
|
||||||
|
- comms-mail
|
||||||
|
- misc-audio
|
||||||
|
entertainment:
|
||||||
|
groups:
|
||||||
|
auxiliary:
|
||||||
|
- media-streaming
|
||||||
|
primary:
|
||||||
|
- console-1
|
||||||
|
- code-1
|
||||||
|
- inet-1
|
||||||
|
- gaming-steam
|
||||||
|
- gaming-minecraft
|
||||||
|
- gaming-dnd
|
||||||
|
- gaming-pf
|
||||||
|
- gaming-other
|
||||||
|
- media-video
|
||||||
|
- misc-audio
|
||||||
|
left-wing:
|
||||||
|
- console-2
|
||||||
|
- gaming-notes-1
|
||||||
|
- inet-2
|
||||||
|
- media-streaming
|
||||||
|
- comms-discord
|
||||||
|
right-wing:
|
||||||
|
- console-3
|
||||||
|
- gaming-notes-2
|
||||||
|
- inet-3
|
||||||
|
- media-webvideo-1
|
||||||
|
- comms-signal
|
||||||
|
builtin:
|
||||||
|
- console-1
|
||||||
|
- gaming-notes-1
|
||||||
|
- gaming-pf
|
||||||
|
- gaming-steam
|
||||||
|
- gaming-minecraft
|
||||||
|
- gaming-dnd
|
||||||
|
- gaming-other
|
||||||
|
- comms-discord
|
||||||
|
- media-video
|
||||||
|
- misc-audio
|
||||||
|
personal:
|
||||||
|
groups:
|
||||||
|
auxiliary:
|
||||||
|
- media-streaming
|
||||||
|
primary:
|
||||||
|
- console-1
|
||||||
|
- code-1
|
||||||
|
- inet-1
|
||||||
|
- gaming-steam
|
||||||
|
- misc-image-editor
|
||||||
|
- misc-password
|
||||||
|
- media-video
|
||||||
|
- comms-matrix
|
||||||
|
- comms-zoom
|
||||||
|
- misc-audio
|
||||||
|
left-wing:
|
||||||
|
- console-2
|
||||||
|
- code-2
|
||||||
|
- inet-2
|
||||||
|
- comms-mail
|
||||||
|
- comms-discord
|
||||||
|
right-wing:
|
||||||
|
- console-3
|
||||||
|
- code-3
|
||||||
|
- inet-3
|
||||||
|
- media-music
|
||||||
|
- comms-signal
|
||||||
|
builtin:
|
||||||
|
- console-1
|
||||||
|
- code-1
|
||||||
|
- inet-1
|
||||||
|
- proj-1
|
||||||
|
- comms-signal
|
||||||
|
- comms-matrix
|
||||||
|
- media-music
|
||||||
|
- comms-discord
|
||||||
|
- comms-mail
|
||||||
|
- misc-audio
|
||||||
33
.config/voidshell/layouts.yml
Normal file
33
.config/voidshell/layouts.yml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
layouts:
|
||||||
|
battlestation:
|
||||||
|
auxiliary:
|
||||||
|
required: false
|
||||||
|
score: 0
|
||||||
|
outputs:
|
||||||
|
- builtin
|
||||||
|
options:
|
||||||
|
scale: 1.5
|
||||||
|
position: [0, 600]
|
||||||
|
left-wing:
|
||||||
|
outputs:
|
||||||
|
- work-left-wing
|
||||||
|
- home-left-wing
|
||||||
|
position: ['{auxiliary}', 0]
|
||||||
|
primary:
|
||||||
|
outputs:
|
||||||
|
- work-center
|
||||||
|
- home-center
|
||||||
|
position: ['{auxiliary} + {left-wing}', 0]
|
||||||
|
right-wing:
|
||||||
|
required: false
|
||||||
|
outputs:
|
||||||
|
- work-right-wing
|
||||||
|
- home-right-wing
|
||||||
|
position: ['{auxiliary} + {left-wing} + {right-wing}', 0]
|
||||||
|
laptop:
|
||||||
|
builtin:
|
||||||
|
outputs:
|
||||||
|
- builtin
|
||||||
|
options:
|
||||||
|
scale: '{scaling-factor}'
|
||||||
|
position: [0, 0]
|
||||||
69
.config/voidshell/outputs.yml
Normal file
69
.config/voidshell/outputs.yml
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
outputs:
|
||||||
|
work-left-wing:
|
||||||
|
criteria:
|
||||||
|
make: Dell Inc.
|
||||||
|
model: DELL U2722D
|
||||||
|
serial: DV3MGH3
|
||||||
|
eww-windows:
|
||||||
|
desktop-leftbar:
|
||||||
|
sidebar:
|
||||||
|
side: left
|
||||||
|
options:
|
||||||
|
resolution: 2560x1440
|
||||||
|
refresh: 59951
|
||||||
|
work-right-wing:
|
||||||
|
criteria:
|
||||||
|
make: Dell Inc.
|
||||||
|
model: DELL U2722D
|
||||||
|
serial: 5X3MGH3
|
||||||
|
eww-windows:
|
||||||
|
desktop-rightbar:
|
||||||
|
sidebar:
|
||||||
|
side: right
|
||||||
|
options:
|
||||||
|
resolution: 2560x1440
|
||||||
|
refresh: 59951
|
||||||
|
work-center:
|
||||||
|
criteria:
|
||||||
|
make: Dell Inc.
|
||||||
|
model: DELL U3818DW
|
||||||
|
serial: 97F8P9350W0L
|
||||||
|
eww-windows:
|
||||||
|
- desktop-mainbar
|
||||||
|
options:
|
||||||
|
resolution: 3840x1600
|
||||||
|
refresh: 59994
|
||||||
|
home-left-wing:
|
||||||
|
criteria:
|
||||||
|
make: ASUSTek COMPUTER INC
|
||||||
|
model: VG245
|
||||||
|
serial: L7LMQS132447
|
||||||
|
eww-windows:
|
||||||
|
desktop-leftbar:
|
||||||
|
sidebar:
|
||||||
|
side: left
|
||||||
|
options:
|
||||||
|
mode: 1920x1080
|
||||||
|
refresh: '75'
|
||||||
|
home-right-wing:
|
||||||
|
criteria:
|
||||||
|
make: ASUSTek COMPUTER INC
|
||||||
|
model: VG245
|
||||||
|
serial: L6LMQS065439
|
||||||
|
eww-windows:
|
||||||
|
desktop-rightbar:
|
||||||
|
sidebar:
|
||||||
|
side: right
|
||||||
|
options:
|
||||||
|
resolution: 1920x1080
|
||||||
|
refresh: '75'
|
||||||
|
home-center:
|
||||||
|
criteria:
|
||||||
|
make: ASUSTek COMPUTER INC
|
||||||
|
model: VG32AQA1A
|
||||||
|
serial: S5LMQS033656
|
||||||
|
eww-windows:
|
||||||
|
- desktop-mainbar
|
||||||
|
options:
|
||||||
|
resolution: 2560x1440
|
||||||
|
refresh: '165'
|
||||||
177
.config/voidshell/workspaces.yml
Normal file
177
.config/voidshell/workspaces.yml
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
workspaces:
|
||||||
|
### ###
|
||||||
|
# Console Workspaces #
|
||||||
|
### ###
|
||||||
|
console-1:
|
||||||
|
name: console
|
||||||
|
exec: console
|
||||||
|
console-2:
|
||||||
|
name: console
|
||||||
|
exec: console
|
||||||
|
console-3:
|
||||||
|
name: console
|
||||||
|
exec: console
|
||||||
|
### ###
|
||||||
|
# Code Workspaces #
|
||||||
|
### ###
|
||||||
|
code-1:
|
||||||
|
name: code
|
||||||
|
exec: emacsclient
|
||||||
|
args:
|
||||||
|
- nc
|
||||||
|
code-2:
|
||||||
|
name: code
|
||||||
|
exec: emacsclient
|
||||||
|
args:
|
||||||
|
- nc
|
||||||
|
code-3:
|
||||||
|
name: code
|
||||||
|
exec: emacsclient
|
||||||
|
args:
|
||||||
|
- nc
|
||||||
|
### ###
|
||||||
|
# Internet Workspaces #
|
||||||
|
### ###
|
||||||
|
inet-1:
|
||||||
|
name: internet
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
inet-2:
|
||||||
|
name: internet
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
inet-3:
|
||||||
|
name: internet
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
### ###
|
||||||
|
# Project Workspaces #
|
||||||
|
### ###
|
||||||
|
proj-1:
|
||||||
|
name: project
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
proj-2:
|
||||||
|
name: project
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
proj-3:
|
||||||
|
name: project
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
### ###
|
||||||
|
# Documentation Workspaces #
|
||||||
|
### ###
|
||||||
|
doc-1:
|
||||||
|
name: project
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
doc-2:
|
||||||
|
name: project
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
doc-3:
|
||||||
|
name: project
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
### ###
|
||||||
|
# Comms Workspaces #
|
||||||
|
### ###
|
||||||
|
comms-discord:
|
||||||
|
name: discord comms
|
||||||
|
exec: discord
|
||||||
|
comms-slack:
|
||||||
|
name: slack comms
|
||||||
|
exec: slack
|
||||||
|
args:
|
||||||
|
- '--enable-features=UseOzonePlatform'
|
||||||
|
- '--ozone-platform=wayland'
|
||||||
|
- '--enable-gpu-rasterization'
|
||||||
|
comms-signal:
|
||||||
|
name: encrypted comms
|
||||||
|
exec: signal-desktop
|
||||||
|
comms-matrix:
|
||||||
|
name: encrypted comms
|
||||||
|
exec: element-desktop
|
||||||
|
comms-zoom:
|
||||||
|
name: video comms
|
||||||
|
exec: zoom
|
||||||
|
comms-mail:
|
||||||
|
name: messages
|
||||||
|
exec: thunderbird
|
||||||
|
environ:
|
||||||
|
MOZ_ENABLE_WAYLAND: 1
|
||||||
|
### ###
|
||||||
|
# Media Workspaces #
|
||||||
|
### ###
|
||||||
|
media-music:
|
||||||
|
name: music
|
||||||
|
exec: feishin
|
||||||
|
media-video:
|
||||||
|
name: video
|
||||||
|
exec: jellyfinmediaplayer
|
||||||
|
media-streaming:
|
||||||
|
name: livestream
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
media-webvideo-1:
|
||||||
|
name: web video
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
media-webvideo-2:
|
||||||
|
name: web video
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
### ###
|
||||||
|
# Gaming Workspaces #
|
||||||
|
### ###
|
||||||
|
gaming-steam:
|
||||||
|
name: steam
|
||||||
|
exec: steam
|
||||||
|
gaming-minecraft:
|
||||||
|
name: minecraft
|
||||||
|
exec: prismlauncher
|
||||||
|
gaming-notes-1:
|
||||||
|
name: notes
|
||||||
|
exec: obsidian
|
||||||
|
gaming-notes-2:
|
||||||
|
name: notes
|
||||||
|
exec: obsidian
|
||||||
|
gaming-dnd:
|
||||||
|
name: 'dungeons & dragons'
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
- 'https://roll20.net'
|
||||||
|
gaming-pf:
|
||||||
|
name: pathfinder
|
||||||
|
exec: firefox
|
||||||
|
args:
|
||||||
|
- '--new-window'
|
||||||
|
- 'https://mossfinder.ezri.dev'
|
||||||
|
gaming-other:
|
||||||
|
name: game
|
||||||
|
### ###
|
||||||
|
# Miscellaneous Workspaces #
|
||||||
|
### ###
|
||||||
|
misc-audio:
|
||||||
|
name: audio mixer
|
||||||
|
exec: pavucontrol
|
||||||
|
misc-password:
|
||||||
|
name: password management
|
||||||
|
exec: bitwarden-desktop
|
||||||
|
misc-image-editor:
|
||||||
|
name: image editor
|
||||||
|
exec: gimp
|
||||||
244
.config/zsh/00-systemd.zsh
Normal file
244
.config/zsh/00-systemd.zsh
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
# Move shell into its own systemd scope if possible
|
||||||
|
if ! hash busctl &>/dev/null; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [[ $_scope_loaded == 1 ]]; then
|
||||||
|
# shell reload, ignore
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
_scope_loaded=1
|
||||||
|
|
||||||
|
# Load new scope unit
|
||||||
|
busctl -q --user call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager StartTransientUnit 'ssa(sv)a(sa(sv))' \
|
||||||
|
"zsh-$$.scope" \
|
||||||
|
replace \
|
||||||
|
2 \
|
||||||
|
PIDs au 1 $$ \
|
||||||
|
Slice s ${SHELL_SLICE:-app-shell.slice} \
|
||||||
|
0 \
|
||||||
|
&>/dev/null # this call fails on a shell re-exec, but we don't really care since the scope will already exist in that case, so forward to dave null
|
||||||
|
|
||||||
|
# Environment variable possibly passed by parent, but we don't want it to be inherited, so unset it
|
||||||
|
unset SHELL_SLICE
|
||||||
|
|
||||||
|
function env_merge {
|
||||||
|
# usage: env_merge <ENVIRON> <VALUE>
|
||||||
|
# If ENVIRON is not already set, set it to VALUE. Then export ENVIRON.
|
||||||
|
: "${(P)1=$2}"
|
||||||
|
export $1
|
||||||
|
}
|
||||||
|
|
||||||
|
# import environment from systemd user daemon.
|
||||||
|
# this is necessary when running in a context not descended from the user manager (e.g. tty login, ssh login, etc.)
|
||||||
|
# use the "env_merge" function defined above to not override existing environment (e.g. SSH-forwarded SSH_AUTH_SOCK or DISPLAY)
|
||||||
|
eval $(systemctl --user show-environment | awk 'match($0, /^([a-zA-Z_]+)=(.*)$/, ary) { print "env_merge " ary[1] " " ary[2] }')
|
||||||
|
|
||||||
|
# discard the env_merge function
|
||||||
|
unset -f env_merge
|
||||||
|
|
||||||
|
# Set and unset variables
|
||||||
|
export INVOCATION_ID=$(systemctl --user show "zsh-$$.scope" | awk -F= '/InvocationID=/{ print $2 }')
|
||||||
|
export SYSTEMD_UNIT="zsh-$$.scope"
|
||||||
|
unset SYSTEMD_EXEC_PID
|
||||||
|
unset JOURNAL_STREAM
|
||||||
|
unset MEMORY_PRESSURE_WATCH
|
||||||
|
unset MEMORY_PRESSURE_WRITE
|
||||||
|
|
||||||
|
|
||||||
|
function lift-constraints() {
|
||||||
|
# Don't lift the PID constraint since there's really no reason a shell should have more than 100 active PIDs. Reap what you sow!
|
||||||
|
env systemctl --user set-property zsh-$$.scope CPUQuota=
|
||||||
|
env systemctl --user set-property zsh-$$.scope MemoryHigh=
|
||||||
|
env systemctl --user set-property zsh-$$.scope MemoryMax=
|
||||||
|
}
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
local args slice type unit passed_envs
|
||||||
|
passed_envs=(SUDO_PROMPT EDITOR SUDO_EDITOR VISUAL)
|
||||||
|
args=(--user --same-dir -q --collect)
|
||||||
|
slice="app-shell.slice"
|
||||||
|
type="scope"
|
||||||
|
while true; do
|
||||||
|
case $1 in
|
||||||
|
--help)
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $0 [OPTIONS] <COMMAND> [ARGS...]
|
||||||
|
|
||||||
|
Invoke a command outside of the shell's execution context, detaching it from any resource
|
||||||
|
constraints on the shell itself.
|
||||||
|
|
||||||
|
It will be run by the user service manager using systemd-run. By default, the command
|
||||||
|
is invoked in the app-shells slice, so is still subject to any restrictions placed
|
||||||
|
on the set of all user shells.
|
||||||
|
|
||||||
|
This is intended to simplify the act of intentionally launching resource-intensive programs
|
||||||
|
(such as compilers) while still limiting most programs in terms of how much they are allowed
|
||||||
|
to consume.
|
||||||
|
|
||||||
|
Some environment variables are inherited by default, which can be disabled with --clean-env:
|
||||||
|
$passed_envs
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
--help - display this help message and exit
|
||||||
|
--app - launch in the main app slice rather than the app-shell slice. Equivalent to --slice app.slice
|
||||||
|
--background - launch in the background slice. Equivalent to --slice background.slice
|
||||||
|
--slice <SLICE> - launch in the specified user slice.
|
||||||
|
--service - create a service unit, rather than a scope, producing a truly clean environment. This separates
|
||||||
|
the program from the shell's process tree, preventing the shell's job management from managing it.
|
||||||
|
--env <VAR>[=VALUE] - inherit the given environment variable from the shell, or set it if a value is given.
|
||||||
|
--clean-env - disable the default set of inherited environment variables
|
||||||
|
--unit <UNIT> - set the unit name. Defaults to "invoke-<shell PID>@<random>" for services,
|
||||||
|
"invoke-<shell PID>-<random>" for scopes.
|
||||||
|
EOF
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
--app)
|
||||||
|
slice="app.slice"
|
||||||
|
;;
|
||||||
|
--background)
|
||||||
|
slice="background.slice"
|
||||||
|
;;
|
||||||
|
--slice)
|
||||||
|
slice=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--service)
|
||||||
|
type="service"
|
||||||
|
;;
|
||||||
|
--env)
|
||||||
|
args+="-E"
|
||||||
|
args+=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--clean-env)
|
||||||
|
passed_envs=()
|
||||||
|
;;
|
||||||
|
--unit)
|
||||||
|
unit=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
for env in $passed_envs; do
|
||||||
|
args+="--setenv=$env"
|
||||||
|
done
|
||||||
|
case $type in
|
||||||
|
service)
|
||||||
|
if [[ $unit == '' ]]; then
|
||||||
|
unit="invoke-$$@$RANDOM.service"
|
||||||
|
fi
|
||||||
|
args+=(--service-type=exec --pty --pipe --wait)
|
||||||
|
;;
|
||||||
|
scope)
|
||||||
|
if [[ $unit == '' ]]; then
|
||||||
|
unit="invoke-$$-$RANDOM.scope"
|
||||||
|
fi
|
||||||
|
args+="--scope"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [[ $unit != *.$type ]]; then
|
||||||
|
echo "Unit suffix does not match unit type! Should end in .$type!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
systemd-run $args --slice=${slice} --unit=${unit} -- "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
function with-group {
|
||||||
|
local args slice unit passed_envs user passed_envs_when_user_is_us
|
||||||
|
passed_envs=(EDITOR VISUAL)
|
||||||
|
passed_envs_when_user_is_us=(DBUS_SESSION_BUS_ADDRESS DISPLAY WAYLAND_DISPLAY XDG_RUNTIME_DIR)
|
||||||
|
args=(--same-dir -q --collect)
|
||||||
|
slice="system.slice"
|
||||||
|
user=$USER
|
||||||
|
groups=${1//,/ }
|
||||||
|
shift
|
||||||
|
while true; do
|
||||||
|
case $1 in
|
||||||
|
--help)
|
||||||
|
cat <<EOF
|
||||||
|
Usage: with-group [OPTIONS] <GROUPS> [<COMMAND> [ARGS...]]
|
||||||
|
|
||||||
|
Invoke a command as the current user with additional supplementary groups. Provides a convenient
|
||||||
|
way to temporarily gain permissions afforded to groups the user does not have, while still retaining
|
||||||
|
regular user permissions (i.e. without switching to another user or fully elevating to root).
|
||||||
|
|
||||||
|
Multiple groups may be specified in a comma-separated list (similar to the -G flag of useradd and usermod).
|
||||||
|
|
||||||
|
It will be run by the system service manager using systemd-run as a transient service. As it has to be
|
||||||
|
invoked by the service manager to gain the additional permissions, there is no way to run it as a scope.
|
||||||
|
|
||||||
|
If no command is specified, the current shell will be launched instead.
|
||||||
|
|
||||||
|
Some environment variables are inherited by default, which can be disabled with --clean-env:
|
||||||
|
$passed_envs
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
--help - display this help message and exit.
|
||||||
|
--slice <SLICE> - launch in the specified system slice.
|
||||||
|
--env <VAR>[=VALUE] - inherit the given environment variable from the shell, or set it if a value is given.
|
||||||
|
--clean-env - disable the default set of inherited environment variables.
|
||||||
|
--unit <UNIT> - set the unit name.
|
||||||
|
--user <USER> - run as the given user rather than the current user.
|
||||||
|
EOF
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
--slice)
|
||||||
|
slice=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--env)
|
||||||
|
args+="-E"
|
||||||
|
args+=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--clean-env)
|
||||||
|
passed_envs=()
|
||||||
|
;;
|
||||||
|
--unit)
|
||||||
|
unit=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--user)
|
||||||
|
user=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
for env in $passed_envs; do
|
||||||
|
args+="--setenv=$env"
|
||||||
|
done
|
||||||
|
if [[ $user == $USER ]]; then
|
||||||
|
for env in $passed_envs_when_user_is_us; do
|
||||||
|
args+="--setenv=$env"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
args+=(--service-type=exec --pty --pipe --wait -p "User=$user" -p "SupplementaryGroups=$groups" -p "PAMName=login")
|
||||||
|
if [[ $unit != "" ]]; then
|
||||||
|
args+=("--unit=$unit")
|
||||||
|
fi
|
||||||
|
if [[ $1 == '' ]]; then
|
||||||
|
systemd-run $args --slice=${slice} -- $SHELL
|
||||||
|
else
|
||||||
|
systemd-run $args --slice=${slice} -- "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
for cmd in $always_detach; do
|
||||||
|
eval $(echo alias $cmd=\"run $cmd\")
|
||||||
|
done
|
||||||
|
|
||||||
|
for cmd in $always_detach_as_service; do
|
||||||
|
eval $(echo alias $cmd=\"run --service $cmd\")
|
||||||
|
done
|
||||||
|
|
||||||
|
alias ssh='run --slice app-ssh.slice --unit ssh-client-$RANDOM.scope ssh'
|
||||||
|
|
||||||
90
.config/zsh/01-introspection.zsh
Normal file
90
.config/zsh/01-introspection.zsh
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#
|
||||||
|
# System introspection script which defines variables for use in later dropins.
|
||||||
|
#
|
||||||
|
# Exposes system data as the SYSTEM_INFO associative array. Primarily pulls information via
|
||||||
|
# systemd-hostnamed if available; falls back to reading /etc/machine-info and /etc/hostname,
|
||||||
|
# or retrieving the system hostname with `uname`. Keys will always be the names of the D-Bus
|
||||||
|
# properties, not their corresponding fields in /etc/machine-info.
|
||||||
|
#
|
||||||
|
# Exposes OS release data as the OS_RELEASE associative array. Data is read directly from
|
||||||
|
# /etc/os-release if available, otherwise it is not provided.
|
||||||
|
#
|
||||||
|
# Exposes all /etc/machine-info fields, including those not defined by the spec, under MACHINE_INFO.
|
||||||
|
# Keys are the field names with no transforms applied.
|
||||||
|
|
||||||
|
_introspection--generate-file-parser() {
|
||||||
|
awk 'match($0, /^([A-Za-z_][A-Za-z0-9_]*)=(.*)/, ary) { print "'"$1"'[" ary[1] "]='\''" ary[2] "'\''"}'
|
||||||
|
}
|
||||||
|
|
||||||
|
_introspection--parse-file() {
|
||||||
|
local varname=$1
|
||||||
|
while read line; do
|
||||||
|
key=${${(LC)line%%=*}//_/}
|
||||||
|
val=${line#*=}
|
||||||
|
eval "${varname}[${key}]=\"${${val%\"}#\"}\""
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
declare -A SYSTEM_INFO
|
||||||
|
declare -A OS_RELEASE
|
||||||
|
declare -A MACHINE_INFO
|
||||||
|
declare -A INTRO_STATE
|
||||||
|
|
||||||
|
refresh-system-info() {
|
||||||
|
INTRO_STATE[SYSTEM_INFO]=none
|
||||||
|
INTRO_STATE[OS_RELEASE]=none
|
||||||
|
INTRO_STATE[MACHINE_INFO]=none
|
||||||
|
INTRO_STATE[hostname]=none
|
||||||
|
|
||||||
|
if [ -f /etc/machine-info ]; then
|
||||||
|
# Populate MACHINE_INFO array
|
||||||
|
_introspection--parse-file MACHINE_INFO </etc/machine-info
|
||||||
|
INTRO_STATE[MACHINE_INFO]=present
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Parse OS release info, trying first from the new os-release file, then from the LSB standard. Variables should have more or less the same names between the two files.
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
_introspection--parse-file OS_RELEASE </etc/os-release
|
||||||
|
INTRO_STATE[OS_RELEASE]=present
|
||||||
|
elif [ -f /etc/lsb_release ]; then
|
||||||
|
_introspection--parse-file OS_RELEASE </etc/lsb_release
|
||||||
|
INTRO_STATE[OS_RELEASE]=legacy_lsb_release
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Parse detailed system info from hostnamectl, or synthesize what we can from /etc/machine-info and static and transient hostnames.
|
||||||
|
if type hostnamectl &>/dev/null && (( $(hostnamectl --version | head -n 1 | cut -d' ' -f2) >= 252 )); then
|
||||||
|
# We can get all relevant data from hostnamectl, so lets do that.
|
||||||
|
eval $(hostnamectl --json=short | jq -r 'to_entries | .[] | select((.value | type) != "array" and (.value | type) != "object" and (.value | type) != "null") | "SYSTEM_INFO[\(.key)]=\(.value | @sh)"')
|
||||||
|
INTRO_STATE[SYSTEM_INFO]=full
|
||||||
|
INTRO_STATE[hostname]=full
|
||||||
|
else
|
||||||
|
# Parse machine info if available
|
||||||
|
if [[ ${INTRO_STATE[MACHINE_INFO]} == present ]]; then
|
||||||
|
# Populate SYSTEM_INFO array as best as possible (this will be missing a _lot_ of fields that hostnamed calculates)
|
||||||
|
local shared_keys=(PrettyHostname IconName Chassis Deployment Location HardwareVendor HardwareModel HardwareVersion)
|
||||||
|
for key val in "${(@kv)MACHINE_INFO}"; do
|
||||||
|
case $key in
|
||||||
|
HardwareSku)
|
||||||
|
SYSTEM_INFO[HardwareSKU]=${MACHINE_INFO[HardwareSku]}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [[ ${${key:*shared_keys}:+x} == 'x' ]]; then
|
||||||
|
SYSTEM_INFO[$key]=${MACHINE_INFO[$key]}
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
INTRO_STATE[SYSTEM_INFO]=limited
|
||||||
|
fi
|
||||||
|
# Read current (transient) hostname
|
||||||
|
SYSTEM_INFO[Hostname]=$(uname -n)
|
||||||
|
INTRO_STATE[hostname]=transient
|
||||||
|
# Read static hostname if available
|
||||||
|
if [ -f /etc/hostname ]; then
|
||||||
|
SYSTEM_INFO[StaticHostname]=$(</etc/hostname)
|
||||||
|
INTRO_STATE[hostname]=full
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh-system-info
|
||||||
65
.config/zsh/02-colors.zsh
Normal file
65
.config/zsh/02-colors.zsh
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#
|
||||||
|
# Color control code variables
|
||||||
|
#
|
||||||
|
|
||||||
|
declare -A fg
|
||||||
|
declare -A bg
|
||||||
|
declare -A ctrl
|
||||||
|
|
||||||
|
fg[black]=$'\033[30m'
|
||||||
|
fg[blue]=$'\033[34m'
|
||||||
|
fg[red]=$'\033[31m'
|
||||||
|
fg[green]=$'\033[32m'
|
||||||
|
fg[magenta]=$'\033[35m'
|
||||||
|
fg[cyan]=$'\033[36m'
|
||||||
|
fg[yellow]=$'\033[33m'
|
||||||
|
fg[white]=$'\033[37m'
|
||||||
|
|
||||||
|
fg[bright_black]=$'\033[90m'
|
||||||
|
fg[bright_blue]=$'\033[94m'
|
||||||
|
fg[bright_red]=$'\033[91m'
|
||||||
|
fg[bright_green]=$'\033[92m'
|
||||||
|
fg[bright_magenta]=$'\033[95m'
|
||||||
|
fg[bright_cyan]=$'\033[96m'
|
||||||
|
fg[bright_yellow]=$'\033[93m'
|
||||||
|
fg[bright_white]=$'\033[97m'
|
||||||
|
|
||||||
|
fg[reset]=$'\033[39m'
|
||||||
|
|
||||||
|
bg[black]=$'\033[40m'
|
||||||
|
bg[blue]=$'\033[44m'
|
||||||
|
bg[red]=$'\033[41m'
|
||||||
|
bg[green]=$'\033[42m'
|
||||||
|
bg[magenta]=$'\033[45m'
|
||||||
|
bg[cyan]=$'\033[46m'
|
||||||
|
bg[yellow]=$'\033[43m'
|
||||||
|
bg[white]=$'\033[47m'
|
||||||
|
|
||||||
|
bg[bright_black]=$'\033[100m'
|
||||||
|
bg[bright_blue]=$'\033[104m'
|
||||||
|
bg[bright_red]=$'\033[101m'
|
||||||
|
bg[bright_green]=$'\033[102m'
|
||||||
|
bg[bright_magenta]=$'\033[105m'
|
||||||
|
bg[bright_cyan]=$'\033[106m'
|
||||||
|
bg[bright_yellow]=$'\033[103m'
|
||||||
|
bg[bright_white]=$'\033[107m'
|
||||||
|
|
||||||
|
bg[reset]=$'\033[49m'
|
||||||
|
|
||||||
|
ctrl[reset]=$'\033[0m'
|
||||||
|
ctrl[bold]=$'\033[1m'
|
||||||
|
ctrl[faint]=$'\033[2m'
|
||||||
|
ctrl[italic]=$'\033[3m'
|
||||||
|
ctrl[underline]=$'\033[4m'
|
||||||
|
ctrl[slowblink]=$'\033[5m'
|
||||||
|
ctrl[fastblink]=$'\033[6m'
|
||||||
|
ctrl[invert]=$'\033[7m'
|
||||||
|
ctrl[hide]=$'\033[8m'
|
||||||
|
ctrl[strike]=$'\033[9m'
|
||||||
|
ctrl[nobold]=$'\033[22m'
|
||||||
|
ctrl[noitalic]=$'\033[23m'
|
||||||
|
ctrl[nounderline]=$'\033[24m'
|
||||||
|
ctrl[noblink]=$'\033[25m'
|
||||||
|
ctrl[noinvert]=$'\033[27m'
|
||||||
|
ctrl[nohide]=$'\033[28m'
|
||||||
|
ctrl[nostrike]=$'\033[29m'
|
||||||
178
.config/zsh/05-prompt-pre.zsh
Normal file
178
.config/zsh/05-prompt-pre.zsh
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
#
|
||||||
|
# Initial setup for prompt generation.
|
||||||
|
#
|
||||||
|
# Defines the arrays for prompt elements ($prompt_list), rprompt elements ($rprompt_list), and history prompt elements ($history_prompt, the prompt is rewritten using this when a command is submitted).
|
||||||
|
#
|
||||||
|
# Prompt elements are strings. Some special prefixes are understood:
|
||||||
|
# - Strings prefixed with 'func:' will run the function given, using the contents of ${prompt_element_contents} as the element. Argument splitting is performed, but variable interpolation is not (you should be able to do that yourself).
|
||||||
|
# - Strings prefixed with 'var:' will expand the given variable specifier when the prompt is generated, within curly braces. This allows specifying that the given variable be evaluated at generation time.
|
||||||
|
# - Strings prefixed with 'literal:' will use the remaining string literally. This allows a static component which starts with "func:" or "var:" if you want to for whatever reason.
|
||||||
|
#
|
||||||
|
# We set the prompt_subst option, so variables can be included in prompt elements (e.g. in single quotes), and changes to them will be reflected the next time the prompt renders.
|
||||||
|
#
|
||||||
|
# We also set precmd_functions to an empty array in this file, so it should be extended.
|
||||||
|
|
||||||
|
declare -a prompt_list
|
||||||
|
declare -a rprompt_list
|
||||||
|
declare -a history_prompt
|
||||||
|
declare -A prompt_elements
|
||||||
|
|
||||||
|
setopt prompt_subst
|
||||||
|
precmd_functions=()
|
||||||
|
|
||||||
|
prompt_elements[privilege]='%B%0(#.%F{red} as root.%(!.%F{red} with privileges.))%b'
|
||||||
|
|
||||||
|
prompt-element-host() {
|
||||||
|
# Adds host info to the prompt.
|
||||||
|
if [[ ${SYSTEM_INFO[Chassis]} == "container" ]] || [[ ${SYSTEM_INFO[Chassis]} == "vm" ]]; then
|
||||||
|
prompt_element_contents='%F{blue}%B${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}}%b%f'
|
||||||
|
elif [[ -v SSH_CLIENT ]]; then
|
||||||
|
prompt_element_contents='%F{blue}%BRemote Console%b%f @ %F{magenta}%B${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}}%b%f'
|
||||||
|
elif [[ -o login ]]; then
|
||||||
|
prompt_element_contents='%F{green}%BLogin Console%b%f @ %F{magenta}%B${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}}%b%f'
|
||||||
|
else
|
||||||
|
prompt_element_contents='%F{magenta}%B${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}}%f%b'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
prompt_elements[host]="func:prompt-element-host"
|
||||||
|
|
||||||
|
prompt-element-console() {
|
||||||
|
if [[ ${TTY} =~ "tty" ]]; then
|
||||||
|
prompt_element_contents=" %F{red}%y%f"
|
||||||
|
else
|
||||||
|
prompt_element_contents=""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
prompt_elements[console]="func:prompt-element-console"
|
||||||
|
|
||||||
|
prompt-element-deployment() {
|
||||||
|
if [[ ${SYSTEM_INFO[Deployment]+yes} == "yes" ]]; then
|
||||||
|
case ${(L)SYSTEM_INFO[Deployment]} in
|
||||||
|
*prod|production)
|
||||||
|
prompt_element_contents='%F{red}%BPROD%b%f '
|
||||||
|
;;
|
||||||
|
*devl|dev|devel|development)
|
||||||
|
prompt_element_contents='%F{green}%BDEV%b%f '
|
||||||
|
;;
|
||||||
|
*pprd|preprod|preproduction)
|
||||||
|
prompt_element_contents='%F{cyan}%BPRE-PROD%b%f '
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
prompt_element_contents='%F{blue}%B${(U)SYSTEM_INFO[Deployment]}%b%f '
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
prompt_elements[deployment]="func:prompt-element-deployment"
|
||||||
|
|
||||||
|
prompt_elements[retcode]="%(?..%F{red} %?%f)"
|
||||||
|
prompt_elements[prompt]="%(?.❯.%F{red}❯%f) "
|
||||||
|
prompt_elements[pwd]="%B%F{blue}%3~%f%b"
|
||||||
|
prompt_elements[pyenv]='$pyenv_info_msg_0_'
|
||||||
|
prompt_elements[vcs]='$vcs_info_msg_0_'
|
||||||
|
|
||||||
|
prompt_elements[clock]='%F{yellow}%T%f'
|
||||||
|
|
||||||
|
prompt-element-groups() {
|
||||||
|
# Produces newlines at start and end.
|
||||||
|
local ambient_groups defined_groups ambient_map defined_map
|
||||||
|
declare -A ambient_map
|
||||||
|
declare -A defined_map
|
||||||
|
ambient_groups=($(id -Gn))
|
||||||
|
defined_groups=($(id -Gn ${USER}))
|
||||||
|
prompt_element_contents=$'\n'
|
||||||
|
# yay 3 loops :/
|
||||||
|
for group in "${ambient_groups[@]}"; do
|
||||||
|
ambient_map[$group]=1
|
||||||
|
done
|
||||||
|
for group in "${defined_groups[@]}"; do
|
||||||
|
defined_map[$group]=1
|
||||||
|
if [ ${ambient_map[$group]:-0} -eq 0 ]; then
|
||||||
|
prompt_element_contents+=" %F{red}$group%f"$'\n'
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
for group in "${ambient_groups[@]}"; do
|
||||||
|
if [ ${defined_map[${group}]:-0} -eq 0 ]; then
|
||||||
|
prompt_element_contents+=" %F{green}$group%f"$'\n'
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
prompt_elements[groups]='func:prompt-element-groups'
|
||||||
|
|
||||||
|
_build-prompt() {
|
||||||
|
PROMPT=""
|
||||||
|
for el in "${prompt_list[@]}"; do
|
||||||
|
case $el in
|
||||||
|
func:*)
|
||||||
|
# Clear the variable
|
||||||
|
prompt_element_contents=''
|
||||||
|
# Run the function
|
||||||
|
${=el/func:/}
|
||||||
|
# Add the variable to the prompt
|
||||||
|
PROMPT+="${prompt_element_contents}"
|
||||||
|
;;
|
||||||
|
var:*)
|
||||||
|
# eval the variable.
|
||||||
|
eval "PROMPT+=\"\${${el/var:/}}\""
|
||||||
|
;;
|
||||||
|
literal:*)
|
||||||
|
# strip the leading 'literal:' and add the string to the prompt
|
||||||
|
PROMPT+="${el/literal:/}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# not a known prefix, so just add it as a string
|
||||||
|
PROMPT+="${el}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
RPROMPT=""
|
||||||
|
for el in "${rprompt_list[@]}"; do
|
||||||
|
case $el in
|
||||||
|
func:*)
|
||||||
|
# Clear the variable
|
||||||
|
prompt_element_contents=''
|
||||||
|
# Run the function
|
||||||
|
${=el/func:/}
|
||||||
|
# Add the variable to the prompt
|
||||||
|
RPROMPT+="${prompt_element_contents}"
|
||||||
|
;;
|
||||||
|
var:*)
|
||||||
|
# eval the variable.
|
||||||
|
eval "RPROMPT+=\"\${${el/var:/}}\""
|
||||||
|
;;
|
||||||
|
literal:*)
|
||||||
|
# strip the leading 'literal:' and add the string to the prompt
|
||||||
|
RPROMPT+="${el/literal:/}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# not a known prefix, so just add it as a string
|
||||||
|
RPROMPT+="${el}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
HISTORY_UNPROMPT=""
|
||||||
|
for el in "${history_prompt[@]}"; do
|
||||||
|
case $el in
|
||||||
|
func:*)
|
||||||
|
# Clear the variable
|
||||||
|
prompt_element_contents=''
|
||||||
|
# Run the function
|
||||||
|
${=el/func:/}
|
||||||
|
# Add the variable to the prompt
|
||||||
|
HISTORY_UNPROMPT+="${prompt_element_contents}"
|
||||||
|
;;
|
||||||
|
var:*)
|
||||||
|
# eval the variable.
|
||||||
|
eval "HISTORY_UNPROMPT+=\"\${${el/var:/}}\""
|
||||||
|
;;
|
||||||
|
literal:*)
|
||||||
|
# strip the leading 'literal:' and add the string to the prompt
|
||||||
|
HISTORY_UNPROMPT+="${el/literal:/}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# not a known prefix, so just add it as a string
|
||||||
|
HISTORY_UNPROMPT+="${el}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
export ASDF_DATA_DIR=$HOME/.local/share/asdf-vm
|
export ASDF_DATA_DIR=$HOME/.local/share/asdf-vm
|
||||||
|
|
||||||
|
export RUSTUP_HOME=$HOME/.local/lib/rustup
|
||||||
|
export CARGO_HOME=$HOME/.local/lib/cargo
|
||||||
|
|
||||||
PATH_pyenv=$HOME/.pyenv/bin:$HOME/.pyenv/shims:/opt/pyenv/pyenv-virtualenv/shims
|
PATH_pyenv=$HOME/.pyenv/bin:$HOME/.pyenv/shims:/opt/pyenv/pyenv-virtualenv/shims
|
||||||
PATH_asdf=$ASDF_DATA_DIR/shims:/opt/asdf-vm/bin
|
PATH_asdf=$ASDF_DATA_DIR/shims:/opt/asdf-vm/bin
|
||||||
PATH_node=$HOME/.opt/npm/bin
|
PATH_node=$HOME/.opt/npm/bin
|
||||||
@@ -8,10 +11,11 @@ PATH_perl=/usr/bin/vendor_perl:/usr/bin/core_perl
|
|||||||
PATH_system=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
PATH_system=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
PATH_user=$HOME/.local/bin
|
PATH_user=$HOME/.local/bin
|
||||||
PATH_wincmake=/opt/msvcmake/bin:/opt/msvc/bin/x64
|
PATH_wincmake=/opt/msvcmake/bin:/opt/msvc/bin/x64
|
||||||
|
PATH_cargo=$CARGO_HOME/bin
|
||||||
|
|
||||||
cdpath=(~ ~/src)
|
cdpath=(~ ~/src)
|
||||||
|
|
||||||
export PATH=.:$PATH_asdf:$PATH_node:$PATH_pyenv:$PATH_java:$PATH_user:$PATH_system
|
export PATH=.:$PATH_node:$PATH_cargo:$PATH_pyenv:$PATH_java:$PATH_user:$PATH_system
|
||||||
|
|
||||||
# Function to run a command with only the "safe" system PATH element
|
# Function to run a command with only the "safe" system PATH element
|
||||||
function safeexec {
|
function safeexec {
|
||||||
@@ -12,13 +12,20 @@ function getkernelpkg() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# function docker() {
|
||||||
|
# # Wrapper for docker command that executes it inside the systemd-nspawn docker container
|
||||||
|
# # This container has our home directory bound, so we should cd to the current directory before running this command
|
||||||
|
|
||||||
|
# ssh -t dockerbox "env ORIGINALWD=\"$(pwd)\" ~/.local/bin/dockerbox.sh $*"
|
||||||
|
#}
|
||||||
|
|
||||||
function random-xkcd() {
|
function random-xkcd() {
|
||||||
blocklist=(
|
blocklist=(
|
||||||
"404"
|
"404"
|
||||||
"631" # "Anatomy Text", don't want that coming up in public thanks
|
"631" # "Anatomy Text", don't want that coming up in public thanks
|
||||||
)
|
)
|
||||||
link="https://xkcd.com/404/"
|
link="https://xkcd.com/404/"
|
||||||
while (( $blocklist[(Ie)$(basename $link)] )); do
|
while (( ${blocklist[(Ie)$(basename $link)]} )); do
|
||||||
link=$(curl https://c.xkcd.com/random/comic/ -v |& grep location | cut -d' ' -f3 | sed 's/\r//')
|
link=$(curl https://c.xkcd.com/random/comic/ -v |& grep location | cut -d' ' -f3 | sed 's/\r//')
|
||||||
done
|
done
|
||||||
html=$(curl -L ${link/http:/https:} 2>/dev/null)
|
html=$(curl -L ${link/http:/https:} 2>/dev/null)
|
||||||
@@ -30,12 +37,12 @@ function random-xkcd() {
|
|||||||
curl $(echo $html | (echo "https:"$(xmllint --html --xpath 'string(//html/body/div[@id="middleContainer"]/div[@id="comic"]/img/@src)' - 2>/dev/null))) 2>/dev/null | feh -
|
curl $(echo $html | (echo "https:"$(xmllint --html --xpath 'string(//html/body/div[@id="middleContainer"]/div[@id="comic"]/img/@src)' - 2>/dev/null))) 2>/dev/null | feh -
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $(hostnamectl chassis) == "container" ]]; then
|
if [[ ${SYSTEM_INFO[Chassis]} == "container" ]]; then
|
||||||
DEFAULT_WINDOW_NAME="Container Connection: [ $os_icon $hostname Console ]"
|
DEFAULT_WINDOW_NAME="[ Container Connection ] ${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}} Console"
|
||||||
elif [[ -z "${SSH_CONNECTION+x}" ]]; then
|
elif [[ -z "${SSH_CONNECTION+x}" ]]; then
|
||||||
DEFAULT_WINDOW_NAME="$os_icon $hostname Console"
|
DEFAULT_WINDOW_NAME="${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}} Console"
|
||||||
else
|
else
|
||||||
DEFAULT_WINDOW_NAME="Remote Connection: [ $os_icon $hostname Console ]"
|
DEFAULT_WINDOW_NAME="[ Remote Connection ] ${SYSTEM_INFO[PrettyHostname]:-${SYSTEM_INFO[Hostname]}} Console"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function _rename_window() {
|
function _rename_window() {
|
||||||
@@ -113,16 +120,12 @@ function bwunlock() {
|
|||||||
|
|
||||||
# Attempt to read Bitwarden password from keyring
|
# Attempt to read Bitwarden password from keyring
|
||||||
if ! (( skipkeyring )); then
|
if ! (( skipkeyring )); then
|
||||||
bwpasswd=$(secret-tool lookup service $secretstore 2>/dev/null)
|
bwpasswd=$(kwallet-query -r bitwarden kdewallet 2>/dev/null)
|
||||||
fi
|
fi
|
||||||
if [[ -z "${bwpasswd}" ]]; then
|
if [[ -z "${bwpasswd}" ]]; then
|
||||||
# If password is not found in keyring, prompt for it
|
# If password is not found in keyring, prompt for it
|
||||||
read -s -p "Enter Bitwarden password: " bwpasswd
|
read -s -p "Enter Bitwarden password: " bwpasswd
|
||||||
echo
|
echo
|
||||||
# Store Bitwarden password in keyring
|
|
||||||
if ! (( skipkeyring )); then
|
|
||||||
secret-tool store --label="Bitwarden" service $secretstore
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
# Unlock Bitwarden vault and export session key
|
# Unlock Bitwarden vault and export session key
|
||||||
export BW_SESSION=$(eval $bwcmd unlock --raw "'$bwpasswd'" 2>/dev/tty)
|
export BW_SESSION=$(eval $bwcmd unlock --raw "'$bwpasswd'" 2>/dev/tty)
|
||||||
@@ -134,3 +137,76 @@ function bwunlock() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if type machinectl &>/dev/null; then
|
||||||
|
function su {
|
||||||
|
local user
|
||||||
|
user=$1
|
||||||
|
if [[ $user == '' ]]; then
|
||||||
|
user=root
|
||||||
|
fi
|
||||||
|
machinectl -q shell "${user}@"
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
alias relog='exec machinectl -q shell "${USER}@"'
|
||||||
|
|
||||||
|
function urlencode {
|
||||||
|
# credit to https://stackoverflow.com/a/34407620 for the jq solution
|
||||||
|
local multiline=0
|
||||||
|
if [[ "$1" == "-m" ]] || [[ "$1" == "--multiline" ]]; then
|
||||||
|
# Multiline mode, read directly from stdin
|
||||||
|
multiline=1
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
# Read from stdin
|
||||||
|
if (( multiline )); then
|
||||||
|
jq -sRr '@uri'
|
||||||
|
else
|
||||||
|
# Treat each line as a separate argument, and encode them separately
|
||||||
|
for line in $(cat); do
|
||||||
|
echo -n "$line" | jq -sRr '@uri'
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Read from arguments (use echo because arguments may contain spaces and --arg wasn't working)
|
||||||
|
echo -n $@ | jq -sRr '@uri'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function ssh-copy-shell {
|
||||||
|
# Copy shell config to the given SSH host
|
||||||
|
local port=22 host
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case $1 in
|
||||||
|
-p|--port)
|
||||||
|
port=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--port=*)
|
||||||
|
port=${1/--port=/}
|
||||||
|
;;
|
||||||
|
*:*)
|
||||||
|
host=${1/:*/}
|
||||||
|
port=${1/*:/}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
host=$1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
if [[ ${host+x} != x ]]; then
|
||||||
|
echo "Target host is required!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
ssh -p ${port} ${host} mkdir -p .config .local/lib
|
||||||
|
# Deploy files
|
||||||
|
sftp -P ${port} ${host} <<SFTP
|
||||||
|
lcd ~
|
||||||
|
put -R .config/zsh .config
|
||||||
|
put -R .local/lib/zsh .local/lib
|
||||||
|
put .zshrc
|
||||||
|
SFTP
|
||||||
|
}
|
||||||
@@ -2,12 +2,11 @@
|
|||||||
|
|
||||||
alias emacs="TERM=screen-256color emacsclient -t"
|
alias emacs="TERM=screen-256color emacsclient -t"
|
||||||
|
|
||||||
alias systemctl="sudo systemctl"
|
alias userctl="systemctl --user"
|
||||||
alias userctl="\systemctl --user"
|
|
||||||
|
|
||||||
alias ujournalctl="\journalctl --user"
|
alias ujournalctl="\journalctl --user"
|
||||||
|
|
||||||
alias reconf="source $HOME/.zshrc"
|
alias reconf="exec zsh"
|
||||||
|
|
||||||
alias cp="cp -i --reflink=auto"
|
alias cp="cp -i --reflink=auto"
|
||||||
alias mv="mv -i"
|
alias mv="mv -i"
|
||||||
@@ -22,15 +21,19 @@ alias l='ls -lh'
|
|||||||
|
|
||||||
alias nuke='echo "Are you sure?"; read -q && rm -rf'
|
alias nuke='echo "Are you sure?"; read -q && rm -rf'
|
||||||
|
|
||||||
alias sudo='sudo '
|
alias pkgfile='pkgfile -D $HOME/.cache/pkgfile'
|
||||||
|
|
||||||
alias sign='gpg --sign-with ezri@ezri.dev --detach-sign'
|
alias sign='gpg --sign-with ezri@ezri.dev --detach-sign'
|
||||||
alias verify='gpg --verify'
|
alias verify='gpg --verify'
|
||||||
|
|
||||||
|
alias dnslookup="resolvectl query"
|
||||||
|
|
||||||
|
alias ip="ip -color=auto"
|
||||||
|
|
||||||
alias bw-personal='BITWARDENCLI_APPDATA_DIR=~/.config/bw-cli-personal bw'
|
alias bw-personal='BITWARDENCLI_APPDATA_DIR=~/.config/bw-cli-personal bw'
|
||||||
|
|
||||||
function didifuckingstutter {
|
function didifuckingstutter {
|
||||||
echo $fg[blue]Apologies, right away.$fg[default]
|
echo $fg[blue]Apologies, milady. Right away.$fg[default]
|
||||||
# Run the last command as root
|
# Run the last command as root
|
||||||
last_cmd=$(fc -ln -1)
|
last_cmd=$(fc -ln -1)
|
||||||
# if last command was emacs, use TRAMP rather than running as root
|
# if last command was emacs, use TRAMP rather than running as root
|
||||||
@@ -39,7 +42,7 @@ function didifuckingstutter {
|
|||||||
echo "> $fg[white]$cmd$fg[default]"
|
echo "> $fg[white]$cmd$fg[default]"
|
||||||
$=cmd
|
$=cmd
|
||||||
else
|
else
|
||||||
cmd="sudo $(fc -ln -1)"
|
cmd="sudo zsh -c '$(fc -ln -1)'"
|
||||||
echo "> $fg[white]$cmd$fg[default]"
|
echo "> $fg[white]$cmd$fg[default]"
|
||||||
sudo -p "$fg[red]I'll need your authorization:$fg[default] " $last_cmd
|
sudo -p "$fg[red]I'll need your authorization:$fg[default] " $last_cmd
|
||||||
fi
|
fi
|
||||||
@@ -119,3 +122,5 @@ function mkcd {
|
|||||||
[[ -e $1 ]] || mkdir -p $1
|
[[ -e $1 ]] || mkdir -p $1
|
||||||
cd $1
|
cd $1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alias ppctl='/usr/bin/python3 /usr/bin/powerprofilesctl'
|
||||||
24
.config/zsh/60-options.zsh
Normal file
24
.config/zsh/60-options.zsh
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# CD to directory when you type it, without having to type cd
|
||||||
|
setopt auto_cd
|
||||||
|
# Use directory stack
|
||||||
|
setopt auto_pushd
|
||||||
|
# resolve links when CDing
|
||||||
|
setopt chase_links
|
||||||
|
|
||||||
|
# Completion
|
||||||
|
setopt auto_list
|
||||||
|
|
||||||
|
# History
|
||||||
|
setopt hist_ignore_dups
|
||||||
|
setopt hist_ignore_space
|
||||||
|
setopt hist_expire_dups_first
|
||||||
|
setopt extended_history # adds timestamps and command durations to history file
|
||||||
|
setopt hist_reduce_blanks
|
||||||
|
unsetopt hist_save_by_copy # we have compression enabled on history file, we don't want to lose that attribute, so truncate and rewrite rather than making a new file and moving.
|
||||||
|
setopt hist_save_no_dups # no reason to save old dups
|
||||||
|
setopt hist_verify # hitting enter on history search will pull it into the current line editor, not execute directly
|
||||||
|
setopt inc_append_history_time
|
||||||
|
|
||||||
|
# I/O
|
||||||
|
unsetopt clobber # disallow clobbering of files with > (require >! or >| instead)
|
||||||
|
|
||||||
37
.config/zsh/80-emacs-vterm.zsh
Normal file
37
.config/zsh/80-emacs-vterm.zsh
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#
|
||||||
|
# Shell-side support for Emacs libvterm terminal
|
||||||
|
#
|
||||||
|
# This file returns immediately if we are not running in an Emacs vterm.
|
||||||
|
|
||||||
|
if [[ ${INSIDE_EMACS} != "vterm" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
vterm_printf() {
|
||||||
|
# Function definition pulled from emacs-libvterm README
|
||||||
|
if [ -n "$TMUX" ] && { [ "${TERM%%-*}" = "tmux" ] || [ "${TERM%%-*}" = "screen" ]; }; then
|
||||||
|
# Tell tmux to pass the escape sequences through
|
||||||
|
printf "\ePtmux;\e\e]%s\007\e\\" "$1"
|
||||||
|
elif [ "${TERM%%-*}" = "screen" ]; then
|
||||||
|
# GNU screen (screen, screen-256color, screen-256color-bce)
|
||||||
|
printf "\eP\e]%s\007\e\\" "$1"
|
||||||
|
else
|
||||||
|
printf "\e]%s\e\\" "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
vterm_prompt_end() {
|
||||||
|
vterm_printf "51;A${USER}@${SYSTEM_INFO[Hostname]}:${PWD}"
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_elements[prompt]="${prompt_elements[prompt]}"'%{$(vterm_prompt_end)%}'
|
||||||
|
|
||||||
|
emacsctl() {
|
||||||
|
local vterm_elisp
|
||||||
|
vterm_elisp=""
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
vterm_elisp="$vterm_elisp""$(printf '"%s" ' "$(printf "%s" "$1" | sed -e 's|\\|\\\\|g' -e 's|"|\\"|g')")"
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
vterm_printf "51;E${vterm_elisp}"
|
||||||
|
}
|
||||||
105
.config/zsh/90-prompt.zsh
Normal file
105
.config/zsh/90-prompt.zsh
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
autoload -Uz vcs_info
|
||||||
|
|
||||||
|
# Show active python virtualenv in prompt
|
||||||
|
precmd_pyenv_info() {
|
||||||
|
# use nerd fonts for icons
|
||||||
|
_pyenv_icon=""
|
||||||
|
# Only update if we've changed directory, since pyenv can be slow
|
||||||
|
if [[ "$PWD" == "$_pyenv_old_pwd" ]]; then
|
||||||
|
return
|
||||||
|
else
|
||||||
|
_pyenv_old_pwd="$PWD"
|
||||||
|
fi
|
||||||
|
_pyenv_version=$(pyenv version-name 2>/dev/null)
|
||||||
|
if [[ $? -eq 0 ]] && [[ ${_pyenv_version} != "system" ]] && [[ ${_pyenv_version} != "personal" ]]; then
|
||||||
|
pyenv_info_msg_0_="%F{yellow} ${_pyenv_icon} ${_pyenv_version}%f"
|
||||||
|
elif [[ ${_pyenv_version} == "system" ]]; then
|
||||||
|
pyenv_info_msg_0_="%F{red} ${_pyenv_icon} ${_pyenv_version}%f"
|
||||||
|
else
|
||||||
|
pyenv_info_msg_0_=""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
precmd_kernel_info() {
|
||||||
|
# check to see if a kernel update has been installed
|
||||||
|
# since we need to reboot to use it
|
||||||
|
|
||||||
|
# if message has been set, don't check again, since a reboot
|
||||||
|
# is required to clear the message
|
||||||
|
if [[ ${kernel_info_msg_0_+x} == "x" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [[ ${OS_RELEASE[Id]} == "arch" ]] || [[ ${OS_RELEASE[IdLike]} == "arch" ]]; then
|
||||||
|
# Arch Linux removes the old kernel when updating, so we can
|
||||||
|
# just check to see if /usr/lib/modules/$(uname -r)/vmlinuz exists
|
||||||
|
if ! [[ -f /usr/lib/modules/$(uname -r)/vmlinuz ]]; then
|
||||||
|
# kernel update available
|
||||||
|
kernel_info_msg_0_="%F{red}%B%b%f"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
precmd_vcs_info() {
|
||||||
|
vcs_info
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ ${TERM} == "alacritty" ]]; then
|
||||||
|
precmd_functions+=(precmd_vcs_info precmd_pyenv_info _reset_window_name)
|
||||||
|
elif ! [[ ${TERM} == "dumb" ]]; then
|
||||||
|
precmd_functions+=(precmd_vcs_info precmd_pyenv_info)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${SYSTEM_INFO[Chassis]} != "container" ]] && [[ ${OS_RELEASE[IdLike]:-${OS_RELEASE[Id]}} == "arch" ]]; then
|
||||||
|
# Only check if a reboot is necessary if we're not in a container, and we're arch-based (the check we're using only works for arch-based distros)
|
||||||
|
precmd_functions+=(precmd_kernel_info)
|
||||||
|
fi
|
||||||
|
|
||||||
|
prompt_list=(
|
||||||
|
$'\n'
|
||||||
|
"%F{cyan}[%f " ${prompt_elements[deployment]} ${prompt_elements[host]} ${prompt_elements[privilege]} " %F{cyan}]%f" ${prompt_elements[console]} ${prompt_elements[pyenv]} ' ' ${prompt_elements[pwd]} ${prompt_elements[groups]}
|
||||||
|
'$kernel_info_msg_0_ ' ${prompt_elements[prompt]}
|
||||||
|
)
|
||||||
|
rprompt_list=(
|
||||||
|
${prompt_elements[vcs]} ${prompt_elements[retcode]}
|
||||||
|
)
|
||||||
|
history_prompt=(
|
||||||
|
"%F{cyan}[%f " ${prompt_elements[host]} ${prompt_elements[privilege]} " %F{cyan}]%f" ${prompt_elements[console]} ' ' ${prompt_elements[clock]} ' ' ${prompt_elements[pwd]} ' ' ${prompt_elements[prompt]}
|
||||||
|
)
|
||||||
|
|
||||||
|
set-prompt() {
|
||||||
|
if [[ ${TERM} == "dumb" ]]; then
|
||||||
|
# Dumb terminal needs a dumb prompt, otherwise things like
|
||||||
|
# emacs TRAMP break
|
||||||
|
PROMPT='[%~] $ '
|
||||||
|
PROMPT2='> '
|
||||||
|
else
|
||||||
|
_build-prompt
|
||||||
|
PROMPT2=" %F{yellow}%_ ❯%f "
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
set-prompt
|
||||||
|
|
||||||
|
rewrite-prompt-and-accept() {
|
||||||
|
local oldprompt
|
||||||
|
if [[ ${TERM} == "dumb" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
oldprompt="${PROMPT}"
|
||||||
|
PROMPT="${HISTORY_UNPROMPT}"
|
||||||
|
|
||||||
|
# Clear any suggestions; we've committed to this command
|
||||||
|
zle autosuggest-clear
|
||||||
|
zle reset-prompt
|
||||||
|
PROMPT="${oldprompt}"
|
||||||
|
zle accept-line
|
||||||
|
}
|
||||||
|
|
||||||
|
zle -N rewrite-prompt-and-accept
|
||||||
|
bindkey '^M' rewrite-prompt-and-accept
|
||||||
|
|
||||||
|
zstyle ':vcs_info:git:*' formats '%c %F{magenta} %B%r%%b %F{cyan} %b%f'
|
||||||
|
zstyle ':vcs_info:git:*' actionformats '%c%F{magenta} %B%r%%b %F{cyan} %b %F{red} %a%f'
|
||||||
|
zstyle ':vcs_info:git:*' stagedstr "%F{green}%f"
|
||||||
|
zstyle ':vcs_info:git:*' check-for-staged-changes true
|
||||||
|
zstyle ':vcs_info:*' enable git
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user