Updated sway stuff

This commit is contained in:
Ezri Brimhall 2025-06-27 16:56:03 -06:00
parent 261400a636
commit 7217d016ea
Signed by: ezri
GPG Key ID: 058A78E5680C6F24
20 changed files with 609 additions and 93 deletions

View File

@ -108,6 +108,12 @@
background-color: $wallpaper;
}
// mpris module
.mpris--miniplayer-album {
border-radius: 10%;
}
// sway module
.sway--root.sway--vertical {
@ -152,3 +158,24 @@
.clock--date {
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;
}
}

View File

@ -58,7 +58,16 @@
:exclusive true
:focusable false
:stacking "fg"
(sidebar :orientation {side}))
(system-sidebar :orientation {side}))
(defwindow user-sidebar [group side]
:geometry (geometry :width "200px"
:height "100%"
:anchor "${side} center")
:exclusive true
:focusable false
:stacking "fg"
(user-sidebar :orientation {side}))
(defwindow laptopbar [group battery]
@ -85,3 +94,15 @@
:battery {battery}
:workspace-group {group}))
(defwindow vertical-bottombar [group]
:geometry (geometry :width "100%"
:height "65px"
:anchor "bottom center")
:exclusive true
:focusable false
:stacking "fg"
(centerbox :orientation "h"
:class "bar root"
(date)
(big-clock)
(horizontal-minigauges-rightalign)))

View File

@ -12,15 +12,41 @@
:spacing -20
:space-evenly true
:class "special"
"${clock--data.hour}"
"${formattime(clock--data, '%H')}"
":"
"${clock--data.minute}"
"${formattime(clock--data, '%M')}"
":"
"${clock--data.second}"
;; (label :class "special"
;; :text "${clock--data.hour}:${clock--data.minute}:${clock--data.second}")
"${formattime(clock--data, '%S')}"
)
(label :text "${clock--data.year}-${clock--data.month}-${clock--data.day}")))
(label :text {formattime(clock--data, "%Y-%m-%d")})))
(defwidget big-clock []
(centerbox :class "bigger nebula"
:space-evenly false
:halign "center"
:valign "center"
:width 100
:orientation "h"
(box :halign "start" {formattime(clock--data, "%H")})
(box :halign "center" ":")
(box :halign "end" {formattime(clock--data, "%M")})))
(defwidget date []
(box :class "nebula module text"
:space-evenly false
:spacing 20
:halign "start"
:valign "center"
:orientation "h"
(label :text {formattime(clock--data, "%A")}
:class "medium"
:valign "center")
(label :text {formattime(clock--data, "%B %d")}
:class "special"
:valign "center")))
(defwidget sideclock []
@ -36,12 +62,12 @@
:width 150
:halign "center"
:orientation "h"
(box :halign "start" "${clock--data.hour}")
(box :halign "start" {formattime(clock--data, "%H")})
(box :halign "center" ":")
(box :halign "end" "${clock--data.minute}"))
(label :text "${clock--data.dow}"
(box :halign "end" {formattime(clock--data, "%M")}))
(label :text {formattime(clock--data, "%A")}
:class "special")
(label :text "${clock--data.month_name} ${clock--data.day}"))
(label :text {formattime(clock--data, "%B %d")}))
(box
:height 100
(revealer :transition "crossfade"

View File

@ -1,29 +1,61 @@
;; -*-lisp-*-
(deflisten mpris--data :initial "{}"
`~/.config/eww/scripts/mpris.py`)
`~/.config/eww/scripts/mpris2.py`)
(defwidget mpris2
[]
[]
(button :onclick "astal-mpris --player '${mpris--data.active_player}' play-pause"
(box :class "module text"
:spacing 0
:orientation "v"
(label :class {mpris--data.playing ? "special" : "offline"}
:visible {mpris--data.running}
:text "${mpris--data.title} by ${mpris--data.artist}")
(box :spacing 5
:space-evenly false
: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}
"/"
{mpris--data.length_minutes}
":"
{mpris--data.length_seconds})
)
(label :class "offline"
:visible {!mpris--data.running}
:text "player offline")
(label :visible {mpris--data.running}
:text "now playing from ${mpris--data.album}")
(label :visible {!mpris--data.running}
:text "player offline")))
:text "player offline"))))
(defwidget mpris-miniplayer []
(box :class "miniplayer"
:orientation "v"
:space-evenly false
:spacing 10
(image :path {mpris--data.album_art}
:image-width 100
:image-height 100)
(label)))
(label :class "nebula medium special"
:text "Music")
(box :orientation "v"
: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")))

View File

@ -67,7 +67,7 @@
:visible {!device.online}
:text "offline")
(label :visible {device.online}
:class {network--data.last_update.unix < clock--data.unix - 30 ? "highlight" : "special"}
:class {network--data.last_update.unix < clock--data - 30 ? "highlight" : "special"}
:text "${device.addresses[0].address}/${device.addresses[0].prefixlen}")))
(defwidget network--secure
@ -237,7 +237,7 @@
(box :halign "end"
:spacing 0
: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 - 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}")))
))

View File

@ -151,7 +151,7 @@
(label :text "%"
:class "offline"))))))))
(defwidget system--memory-gauge-small []
(defwidget system--memory-gauge-small [?invert]
(box :orientation "v"
:halign "center"
:width 35
@ -159,10 +159,14 @@
:spacing 10
:class ""
(label :text "MEM"
:visible {!(invert ?: false)}
:class "special")
(box :halign "center"
(overlay
(system--small-gauge :value {system--data.memory.percent})))))
(system--small-gauge :value {system--data.memory.percent})))
(label :text "MEM"
:visible {invert ?: false}
:class "special")))
@ -194,7 +198,7 @@
:class "offline"))))))
))
(defwidget system--cpu-gauge-small []
(defwidget system--cpu-gauge-small [?invert]
(box :orientation "v"
:halign "center"
:width 35
@ -202,11 +206,15 @@
: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)))))
:threshold 80)))
(label :text "CPU"
:visible {(invert ?: false)}
:class "special")))
(defwidget system--gpu-gauge []
(box :orientation "v"
@ -235,7 +243,7 @@
(label :text "%"
:class "offline"))))))))
(defwidget system--gpu-gauge-small []
(defwidget system--gpu-gauge-small [?invert]
(box :orientation "v"
:halign "center"
:width 35
@ -243,10 +251,14 @@
:spacing 10
:class ""
(label :text "GPU"
:visible {!(invert ?: false)}
:class "special")
(box :halign "center"
(overlay
(system--small-gauge :value {system--data.gpu.load * 100})))))
(system--small-gauge :value {system--data.gpu.load * 100})))
(label :text "GPU"
:visible {invert ?: false}
:class "special")))
(defwidget system--vram-gauge []
(box :orientation "v"
@ -275,7 +287,7 @@
(label :text "%"
:class "offline"))))))))
(defwidget system--vram-gauge-small []
(defwidget system--vram-gauge-small [?invert]
(box :orientation "v"
:halign "center"
:width 35
@ -283,10 +295,14 @@
:spacing 10
:class ""
(label :text "VMEM"
:visible {!(invert ?: false)}
:class "special")
(box :halign "center"
(overlay
(system--small-gauge :value {system--data.gpu.memory * 100})))))
(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]

View File

@ -28,7 +28,7 @@
:text "${volume--data.input.volume}%"))
"audio system"))
(defwidget volume-small-gauge []
(defwidget volume-small-gauge [?invert]
(box :orientation "v"
:halign "center"
:width 35
@ -36,6 +36,7 @@
:spacing 10
:class ""
(label :text "VOL"
:visible {!(invert ?: false)}
:class "special")
(overlay :width 30
:height 30
@ -56,7 +57,10 @@
:class 'gauge ${volume--data.input.mute ? "green" : volume--data.input.volume > 100 ? "highlight" : ""}'
:start-at 12.5
:clockwise false
:thickness 2))))
:thickness 2))
(label :text "VOL"
:visible {invert ?: false}
:class "special")))
(defwidget volume--gauge [io]
(box :orientation "v"

View File

@ -12,9 +12,7 @@ import time
def get_date():
"""Return the current date as a JSON object string."""
return datetime.datetime.now().strftime(
'{"hour": "%H", "minute": "%M", "second": "%S", "day": "%d", "month": "%m", "year": "%Y", "dow": "%A","month_name": "%B", "unix": %s}'
)
return int(datetime.datetime.now().timestamp())
if __name__ == "__main__":

142
.config/eww/scripts/mpris2.py Executable file
View File

@ -0,0 +1,142 @@
#!/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"}
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": 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()

View File

@ -0,0 +1,72 @@
#!/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
MONITOR_IPS = {"ezrinet": IPAddress("10.242.3.1"), "internet": IPAddress("1.1.1.1")}
INTERFACE_IGNORE_PATTERNS = [
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:
await func()
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)))
@timer(5)
async def ping_checks():
"""Recurring ping checks for configured IP addresses."""

View 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)

View File

