1
0
Fork 0

Updates for barista bar

main
Mari 3 years ago
parent 368dd54d39
commit 2757bc6f16
  1. 7
      TODO.md
  2. 2
      bash/bash_aliases.sh
  3. 2
      bash/bash_tmux.sh
  4. 56
      borgmatic/borgmatic-daily.service
  5. 9
      borgmatic/borgmatic-daily.timer
  6. 56
      borgmatic/borgmatic-hourly.service
  7. 9
      borgmatic/borgmatic-hourly.timer
  8. 56
      borgmatic/borgmatic-monthly.service
  9. 9
      borgmatic/borgmatic-monthly.timer
  10. 56
      borgmatic/borgmatic-weekly.service
  11. 9
      borgmatic/borgmatic-weekly.timer
  12. 1
      i3/.gitignore
  13. 100
      i3/config
  14. 2
      i3/helpers/barista/.gitignore
  15. 8
      i3/helpers/barista/.idea/.gitignore
  16. 17
      i3/helpers/barista/.idea/barista.iml
  17. 8
      i3/helpers/barista/.idea/modules.xml
  18. 371
      i3/helpers/barista/barista-bar.go
  19. 7
      i3/helpers/barista/build-barista-bar.sh
  20. 10
      i3/helpers/barista/cache-for-testing.go.bak
  21. 23
      i3/helpers/barista/color-scheme.go
  22. 31
      i3/helpers/barista/format.go
  23. 5
      i3/helpers/barista/go.mod
  24. 28
      i3/helpers/barista/go.sum
  25. 55
      i3/helpers/barista/media.go
  26. 157
      i3/helpers/barista/nerdfont-process-css.go
  27. 21
      i3/helpers/barista/nerdfont-provider.go
  28. 46
      i3/helpers/barista/oauth.go
  29. 91
      i3/helpers/barista/power.go
  30. 81
      i3/helpers/barista/system.go
  31. 34
      i3/helpers/barista/user.go
  32. 1
      ssh/config
  33. 2
      zsh/customizations/zsh_aliases.zsh
  34. 2
      zsh/customizations/zsh_tmux.zsh
  35. 2
      zsh/ohmyzsh

@ -10,9 +10,7 @@
* Use dunstify for a notification after reloading the i3 config
* Include the mozc and dunst configs and rofi configs in here
* Install+configure (or is it configure+install?) xst and make it the new i3 terminal
* Store the Ubuntu NerdFonts on Gubal.
* Wrap the lock process in a wrapper which pauses dunst and then unpauses it
* Enable automatic gamma shifting with gammastep using the randr method
* Replace i3 shell scripts with Go binaries - or maybe just one Go binary with many options, busybox-style?
* Set up picom as compositor for i3, and embed its config here
* Set up individual desktop entries for the two firefox profiles with their -P and --class settings.
@ -22,3 +20,8 @@
* Upgrade rofi to the latest - v 1.6.1 - from source
* Add user scripts to rofi to make it prettier and more useful: https://github.com/davatorium/rofi/wiki/User-scripts or https://github.com/topics/rofi
* Set up a desktop background
* Theme zsh's prompt with the same colors
* Add the playerctl utility for the play/pause button
* Take stock of requirements and set up an install script
* Add temperature and memory and load monitor which provides notifications (including picking a process likely to be responsible) when any or several are critical
* Add food/drink/etc. reminders when still haven't eaten at some time past meal time

