Compare commits
No commits in common. "bc50f371874a64749209bfb6e650b87c4067b0e2" and "f7284f1104e44b2fad060c44a1e8ac01c644e0cf" have entirely different histories.
bc50f37187
...
f7284f1104
12 changed files with 209 additions and 298 deletions
11
cmd/eww.go
11
cmd/eww.go
|
@ -5,13 +5,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var ewwCmd = &cobra.Command{
|
var ewwCmd = &cobra.Command{
|
||||||
Use: "eww",
|
Use:"eww" ,
|
||||||
Short: "eww integration",
|
Short: "eww integration",
|
||||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
hm.LoadConfig(configPath)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(ewwCmd)
|
rootCmd.AddCommand(ewwCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ var startCmd = &cobra.Command{
|
||||||
Use: "start",
|
Use: "start",
|
||||||
Short: "Launch eww",
|
Short: "Launch eww",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
hm.LaunchEww()
|
hm.LaunchEww()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ var watchCmd = &cobra.Command{
|
||||||
Use: "watch",
|
Use: "watch",
|
||||||
Short: "Watch hyprland events and propagate to eww",
|
Short: "Watch hyprland events and propagate to eww",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
hm.Watch()
|
hm.Watch()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
cmd/mako.go
26
cmd/mako.go
|
@ -1,26 +1,22 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"fmt"
|
||||||
|
|
||||||
hyprman "git.dayl.in/daylin/hyprman/internal"
|
"github.com/spf13/cobra"
|
||||||
|
// "git.dayl.in/daylin/hyprman/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
var makoCmd = &cobra.Command{
|
var makoCmd = &cobra.Command{
|
||||||
Use: "mako",
|
Use:"mako" ,
|
||||||
Short: "mako integration",
|
Short: "mako integration",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
hyprman.ListNotifications(number, json)
|
fmt.Println("hahah mako baby")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
number int
|
|
||||||
json bool
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(makoCmd)
|
rootCmd.AddCommand(makoCmd)
|
||||||
makoCmd.Flags().IntVarP(&number, "number", "n", 10, "number of notifications")
|
|
||||||
makoCmd.Flags().BoolVar(&json, "json", false, "output data as json")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
22
cmd/root.go
22
cmd/root.go
|
@ -2,13 +2,12 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
cc "github.com/ivanpirog/coloredcobra"
|
cc "github.com/ivanpirog/coloredcobra"
|
||||||
|
"git.dayl.in/daylin/hyprman/internal"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
hyprman "git.dayl.in/daylin/hyprman/internal"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func Execute() {
|
func Execute() {
|
||||||
cc.Init(&cc.Config{
|
cc.Init(&cc.Config{
|
||||||
RootCmd: rootCmd,
|
RootCmd: rootCmd,
|
||||||
|
@ -26,17 +25,22 @@ func Execute() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var configPath string
|
||||||
configPath string
|
var hm = &hyprman.Hyprman{}
|
||||||
hm = &hyprman.Hyprman{}
|
|
||||||
)
|
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "hyprman",
|
Use: "hyprman",
|
||||||
Short: "hyprland companion app",
|
Short: "hyprland companion app",
|
||||||
|
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
hm.LoadConfig(configPath)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.CompletionOptions.HiddenDefaultCmd = true
|
rootCmd.CompletionOptions.HiddenDefaultCmd = true
|
||||||
rootCmd.PersistentFlags().StringVarP(&configPath, "config", "c", hyprman.DefaultConfigPath(), "path to config file")
|
rootCmd.PersistentFlags().StringVarP(&configPath, "config", "c", hyprman.DefaultConfigPath(), "path to config file")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1717646450,
|
"lastModified": 1716312448,
|
||||||
"narHash": "sha256-KE+UmfSVk5PG8jdKdclPVcMrUB8yVZHbsjo7ZT1Bm3c=",
|
"narHash": "sha256-PH3w5av8d+TdwCkiWN4UPBTxrD9MpxIQPDVWctlomVo=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "818dbe2f96df233d2041739d6079bb616d3e5597",
|
"rev": "e381a1288138aceda0ac63db32c7be545b446921",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
devShells = forAllSystems (pkgs: {
|
devShells = forAllSystems (pkgs: {
|
||||||
default = pkgs.mkShell {
|
default = pkgs.mkShell {
|
||||||
packages = with pkgs; [go];
|
packages = with pkgs; [go];
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -30,9 +30,9 @@
|
||||||
default = self.packages.${pkgs.system}.hyprman;
|
default = self.packages.${pkgs.system}.hyprman;
|
||||||
hyprman = pkgs.buildGoModule {
|
hyprman = pkgs.buildGoModule {
|
||||||
pname = "hyprman";
|
pname = "hyprman";
|
||||||
version = "${self.shortRev or "dirty"}";
|
version = "unstable";
|
||||||
src = cleanSource ./.;
|
src = cleanSource ./.;
|
||||||
vendorHash = "sha256-hJwRLVIiWxLbX2tAPVVVLGFk4OaAy5qiFcICEqhVMJM=";
|
vendorHash = "sha256-eKeUhS2puz6ALb+cQKl7+DGvm9Cl+miZAHX0imf9wdg=";
|
||||||
|
|
||||||
nativeBuildInputs = with pkgs; [installShellFiles];
|
nativeBuildInputs = with pkgs; [installShellFiles];
|
||||||
|
|
||||||
|
|
7
go.mod
7
go.mod
|
@ -3,23 +3,16 @@ module git.dayl.in/daylin/hyprman
|
||||||
go 1.22.2
|
go 1.22.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/charmbracelet/lipgloss v0.11.0
|
|
||||||
github.com/goccy/go-yaml v1.11.3
|
github.com/goccy/go-yaml v1.11.3
|
||||||
github.com/ivanpirog/coloredcobra v1.0.1
|
github.com/ivanpirog/coloredcobra v1.0.1
|
||||||
github.com/spf13/cobra v1.8.0
|
github.com/spf13/cobra v1.8.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
|
||||||
github.com/charmbracelet/x/ansi v0.1.2 // indirect
|
|
||||||
github.com/fatih/color v1.17.0 // indirect
|
github.com/fatih/color v1.17.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
|
||||||
github.com/muesli/termenv v0.15.2 // indirect
|
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
golang.org/x/sys v0.20.0 // indirect
|
golang.org/x/sys v0.20.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||||
|
|
15
go.sum
15
go.sum
|
@ -1,9 +1,3 @@
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
|
||||||
github.com/charmbracelet/lipgloss v0.11.0 h1:UoAcbQ6Qml8hDwSWs0Y1cB5TEQuZkDPH/ZqwWWYTG4g=
|
|
||||||
github.com/charmbracelet/lipgloss v0.11.0/go.mod h1:1UdRTH9gYgpcdNN5oBtjbu/IzNKtzVtb7sqN1t9LNn8=
|
|
||||||
github.com/charmbracelet/x/ansi v0.1.2 h1:6+LR39uG8DE6zAmbu023YlqjJHkYXDF1z36ZwzO4xZY=
|
|
||||||
github.com/charmbracelet/x/ansi v0.1.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/daylinmorgan/coloredcobra v0.0.0-20240527152736-9d3ce38297a6 h1:Zst7HlWvQj8LPJ3mhIWtGH2DxqUo6VEq0oekNyAho6M=
|
github.com/daylinmorgan/coloredcobra v0.0.0-20240527152736-9d3ce38297a6 h1:Zst7HlWvQj8LPJ3mhIWtGH2DxqUo6VEq0oekNyAho6M=
|
||||||
|
@ -26,20 +20,11 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
|
||||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
|
||||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
|
||||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
|
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
|
||||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||||
|
|
122
internal/eww.go
122
internal/eww.go
|
@ -1,122 +0,0 @@
|
||||||
package hyprman
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type EwwWorkspace struct {
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
Class string `json:"class"`
|
|
||||||
Id int `json:"id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hm *Hyprman) pickIcon(class string) string {
|
|
||||||
for k, v := range hm.Config.Classes {
|
|
||||||
if strings.Contains(k, class) {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hm.Config.DefaultIcon
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hm *Hyprman) generateEwwClasses() {
|
|
||||||
monitors := getMonitors()
|
|
||||||
clients := getClients()
|
|
||||||
|
|
||||||
var ewwClasses [][]EwwWorkspace
|
|
||||||
|
|
||||||
monitor := make([]EwwWorkspace, 9)
|
|
||||||
|
|
||||||
for i := range 9 {
|
|
||||||
monitor[i] = EwwWorkspace{
|
|
||||||
hm.Config.NoClientIcon,
|
|
||||||
fmt.Sprintf("ws-button-%d", i+1),
|
|
||||||
i + 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, client := range clients {
|
|
||||||
id := client.Workspace.Id - 1
|
|
||||||
currentIcon := monitor[id].Icon
|
|
||||||
if currentIcon == hm.Config.NoClientIcon {
|
|
||||||
monitor[id].Icon = hm.pickIcon(client.Class)
|
|
||||||
} else {
|
|
||||||
monitor[id].Icon = fmt.Sprintf("%s%s", currentIcon, hm.pickIcon(client.Class))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, id := range openWorkspaces(monitors) {
|
|
||||||
// activeId := m.ActiveWorkspace.Id
|
|
||||||
monitor[id-1].Class = fmt.Sprintf("%s %s", monitor[id-1].Class, "ws-button-open")
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, m := range monitors {
|
|
||||||
activeId := m.ActiveWorkspace.Id - 1
|
|
||||||
ewwClasses = append(ewwClasses, make([]EwwWorkspace, 9))
|
|
||||||
copy(ewwClasses[i], monitor)
|
|
||||||
ewwClasses[i][activeId].Class = fmt.Sprintf("%s %s-%d", monitor[activeId].Class, "ws-button-active", activeId+1)
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes, err := json.Marshal(ewwClasses)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fmt.Println(string(bytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ewwBar1(cmd string) {
|
|
||||||
time.Sleep(3 * time.Second)
|
|
||||||
output, err := exec.Command("eww", cmd, "bar1").CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
notify(fmt.Sprintf("failed to %s bar 1\n\n%s\n\n%v", cmd, output, err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hm *Hyprman) handleHyprEvent(line string) {
|
|
||||||
s := strings.Split(line, ">>")
|
|
||||||
event, _ := s[0], s[1]
|
|
||||||
if event == "monitoradded" {
|
|
||||||
notify("Monitor added opening bar1")
|
|
||||||
go ewwBar1("open")
|
|
||||||
}
|
|
||||||
hm.generateEwwClasses()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hm *Hyprman) LaunchEww() {
|
|
||||||
for i := range getMonitors() {
|
|
||||||
if err := exec.Command("eww", "open", fmt.Sprintf("bar%d", i)).Run(); err != nil {
|
|
||||||
notify(fmt.Sprintf("Error lanching eww:\n%v", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hm *Hyprman) Watch() {
|
|
||||||
socketPath := hyprSocket2()
|
|
||||||
conn, err := net.Dial("unix", socketPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("Error connecting to hyprland IPC:", err)
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
reader := bufio.NewReader(conn)
|
|
||||||
hm.generateEwwClasses()
|
|
||||||
for {
|
|
||||||
line, err := reader.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
if err == io.EOF {
|
|
||||||
// log.Printf("reached EOF for %s\n", socketPath)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// log.Println("error reading line")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
hm.handleHyprEvent(line)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +1,17 @@
|
||||||
package hyprman
|
package hyprman
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
)
|
)
|
||||||
|
@ -129,6 +133,21 @@ func getClients() []Client {
|
||||||
return clients
|
return clients
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EwwWorkspace struct {
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
Class string `json:"class"`
|
||||||
|
Id int `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hm *Hyprman) pickIcon(class string) string {
|
||||||
|
for k, v := range hm.Config.Classes {
|
||||||
|
if strings.Contains(k, class) {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hm.Config.DefaultIcon
|
||||||
|
}
|
||||||
|
|
||||||
func openWorkspaces(monitors []Monitor) []int {
|
func openWorkspaces(monitors []Monitor) []int {
|
||||||
open := make([]int, len(monitors))
|
open := make([]int, len(monitors))
|
||||||
for i, m := range monitors {
|
for i, m := range monitors {
|
||||||
|
@ -137,12 +156,125 @@ func openWorkspaces(monitors []Monitor) []int {
|
||||||
return open
|
return open
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hm *Hyprman) generateEwwClasses() {
|
||||||
|
monitors := getMonitors()
|
||||||
|
clients := getClients()
|
||||||
|
|
||||||
|
var ewwClasses [][]EwwWorkspace
|
||||||
|
|
||||||
|
monitor := make([]EwwWorkspace, 9)
|
||||||
|
|
||||||
|
for i := range 9 {
|
||||||
|
monitor[i] = EwwWorkspace{
|
||||||
|
hm.Config.NoClientIcon,
|
||||||
|
fmt.Sprintf("ws-button-%d", i+1),
|
||||||
|
i + 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, client := range clients {
|
||||||
|
id := client.Workspace.Id - 1
|
||||||
|
currentIcon := monitor[id].Icon
|
||||||
|
if currentIcon == hm.Config.NoClientIcon {
|
||||||
|
monitor[id].Icon = hm.pickIcon(client.Class)
|
||||||
|
} else {
|
||||||
|
monitor[id].Icon = fmt.Sprintf("%s%s", currentIcon, hm.pickIcon(client.Class))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, id := range openWorkspaces(monitors) {
|
||||||
|
// activeId := m.ActiveWorkspace.Id
|
||||||
|
monitor[id-1].Class = fmt.Sprintf("%s %s", monitor[id-1].Class, "ws-button-open")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, m := range monitors {
|
||||||
|
activeId := m.ActiveWorkspace.Id - 1
|
||||||
|
ewwClasses = append(ewwClasses, make([]EwwWorkspace, 9))
|
||||||
|
copy(ewwClasses[i], monitor)
|
||||||
|
ewwClasses[i][activeId].Class = fmt.Sprintf("%s %s-%d", monitor[activeId].Class, "ws-button-active", activeId+1)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(ewwClasses)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(string(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ewwBar1(cmd string) {
|
||||||
|
time.Sleep(200 * time.Second)
|
||||||
|
if err := exec.Command("eww", cmd, "bar1").Run(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func notify(message string) {
|
func notify(message string) {
|
||||||
cmd := exec.Command(
|
cmd := exec.Command("notify-send", "hyprman", message)
|
||||||
"notify-send",
|
|
||||||
"--app-name=hyprman",
|
|
||||||
"--transient",
|
|
||||||
message,
|
|
||||||
)
|
|
||||||
cmd.Run()
|
cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hm *Hyprman) handleHyprEvent(line string) {
|
||||||
|
s := strings.Split(line, ">>")
|
||||||
|
event, _ := s[0], s[1]
|
||||||
|
switch event {
|
||||||
|
case "monitorremoved":
|
||||||
|
notify("Monitor removed closing bar1")
|
||||||
|
go ewwBar1("close")
|
||||||
|
hm.generateEwwClasses()
|
||||||
|
case "monitoradded":
|
||||||
|
notify("Monitor added opening bar1")
|
||||||
|
go ewwBar1("open")
|
||||||
|
hm.generateEwwClasses()
|
||||||
|
case "workspace",
|
||||||
|
"focusedmon",
|
||||||
|
"activewindow",
|
||||||
|
"createworkspace",
|
||||||
|
"destroyworkspace",
|
||||||
|
"moveworkspace",
|
||||||
|
"renameworkspace",
|
||||||
|
"openwindow",
|
||||||
|
"closewindow",
|
||||||
|
"movewindow",
|
||||||
|
"movewindowv2",
|
||||||
|
"changefloatingmode",
|
||||||
|
"windowtitle",
|
||||||
|
"togglegroup",
|
||||||
|
"moveintogroup",
|
||||||
|
"moveoutofgroup",
|
||||||
|
"configreloaded":
|
||||||
|
hm.generateEwwClasses()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hm *Hyprman) LaunchEww() {
|
||||||
|
for i := range getMonitors() {
|
||||||
|
if err := exec.Command("eww", "open", fmt.Sprintf("bar%d", i)).Run(); err != nil {
|
||||||
|
notify(fmt.Sprintf("Error lanching eww:\n%v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hm *Hyprman) Watch() {
|
||||||
|
socketPath := hyprSocket2()
|
||||||
|
conn, err := net.Dial("unix", socketPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error connecting to hyprland IPC:", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
reader := bufio.NewReader(conn)
|
||||||
|
hm.generateEwwClasses()
|
||||||
|
for {
|
||||||
|
line, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
// log.Printf("reached EOF for %s\n", socketPath)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// log.Println("error reading line")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hm.handleHyprEvent(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
144
internal/mako.go
144
internal/mako.go
|
@ -1,112 +1,36 @@
|
||||||
package hyprman
|
package hyprman
|
||||||
|
|
||||||
import (
|
// import (
|
||||||
"encoding/json"
|
// "log"
|
||||||
"fmt"
|
// "os/exec"
|
||||||
"log"
|
// )
|
||||||
"os/exec"
|
//
|
||||||
|
// type MakoHistory struct {
|
||||||
"github.com/charmbracelet/lipgloss"
|
// Type string `json:"type"`
|
||||||
)
|
// Data [][]MakoNotification `json:"data"`
|
||||||
|
// }
|
||||||
type MakoHistory struct {
|
//
|
||||||
Type string `json:"type"`
|
// type MakoNotification struct {
|
||||||
Data [][]MakoNotification `json:"data"`
|
// AppName MakoNotificationData `json:"app-name"`
|
||||||
}
|
// // AppIcon MakoNotificationData `json:"app-icon"`
|
||||||
|
// // Category MakoNotificationData
|
||||||
type MakoNotification struct {
|
// // DesktopEntry MakoNotificationData `json:"desktop-entry"`
|
||||||
AppName MakoNotificationData `json:"app-name"`
|
// Summary MakoNotificationData `json:"summary"`
|
||||||
Summary MakoNotificationData
|
// Body MakoNotificationData
|
||||||
Body MakoNotificationData
|
// // Id MakoNotificationData
|
||||||
// AppIcon MakoNotificationData `json:"app-icon"`
|
// // Urgency MakoNotificationData
|
||||||
// Category MakoNotificationData
|
// // Actions MakoNotificationData
|
||||||
// DesktopEntry MakoNotificationData `json:"desktop-entry"`
|
// }
|
||||||
// Id MakoNotificationData
|
//
|
||||||
// Urgency MakoNotificationData
|
// type MakoNotificationData struct {
|
||||||
// Actions MakoNotificationData
|
// Type string `json:"type"`
|
||||||
}
|
// Data string `json:"data"`
|
||||||
|
// }
|
||||||
type MakoNotificationData struct {
|
//
|
||||||
Type string `json:"type"`
|
// func getHistory() MakoHistory {
|
||||||
Data string `json:"data"`
|
// makoOutput, err := exec.Command("makoctl", "history").CombinedOutput()
|
||||||
}
|
// if err != nil {
|
||||||
|
// log.Fatal(err)
|
||||||
type History struct {
|
// }
|
||||||
Notifications []Notifcation
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
type Notifcation struct {
|
|
||||||
AppName string
|
|
||||||
Summary string
|
|
||||||
Body string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mn MakoNotification) toNotification() Notifcation {
|
|
||||||
var n Notifcation
|
|
||||||
n.AppName = mn.AppName.Data
|
|
||||||
n.Summary = mn.Summary.Data
|
|
||||||
n.Body = mn.Body.Data
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mh MakoHistory) toHistory() History {
|
|
||||||
var h History
|
|
||||||
var notifications []Notifcation
|
|
||||||
for _, mn := range mh.Data[0] {
|
|
||||||
notifications = append(notifications, mn.toNotification())
|
|
||||||
}
|
|
||||||
h.Notifications = notifications
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
func getHistory() History {
|
|
||||||
var makoHistory MakoHistory
|
|
||||||
makoOutput, err := exec.Command("makoctl", "history").CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
json.Unmarshal(makoOutput, &makoHistory)
|
|
||||||
return makoHistory.toHistory()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *History) truncate(number int) {
|
|
||||||
h.Notifications = h.Notifications[:min(len(h.Notifications), number)]
|
|
||||||
}
|
|
||||||
|
|
||||||
func ListNotifications(number int, outputJson bool) {
|
|
||||||
history := getHistory()
|
|
||||||
history.truncate(number)
|
|
||||||
if !outputJson {
|
|
||||||
for _, n := range history.Notifications {
|
|
||||||
n.Render()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
b, err := json.MarshalIndent(history.Notifications, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(string(b))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n Notifcation) Render() {
|
|
||||||
appStyle := lipgloss.NewStyle().
|
|
||||||
Bold(true).
|
|
||||||
Foreground(lipgloss.Color("3")).
|
|
||||||
PaddingTop(1)
|
|
||||||
textStyle := lipgloss.NewStyle().Width(80).PaddingLeft(2).
|
|
||||||
BorderStyle(lipgloss.ThickBorder()).
|
|
||||||
BorderLeft(true)
|
|
||||||
|
|
||||||
fmt.Println(appStyle.Render(n.AppName))
|
|
||||||
if len(n.Summary) > 0 {
|
|
||||||
fmt.Println(textStyle.
|
|
||||||
BorderForeground(lipgloss.Color("14")).
|
|
||||||
Render(n.Summary))
|
|
||||||
}
|
|
||||||
if len(n.Body) > 0 {
|
|
||||||
fmt.Println(textStyle.
|
|
||||||
BorderForeground(lipgloss.Color("2")).
|
|
||||||
Render(n.Body))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue