dotfiles/hypr/hyprscript

236 lines
7.1 KiB
Python
Executable File

#!/usr/bin/env python
import json
import os
import os.path
import subprocess
import sys
os.chdir(os.path.expanduser('~/.config/dotfiles/hypr'))
bars = "_▂▃▄▅▆▇█"
batteries = "󰂎󰁺󰁻󰁼󰁽󰁾󰁿󰂀󰂁󰂁󰁹"
batteries_charging = "󰢟󰢜󰂆󰂇󰂈󰢝󰂉󰢞󰂊󰂋󰂅"
class Monitor:
"""
A monitor on which many workspaces can appear.
"""
def __init__(self, id: int, name: str):
self.id = id
self.name = name
def __eq__(self, other):
"""
Returns true if the monitors are the same.
"""
self.id == other.id
@staticmethod
def active(monitors: list['Monitor']) -> 'Monitor':
"""
Returns the active monitor.
"""
proc = subprocess.run(['hyprctl', 'activeworkspace', '-j'], capture_output=True)
result = json.loads(proc.stdout)
return next((monitor for monitor in monitors if monitor.id == result['monitorID']))
@staticmethod
def all() -> list['Monitor']:
"""
Returns the list of available monitors.
"""
monitors: list['Monitor'] = []
proc = subprocess.run(['hyprctl', 'monitors', '-j'], capture_output=True)
result = json.loads(proc.stdout)
for mon in result:
monitors.append(Monitor(mon['id'], mon['name']))
return monitors
def previous(self, monitors: list['Monitor'], move: bool = False):
"""
Moves the focus to the previous monitor.
Params:
move: whether you want to move the active window to the new monitor.
"""
mon = monitors[(monitors.index(self) - 1) % len(monitors)]
if move:
subprocess.run(['hyprctl', 'dispatch', 'movewindow', 'mon:' + str(mon.id)])
else:
subprocess.run(['hyprctl', 'dispatch', 'focusmonitor', str(mon.id)])
def next(self, monitors: list['Monitor'], move: bool = False):
"""
Moves the focus to the next monitor.
Params:
move: whether you want to move the active window to the new monitor.
"""
mon = monitors[(monitors.index(self) + 1) % len(monitors)]
if move:
subprocess.run(['hyprctl', 'dispatch', 'movewindow', 'mon:' + str(mon.name)])
else:
subprocess.run(['hyprctl', 'dispatch', 'focusmonitor', str(mon.name)])
class Workspace:
"""
A workspace bound to a monitor.
Workspaces with id from 10 * n + k belongs to the same monitor for k in [1, 10].
"""
def __init__(self, id: int):
self.id = id
@staticmethod
def active() -> 'Workspace':
"""
Returns the active workspace.
"""
proc = subprocess.run(['hyprctl', 'activeworkspace', '-j'], capture_output=True)
result = json.loads(proc.stdout)
return Workspace(result['id'])
def nth(self, n: int, move: bool = False):
"""
Goes to the nth workspace on the same monitor as the current workspace.
Params:
n: workspace to go to, between 1 and 10.
move: whether you want to move the active window to the new workspace.
"""
new_id = (self.id - 1) // 10 * 10 + n
subprocess.run(['hyprctl', 'dispatch', 'movetoworkspace' if move else 'workspace', str(new_id)])
def previous(self, move: bool = False):
"""
Goes to the previous workspace on the same monitor, or the last if we're on the first.
Params:
move: whether you want to move the active window to the new workspace.
"""
new_id = self.id - 1
if new_id % 10 == 0:
new_id += 10
subprocess.run(['hyprctl', 'dispatch', 'movetoworkspace' if move else 'workspace', str(new_id)])
def next(self, move: bool = False):
"""
Goes to the next workspace on the same monitor, or the first if we're on the last.
Params:
move: whether you want to move the active window to the new workspace.
"""
new_id = self.id + 1
if new_id % 10 == 1:
new_id -= 10
subprocess.run(['hyprctl', 'dispatch', 'movetoworkspace' if move else 'workspace', str(new_id)])
def to_bar(x):
return bars[round((len(bars) - 1) * x / 100)]
def monitor_stats():
try:
import psutil
except:
print('Stats requires psutil (run `pip install psutil`)', file=sys.stderr)
sys.exit(1)
"""
Monitors CPU and MEM usage and prints info in file.
"""
cpu_values = [0] * 10
mem_values = [0] * 10
while True:
cpu_percent = psutil.cpu_percent(interval=2)
mem_percent = psutil.virtual_memory().percent
battery = psutil.sensors_battery()
for i in range(len(cpu_values) - 1):
cpu_values[i] = cpu_values[i+1]
mem_values[i] = mem_values[i+1]
cpu_values[-1] = cpu_percent
mem_values[-1] = mem_percent
if battery is None:
battery_json = '{"text": "", "class": "hidden"}'
else:
battery_index = round(battery.percent / 10)
battery_icon = batteries_charging[battery_index] if battery.power_plugged else batteries[battery_index]
if battery.power_plugged:
battery_class = 'charging'
elif battery.percent < 30.0:
battery_class = 'low'
elif battery.percent < 15.0:
battery_class = 'critical'
else:
battery_class = None
battery_json = f', "class": "{battery_class}"' if battery_class else ''
battery_json = '{"text": "' + battery_icon + ' ' + "% 3.0f"%battery.percent + '%"' + battery_json + '}'
with open('.stat.txt', 'w') as f:
f.write(
'' + ''.join([to_bar(x) for x in cpu_values]) + ' ' + "% 5.1f"%cpu_percent + '%\n' +
'' + ''.join([to_bar(x) for x in mem_values]) + ' ' + "% 5.1f"%mem_percent + '%\n' +
battery_json
)
def main():
if len(sys.argv) < 2:
return
if sys.argv[1] == 'workspace' or sys.argv[1] == 'movetoworkspace':
workspace = Workspace.active()
move = sys.argv[1] == 'movetoworkspace'
if sys.argv[2] == 'next':
workspace.next(move)
elif sys.argv[2] == 'previous':
workspace.previous(move)
else:
new_workspace = int(sys.argv[2])
workspace.nth(new_workspace, move)
elif sys.argv[1] in ['movewindow', 'focusnextmonitor', 'focuspreviousmonitor']:
monitors = Monitor.all()
monitor = Monitor.active(monitors)
if sys.argv[1] == 'movewindow':
monitor.next(monitors, True)
elif sys.argv[1] == 'focusnextmonitor':
monitor.next(monitors)
elif sys.argv[1] == 'focuspreviousmonitor':
monitor.previous(monitors)
elif sys.argv[1] == 'reload':
subprocess.run(['systemctl', 'restart', 'waybar', '--user'])
elif sys.argv[1] == 'stat':
monitor_stats()
else:
print(f'Command not found: {sys.argv[1]}', file=sys.stderr)
sys.exit(1)
if __name__ == '__main__':
main()