diff options
Diffstat (limited to '.config')
| -rw-r--r-- | .config/waybar/config | 102 | ||||
| -rw-r--r-- | .config/waybar/modules/gammastep.go (renamed from .config/waybar/modules/redshift.go) | 21 | ||||
| -rw-r--r-- | .config/waybar/modules/go.mod | 5 | ||||
| -rw-r--r-- | .config/waybar/modules/go.sum | 4 | ||||
| -rw-r--r-- | .config/waybar/modules/todo.go | 246 | ||||
| -rw-r--r-- | .config/waybar/style.css | 145 |
6 files changed, 386 insertions, 137 deletions
diff --git a/.config/waybar/config b/.config/waybar/config index 40e06a4..557dafe 100644 --- a/.config/waybar/config +++ b/.config/waybar/config @@ -5,9 +5,9 @@ "height": 25, "gtk-layer-shell": true, - "modules-left": ["sway/mode", "sway/workspaces", "sway/window", "custom/mpv", "custom/mpd", "custom/spotify", "custom/toggl"], - "modules-center": ["custom/weather", "clock#local", "clock#utc"], - "modules-right": ["tray", "cpu", "memory", "disk#root", "disk#home", "temperature", "idle_inhibitor", "backlight", "custom/redshift", "pulseaudio", "network#vpn", "network#tailscale", "network", "battery"], + "modules-left": ["sway/mode", "sway/workspaces", "sway/window", "custom/mpris"], + "modules-center": ["custom/weather", "clock#local", "clock#utc", "custom/toggl", "custom/todo"], + "modules-right": ["tray", "cpu", "memory", "disk#root", "disk#home", "temperature", "idle_inhibitor", "backlight", "custom/gammastep", "pulseaudio", "network#vpn", "network#tailscale", "network", "battery"], "sway/workspaces": { "disable-scroll": true, @@ -38,10 +38,9 @@ "spacing": 10 }, "clock#local": { - // "timezone": "Europe/Berlin", - // "timezone": "Europe/Istanbul", "format": "{:<i>%a</i> %d %b <b>%H:%M</b>}", - "tooltip-format": "TZ: {:%Z %z}\n\n{calendar}" + "tooltip-format": "TZ: {:%Z %z}\n\n{calendar}", + "locale": "ja_JP.utf-8" }, "clock#utc": { "timezone": "UTC", @@ -113,7 +112,7 @@ }, "network#tailscale": { "interface": "tailscale0", - "format": "", // "", // "", + "format": "", "tooltip-format": "{ifname}: {ipaddr}/{cidr}", "tooltip-format-disconnected": "disconnected", "on-click": "doas rc-service tailscale start", @@ -137,47 +136,44 @@ "on-click-right": "pactl set-sink-mute @DEFAULT_SINK@ toggle", "on-click": "swx -t -f pulsemixer" }, - "custom/spotify": { - "format": " {}", - "return-type": "json", - "max-length": 80, - "escape": false, - "interval": 2, - "exec": "$HOME/.config/waybar/modules/waybar-media spotify", - "exec-if": "pgrep spotify" - }, - "custom/mpd": { - "format": " {}", - "return-type": "json", - "max-length": 80, - "interval": 2, - "exec": "$HOME/.config/waybar/modules/waybar-media mpd", - "exec-if": "pgrep mpd" - }, - "custom/mpv": { - "format": " {}", - "return-type": "json", - "max-length": 80, - "interval": 2, - "exec": "$HOME/.config/waybar/modules/waybar-media mpv", - "exec-if": "pgrep mpv" + "custom/mpris": { + "format": "{}", + "exec": "waybar-mpris --position --autofocus --interpolate --play --pause ", + "on-click": "waybar-mpris --send toggle", + "on-click-right": "waybar-mpris --send player-next", + "escape": true, + "max-width": 90, + "return-type": "json" }, "custom/toggl": { - "format": " {}", + "format": " {}", "exec": "$HOME/.config/waybar/modules/toggl.lua 2>/dev/null", "interval": 30 }, - "custom/redshift": { - "format": "{icon}", - "format-icons": { + "custom/todo": { + "format": "{icon} {}", + "format-icons": { + "off": "!", + "on": "!", + // "work": "" + }, + "exec": "$HOME/.config/waybar/modules/waybar-todo", + "on-click": "pkill -x -USR1 waybar-todo", + "on-click-right": "pkill -x -USR2 waybar-todo", + "escape": true, + "return-type": "json" + }, + "custom/gammastep": { + "format": "{icon}", + "format-icons": { "day": "", "night": "" }, - "exec-if": "pgrep redshift", - "exec": "$HOME/.config/waybar/modules/waybar-redshift", + "exec-if": "pgrep gammastep", + "exec": "$HOME/.config/waybar/modules/waybar-gammastep", "return-type": "json", - "on-click": "pkill -x -USR1 redshift", - "on-click-right": "pkill -x -HUP waybar-redshift" + "on-click": "pkill -x -USR1 gammastep", + "on-click-right": "pkill -x -HUP waybar-gammastep" }, "custom/weather": { "format": "{icon} {percentage}℃", @@ -199,32 +195,8 @@ "interval": 600, "return-type": "json", "tooltip": true, - "signal": 4, - "on-click-right": "pkill -SIGRTMIN+5 waybar", + // "signal": 4, + // "on-click-right": "pkill -SIGRTMIN+5 waybar", "on-click": "swx -t env REPORT=1 $HOME/.config/waybar/modules/weather.sh Berlin" - }, - "mpd": { - "format": "{stateIcon} {artist} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S})", - "format-disconnected": "", - "unknown-tag": "N/A", - "consume-icons": { - "on": "" - }, - "random-icons": { - "off": "", - "on": "" - }, - "repeat-icons": { - "on": "" - }, - "single-icons": { - "on": "" - }, - "state-icons": { - "paused": "", - "playing": "" - }, - "tooltip-format": "mpd (connected)", - "tooltip-format-disconnected": "mpd (disconnected)" } } diff --git a/.config/waybar/modules/redshift.go b/.config/waybar/modules/gammastep.go index b336748..c855e1b 100644 --- a/.config/waybar/modules/redshift.go +++ b/.config/waybar/modules/gammastep.go @@ -1,10 +1,10 @@ // usage: -// go build -o waybar-redshift redshift.go +// go build -o waybar-gammastep gammastep.go package main import ( "encoding/json" - "fmt" + "log" "os" "os/exec" "os/signal" @@ -27,6 +27,7 @@ func main() { uintptr(PR_SET_PDEATHSIG), uintptr(SIGTERM), 0, 0, 0, 0); e != 0 { + log.Printf("error: %v", e) os.Exit(1) } // if err := Prctl(PR_SET_PDEATHSIG, @@ -51,7 +52,7 @@ func main() { lookup() } case <-cancel: - fmt.Fprintf(os.Stderr, "%v exiting\n", os.Args[0]) + log.Printf("%v exiting\n", os.Args[0]) os.Exit(0) } } @@ -61,29 +62,33 @@ func printJson(state, tooltip string) { _ = json.NewEncoder(os.Stdout).Encode(map[string]interface{}{ "class": state, "alt": state, - "tooltip": "redshift: " + tooltip, + "tooltip": "gammastep: " + tooltip, "text": state, }) } func lookup() { - b, err := exec.Command("redshift", "-p").Output() + b, err := exec.Command("gammastep", "-p").CombinedOutput() if err != nil { + log.Printf("error: %v", err) return } - fds := strings.Fields(string(b)) + var period string + var fds = strings.Fields(string(b)) for idx, f := range fds { if f == "Period:" { - fds = fds[idx+1:] + period = fds[idx+1] break } } - switch fds[0] { + switch period { case "Night": printJson("night", "night") case "Transition": printJson("night", "transition") case "Daytime": printJson("day", "day") + default: + printJson("unknown", "unknown") } } diff --git a/.config/waybar/modules/go.mod b/.config/waybar/modules/go.mod new file mode 100644 index 0000000..fdeae95 --- /dev/null +++ b/.config/waybar/modules/go.mod @@ -0,0 +1,5 @@ +module git.sr.ht/~robertgzr/dotfiles/.config/waybar/modules + +go 1.15 + +require github.com/fsnotify/fsnotify v1.4.9 // indirect diff --git a/.config/waybar/modules/go.sum b/.config/waybar/modules/go.sum new file mode 100644 index 0000000..b12c1ed --- /dev/null +++ b/.config/waybar/modules/go.sum @@ -0,0 +1,4 @@ +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/.config/waybar/modules/todo.go b/.config/waybar/modules/todo.go new file mode 100644 index 0000000..449f991 --- /dev/null +++ b/.config/waybar/modules/todo.go @@ -0,0 +1,246 @@ +// # Documentation +// we try to read a file pointed to by WAYBAR_TODO_FILE +// or `nb show --path todo`. +// While no particular format is assumed, we recommend +// Markdown. +// We extract the todos from the top-level list items +// (listings start with a `*` character). +// +// # Usage: +// go build -o waybar-todo todo.go +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "os/signal" + "regexp" + "strings" + "text/scanner" + "time" + + "github.com/fsnotify/fsnotify" + "golang.org/x/sys/unix" +) + +const ( + TODO_LINE_CHAR rune = '*' + TODO_INACTIVE_STRING string = "" + TODO_LABEL_REGEX string = `\[\[!(.*)\]\]` +) + +var ( + active = true + todofile = os.Getenv("WAYBAR_TODO_FILE") + cookiefile = os.ExpandEnv("${XDG_RUNTIME_DIR}/waybar-todo.cookie") + labelFilter = os.Getenv("WAYBAR_TODO_FILTER") +) + +func printJson(text, tooltip string, class []string, alt string, percentage int) error { + return json.NewEncoder(os.Stdout).Encode(map[string]interface{}{ + "text": text, + "tooltip": tooltip, + "class": class, + "alt": alt, + "percentage": percentage, + }) +} + +type todoItem struct { + text string + label string +} + +func readTodofile(path string) ([]todoItem, error) { + content, err := ioutil.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("reading file: %v", err) + } + + var ( + sc scanner.Scanner + validLine bool + todos []todoItem + ) + sc.Init(bytes.NewReader(content)) + sc.Filename = path + sc.Whitespace ^= 1<<'\n' | 1<<' ' // don't skip newlines or spaces + sc.Mode ^= scanner.GoTokens + for tok := sc.Scan(); tok != scanner.EOF; tok = sc.Scan() { + switch { + // a valid line stats with TODO_LINE_CHAR + // followed by a space + // we strip them before appending the line array + case tok == TODO_LINE_CHAR && sc.Peek() == ' ': + validLine = true + _ = sc.Scan() // swallow the space + todos = append(todos, todoItem{}) // grow the array + + case tok == '\n': + validLine = false + if len(todos) > 0 { + idx := len(todos) - 1 + matches := labelre.FindAllStringSubmatch(todos[idx].text, -1) + if matches != nil && len(matches) > 0 { + todos[idx].label = matches[0][1] + todos[idx].text = strings.TrimSpace( + strings.Replace(todos[idx].text, matches[0][0], "", 1)) + } + } + + case validLine: + todos[len(todos)-1].text = todos[len(todos)-1].text + sc.TokenText() + } + + } + return todos, nil +} + +func setCookie(active bool) error { + if !active { + _, err := os.Create(cookiefile) + return err + } + return os.Remove(cookiefile) +} + +func update() error { + if _, err := os.Stat(cookiefile); err == nil { + log.Printf("cookie set, we're inactive") + active = false + } + if !active { + return printJson(TODO_INACTIVE_STRING, "* inactive *", []string{"off"}, "todo-off", 0) + } + todos, err := readTodofile(todofile) + if err != nil { + return err + } + var ( + text string + tooltip string + extraClass string + ) + for _, item := range todos { + if labelFilter != "" && strings.Contains(labelFilter, item.label) { + continue + } + if text == "" { + text = item.text + extraClass = item.label + continue + } + // render out the rest of the todos into the tooltip + tooltip = strings.Join([]string{tooltip, item.text}, "\n") + } + return printJson(text, tooltip, []string{"on", extraClass}, "todo-on", 1) +} + +var ( + labelre *regexp.Regexp +) + +func init() { + labelre = regexp.MustCompile(TODO_LABEL_REGEX) +} + +func main() { + var ( + updateC = make(chan os.Signal, 1) + cancelC = make(chan os.Signal, 1) + ) + signal.Notify(updateC, unix.SIGUSR1, unix.SIGUSR2, unix.SIGHUP) + signal.Notify(cancelC, unix.SIGTERM, unix.SIGINT) + + var err error + // we will receive a SIGTERM if our parent dies + err = unix.Prctl(unix.PR_SET_PDEATHSIG, uintptr(unix.SIGTERM), 0, 0, 0) + if err != nil { + log.Fatalf("error: setting prctl: %v", err) + } + + if todofile == "" { + // get from nb(1) + nb := exec.Command("sh", "-c", "nb show --no-color --path todo") + nb_output, err := nb.Output() + if err != nil { + e := err.(*exec.ExitError) + log.Fatalf("error: finding todofile via nb: %s", e.Stderr) + } + todofile = strings.TrimSpace(string(nb_output)) + } + + log.Printf("watching %q", todofile) + + w, err := fsnotify.NewWatcher() + if err != nil { + log.Fatalf("error: creating watcher: %v", err) + } + defer w.Close() + + if err := w.Add(todofile); err != nil { + log.Fatalf("error: adding watch: %v", err) + } + + if err := update(); err != nil { + // fail here because it's the first time we + // try to read the todofile. + log.Fatalf("error: %v", err) + } + for { + select { + case evt, ok := <-w.Events: + if !ok { + return + } + // see https://github.com/fsnotify/fsnotify/issues/94 + // https://github.com/gohugoio/hugo/pull/4720 + if evt.Op&fsnotify.Remove == fsnotify.Remove { + counter := 0 + for w.Add(todofile) != nil { + counter++ + if counter >= 1000 { + log.Panic("error: unable to add file watcher") + } + time.Sleep(100 * time.Millisecond) + } + } + goto force_update + case err, ok := <-w.Errors: + if !ok { + return + } + log.Printf("error: from watcher: %v", err) + + case sig := <-updateC: + switch sig { + case unix.SIGUSR1: // on + active = !active + if err := setCookie(active); err != nil { + log.Printf("err: %v", err) + } + goto force_update + case unix.SIGUSR2: // + if strings.Contains(labelFilter, "work") { + labelFilter = strings.Trim(strings.ReplaceAll(labelFilter, "work", ""), ",") + } else { + labelFilter = strings.Join([]string{labelFilter, "work"}, ",") + } + continue + case unix.SIGHUP: // force update + log.Println("force update") + goto force_update + } + case <-cancelC: + log.Printf("%s exiting", os.Args[0]) + os.Exit(0) + } + force_update: + _ = update() + } +} diff --git a/.config/waybar/style.css b/.config/waybar/style.css index 9e41694..d28b142 100644 --- a/.config/waybar/style.css +++ b/.config/waybar/style.css @@ -1,10 +1,30 @@ -@define-color foreground #fffefe; -@define-color background #221e1d; +@define-color color00 #1c1c1c; +@define-color color01 #e03c8a; +@define-color color02 #90b44b; +@define-color color03 #caad5f; +@define-color color04 #58b2dc; +@define-color color05 #828282; +@define-color color06 #e3916e; +@define-color color07 #bdc0ba; +@define-color color08 #535953; +@define-color color09 #86c166; +@define-color color10 #ddd23b; +@define-color color11 #b28fce; +@define-color color12 #ffb11b; +@define-color color13 #66bab7; +@define-color color14 #77969a; +@define-color color15 #fffffb; + @define-color accent #4e4371; @define-color accentdarker #3e355a; -@define-color dimmed #777777; -@define-color dimmeddarker #302a29; -@define-color urgent #db4d6d; + +@define-color foreground @color07; +@define-color background @color00; +/* @define-color dimmed #777777; */ +/* @define-color dimmeddarker #302a29; */ +@define-color dimmed @color05; +@define-color dimmeddarker #292929; +@define-color urgent #9f353a; * { border: none; @@ -22,22 +42,36 @@ #disk, #temperature, #backlight, +#idle_inhibitor, #network, #pulseaudio, -#custom-mpd, -#custom-mpv, -#custom-spotify, #custom-toggl, -#custom-redshift, +#custom-gammastep, #custom-weather, -#mpd, -#tray, -#idle_inhibitor { +#custom-mpris, +#custom-todo, +#tray { border-top: 2px solid @dimmeddarker; padding: 0 0.3rem; margin: 0 0.25rem; color: @foreground; } +#cpu:hover, +#memory:hover, +#backlight:hover, +#idle_inhibitor:hover, +#network:hover, +#network.vpn:hover, +#network.tailscale:hover, +#pulseaudio:hover, +#custom-mpris:hover, +#custom-gammastep:hover, +#custom-todo:hover { + background: red; + color: @foreground; + transition-property: background; + transition-duration: 0.1s; +} #workspaces button { padding: 0 5px; @@ -46,6 +80,7 @@ /* border-bottom: 3px solid transparent; */ } #workspaces button.focused { + font-weight: bold; color: @foreground; background: @accentdarker; transition-property: background; @@ -88,8 +123,9 @@ window#waybar.solo {} #mode { font-style: italic; - background: #64727d; - border-top: 2px solid @foreground; + color: @background; + background: @color06; + border-top: none; } #clock {} @@ -109,8 +145,8 @@ window#waybar.solo {} #battery {} #battery.charging { - color: @foreground; - background: #26a65b; + color: @background; + background: @color09; } @keyframes blink { to { @@ -119,8 +155,8 @@ window#waybar.solo {} } } #battery.critical:not(.charging) { - background: #f53c3c; color: @foreground; + background: @urgent; animation-name: blink; animation-duration: 0.5s; animation-timing-function: linear; @@ -147,17 +183,13 @@ label:focus { border-top: 2px solid @dimmeddarker; } #network.vpn:not(.disconnected) { - border-top: 2px solid #c476ff; - /* background: #c476ff; */ - /* color: @dimmeddarker; */ + border-top: 2px solid @color11; } #network.tailscale.disconnected { border-top: 2px solid @dimmeddarker; } #network.tailscale:not(.disconnected) { - border-top: 2px solid #497e7a; - /* background: #497e7a; */ - /* color: @dimmeddarker; */ + border-top: 2px solid @color14; } #pulseaudio {} #pulseaudio.muted { @@ -167,7 +199,8 @@ label:focus { #temperature {} #temperature.critical { - background: #eb4d4b; + background: @urgent; + border-top: none; } #tray {} @@ -177,32 +210,32 @@ label:focus { } #idle_inhibitor.activated { color: unset; - border-top: 2px solid #7a8530; + border-top: 2px solid @color02; } -#custom-mpd, -#custom-mpv, -#custom-spotify { +#custom-mpris { min-width: 100px; color: @foreground; - border-top: 2px solid #628aaa; -} -#custom-mpd.paused, -#custom-mpv.paused, -#custom-spotify.paused { - color: @dimmed; -} -#custom-spotify { - border-top: 2px solid #1DB954; -} -#custom-mpv { - border-top: 2px solid #520053; + border-top: 2px solid @color04; } #custom-toggl { color: @foreground; - /* background: #DB4D6D; */ - border-top: 2px solid #DB4D60; + border-top: 2px solid @urgent; +} + +#custom-todo.off { + color: red; + border-top: 2px solid @dimmeddarker; +} +#custom-todo.on { + color: @foreground; + font-weight: bold; + border-top: none; + padding: 0 0.6rem 0 0.4rem; +} +#custom-todo.work { + background: @urgent; } @keyframes flash { @@ -211,19 +244,19 @@ label:focus { color: @background; } } -#custom-redshift.night { - border-top: 2px solid #97822e; +#custom-gammastep.night { + border-top: 2px solid @color12; color: @foreground; animation-name: flash; animation-duration: 0.3s; animation-timing-function: linear; animation-iteration-count: 1; } -#custom-redshift.day { +#custom-gammastep.day { color: @dimmed; } -#custom-redshift.off, -#custom-redshift.unknown { +#custom-gammastep.off, +#custom-gammastep.unknown { border-top: 2px solid @urgent; color: @dimmed; } @@ -232,21 +265,5 @@ label:focus { color: @dimmed; } #custom-weather.sunny { - /* color: rgba(255,206,66, 0.4); */ -} - -#mpd { - color: @foreground; - border-top: 2px solid #d75f00; -} -#mpd.disconnected { - margin: 0; - padding: 0; -} -#mpd.stopped { - margin: 0; - padding: 0; -} -#mpd.paused { - border-top: 2px solid #8b3d00; + color: rgba(255,255,0, 0.6); } |