@ -6,7 +6,7 @@
;; Generic Windows ;;
;;; ;;;
(defwidget sidebar [orientation]
(defwidget system-sidebar [orientation]
(box :orientation "v"
:valign "start"
:space-evenly false
@ -17,6 +17,16 @@
(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 small-sidebar [orientation battery workspace-group]
(centerbox :orientation "v"
:class "root ${orientation}-side"
@ -113,7 +123,18 @@
(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--gpu-gauge-small :invert {false})
(system--vram-gauge-small :invert {false})
(volume-small-gauge :invert {false})))
;;; ;;;
;; Bars for Rocinante ;;

View File

@ -4,6 +4,7 @@ certifi
charset-normalizer
dbus-python
decorator
exceptiongroup
executing
i3ipc
idna
@ -14,10 +15,13 @@ netifaces
parso
pexpect
pickleshare
prompt-toolkit
prompt_toolkit
psutil
ptyprocess
pure-eval
pulsectl
pulsectl-asyncio
pure_eval
pyamdgpuinfo
pycairo
Pygments
PyGObject
@ -28,5 +32,6 @@ six
stack-data
traitlets
trparse
typing_extensions
urllib3
wcwidth

View File

@ -71,6 +71,13 @@ bindsym {
$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
bindsym {
$mod+Shift+1 exec busctl --user call dev.ezri.sway /ContextManager dev.ezri.sway.ContextManager MoveContainer y 1
@ -209,7 +216,7 @@ for_window [app_id="rg.kde.kwalletd6"] floating enable
bindsym $mod+Shift+r reload
## Default Application Launcher
bindsym $mod+Return exec default-application-launcher
bindsym $mod+Return exec ~/.local/bin/default-application-launcher
## Terminal Launcher
bindsym $mod+Shift+Return exec alacritty msg create-window || alacritty
@ -253,14 +260,7 @@ include input.conf
# Service Management #
### ###
## Import Environment Variables
exec_always XDG_CURRENT_DESKTOP=sway ELECTRON_OZONE_PLATFORM_HINT=wayland {
systemctl --user import-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP PATH ASDF_DATA_DIR ELECTRON_OZONE_PLATFORM_HINT
dbus-update-activation-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP PATH ASDF_DATA_DIR ELECTRON_OZONE_PLATFORM_HINT
}
## Start Session Target
exec_always systemctl --user start sway-session.target
exec ~/.local/lib/voidshell/sway-systemd-start.sh
### ###
# Generic Local Configuration #

View File

@ -32,7 +32,7 @@
{
"index": 5,
"name": "discord",
"exec": "discord",
"exec": "vesktop",
"program_name": "discord"
},
{
@ -160,7 +160,13 @@
"name": "steam",
"exec": "steam",
"program_name": "steam"
}
},
{
"index": 24,
"name": "telephony",
"exec": "telephony-launcher.sh",
"program_name": "telephony"
}
],
"contexts": {
"docked": {
@ -209,13 +215,11 @@
"model": "DELL U2722D",
"serial": "5X3MGH3",
"group": "right",
"position": [8107, 0],
"mode": "2560x1440 color_profile icc /usr/share/color/icc/colord/DCI-P3.icd",
"position": [8107, -500],
"mode": "2560x1440 transform 270 color_profile icc /usr/share/color/icc/colord/DCI-P3.icd",
"eww_windows": {
"desktop-rightbar": {},
"sidebar": {
"side": "right"
}
"vertical-bottombar": {}
}
}
],
@ -225,15 +229,15 @@
"reverse": false
},
"left": {
"workspaces": [6, 2, 3, 4, 5],
"workspaces": [6, 2, 3, 13, 5],
"reverse": true
},
"center": {
"workspaces": [1, 7, 8, 9, 10, 11, 12, 13, 14, 15],
"workspaces": [1, 7, 8, 9, 10, 11, 12, 24, 14, 15],
"reverse": false
},
"right": {
"workspaces": [16, 17, 19, 18, 20, 13],
"workspaces": [16, 17, 19, 18, 20],
"reverse": false
}
}
@ -241,27 +245,12 @@
"battlestation": {
"primary": "center",
"outputs": [
{
"names": ["eDP-1"],
"group": "builtin",
"position": [0, 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"
},
{
"make": "ASUSTek COMPUTER INC",
"model": "VG245",
"serial": "L7LMQS132447",
"group": "left",
"position": [1707, 200],
"position": [0, 200],
"mode": "1920x1080@75Hz",
"eww_windows": {
"desktop-leftbar": {},
@ -275,7 +264,7 @@
"model": "VG32AQA1A",
"serial": "S5LMQS033656",
"group": "center",
"position": [3627, 0],
"position": [1920, 0],
"mode": "2560x1440@165Hz",
"eww_windows": ["desktop-mainbar"]
},
@ -284,9 +273,29 @@
"model": "VG245",
"serial": "L6LMQS065439",
"group": "right",
"position": [6187, 200],
"position": [4480, 200],
"mode": "1920x1080@75Hz",
"eww_windows": ["desktop-rightbar"]
"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": {
@ -299,7 +308,7 @@
"reverse": true
},
"center": {
"workspaces": [1, 7, 8, 9, 10, 11, 12, 4, 14, 15],
"workspaces": [1, 7, 8, 9, 10, 11, 12, 24, 14, 15],
"reverse": false
},
"right": {

View File

@ -4,6 +4,10 @@ PartOf=sway-session.target
[Service]
Type=simple
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
ExecStop=eww kill

View File

@ -5,6 +5,11 @@ PartOf=sway-session.target
[Service]
Type=dbus
BusName=dev.ezri.sway
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
Restart=on-abnormal

View File

@ -7,7 +7,7 @@ alias userctl="\systemctl --user"
alias ujournalctl="\journalctl --user"
alias reconf="exec $SHELL"
alias reconf="exec zsh"
# Use safeexec to ensure we are using system binaries (required for some AUR packages)
alias paru="safeexec paru"

View File

@ -1,5 +1,8 @@
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_asdf=$ASDF_DATA_DIR/shims:/opt/asdf-vm/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_user=$HOME/.local/bin
PATH_wincmake=/opt/msvcmake/bin:/opt/msvc/bin/x64
PATH_cargo=$CARGO_HOME/bin
cdpath=(~ ~/src)
export PATH=.:$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 safeexec {

View File

@ -143,6 +143,13 @@ Indent using tabs, render with tab-width of 2.
`(("irc.libera.chat" nickserv "netsorc" ,(secrets-get-secret "Default keyring" "libera.chat"))))
#+END_SRC
** Terminal
#+BEGIN_SRC emacs-lisp
(use-package vterm
:ensure t)
#+END_SRC
* Theming
** Highlight current line
#+BEGIN_SRC emacs-lisp
@ -422,11 +429,14 @@ Indent using tabs, render with tab-width of 2.
** Markdown
*** Auto Text Wrap
#+BEGIN_SRC emacs-lisp
(add-hook 'markdown-mode-hook (lambda ()
(setq fill-column 85)
(visual-fill-column-mode)
(visual-line-mode)
(display-fill-column-indicator-mode)))
(use-package visual-fill-column
:ensure t
:init
(add-hook 'markdown-mode-hook (lambda ()
(setq fill-column 85)
(visual-fill-column-mode)
(visual-line-mode)
(display-fill-column-indicator-mode))))
#+END_SRC
** YAML
#+BEGIN_SRC emacs-lisp
@ -653,11 +663,11 @@ Indent using tabs, render with tab-width of 2.
:bind (:map eglot-mode-map
("C-c C-e" . eglot-rename)
("C-." . eglot-code-actions)
("<f2>" . eglot-find-declaration))
:hook ((python-mode . eglot-ensure)
(python-mode . flyspell-prog-mode)
(python-mode . superword-mode)
(python-mode . hs-minor-mode)
("<f2>" . eglot-find-implementation))
:hook ((python-base-mode . eglot-ensure)
(python-base-mode . flyspell-prog-mode)
(python-base-mode . superword-mode)
(python-base-mode . hs-minor-mode)
(typescript-ts-mode . eglot-ensure)
(typescript-ts-mode . flyspell-prog-mode)
(typescript-ts-mode . superword-mode)
@ -671,9 +681,10 @@ Indent using tabs, render with tab-width of 2.
(typescript-mode . superword-mode)
(typescript-mode . hs-minor-mode))
:config
(add-to-list 'eglot-server-programs '(python-base-mode . ("pylsp")))
(setq-default eglot-workspace-configuration
'((:pylsp . (:configurationSources ["flake8"]
:plugins (
:plugins (
:mccabe (:enabled :json-false)
:pyflakes (:enabled :json-false)
:flake8 (:enabled :json-false
@ -682,13 +693,39 @@ Indent using tabs, render with tab-width of 2.
:pydocstyle (:enabled t :convention "numpy")
:yapf (:enabled :json-false)
:autopep8 (:enabled :json-false)
:black (:enabled t :line_length 88 :cache_config t)))))))
:black (:enabled t :line_length 88 :cache_config t)
:mypy (:enabled t))
)))))
#+END_SRC
** Git
*** Magit
#+BEGIN_SRC emacs-lisp
(use-package magit :ensure t)
#+END_SRC
*** Blame
#+BEGIN_SRC emacs-lisp
(use-package blamer
:straight (:host github :repo "artawower/blamer.el")
:bind (("s-i" . blamer-show-commit-info))
:custom
(blamer-idle-time 0.3)
(blamer-min-offset 70)
:custom-face
(blamer-face ((t :foreground "#7a88cf"
:background nil
:italic t)))
:config
(global-blamer-mode 1))
#+END_SRC
** Languages
*** Python
#+BEGIN_SRC emacs-lisp
(use-package pet
:config
(add-hook 'python-base-mode-hook 'pet-mode -10)
)
#+END_SRC
*** Elixir
#+BEGIN_SRC emacs-lisp
(use-package elixir-mode