@ -11,6 +11,8 @@ if [[ -n $SSH_AUTH_SOCK ]] && [[ $SSH_AUTH_SOCK != $HOME/.ssh/ssh_auth_sock ]];
fi
export SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock"
# Set TZ if it's not set
LOCALZONE=$(readlink -e /etc/localtime); export TZ=${TZ:-${LOCALZONE#/usr/share/zoneinfo/}}
# Install EDITOR
export EDITOR='nvim'
# Install PAGER

@ -11,7 +11,7 @@ function tmux_running() {
}
function tmux_init() {
tmux -2 new-session -d -s "Nexus" -n "Misc." 'LC_ALL=C.UTF-8 fortune | cowsay -f eyes -W "$COLUMNS"; exec "$SHELL" -i'
tmux -2 new-session -d -s "Nexus" 'LC_ALL=C.UTF-8 fortune | cowsay -f eyes -W "$COLUMNS"; exec "$SHELL" -i'
}
function go_tmux ()

@ -0,0 +1,56 @@
[Unit]
Description=borgmatic backup
Wants=network-online.target
After=network-online.target
ConditionACPower=true
[Service]
Type=simple
# Security settings for systemd running as root
# For more details about this settings check the systemd manuals
# https://www.freedesktop.org/software/systemd/man/systemd.exec.html
LockPersonality=true
# Certain borgmatic features like Healthchecks integration need MemoryDenyWriteExecute to be off.
# But you can try setting it to "yes" for improved security if you don't use those features.
MemoryDenyWriteExecute=no
NoNewPrivileges=yes
PrivateDevices=yes
PrivateTmp=yes
ProtectClock=yes
ProtectControlGroups=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service
# Restrict write access
# Change to 'ProtectSystem=strict' and uncomment 'ProtectHome' to make the whole file
# system read-only be default and uncomment 'ReadWritePaths' for the required write access.
# Add local repositroy paths to the list of 'ReadWritePaths' like '-/mnt/my_backup_drive'.
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=-/root/.config/borg -/root/.cache/borg -/root/.borgmatic /var/backups/postgres -/mnt/backup-1/borg/gubal.borg -/mnt/backup-2/borg/gubal.borg -/mnt/backup-1/borg/goldsaucer.borg -/mnt/backup-2/borg/goldsaucer.borg
CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_AUDIT_WRITE
# Lower CPU and I/O priority.
Nice=19
CPUSchedulingPolicy=batch
IOSchedulingClass=best-effort
IOSchedulingPriority=7
IOWeight=100
Restart=no
# Prevent rate limiting of borgmatic log events. If you are using an older version of systemd that
# doesn't support this (pre-240 or so), you may have to remove this option.
LogRateLimitIntervalSec=0
# Delay start to prevent backups running during boot. Note that systemd-inhibit requires dbus and
# dbus-user-session to be installed.
ExecStart=systemd-inhibit --who="borgmatic" --why="Prevent interrupting scheduled backup" /usr/bin/borgmatic -c /etc/borgmatic/configs-nightly /etc/borgmatic/configs-enabled --syslog-verbosity 1 prune create check --only repository --only archives

@ -0,0 +1,9 @@
[Unit]
Description=Run borgmatic backup
[Timer]
OnCalendar=Mon..Sat *-*-2..31 11:00:00 UTC
Persistent=true
[Install]
WantedBy=timers.target

@ -0,0 +1,56 @@
[Unit]
Description=borgmatic backup
Wants=network-online.target
After=network-online.target
ConditionACPower=true
[Service]
Type=simple
# Security settings for systemd running as root
# For more details about this settings check the systemd manuals
# https://www.freedesktop.org/software/systemd/man/systemd.exec.html
LockPersonality=true
# Certain borgmatic features like Healthchecks integration need MemoryDenyWriteExecute to be off.
# But you can try setting it to "yes" for improved security if you don't use those features.
MemoryDenyWriteExecute=no
NoNewPrivileges=yes
PrivateDevices=yes
PrivateTmp=yes
ProtectClock=yes
ProtectControlGroups=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service
# Restrict write access
# Change to 'ProtectSystem=strict' and uncomment 'ProtectHome' to make the whole file
# system read-only be default and uncomment 'ReadWritePaths' for the required write access.
# Add local repositroy paths to the list of 'ReadWritePaths' like '-/mnt/my_backup_drive'.
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=-/root/.config/borg -/root/.cache/borg -/root/.borgmatic /var/backups/postgres -/mnt/backup-1/borg/gubal.borg -/mnt/backup-2/borg/gubal.borg -/mnt/backup-1/borg/goldsaucer.borg -/mnt/backup-2/borg/goldsaucer.borg
CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_AUDIT_WRITE
# Lower CPU and I/O priority.
Nice=19
CPUSchedulingPolicy=batch
IOSchedulingClass=best-effort
IOSchedulingPriority=7
IOWeight=100
Restart=no
# Prevent rate limiting of borgmatic log events. If you are using an older version of systemd that
# doesn't support this (pre-240 or so), you may have to remove this option.
LogRateLimitIntervalSec=0
# Delay start to prevent backups running during boot. Note that systemd-inhibit requires dbus and
# dbus-user-session to be installed.
ExecStart=systemd-inhibit --who="borgmatic" --why="Prevent interrupting scheduled backup" /usr/bin/borgmatic -c /etc/borgmatic/configs-enabled --syslog-verbosity 1 create

@ -0,0 +1,9 @@
[Unit]
Description=Run borgmatic backup
[Timer]
OnCalendar=*-*-* 0..10,16..23:00:00 UTC
Persistent=true
[Install]
WantedBy=timers.target

@ -0,0 +1,56 @@
[Unit]
Description=borgmatic backup
Wants=network-online.target
After=network-online.target
ConditionACPower=true
[Service]
Type=simple
# Security settings for systemd running as root
# For more details about this settings check the systemd manuals
# https://www.freedesktop.org/software/systemd/man/systemd.exec.html
LockPersonality=true
# Certain borgmatic features like Healthchecks integration need MemoryDenyWriteExecute to be off.
# But you can try setting it to "yes" for improved security if you don't use those features.
MemoryDenyWriteExecute=no
NoNewPrivileges=yes
PrivateDevices=yes
PrivateTmp=yes
ProtectClock=yes
ProtectControlGroups=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service
# Restrict write access
# Change to 'ProtectSystem=strict' and uncomment 'ProtectHome' to make the whole file
# system read-only be default and uncomment 'ReadWritePaths' for the required write access.
# Add local repositroy paths to the list of 'ReadWritePaths' like '-/mnt/my_backup_drive'.
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=-/root/.config/borg -/root/.cache/borg -/root/.borgmatic /var/backups/postgres -/mnt/backup-1/borg/gubal.borg -/mnt/backup-2/borg/gubal.borg -/mnt/backup-1/borg/goldsaucer.borg -/mnt/backup-2/borg/goldsaucer.borg
CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_AUDIT_WRITE
# Lower CPU and I/O priority.
Nice=19
CPUSchedulingPolicy=batch
IOSchedulingClass=best-effort
IOSchedulingPriority=7
IOWeight=100
Restart=no
# Prevent rate limiting of borgmatic log events. If you are using an older version of systemd that
# doesn't support this (pre-240 or so), you may have to remove this option.
LogRateLimitIntervalSec=0
# Delay start to prevent backups running during boot. Note that systemd-inhibit requires dbus and
# dbus-user-session to be installed.
ExecStart=systemd-inhibit --who="borgmatic" --why="Prevent interrupting scheduled backup" /usr/bin/borgmatic -c /etc/borgmatic/configs-nightly /etc/borgmatic/configs-enabled --syslog-verbosity 1 prune create check --only repository --only archives --only extract --only data

@ -0,0 +1,9 @@
[Unit]
Description=Run borgmatic backup
[Timer]
OnCalendar=*-*-1 11:00:00 UTC
Persistent=true
[Install]
WantedBy=timers.target

@ -0,0 +1,56 @@
[Unit]
Description=borgmatic backup
Wants=network-online.target
After=network-online.target
ConditionACPower=true
[Service]
Type=simple
# Security settings for systemd running as root
# For more details about this settings check the systemd manuals
# https://www.freedesktop.org/software/systemd/man/systemd.exec.html
LockPersonality=true
# Certain borgmatic features like Healthchecks integration need MemoryDenyWriteExecute to be off.
# But you can try setting it to "yes" for improved security if you don't use those features.
MemoryDenyWriteExecute=no
NoNewPrivileges=yes
PrivateDevices=yes
PrivateTmp=yes
ProtectClock=yes
ProtectControlGroups=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service
# Restrict write access
# Change to 'ProtectSystem=strict' and uncomment 'ProtectHome' to make the whole file
# system read-only be default and uncomment 'ReadWritePaths' for the required write access.
# Add local repositroy paths to the list of 'ReadWritePaths' like '-/mnt/my_backup_drive'.
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=-/root/.config/borg -/root/.cache/borg -/root/.borgmatic /var/backups/postgres -/mnt/backup-1/borg/gubal.borg -/mnt/backup-2/borg/gubal.borg -/mnt/backup-1/borg/goldsaucer.borg -/mnt/backup-2/borg/goldsaucer.borg
CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_AUDIT_WRITE
# Lower CPU and I/O priority.
Nice=19
CPUSchedulingPolicy=batch
IOSchedulingClass=best-effort
IOSchedulingPriority=7
IOWeight=100
Restart=no
# Prevent rate limiting of borgmatic log events. If you are using an older version of systemd that
# doesn't support this (pre-240 or so), you may have to remove this option.
LogRateLimitIntervalSec=0
# Delay start to prevent backups running during boot. Note that systemd-inhibit requires dbus and
# dbus-user-session to be installed.
ExecStart=systemd-inhibit --who="borgmatic" --why="Prevent interrupting scheduled backup" /usr/bin/borgmatic -c /etc/borgmatic/configs-nightly /etc/borgmatic/configs-enabled --syslog-verbosity 1 prune create check --only repository --only archives --only extract

@ -0,0 +1,9 @@
[Unit]
Description=Run borgmatic backup
[Timer]
OnCalendar=Sun *-*-2..31 11:00:00 UTC
Persistent=true
[Install]
WantedBy=timers.target

1
i3/.gitignore vendored

@ -1 +0,0 @@
barista-bar

@ -13,7 +13,7 @@ set $mod Mod4
# Font for window titles. Will also be used by the bar unless a different font
# is used in the bar {} block below.
font pango:Ubuntu Mono, UbuntuMono Nerd Font 10
font pango:Ubuntu Mono, UbuntuMono Nerd Font 14
# This font is widely installed, provides lots of unicode glyphs, right-to-left
# text rendering and scalability on retina/hidpi displays (thanks to pango).
@ -24,61 +24,60 @@ font pango:Ubuntu Mono, UbuntuMono Nerd Font 10
# xss-lock grabs a logind suspend inhibit lock and will use i3lock to lock the
# screen before suspend. Use loginctl lock-session to lock your screen.
exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork -c 0081a7 -e
exec --no-startup-id exec xss-lock --transfer-sleep-lock -- i3lock --nofork -c 0081a7 -e
# NetworkManager is the most popular way to manage wireless networks on Linux,
# and nm-applet is a desktop environment-independent system tray GUI for it.
exec --no-startup-id nm-applet
exec --no-startup-id exec nm-applet
# Set up the gnome settings daemon for better gnome support
exec --no-startup-id /usr/libexec/gnome-settings-daemon-localeexec
exec --no-startup-id exec /usr/libexec/gnome-settings-daemon-localeexec
# Fix a bug in gnome-settings-daemon: http://feeding.cloud.geek.nz/posts/creating-a-modern-tiling-desktop-environment-using-i3/
exec --no-startup-id dconf write /org/gnome/settings-daemon/plugins/cursor/active false
exec --no-startup-id exec dconf write /org/gnome/settings-daemon/plugins/cursor/active false
# Initialize a tmux session on startup
exec --no-startup-id zsh -ic "tmux_init"
exec --no-startup-id exec zsh -ic "tmux_init"
# Start up the gammastep color temperature adjustment daemon.
exec --no-startup-id gammastep
exec --no-startup-id exec gammastep
# Enable the relevant xkb options to allow the capslock remapping to proceed
exec --no-startup-id setxkbmap -option shift:both_capslock,caps:hyper
exec --no-startup-id exec setxkbmap -option shift:both_capslock,caps:hyper
# Set up xcape to switch input modes for mozc with caps lock
exec --no-startup-id xcape -e 'Hyper_L=Control_L|grave'
exec --no-startup-id exec xcape -e 'Hyper_L=Control_L|grave'
# Set up xcape to make control a closer escape instead
exec --no-startup-id xcape -e 'Control_L=Escape'
exec --no-startup-id exec xcape -e 'Control_L=Escape'
# Set up xcape to make tapping the super key trigger the tmux modifier key.
exec --no-startup-id xcape -e 'Super_L=Control_L|a'
exec --no-startup-id exec xcape -e 'Super_L=Control_L|a'
# Use pactl to adjust volume in PulseAudio.
set $refresh_i4status killall -SIGUSR1 i3status
bindsym XF86AudioRaiseVolume exec --no-startup-id ~/.config/i3/helpers/volume.sh up
bindsym XF86AudioLowerVolume exec --no-startup-id ~/.config/i3/helpers/volume.sh down
bindsym Shift+XF86AudioLowerVolume exec --no-startup-id ~/.config/i3/helpers/volume.sh off
bindsym Shift+XF86AudioRaiseVolume exec --no-startup-id ~/.config/i3/helpers/volume.sh max
bindsym XF86AudioMute exec --no-startup-id ~/.config/i3/helpers/volume.sh toggle_mute
bindsym Shift+XF86AudioMute exec --no-startup-id ~/.config/i3/helpers/volume.sh full_mute
bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status
bindsym XF86AudioRaiseVolume exec --no-startup-id exec ~/.config/i3/helpers/volume.sh up
bindsym XF86AudioLowerVolume exec --no-startup-id exec ~/.config/i3/helpers/volume.sh down
bindsym Shift+XF86AudioLowerVolume exec --no-startup-id exec ~/.config/i3/helpers/volume.sh off
bindsym Shift+XF86AudioRaiseVolume exec --no-startup-id exec ~/.config/i3/helpers/volume.sh max
bindsym XF86AudioMute exec --no-startup-id exec ~/.config/i3/helpers/volume.sh toggle_mute
bindsym Shift+XF86AudioMute exec --no-startup-id exec ~/.config/i3/helpers/volume.sh full_mute
bindsym XF86AudioMicMute exec --no-startup-id exec pactl set-source-mute @DEFAULT_SOURCE@ toggle
# Use brightnessctl to adjust screen brightness.
bindsym XF86MonBrightnessUp exec --no-startup-id ~/.config/i3/helpers/brightness.sh up
bindsym XF86MonBrightnessDown exec --no-startup-id ~/.config/i3/helpers/brightness.sh down
bindsym Shift+XF86MonBrightnessUp exec --no-startup-id ~/.config/i3/helpers/brightness.sh max
bindsym Shift+XF86MonBrightnessDown exec --no-startup-id ~/.config/i3/helpers/brightness.sh off
bindsym XF86MonBrightnessUp exec --no-startup-id exec ~/.config/i3/helpers/brightness.sh up
bindsym XF86MonBrightnessDown exec --no-startup-id exec ~/.config/i3/helpers/brightness.sh down
bindsym Shift+XF86MonBrightnessUp exec --no-startup-id exec ~/.config/i3/helpers/brightness.sh max
bindsym Shift+XF86MonBrightnessDown exec --no-startup-id exec ~/.config/i3/helpers/brightness.sh off
# Use the screenshot wrapper script.
bindsym Print --release exec --no-startup-id ~/.config/i3/helpers/screenshot.sh screen
bindsym Shift+Print --release exec --no-startup-id ~/.config/i3/helpers/screenshot.sh area
bindsym Print --release exec --no-startup-id exec ~/.config/i3/helpers/screenshot.sh screen
bindsym Shift+Print --release exec --no-startup-id exec ~/.config/i3/helpers/screenshot.sh area
# This is Alt+Print, but it's actually registered as a different key (on laptops at least).
bindsym Sys_Req --release exec --no-startup-id ~/.config/i3/helpers/screenshot.sh current_window
bindsym Shift+Sys_Req --release exec --no-startup-id ~/.config/i3/helpers/screenshot.sh select_window
bindsym Sys_Req --release exec --no-startup-id exec ~/.config/i3/helpers/screenshot.sh current_window
bindsym Shift+Sys_Req --release exec --no-startup-id exec ~/.config/i3/helpers/screenshot.sh select_window
# Nonetheless, we bind the same Alt+Printscreen shortcut just in case.
bindsym Mod1+Print --release exec --no-startup-id ~/.config/i3/helpers/screenshot.sh current_window
bindsym Shift+Mod1+Print --release exec --no-startup-id ~/.config/i3/helpers/screenshot.sh select_window
bindsym Mod1+Print --release exec --no-startup-id exec ~/.config/i3/helpers/screenshot.sh current_window
bindsym Shift+Mod1+Print --release exec --no-startup-id exec ~/.config/i3/helpers/screenshot.sh select_window
# Use Control instead of Alt in case Alt+Printscreen is ignored by i3.
bindsym Control+Print --release exec --no-startup-id ~/.config/i3/helpers/screenshot.sh current_window
bindsym Shift+Control+Print --release exec --no-startup-id ~/.config/i3/helpers/screenshot.sh select_window
bindsym Control+Print --release exec --no-startup-id exec ~/.config/i3/helpers/screenshot.sh current_window
bindsym Shift+Control+Print --release exec --no-startup-id exec ~/.config/i3/helpers/screenshot.sh select_window
# Use Mouse+$mod to drag floating windows to their wanted position
@ -88,12 +87,12 @@ floating_modifier $mod
# kill focused window
bindsym $mod+Shift+q kill
bindsym $mod+Shift+l exec --no-startup-id loginctl lock-session
bindsym $mod+Shift+l exec --no-startup-id exec loginctl lock-session
# start dmenu (a program launcher)
# bindsym $mod+d exec --no-startup-id dmenu_run
# A more modern dmenu replacement is rofi:
bindsym $mod+d --release exec "rofi -modi drun,run -show drun -show-icons"
bindsym $mod+d --release exec "exec rofi -modi drun,run -show drun -show-icons"
# bindcode $mod+40 exec "rofi -modi drun,run -show drun"
# There also is i3-dmenu-desktop which only displays applications shipping a
# .desktop file. It is a wrapper around dmenu, so you need that installed.
@ -157,7 +156,7 @@ set $ws3 "3: Chat"
set $ws4 "4: IDE"
set $ws5 "5: Terminal"
set $ws6 "6: Files"
set $ws7 "7"
set $ws7 "7: Parsec"
set $ws8 "8"
set $ws9 "9"
set $ws10 "10: Lewd Zone"
@ -187,11 +186,13 @@ bindsym $mod+Shift+9 move container to workspace number $ws9
bindsym $mod+Shift+0 move container to workspace number $ws10
# reload the configuration file
bindsym $mod+Shift+c reload
bindsym $mod+Shift+c exec "i3-msg reload && dunstify 'Reloaded i3.' || dunstify 'Failed to reload i3.'"
bindsym $mod+Control+Shift+c exec "mkdir -p ~/.cache/barista && ~/.config/i3/helpers/barista/build-barista-bar.sh > ~/.cache/barista/build.log 2<&1 && i3-msg reload && dunstify 'Upgraded barista bar and reloaded i3.' || dunstify 'Barista bar could not be upgraded, or i3 could not be reloaded.'"
# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
bindsym $mod+Shift+r restart
bindsym $mod+Shift+r exec "i3-msg restart && dunstify 'Restarted i3.' || dunstify 'Failed to restart i3.'"
bindsym $mod+Control+Shift+r exec "mkdir -p ~/.cache/barista && ~/.config/i3/helpers/barista/build-barista-bar.sh > ~/.cache/barista/build.log 2<&1 && i3-msg restart && dunstify 'Upgraded barista bar and restarted i3.' || dunstify 'Barista bar could not be upgraded, or i3 could not be restarted.'"
# exit i3 (logs you out of your X session)
bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'"
bindsym $mod+Shift+e exec "exec i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'"
# resize window (you can also use the mouse for that)
mode "resize" {
@ -227,15 +228,16 @@ hide_edge_borders smart
# Place normal firefox windows on workspace 1.
assign [class="^Firefox\.Main$"] workspace number $ws1
bindsym $mod+Control+1 workspace $ws1 ; exec firefox -P "Mari" --class "Firefox.Main"
bindsym $mod+Control+1 workspace $ws1 ; exec exec firefox -P "Mari" --class "Firefox.Main"
# Place Spotify windows on workspace 2.
for_window [class="^Spotify$"] move to workspace number $ws2
bindsym $mod+Control+2 workspace $ws2 ; exec spotify
for_window [class="^Sublime-music$"] move to workspace number $ws2
bindsym $mod+Control+2 workspace $ws2 ; exec exec ~/.local/bin/sublime-music
# Place Discord windows on workspace 3.
assign [class="^discord$"] workspace number $ws3
bindsym $mod+Control+3 workspace $ws3 ; exec discord
bindsym $mod+Control+3 workspace $ws3 ; exec exec discord
# Make the JetBrains IDEs' opening windows float
for_window [class="^jetbrains-.*$" title="win0"] floating enable
@ -244,19 +246,27 @@ assign [class="^jetbrains-.*$"] workspace number $ws4
# start a terminal
assign [class="^Lxterminal$"] workspace number $ws5
bindsym $mod+Control+5 workspace $ws5 ; exec lxterminal -e '$SHELL -ic "go_tmux -x"'
bindsym $mod+Return workspace $ws5 ; exec lxterminal -e '$SHELL -ic "go_tmux -x"'
bindsym $mod+Control+5 workspace $ws5 ; exec exec lxterminal -e '$SHELL -ic "go_tmux -x"'
bindsym $mod+Return workspace $ws5 ; exec exec lxterminal -e '$SHELL -ic "go_tmux -x"'
# open a file manager
assign [class="^Org\.gnome\.Nautilus$"] workspace number $ws6
bindsym $mod+Control+6 workspace $ws6 ; exec nautilus
bindsym $mod+Control+6 workspace $ws6 ; exec exec nautilus
# connect to parsec
assign [class="^parsecd$"] workspace number $ws7
bindsym $mod+Control+7 workspace $ws7 ; exec exec parsecd
# Place lewd firefox windows on workspace 10.
assign [class="^Firefox\.Lewd$"] workspace number $ws10
bindsym $mod+Control+0 workspace $ws10 ; exec firefox -P "Reya" --class "Firefox.Lewd"
bindsym $mod+Control+0 workspace $ws10 ; exec exec firefox -P "Reya" --class "Firefox.Lewd"
# Start i3bar to display a workspace bar (plus the system information i3status
# finds out, if available)
bar {
status_command i3status
status_command exec ~/.config/i3/helpers/barista/barista-bar
colors {
background #000000
statusline #e8e8e8
}
}

@ -0,0 +1,2 @@
barista-bar
nerdfont-provider-data.go

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true">
<buildTags>
<option name="customFlags">
<array>
<option value="generation" />
</array>
</option>
</buildTags>
</component>
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/barista.iml" filepath="$PROJECT_DIR$/.idea/barista.iml" />
</modules>
</component>
</project>

@ -17,205 +17,47 @@
package main
import (
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"os"
"os/user"
"path/filepath"
"math"
"time"
"barista.run"
"barista.run/bar"
"barista.run/base/click"
"barista.run/base/watchers/netlink"
"barista.run/colors"
"barista.run/format"
"barista.run/group/collapsing"
"barista.run/modules/battery"
"barista.run/modules/clock"
"barista.run/modules/cputemp"
"barista.run/modules/github"
"barista.run/modules/media"
"barista.run/modules/meminfo"
"barista.run/modules/netspeed"
"barista.run/modules/sysinfo"
"barista.run/modules/volume"
"barista.run/modules/volume/alsa"
"barista.run/modules/weather"
"barista.run/modules/weather/openweathermap"
"barista.run/oauth"
"barista.run/outputs"
"barista.run/pango"
"barista.run/pango/icons/fontawesome"
"barista.run/pango/icons/material"
"barista.run/pango/icons/mdi"
"barista.run/pango/icons/typicons"
"barista.run/testing/httpcache"
colorful "github.com/lucasb-eyer/go-colorful"
"github.com/martinlindhe/unit"
keyring "github.com/zalando/go-keyring"
)
func init() {
http.DefaultTransport = httpcache.Wrap(http.DefaultTransport)
}
var spacer = pango.Text(" ").XXSmall()
func truncate(in string, l int) string {
if len([]rune(in)) <= l {
return in
}
return string([]rune(in)[:l-1]) + "⋯"
}
func hms(d time.Duration) (h int, m int, s int) {
h = int(d.Hours())
m = int(d.Minutes()) % 60
s = int(d.Seconds()) % 60
return
}
func formatMediaTime(d time.Duration) string {
h, m, s := hms(d)
if h > 0 {
return fmt.Sprintf("%d:%02d:%02d", h, m, s)
}
return fmt.Sprintf("%d:%02d", m, s)
}
func mediaFormatFunc(m media.Info) bar.Output {
if m.PlaybackStatus == media.Stopped || m.PlaybackStatus == media.Disconnected {
return nil
}
artist := truncate(m.Artist, 20)
title := truncate(m.Title, 40-len(artist))
if len(title) < 20 {
artist = truncate(m.Artist, 40-len(title))
}
iconAndPosition := pango.Icon("fa-music").Color(colors.Hex("#f70"))
if m.PlaybackStatus == media.Playing {
iconAndPosition.Append(
spacer, pango.Textf("%s/%s",
formatMediaTime(m.Position()),
formatMediaTime(m.Length)),
)
}
return outputs.Pango(iconAndPosition, spacer, title, " - ", artist)
}
var startTaskManager = click.RunLeft("xfce4-taskmanager")
func home(path string) string {
usr, err := user.Current()
if err != nil {
panic(err)
}
return filepath.Join(usr.HomeDir, path)
}
type freegeoipResponse struct {
Lat float64 `json:"latitude"`
Lng float64 `json:"longitude"`
type autoWeatherProvider struct{
ApiKey string
}
func whereami() (lat float64, lng float64, err error) {
resp, err := http.Get("https://freegeoip.app/json/")
if err != nil {
return 0, 0, err
}
var res freegeoipResponse
err = json.NewDecoder(resp.Body).Decode(&res)
if err != nil {
return 0, 0, err
}
return res.Lat, res.Lng, nil
}
type autoWeatherProvider struct{}
func (a autoWeatherProvider) GetWeather() (weather.Weather, error) {
lat, lng, err := whereami()
if err != nil {
return weather.Weather{}, err
}
return openweathermap.
New("%%OWM_API_KEY%%").
New(a.ApiKey).
Coords(lat, lng).
GetWeather()
}
func setupOauthEncryption() error {
const service = "barista-sample-bar"
var username string
if u, err := user.Current(); err == nil {
username = u.Username
} else {
username = fmt.Sprintf("user-%d", os.Getuid())
}
var secretBytes []byte
// IMPORTANT: The oauth tokens used by some modules are very sensitive, so
// we encrypt them with a random key and store that random key using
// libsecret (gnome-keyring or equivalent). If no secret provider is
// available, there is no way to store tokens (since the version of
// sample-bar used for setup-oauth will have a different key from the one
// running in i3bar). See also https://github.com/zalando/go-keyring#linux.
secret, err := keyring.Get(service, username)
if err == nil {
secretBytes, err = base64.RawURLEncoding.DecodeString(secret)
}
if err != nil {
secretBytes = make([]byte, 64)
_, err := rand.Read(secretBytes)
if err != nil {
return err
}
secret = base64.RawURLEncoding.EncodeToString(secretBytes)
keyring.Set(service, username, secret)
}
oauth.SetEncryptionKey(secretBytes)
return nil
}
var gsuiteOauthConfig = []byte(`{"installed": {
"client_id":"%%GOOGLE_CLIENT_ID%%",
"project_id":"i3-barista",
"auth_uri":"https://accounts.google.com/o/oauth2/auth",
"token_uri":"https://www.googleapis.com/oauth2/v3/token",
"auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
"client_secret":"%%GOOGLE_CLIENT_SECRET%%",
"redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]
}}`)
func main() {
material.Load(home("Github/material-design-icons"))
mdi.Load(home("Github/MaterialDesign-Webfont"))
typicons.Load(home("Github/typicons.font"))
fontawesome.Load(home("Github/Font-Awesome"))
colors.LoadBarConfig()
bg := colors.Scheme("background")
fg := colors.Scheme("statusline")
if fg != nil && bg != nil {
iconColor := fg.Colorful().BlendHcl(bg.Colorful(), 0.5).Clamped()
colors.Set("dim-icon", iconColor)
_, _, v := fg.Colorful().Hsv()
if v < 0.3 {
v = 0.3
}
colors.Set("bad", colorful.Hcl(40, 1.0, v).Clamped())
colors.Set("degraded", colorful.Hcl(90, 1.0, v).Clamped())
colors.Set("good", colorful.Hcl(120, 1.0, v).Clamped())
}
if err := setupOauthEncryption(); err != nil {
panic(fmt.Sprintf("Could not setup oauth token encryption: %v", err))
}
installNerdFontProvider("UbuntuMono Nerd Font")
configureColors()
localtime := clock.Local().
Output(time.Second, func(now time.Time) bar.Output {
return outputs.Pango(
@ -228,194 +70,20 @@ func main() {
// Weather information comes from OpenWeatherMap.
// https://openweathermap.org/api.
wthr := weather.New(autoWeatherProvider{}).Output(func(w weather.Weather) bar.Output {
iconName := ""
switch w.Condition {
case weather.Thunderstorm,
weather.TropicalStorm,
weather.Hurricane:
iconName = "stormy"
case weather.Drizzle,
weather.Hail:
iconName = "shower"
case weather.Rain:
iconName = "downpour"
case weather.Snow,
weather.Sleet:
iconName = "snow"
case weather.Mist,
weather.Smoke,
weather.Whirls,
weather.Haze,
weather.Fog:
iconName = "windy-cloudy"
case weather.Clear:
if !w.Sunset.IsZero() && time.Now().After(w.Sunset) {
iconName = "night"
} else {
iconName = "sunny"
}
case weather.PartlyCloudy:
iconName = "partly-sunny"
case weather.Cloudy, weather.Overcast:
iconName = "cloudy"
case weather.Tornado,
weather.Windy:
iconName = "windy"
}
if iconName == "" {
iconName = "warning-outline"
} else {
iconName = "weather-" + iconName
}
return outputs.Pango(
pango.Icon("typecn-"+iconName), spacer,
pango.Textf("%.1f℃", w.Temperature.Celsius()),
pango.Textf(" (provided by %s)", w.Attribution).XSmall(),
)
})
buildBattOutput := func(i battery.Info, disp *pango.Node) *bar.Segment {
if i.Status == battery.Disconnected || i.Status == battery.Unknown {
return nil
}
iconName := "battery"
if i.Status == battery.Charging {
iconName += "-charging"
}
tenth := i.RemainingPct() / 10
switch {
case tenth == 0:
iconName += "-outline"
case tenth < 10:
iconName += fmt.Sprintf("-%d0", tenth)
}
out := outputs.Pango(pango.Icon("mdi-"+iconName), disp)
switch {
case i.RemainingPct() <= 5:
out.Urgent(true)
case i.RemainingPct() <= 15:
out.Color(colors.Scheme("bad"))
case i.RemainingPct() <= 25:
out.Color(colors.Scheme("degraded"))
}
return out
}
var showBattPct, showBattTime func(battery.Info) bar.Output
batt := battery.All()
showBattPct = func(i battery.Info) bar.Output {
out := buildBattOutput(i, pango.Textf("%d%%", i.RemainingPct()))
if out == nil {
return nil
}
return out.OnClick(click.Left(func() {
batt.Output(showBattTime)
}))
}
showBattTime = func(i battery.Info) bar.Output {
rem := i.RemainingTime()
out := buildBattOutput(i, pango.Textf(
"%d:%02d", int(rem.Hours()), int(rem.Minutes())%60))
if out == nil {
return nil
}
return out.OnClick(click.Left(func() {
batt.Output(showBattPct)
}))
}
batt.Output(showBattPct)
vol := volume.New(alsa.DefaultMixer()).Output(func(v volume.Volume) bar.Output {
if v.Mute {
return outputs.
Pango(pango.Icon("fa-volume-mute"), spacer, "MUT").
Color(colors.Scheme("degraded"))
}
iconName := "off"
pct := v.Pct()
if pct > 66 {
iconName = "up"
} else if pct > 33 {
iconName = "down"
}
wthr := weather.New(autoWeatherProvider{ApiKey: "%%OWM_API_KEY%%"}).Output(func(w weather.Weather) bar.Output {
return outputs.Pango(
pango.Icon("fa-volume-"+iconName),
spacer,
pango.Textf("%2d%%", pct),
pango.Text("Air").XSmall(), spacer,
pango.Textf("%.0f", math.Round(w.Temperature.Celsius())),
pango.Text("℃").XSmall(),
)
})
loadAvg := sysinfo.New().Output(func(s sysinfo.Info) bar.Output {
out := outputs.Textf("%0.2f %0.2f", s.Loads[0], s.Loads[2])
// Load averages are unusually high for a few minutes after boot.
if s.Uptime < 10*time.Minute {
// so don't add colours until 10 minutes after system start.
return out
}
switch {
case s.Loads[0] > 128, s.Loads[2] > 64:
out.Urgent(true)
case s.Loads[0] > 64, s.Loads[2] > 32:
out.Color(colors.Scheme("bad"))
case s.Loads[0] > 32, s.Loads[2] > 16:
out.Color(colors.Scheme("degraded"))
}
out.OnClick(startTaskManager)
return out
})
batt := batterySegment()
vol := volumeSegment()
loadAvg := loadAverageSegment()
freeMem := memorySegment()
freeMem := meminfo.New().Output(func(m meminfo.Info) bar.Output {
out := outputs.Pango(pango.Icon("material-memory"), format.IBytesize(m.Available()))
freeGigs := m.Available().Gigabytes()
switch {
case freeGigs < 0.5:
out.Urgent(true)
case freeGigs < 1:
out.Color(colors.Scheme("bad"))
case freeGigs < 2:
out.Color(colors.Scheme("degraded"))
case freeGigs > 12:
out.Color(colors.Scheme("good"))
}
out.OnClick(startTaskManager)
return out
})
temp := cputemp.New().
RefreshInterval(2 * time.Second).
Output(func(temp unit.Temperature) bar.Output {
out := outputs.Pango(
pango.Icon("mdi-fan"), spacer,
pango.Textf("%2d℃", int(temp.Celsius())),
)
switch {
case temp.Celsius() > 90:
out.Urgent(true)
case temp.Celsius() > 70:
out.Color(colors.Scheme("bad"))
case temp.Celsius() > 60:
out.Color(colors.Scheme("degraded"))
}
return out
})
sub := netlink.Any()
iface := sub.Get().Name
sub.Unsubscribe()
net := netspeed.New(iface).
RefreshInterval(2 * time.Second).
Output(func(s netspeed.Speeds) bar.Output {
return outputs.Pango(
pango.Icon("fa-upload"), spacer, pango.Textf("%7s", format.Byterate(s.Tx)),
pango.Text(" ").Small(),
pango.Icon("fa-download"), spacer, pango.Textf("%7s", format.Byterate(s.Rx)),
)
})
rhythmbox := media.New("rhythmbox").Output(mediaFormatFunc)
grp, _ := collapsing.Group(net, temp, freeMem, loadAvg)
temp := cputempSegment()
ghNotify := github.New("%%GITHUB_CLIENT_ID%%", "%%GITHUB_CLIENT_SECRET%%").
Output(func(n github.Notifications) bar.Output {
@ -439,12 +107,13 @@ func main() {
})
panic(barista.Run(
rhythmbox,
grp,
temp,
freeMem,
loadAvg,
ghNotify,
vol,
batt,
wthr,
localtime,
))
}
}

@ -31,7 +31,9 @@ KEYS=(
'OWM_API_KEY'
)
TARGET_FILE="$(dirname "$(realpath -e "${BASH_SOURCE[0]}")")/barista-bar.go"
DESTDIR="$(dirname "$(realpath -e "${BASH_SOURCE[0]}")")"
cd "$DESTDIR"
TARGET_FILE="barista-bar.go"
# Save the current sample-bar, so we can revert it after building, to
# prevent accidentally checking in the keys. We can't use git checkout
@ -55,5 +57,4 @@ done
# Build the sample bar with all the keys set. Pass all arguments to the
# `go build` command, allowing e.g. `./build.sh -o ~/bin/mybar`, or even
# `./build.sh -race -tags debuglog`.
go build -o "$(dirname ${TARGET_FILE})/barista-bar" "${TARGET_FILE}" "$@"
go build -o "barista-bar" . "$@"

@ -0,0 +1,10 @@
package main
import (
"barista.run/testing/httpcache"
"net/http"
)
func init() {
http.DefaultTransport = httpcache.Wrap(http.DefaultTransport)
}

@ -0,0 +1,23 @@
package main
import (
"barista.run/colors"
"github.com/lucasb-eyer/go-colorful"
)
func configureColors() {
colors.LoadBarConfig()
bg := colors.Scheme("background")
fg := colors.Scheme("statusline")
if fg != nil && bg != nil {
iconColor := fg.Colorful().BlendHcl(bg.Colorful(), 0.5).Clamped()
colors.Set("dim-icon", iconColor)
_, _, v := fg.Colorful().Hsv()
if v < 0.3 {
v = 0.3
}
colors.Set("bad", colorful.Hcl(40, 1.0, v).Clamped())
colors.Set("degraded", colorful.Hcl(90, 1.0, v).Clamped())
colors.Set("good", colorful.Hcl(120, 1.0, v).Clamped())
}
}

@ -0,0 +1,31 @@
package main
import (
"barista.run/pango"
"fmt"
"time"
)
var spacer = pango.Text(" ").XXSmall()
func truncate(in string, l int) string {
if len([]rune(in)) <= l {
return in
}
return string([]rune(in)[:l-1]) + "⋯"
}
func hms(d time.Duration) (h int, m int, s int) {
h = int(d.Hours())
m = int(d.Minutes()) % 60
s = int(d.Seconds()) % 60
return
}
func formatMediaTime(d time.Duration) string {
h, m, s := hms(d)
if h > 0 {
return fmt.Sprintf("%d:%02d:%02d", h, m, s)
}
return fmt.Sprintf("%d:%02d", m, s)
}

@ -1,9 +1,10 @@
module i3barista.reya.zone
module barista
go 1.16
require (
barista.run v0.0.0-20210701172726-58d911037491
barista.run v0.0.0-20210724204839-32474b6f85a7
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/martinlindhe/unit v0.0.0-20210313160520-19b60e03648d
github.com/zalando/go-keyring v0.1.1

@ -1,5 +1,5 @@
barista.run v0.0.0-20210701172726-58d911037491 h1:WUQWmDdOjDBDx/xOR0vyCTdD/Wnxc4Ha3XmUAScOm2M=
barista.run v0.0.0-20210701172726-58d911037491/go.mod h1:sZmKW7UshHL/5R+Tyg2/0WOpOS77ZWPh13L6u2EOv9U=
barista.run v0.0.0-20210724204839-32474b6f85a7 h1:QP6z7qLYSQJZuHlkc21I0uoWGqrIpSe7K26tnyuLAfs=
barista.run v0.0.0-20210724204839-32474b6f85a7/go.mod h1:hMYHc1In5djZ/4H/26euwq/6XCFiwx+esya8/JqAex0=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@ -22,6 +22,7 @@ cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@ -42,6 +43,7 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
@ -50,6 +52,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/danieljoos/wincred v1.1.0 h1:3RNcEpBg4IhIChZdFRSdlQt1QjCp1sMAPIrOnm7Yf8g=
github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
@ -64,9 +67,11 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -85,6 +90,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -135,10 +141,12 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@ -166,6 +174,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
@ -198,6 +207,7 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -347,8 +357,9 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -414,6 +425,7 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -443,6 +455,7 @@ google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -474,6 +487,7 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
@ -495,6 +509,8 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@ -508,6 +524,7 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
@ -516,6 +533,7 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@ -528,13 +546,15 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=

@ -0,0 +1,55 @@
package main
import (
"barista.run/bar"
"barista.run/colors"
"barista.run/modules/media"
"barista.run/modules/volume"
"barista.run/modules/volume/alsa"
"barista.run/outputs"
"barista.run/pango"
)
func mediaFormatFunc(m media.Info) bar.Output {
if m.PlaybackStatus == media.Stopped || m.PlaybackStatus == media.Disconnected {
return nil
}
artist := truncate(m.Artist, 20)
title := truncate(m.Title, 40-len(artist))
if len(title) < 20 {
artist = truncate(m.Artist, 40-len(title))
}
iconAndPosition := pango.Icon("nf-fa-music").Color(colors.Hex("#f70"))
if m.PlaybackStatus == media.Playing {
iconAndPosition.Append(
spacer, pango.Textf("%s/%s",
formatMediaTime(m.Position()),
formatMediaTime(m.Length)),
)
}
return outputs.Pango(iconAndPosition, spacer, title, " - ", artist)
}
func volumeSegment() bar.Module {
return volume.New(alsa.DefaultMixer()).Output(func(v volume.Volume) bar.Output {
pct := v.Pct()
var indicatorText *pango.Node
var pctText *pango.Node
if pct > 99 {
pctText = pango.Text("MAX")
} else {
pctText = pango.Textf("%2d%%", pct)
}
if v.Mute {
indicatorText = pango.Text("MUT").Color(colors.Scheme("degraded"))
pctText = pctText.Color(colors.Scheme("degraded")).XSmall()
} else {
indicatorText = pango.Text("Vol").XSmall()
}
return outputs.Pango(
indicatorText,
spacer,
pctText,
)
})
}

@ -0,0 +1,157 @@
// This file is run by go generate, and generates nerdfont-provider-data.go.
// +build generation
package main
import (
"bufio"
"bytes"
"io"
"log"
"net/http"
"os"
"strconv"
"strings"
"text/template"
"time"
"unicode"
)
var fileTemplate = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// {{ .Timestamp }}
// using data from
// {{ .URL }}
package main
var NerdFontGlyphs = []Glyph{
{{- range $key, $rune := .Glyphs }}
{
Key: {{ printf "%q" $key }},
Rune: 0x{{ printf "%x" $rune }},
},
{{- end }}
}
`))
const TokenStartString = ".nf-"
const ClassStartString = ":before {\n content: \"\\"
const ClassEndString = "\";\n}\n"
// SplitCSS scans the reader looking for data of the form
// .nf-(key):before {
// content: "\(hex)";
// }
// and returns (key):(hex) when it finds this data.
func SplitCSS(data []byte, atEOF bool) (advance int, token []byte, err error) {
if !bytes.HasPrefix(data, []byte(TokenStartString)) {
// This is not our goal. Skip this line.
nextNewline := bytes.IndexRune(data, '\n');
if nextNewline == -1 {
// Can't skip this line yet because we don't know where it ends!
return 0, nil, nil
} else {
offset := nextNewline + 1
// Skip this line in our own head and see if we get a result.
advance, token, err = SplitCSS(data[offset:], atEOF)
if advance > 0 || token != nil || err != nil {
// If we do, return it adjusted by the offset.
return advance + offset, token, err
} else {
// Otherwise, just tell the scanner to skip the line we found and keep going.
return offset, nil, nil
}
}
}
keyEnd := bytes.Index(data, []byte(ClassStartString))
if keyEnd == -1 {
// We don't know where the key ends!
return 0, nil, nil
}
key := data[len(TokenStartString):keyEnd]
contentEnd := bytes.Index(data, []byte(ClassEndString))
if contentEnd == -1 {
// We don't know where the content ends!
return 0, nil, nil
}
content := data[keyEnd + len(ClassStartString):contentEnd]
token = make([]byte, len(key) + len(content) + 1)
copy(token[:len(key)], key)
token[len(key)] = ':'
copy(token[len(key) + 1:], content)
return contentEnd + len(ClassEndString), token, nil
}
func SplitOnce(s string, sep string) (string, string) {
result := strings.SplitN(s, sep, 2)
if len(result) == 2 {
return result[0], result[1]
} else if len(result) == 1 {
return result[0], ""
} else {
panic("How did we get a different number of strings than 1 or 2 out of SplitN(2)?")
}
}
func main() {
const url = "https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/css/nerd-fonts-generated.css"
rsp, err := http.Get(url)
if err != nil {
log.Fatalf("failed to get css file: %s", err)
}
defer func(b io.ReadCloser) {
err := b.Close()
if err != nil {
log.Printf("failed closing the css file: %s", err)
}
}(rsp.Body)
sc := bufio.NewScanner(rsp.Body)
sc.Split(SplitCSS)
glyphs := make(map[string]rune)
for sc.Scan() {
key, hex := SplitOnce(sc.Text(), ":")
val, err := strconv.ParseInt(hex, 16, 64)
if err != nil {
log.Printf("val %s for %s cannot be parsed as hex: %s", hex, key, err)
continue
}
if val > int64(unicode.MaxRune) {
log.Printf("val 0x%x for %s exceeds MaxRune", val, key)
continue
}
if old, ok := glyphs[key]; ok {
log.Printf("already stored %s as 0x%x but got 0x%x, replacing", key, old, val)
}
glyphs[key] = rune(val)
}
if sc.Err() != nil {
log.Fatalf("failed to scan: %s", sc.Err())
}
f, err := os.Create("nerdfont-provider-data.go")
if err != nil {
log.Fatalf("failed to open the data file: %s", err)
}
defer func(f *os.File) {
err := f.Close()
if err != nil {
log.Printf("failed closing the data file: %s", err)
}
}(f)
err = fileTemplate.Execute(f, struct {
Timestamp time.Time
URL string
Glyphs map[string]rune
}{
Timestamp: time.Now(),
URL: url,
Glyphs: glyphs,
})
if err != nil {
log.Fatalf("failed writing template to the data file: %s", err)
}
}

@ -0,0 +1,21 @@
package main
//go:generate go run nerdfont-process-css.go
import (
"barista.run/pango/icons"
)
type Glyph struct {
Key string
Rune rune
}
func installNerdFontProvider(face string) *icons.Provider {
nf := icons.NewProvider("nf")
nf.Font(face)
for _, glyph := range NerdFontGlyphs {
nf.Symbol(glyph.Key, string(glyph.Rune))
}
return nf
}

@ -0,0 +1,46 @@
package main
import (
"barista.run/oauth"
"crypto/rand"
"encoding/base64"
"fmt"
"github.com/zalando/go-keyring"
"os"
"os/user"
)
func setupOauthEncryption() error {
const service = "reya.zone-barista-bar"
var username string
if u, err := user.Current(); err == nil {
username = u.Username
} else {
username = fmt.Sprintf("user-%d", os.Getuid())
}
var secretBytes []byte
// IMPORTANT: The oauth tokens used by some modules are very sensitive, so
// we encrypt them with a random key and store that random key using
// libsecret (gnome-keyring or equivalent). If no secret provider is
// available, there is no way to store tokens (since the version of
// sample-bar used for setup-oauth will have a different key from the one
// running in i3bar). See also https://github.com/zalando/go-keyring#linux.
secret, err := keyring.Get(service, username)
if err == nil {
secretBytes, err = base64.RawURLEncoding.DecodeString(secret)
}
if err != nil {
secretBytes = make([]byte, 64)
_, err := rand.Read(secretBytes)
if err != nil {
return err
}
secret = base64.RawURLEncoding.EncodeToString(secretBytes)
err = keyring.Set(service, username, secret)
if err != nil {
return err
}
}
oauth.SetEncryptionKey(secretBytes)
return nil
}

@ -0,0 +1,91 @@
package main
import (
"barista.run/bar"
"barista.run/base/click"
"barista.run/colors"
"barista.run/modules/battery"
"barista.run/outputs"
"barista.run/pango"
)
func buildBattOutput(i battery.Info, render func (i battery.Info) *pango.Node) *bar.Segment {
var indicator, display *pango.Node
display = render(i)
switch i.Status {
case battery.Disconnected:
indicator = pango.Text("---")
case battery.Full:
indicator = pango.Text("AC ")
case battery.Charging:
indicator = pango.Text("AC+")
case battery.Discharging:
indicator = pango.Text("Bat")
case battery.NotCharging:
indicator = pango.Text("AC?")
default:
indicator = pango.Text("???")
}
out := outputs.Pango(indicator.XSmall(), spacer, display)
switch {
case i.RemainingPct() <= 5:
out.Urgent(true)
case i.RemainingPct() <= 15:
out.Color(colors.Scheme("bad"))
case i.RemainingPct() <= 25:
out.Color(colors.Scheme("degraded"))
}
return out
}
func batterySegment() bar.Module {
var showBattPct, showBattTime func(battery.Info) bar.Output
batt := battery.All()
showBattPct = func(i battery.Info) bar.Output {
out := buildBattOutput(i, func(i battery.Info) *pango.Node {
switch i.Status {
case battery.Full, battery.Charging, battery.Discharging, battery.NotCharging:
if i.RemainingPct() < 0 {
return pango.Text(" 0%")
} else if i.RemainingPct() > 99 {
return pango.Text("MAX")
} else {
return pango.Textf("%d%%", i.RemainingPct())
}
case battery.Disconnected:
return pango.Text("---")
default:
return pango.Text("???")
}
})
if out == nil {
return nil
}
return out.OnClick(click.Left(func() {
batt.Output(showBattTime)
}))
}
showBattTime = func(i battery.Info) bar.Output {
rem := i.RemainingTime()
out := buildBattOutput(i, func(i battery.Info) *pango.Node {
switch i.Status {
case battery.Full, battery.Charging, battery.Discharging, battery.NotCharging:
return pango.Textf("%d:%02d", int(rem.Hours()), int(rem.Minutes())%60)
case battery.Disconnected:
return pango.Text("-:--")
default:
return pango.Text("?:??")
}
})
if out == nil {
return nil
}
return out.OnClick(click.Left(func() {
batt.Output(showBattPct)
}))
}
batt.Output(showBattPct)
return batt
}

@ -0,0 +1,81 @@
package main
import (
"barista.run/bar"
"barista.run/colors"
"barista.run/modules/cputemp"
"barista.run/modules/meminfo"
"barista.run/modules/sysinfo"
"barista.run/outputs"
"barista.run/pango"
"github.com/dustin/go-humanize"
"github.com/martinlindhe/unit"
"strings"
"time"
)
func memorySegment() bar.Module {
return meminfo.New().Output(func(m meminfo.Info) bar.Output {
h := strings.SplitN(humanize.IBytes(uint64(m.Available().Bytes())), " ", 2)
freeText := pango.Text(h[0])
if len(h) == 2 {
freeText = freeText.Append(spacer, pango.Text(h[1]).Small())
}
out := outputs.Pango(pango.Text("Mem").XSmall(), spacer, freeText)
freeGigs := m.Available().Gigabytes()
switch {
case freeGigs < 0.5:
out.Urgent(true)
case freeGigs < 1:
out.Color(colors.Scheme("bad"))
case freeGigs < 2:
out.Color(colors.Scheme("degraded"))
case freeGigs > 12:
out.Color(colors.Scheme("good"))
}
out.OnClick(startTaskManager)
return out
})
}
func loadAverageSegment() bar.Module {
return sysinfo.New().Output(func(s sysinfo.Info) bar.Output {
out := outputs.Pango(pango.Text("Load 1m").XSmall(), spacer, pango.Textf("%0.2f", s.Loads[0]), spacer, pango.Text("15m").XSmall(), spacer, pango.Textf("%0.2f", s.Loads[2]))
// Load averages are unusually high for a few minutes after boot.
if s.Uptime < 10*time.Minute {
// so don't add colours until 10 minutes after system start.
return out
}
switch {
case s.Loads[0] > 128, s.Loads[2] > 64:
out.Urgent(true)
case s.Loads[0] > 64, s.Loads[2] > 32:
out.Color(colors.Scheme("bad"))
case s.Loads[0] > 32, s.Loads[2] > 16:
out.Color(colors.Scheme("degraded"))
}
out.OnClick(startTaskManager)
return out
})
}
func cputempSegment() bar.Module {
return cputemp.New().
RefreshInterval(2 * time.Second).
Output(func(temp unit.Temperature) bar.Output {
out := outputs.Pango(
pango.Text("CPU").XSmall(), spacer,
pango.Textf("%2d", int(temp.Celsius())),
pango.Text("℃").XSmall(),
)
switch {
case temp.Celsius() > 90:
out.Urgent(true)
case temp.Celsius() > 70:
out.Color(colors.Scheme("bad"))
case temp.Celsius() > 60:
out.Color(colors.Scheme("degraded"))
}
return out
})
}

@ -0,0 +1,34 @@
package main
import (
"encoding/json"
"net/http"
"os/user"
"path/filepath"
)
func home(path string) string {
usr, err := user.Current()
if err != nil {
panic(err)
}
return filepath.Join(usr.HomeDir, path)
}
type freegeoipResponse struct {
Lat float64 `json:"latitude"`
Lng float64 `json:"longitude"`
}
func whereami() (lat float64, lng float64, err error) {
resp, err := http.Get("https://freegeoip.app/json/")
if err != nil {
return 0, 0, err
}
var res freegeoipResponse
err = json.NewDecoder(resp.Body).Decode(&res)
if err != nil {
return 0, 0, err
}
return res.Lat, res.Lng, nil
}

@ -2,6 +2,7 @@ AddKeysToAgent yes
VisualHostKey yes
Host gubal gubal.reya.zone *.gubal.reya.zone *.gubal
SendEnv TZ LANG LANGUAGE LC_*
ForwardAgent yes
StrictHostKeyChecking yes
Hostname gubal.reya.zone

@ -3,6 +3,8 @@
# Disable the gosh darn XON/XOFF function that serves no purpose but to confuse me when I accidentally press Ctrl+S
stty -ixon
# Set TZ if it's not set
LOCALZONE=$(readlink -e /etc/localtime); export TZ=${TZ:-${LOCALZONE#/usr/share/zoneinfo/}}
# Install EDITOR
export EDITOR='nvim'
# Install PAGER

@ -6,7 +6,7 @@ function tmux_running() {
}
function tmux_init() {
tmux -2 new-session -d -s "Nexus" -n "Misc." 'LC_ALL=C.UTF-8 fortune | cowsay -f eyes -W "$COLUMNS"; exec "$SHELL" -i'
tmux -2 new-session -d -s "Nexus" 'LC_ALL=C.UTF-8 fortune | cowsay -f eyes -W "$COLUMNS"; exec "$SHELL" -i'
}
function go_tmux() {

@ -1 +1 @@
Subproject commit 079e7bb5e0a79171f3356d55d3f6302a82645a39
Subproject commit 5377cc37c0f71fe22484303a4c6f387aa339f3f5
Loading…
Cancel
Save