~rycwo/workspace

d88ad730fa09ddbf4eac2d7a5ea657972d0fb2d1 — Ryan Chan 7 months ago 167a47b heron
Migrate to Wayland and simplify various dotfiles
29 files changed, 492 insertions(+), 633 deletions(-)

M bash/.bash_profile
M bash/.bashrc
R bin/{backup-host => backup_host}
A bin/bar_status
D bin/dmenu_pass_otp
A bin/fmenu
A bin/fmenu_pass
A bin/fmenu_path
A bin/grim_clip
D bin/screencap
D bin/start-barrier
D bin/start-lemonbar
D bin/start-vncserver
R bin/{tag-release => tag_release}
D bspwm/bspwmrc
A fontconfig/fonts.conf
M gnupg/gpg.conf
A mako/config
D patch/st-config.patch
A sway/config
D sxhkd/sxhkdrc
D systemd/backup-host.service
D systemd/backup-host.timer
D tmux/.tmux.conf
D tmux/default.yml
M vim/.vimrc
D xinit/.xinitrc
D xinit/.xserverrc
A yay/config.json
M bash/.bash_profile => bash/.bash_profile +3 -12
@@ 1,15 1,6 @@
[[ -f ~/.bashrc ]] && . ~/.bashrc

# Path for Go installation
export GOPATH="$HOME""/go"
PATH="$PATH"":""$HOME""/dev/repos/workspace/bin"

# Package install prefix for node modules
export npm_config_prefix="$HOME""/.node_modules"

# Extend PATH
PATH="$PATH"":""$GOPATH""/bin"                         # Go executables
PATH="$PATH"":""$HOME""/.local/bin"                    # Python scripts
PATH="$PATH"":""$HOME""/.node_modules/bin"             # Node scripts
PATH="$PATH"":""$HOME""/dev/workspace/bin"             # Personal executables

export LEDGER_FILE="$HOME""/Documents/ledger/business.journal"
# Enable Wayland mode for Firefox
export MOZ_ENABLE_WAYLAND=1

M bash/.bashrc => bash/.bashrc +8 -11
@@ 1,4 1,4 @@
# If not running interactively, don't do anything.
# If not running interactively, don't do anything
[[ "$-" != *i* ]] && return

export EDITOR=vim


@@ 7,19 7,16 @@ alias ls="ls --color=auto"
alias ll="ls -l -all --classify"
alias grep="grep --color=auto"

# dmenu options
dmenu_options="\
    -fn Roboto\ Mono:style=Medium:antialias=true:autohint=true:pixelsize=13\
    -nb \#dadada -nf \#4e4e4e -sb \#4e4e4e -sf \#dadada"
alias dmenu_run="dmenu_run ""$dmenu_options"
alias passmenu="passmenu ""$dmenu_options"
alias dmenu_pass_otp="dmenu_pass_otp ""$dmenu_options"

# TODO: Add colors to the prompt.
PS1="[\u@\h:\w]\$ "

# Set SSH_AUTH_SOCK so that SSH will use gpg-agent instead of ssh-agent.
# Set SSH_AUTH_SOCK so that SSH will use gpg-agent instead of ssh-agent
unset SSH_AGENT_PID
if [[ -z "$SSH_AUTH_SOCK" ]]; then
    export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi

# Point GPG to the current interactive shell
export GPG_TTY="$(tty)"

# Set fzf to use light color theme
export FZF_DEFAULT_OPTS="--color=light"

R bin/backup-host => bin/backup_host +0 -0
A bin/bar_status => bin/bar_status +20 -0
@@ 0,0 1,20 @@
#!/usr/bin/env sh
em() {
	printf "<span color=\"#3A3A3A\">%s</span>" "$1"
}

day="$(date +'%a %b %-d')"

utc="$(date -u +'%H:%M')"

ldn="$(TZ="Europe/London" date +'%H:%M')"
ldn_tz="$(TZ="Europe/London" date +'%Z')"

tor="$(TZ="America/Toronto" date +'%H:%M')"
tor_tz="$(TZ="America/Toronto" date +'%Z')"

printf "%s   %s UTC   %s %s   %s %s \n" \
	"$(em "$day")" \
	"$(em "$utc")" \
	"$(em "$ldn")" "$ldn_tz" \
	"$(em "$tor")" "$tor_tz"

D bin/dmenu_pass_otp => bin/dmenu_pass_otp +0 -5
@@ 1,5 0,0 @@
#!/bin/sh

password=$(find ~/.password-store/ -type f -name '*.gpg' |
	sed 's/.*\.password-store\/\(.*\)\.gpg$/\1/' | dmenu -i "$@")
[ -n "$password" ] && pass otp show -c "$password"

A bin/fmenu => bin/fmenu +16 -0
@@ 0,0 1,16 @@
#!/usr/bin/env bash
shopt -s nullglob globstar

tempdir="$(mktemp -d)"
# exit 0 is important to signal all processes in the current process group
trap "rm -rf ""$tempdir""; exit 0" EXIT

input="$tempdir""/input"
output="$tempdir""/output"

mkfifo "$input"
mkfifo "$output"

st -n fmenu -e bash -c "fzf < ""$input"" > ""$output" > /dev/null 2>&1 &
printf "%s\n" "$(</dev/stdin)" > "$input"
printf "%s\n" "$(<"$output")"

A bin/fmenu_pass => bin/fmenu_pass +43 -0
@@ 0,0 1,43 @@
#!/usr/bin/env bash
# Modified from original script which can be found here:
# https://git.zx2c4.com/password-store/tree/contrib/dmenu/passmenu

shopt -s nullglob globstar

typeit=0
if [[ $1 == "--type" ]]; then
	typeit=1
	shift
fi

cmd=("show")
if [[ $1 == "--otp" ]]; then
	cmd=("otp" "show")
	shift
fi

if [[ -n $WAYLAND_DISPLAY ]]; then
	dmenu=fmenu
	xdotool="ydotool type --file -"
elif [[ -n $DISPLAY ]]; then
	dmenu=dmenu
	xdotool="xdotool type --clearmodifiers --file -"
else
	echo "Error: No Wayland or X11 display detected" >&2
	exit 1
fi

prefix=${PASSWORD_STORE_DIR-~/.password-store}
password_files=( "$prefix"/**/*.gpg )
password_files=( "${password_files[@]#"$prefix"/}" )
password_files=( "${password_files[@]%.gpg}" )

password=$(printf '%s\n' "${password_files[@]}" | "$dmenu" "$@")

[[ -n $password ]] || exit

if [[ $typeit -eq 0 ]]; then
	pass "${cmd[@]}" -c "$password" 2>/dev/null
else
	pass "${cmd[@]}" | { IFS= read -r pass; printf %s "$pass"; } | $xdotool
fi

A bin/fmenu_path => bin/fmenu_path +15 -0
@@ 0,0 1,15 @@
#!/usr/bin/env bash
find_executables() {
	IFS=":" read -d "" -ra paths <<< "$PATH"
	for path in "${paths[@]}"; do
		if [[ -z "$path" ]]; then
			continue
		fi
		for f in "$path"/*; do
			if [[ -f "$f" ]] && [[ -x "$f" ]]; then
				printf "%s\n" "$f"
			fi
		done
	done
}
find_executables | xargs -L 1 -P 0 basename | sort -u

A bin/grim_clip => bin/grim_clip +4 -0
@@ 0,0 1,4 @@
#!/usr/bin/env sh
# Alternative script:
# https://github.com/swaywm/sway/blob/master/contrib/grimshot
grim -g "$(slurp)" - | wl-copy

D bin/screencap => bin/screencap +0 -77
@@ 1,77 0,0 @@
#!/usr/bin/env python
from collections import OrderedDict
from contextlib import contextmanager
from datetime import datetime
from pathlib import Path
from tempfile import NamedTemporaryFile
import argparse
import os
import subprocess
import sys


@contextmanager
def mktemp(**kwargs):
    tmpfile = NamedTemporaryFile(delete=False, **kwargs)
    # Immediately close the returned file object so we can write to it elsewhere
    tmpfile.close()
    try:
        yield tmpfile.name
    finally:
        # It is the caller's responsibility to close the file after using it
        os.unlink(tmpfile.name)


def output_filename():
    # Generate output filename
    timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
    return Path(f"screencap_{timestamp}.mkv")


def generate_args(flags):
    for k, v in flags.items():
        yield k
        yield v


def main():
    parser = argparse.ArgumentParser("Record screen contents")
    parser.add_argument("-o", "--output", type=Path, default=output_filename())
    parser.add_argument("--resolution", type=str, default="1920x1080")
    parser.add_argument("--framerate", type=float, default=60.0)
    parser.add_argument("--monitor", type=str, default=":0.0")
    parser.add_argument("--quality", type=int, default=18)
    parser.add_argument("--pixel-format", type=str, default="yuv420p")
    args = parser.parse_args()

    with mktemp(suffix=".mkv") as tmpfilename:
        flags = OrderedDict([])
        flags["-video_size"] = args.resolution
        flags["-framerate"] = str(args.framerate)
        flags["-f"] = "x11grab"
        flags["-i"] = args.monitor
        flags["-c:v"] = "libx264rgb"
        flags["-crf"] = "0"  # Lossless quality
        flags["-preset"] = "ultrafast"  # Low CPU usage

        process_args = list(generate_args(flags))
        process_args.append(tmpfilename)
        # FIXME: This presents a security threat as the file can be created
        # between removal and ffmpeg invocation.
        os.unlink(tmpfilename)
        subprocess.run(["ffmpeg"] + process_args)

        flags = OrderedDict([])
        flags["-i"] = tmpfilename
        flags["-c:v"] = "libx264"
        flags["-crf"] = str(args.quality)
        flags["-pix_fmt"] = args.pixel_format
        flags["-preset"] = "veryslow"

        process_args = list(generate_args(flags))
        process_args.append(str(args.output))
        subprocess.run(["ffmpeg"] + process_args)


if __name__ == "__main__":
    sys.exit(main())

D bin/start-barrier => bin/start-barrier +0 -5
@@ 1,5 0,0 @@
#!/usr/bin/env sh
# Stop the process with:
# pkill -x barrierc
barrierc --no-tray "$@" &
setxkbmap -device "$(xinput list --id-only "Virtual core XTEST keyboard")" "gb"

D bin/start-lemonbar => bin/start-lemonbar +0 -15
@@ 1,15 0,0 @@
#!/usr/bin/env sh
pkill -f lemons

readonly lemons_log="/tmp/lemons_""$XDG_SESSION_ID"".txt"

LEMONBAR_PIPE="/tmp/lemonbar_pipe_""$XDG_SESSION_ID"
export LEMONBAR_PIPE

# setsid necessary so pkill-ing lemonbar doesn't bring down the parent
# process with it.
setsid /usr/bin/lemons \
	-g "x26" \
	-f "Roboto Mono:style=Medium:antialias=true:autohint=true:pixelsize=13" \
	-f "Roboto Mono:style=Bold:antialias=true:autohint=true:pixelsize=13" \
	> "$lemons_log" 2>&1 &

D bin/start-vncserver => bin/start-vncserver +0 -7
@@ 1,7 0,0 @@
#!/usr/bin/env sh
# autorandr postswitch hook is responsible for restarting lemonbar
trap "autorandr --load default" EXIT INT TERM QUIT
autorandr --load vnc
systemd-inhibit \
	--what="sleep:handle-lid-switch" --why="Keep VNC alive" \
	x0vncserver -rfbauth "$HOME""/.vnc/passwd"

R bin/tag-release => bin/tag_release +0 -0
D bspwm/bspwmrc => bspwm/bspwmrc +0 -29
@@ 1,29 0,0 @@
#!/usr/bin/env sh
readonly gray="#c8c8c8"
readonly white="#dadada"

sxhkd &

start-lemonbar

# TODO(rycwo): xrandr --listmonitors might be more reliable
IFS='\n' read -ra monitors <<< "$(bspc query -M)"
for monitor in "${monitors[@]}"; do
	bspc monitor "$monitor" -d 1 2 3 4 5
done

bspc config normal_border_color "$white"
bspc config active_border_color "$gray"
bspc config focused_border_color "$gray"

bspc config split_ratio 0.5
bspc config border_width 1
bspc config window_gap 2

# Monocle layout settings
bspc config borderless_monocle true
bspc config gapless_monocle true
bspc config single_monocle true

# Temporary rules
bspc rule -a Borann state=floating

A fontconfig/fonts.conf => fontconfig/fonts.conf +12 -0
@@ 0,0 1,12 @@
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
<fontconfig>
	<match target="pattern">
		<test qual="any" name="family">
			<string>monospace</string>
		</test>
		<edit name="family" mode="assign" binding="same">
			<string>Roboto Mono</string>
		</edit>
	</match>
</fontconfig>

M gnupg/gpg.conf => gnupg/gpg.conf +10 -10
@@ 1,17 1,17 @@
# Default key for signing.
default-key 0xECF139A777CA3454

# Avoid pulling from user-designated (potentially insecure) keyservers.
keyserver-options no-honor-keyserver-url
# SHA512 as digest to sign keys
cert-digest-algo SHA512

# Increase the Key ID display size to 64-bit.
# Long hexidecimal key format
keyid-format 0xlong

# Display keys with their fingerprints
with-fingerprint

# Hide stuff on export.
# No comments in signature
no-comments

# No version in output
no-emit-version

# Use SHA512 as the message digest algorithm used when signing a key.
cipher-algo AES256
cert-digest-algo SHA512
# Default key ID to use
default-key 0xECF139A777CA3454

A mako/config => mako/config +11 -0
@@ 0,0 1,11 @@
font=SF Pro Display 11
border-size=0
background-color=#BCBCBC
text-color=#4E4E4E
progress-color=over #5F87AE
width=360
margin=8
padding=5,10
icons=0
default-timeout=12000
anchor=bottom-right

D patch/st-config.patch => patch/st-config.patch +0 -83
@@ 1,83 0,0 @@
diff --git a/config.h b/config.h
index 0e01717..a7e1f55 100644
--- a/config.h
+++ b/config.h
@@ -5,7 +5,7 @@
  *
  * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
  */
-static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
+static char *font = "Roboto Mono:style=Medium:pixelsize=13:antialias=true:autohint=true";
 static int borderpx = 2;
 
 /*
@@ -80,35 +80,35 @@ char *termname = "st-256color";
  *
  *	stty tabs
  */
-unsigned int tabspaces = 8;
+unsigned int tabspaces = 4;
 
 /* Terminal colors (16 first used in escape sequence) */
 static const char *colorname[] = {
 	/* 8 normal colors */
-	"black",
-	"red3",
-	"green3",
-	"yellow3",
-	"blue2",
-	"magenta3",
-	"cyan3",
-	"gray90",
+	"#4e4e4e",
+	"#af5f5f",
+	"#5f885f",
+	"#af8760",
+	"#5f87ae",
+	"#875f87",
+	"#5f8787",
+	"#e4e4e4",
 
 	/* 8 bright colors */
-	"gray50",
-	"red",
-	"green",
-	"yellow",
-	"#5c5cff",
-	"magenta",
-	"cyan",
-	"white",
+	"#3a3a3a",
+	"#870100",
+	"#005f00",
+	"#d8865f",
+	"#0087af",
+	"#87025f",
+	"#008787",
+	"#eeeeee",
 
 	[255] = 0,
 
 	/* more colors can be added after 255 to use with DefaultXX */
-	"#cccccc",
-	"#555555",
+	"#dadada",
+	"#4e4e4e",
 };
 
 
@@ -116,10 +116,10 @@ static const char *colorname[] = {
  * Default colors (colorname index)
  * foreground, background, cursor, reverse cursor
  */
-unsigned int defaultfg = 7;
-unsigned int defaultbg = 0;
-static unsigned int defaultcs = 256;
-static unsigned int defaultrcs = 257;
+unsigned int defaultfg = 257;
+unsigned int defaultbg = 256;
+static unsigned int defaultcs = 257;
+static unsigned int defaultrcs = 256;
 
 /*
  * Default shape of cursor

A sway/config => sway/config +266 -0
@@ 0,0 1,266 @@
# Default config for sway
#
# Copy this to ~/.config/sway/config and edit it to your liking.
#
# Read `man 5 sway` for a complete reference.

### Variables
#
# Logo key. Use Mod1 for Alt.
set $mod Mod4
# Home row direction keys, like vim
set $left h
set $down j
set $up k
set $right l
# Your preferred terminal emulator
set $term st
# Your preferred application launcher
# Note: pass the final command to swaymsg so that the resulting window can be opened
# on the original workspace that the command was run on.
# set $menu dmenu_path | dmenu | xargs swaymsg exec --
set $menu fmenu_path | fmenu | xargs swaymsg exec --
for_window [instance="^fmenu$"] floating enable, border none, resize set 360 200

### Style configuration
#
# Default font is pango:monospace 10 which can be configured via Fontconfig
default_border normal 0
default_floating_border normal 0
font pango:SF Pro Display 10
gaps inner 4
smart_gaps on
client.focused #3A3A3A #3A3A3A #DADADA
client.focused_inactive #DADADA #DADADA #4E4E4E
client.unfocused #BCBCBC #BCBCBC #4E4E4E
client.urgent #AF5F5F #AF5F5F #DADADA

### Output configuration
#
output * bg ~/wallpaper.jpg fill
#
# Example configuration:
#
#   output HDMI-A-1 resolution 1920x1080 position 1920,0
#
# You can get the names of your outputs by running: swaymsg -t get_outputs
output DP-1 adaptive_sync on

### Idle configuration
#
exec swayidle -w \
         timeout 300 'swaymsg "output * dpms off"' resume 'swaymsg "output * dpms on"' \
         before-sleep 'playerctl pause' \
         before-sleep 'swaylock -f -c 000000'

### Input configuration
#
# Example configuration:
#
#   input "2:14:SynPS/2_Synaptics_TouchPad" {
#       dwt enabled
#       tap enabled
#       natural_scroll enabled
#       middle_emulation enabled
#   }
#
# You can get the names of your inputs by running: swaymsg -t get_inputs
# Read `man 5 sway-input` for more information about this section.

### Key bindings
#
# Basics:
#
    # Start a terminal
    bindsym $mod+Return exec $term

    # Kill focused window
    bindsym $mod+Shift+q kill

    # Start your launcher
    bindsym $mod+d exec $menu

    # Drag floating windows by holding down $mod and left mouse button.
    # Resize them with right mouse button + $mod.
    # Despite the name, also works for non-floating windows.
    # Change normal to inverse to use left mouse button for resizing and right
    # mouse button for dragging.
    floating_modifier $mod normal

    # Reload the configuration file
    bindsym $mod+Shift+c reload

    # Exit sway (logs you out of your Wayland session)
    bindsym $mod+Shift+e exec swaymsg exit
#
# Utilities:
#
    # Take a screenshot
    bindsym $mod+g exec grim_clip

    # Take a screenshot and upload it
    bindsym $mod+Shift+g exec grim_clip \
            && wl-paste | curl -F'file=@-;type=image/png' https://0x0.st | wl-copy

    # Find and copy password to clipboard
    bindsym $mod+Shift+p exec fmenu_pass

    # Find and copy otp to clipboard
    bindsym $mod+Shift+o exec fmenu_pass --otp

    # Media player control
    bindsym XF86AudioPlay exec playerctl play-pause
    bindsym XF86AudioNext exec playerctl next
    bindsym XF86AudioPrev exec playerctl previous
#
# Moving around:
#
    # Move your focus around
    bindsym $mod+$left focus left
    bindsym $mod+$down focus down
    bindsym $mod+$up focus up
    bindsym $mod+$right focus right
    # Or use $mod+[up|down|left|right]
    bindsym $mod+Left focus left
    bindsym $mod+Down focus down
    bindsym $mod+Up focus up
    bindsym $mod+Right focus right

    # Move the focused window with the same, but add Shift
    bindsym $mod+Shift+$left move left
    bindsym $mod+Shift+$down move down
    bindsym $mod+Shift+$up move up
    bindsym $mod+Shift+$right move right
    # Ditto, with arrow keys
    bindsym $mod+Shift+Left move left
    bindsym $mod+Shift+Down move down
    bindsym $mod+Shift+Up move up
    bindsym $mod+Shift+Right move right
#
# Workspaces:
#
    # Switch to workspace
    bindsym $mod+1 workspace number 1
    bindsym $mod+2 workspace number 2
    bindsym $mod+3 workspace number 3
    bindsym $mod+4 workspace number 4
    bindsym $mod+5 workspace number 5
    bindsym $mod+6 workspace number 6
    bindsym $mod+7 workspace number 7
    bindsym $mod+8 workspace number 8
    bindsym $mod+9 workspace number 9
    bindsym $mod+0 workspace number 10
    # Move focused container to workspace
    bindsym $mod+Shift+1 move container to workspace number 1
    bindsym $mod+Shift+2 move container to workspace number 2
    bindsym $mod+Shift+3 move container to workspace number 3
    bindsym $mod+Shift+4 move container to workspace number 4
    bindsym $mod+Shift+5 move container to workspace number 5
    bindsym $mod+Shift+6 move container to workspace number 6
    bindsym $mod+Shift+7 move container to workspace number 7
    bindsym $mod+Shift+8 move container to workspace number 8
    bindsym $mod+Shift+9 move container to workspace number 9
    bindsym $mod+Shift+0 move container to workspace number 10
    # Note: workspaces can have any name you want, not just numbers.
    # We just use 1-10 as the default.
#
# Layout stuff:
#
    # You can "split" the current object of your focus with
    # $mod+b or $mod+v, for horizontal and vertical splits
    # respectively.
    bindsym $mod+b splith
    bindsym $mod+v splitv

    # Switch the current container between different layout styles
    bindsym $mod+s layout stacking
    bindsym $mod+w layout tabbed
    bindsym $mod+e layout toggle split

    # Make the current focus fullscreen
    bindsym $mod+f fullscreen

    # Toggle the current focus between tiling and floating mode
    bindsym $mod+Shift+space floating toggle

    # Swap focus between the tiling area and the floating area
    bindsym $mod+space focus mode_toggle

    # Move focus to the parent container
    bindsym $mod+a focus parent
#
# Scratchpad:
#
    # Sway has a "scratchpad", which is a bag of holding for windows.
    # You can send windows there and get them back later.

    # Move the currently focused window to the scratchpad
    bindsym $mod+Shift+minus move scratchpad

    # Show the next scratchpad window or hide the focused scratchpad window.
    # If there are multiple scratchpad windows, this command cycles through them.
    bindsym $mod+minus scratchpad show
#
# Resizing containers:
#
mode "resize" {
    # left will shrink the containers width
    # right will grow the containers width
    # up will shrink the containers height
    # down will grow the containers height
    bindsym $left resize shrink width 10px
    bindsym $down resize grow height 10px
    bindsym $up resize shrink height 10px
    bindsym $right resize grow width 10px

    # Ditto, with arrow keys
    bindsym Left resize shrink width 10px
    bindsym Down resize grow height 10px
    bindsym Up resize shrink height 10px
    bindsym Right resize grow width 10px

    # Return to default mode
    bindsym Return mode "default"
    bindsym Escape mode "default"
}
bindsym $mod+r mode "resize"

#
# Status Bar:
#
# Read `man 5 sway-bar` for more information about this section.
bar {
    # When the status_command prints a new line to stdout, swaybar updates.
    # The default just shows the current date and time.
    status_command while ~/dev/repos/workspace/bin/bar_status; do sleep 1; done

    tray_output none

    colors {
        statusline #4E4E4E
        background #DADADA
        focused_workspace #3A3A3A #3A3A3A #DADADA
        inactive_workspace #BCBCBC #BCBCBC #4E4E4E
        urgent_workspace #AF5F5F #AF5F5F #DADADA
    }
}

#
# Clipboard:
#
exec wl-paste -t text --watch clipman store --no-persist

#
# Notifications:
#
exec mako

#
# Screen sharing:
#
exec dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway
# Workaround for Firefox WebRTC sharing indicator:
# https://bugzilla.mozilla.org/show_bug.cgi?id=1628431
for_window [app_id="firefox" title="Firefox — Sharing Indicator"] kill

include /etc/sway/config.d/*

D sxhkd/sxhkdrc => sxhkd/sxhkdrc +0 -158
@@ 1,158 0,0 @@
# Adapted from the default example given in the bspwm repo.

###############################################################################
# wm independent hotkeys.
###############################################################################
super + Return
    st -e tmux -2

super + shift + Return
    st -e tmux -2 attach-session

super + r
    bash -ic dmenu_run

super + p
    bash -ic passmenu

super + o
    bash -ic dmenu_pass_otp

# Reload sxhkd configs.
super + Escape
    pkill -USR1 -x sxhkd

#------------------------------------------------------------------------------
# Audio.
#------------------------------------------------------------------------------
# Adapted from Arch wiki:
# https://wiki.archlinux.org/index.php/PulseAudio#Keyboard_volume_control.

# Increase volume.
XF86AudioRaiseVolume
    pactl set-sink-mute @DEFAULT_SINK@ false; pactl set-sink-volume @DEFAULT_SINK@ +5%

# Decrease volume.
XF86AudioLowerVolume
    pactl set-sink-mute @DEFAULT_SINK@ false; pactl set-sink-volume @DEFAULT_SINK@ -5%

# Mute.
XF86AudioMute
    pactl set-sink-mute @DEFAULT_SINK@ toggle

#------------------------------------------------------------------------------
# Backlight.
#------------------------------------------------------------------------------
# Using Light:
# https://haikarainen.github.io/light/.

# Increase brightness.
XF86MonBrightnessUp
    light -A 5

# Decrease brightness.
XF86MonBrightnessDown
    light -U 5

###############################################################################
# bspwm hotkeys.
###############################################################################
# Quit bspwm normally.
# It's important we also kill lemonbar since the bspwmrc doesn't
# clean it up as we'd hope it would.
super + alt + Escape
    bspc quit && pkill -f lemons

# Close and kill.
super + {_,shift + }w
    bspc node -{c,k}

# Alternate between the tiled and monocle layout.
super + m
    bspc desktop -l next

# Send the newest marked node to the newest preselected node.
super + y
    bspc node newest.marked.local -n newest.!automatic.local

# Swap the current node and the biggest node.
super + g
    bspc node -s biggest

#------------------------------------------------------------------------------
# State/flags.
#------------------------------------------------------------------------------
# Set the window state.
super + {t,shift + t,s,f}
    bspc node -t {tiled,pseudo_tiled,floating,fullscreen}

# Set the node flags.
super + ctrl + {m,x,y,z}
    bspc node -g {marked,locked,sticky,private}

#------------------------------------------------------------------------------
# Focus/swap.
#------------------------------------------------------------------------------
# Focus the node in the given direction.
super + {_,shift + }{h,j,k,l}
    bspc node -{f,s} {west,south,north,east}

# Focus the node for the given path jump.
super + shift + {p,b,comma,period}
    bspc node -f @{parent,brother,first,second}

# Focus the next/previous node in the current desktop.
super + {_,shift + }c
    bspc node -f {next,prev}.local

# Focus the next/previous desktop in the current monitor.
super + bracket{left,right}
    bspc desktop -f {prev,next}.local

# Focus the last node/desktop.
super + {grave,Tab}
    bspc {node,desktop} -f last

# Focus the older or newer node in the focus history.
super + shift + {o,i}
    bspc wm -h off; \
    bspc node {older,newer} -f; \
    bspc wm -h on

# Focus or send to the given desktop.
super + {_,ctrl + }{1-9,0}
    bspc {desktop -f,node -d} '^{1-9,10}'

#------------------------------------------------------------------------------
# Pre-select.
#------------------------------------------------------------------------------
# Pre-select the direction.
super + ctrl + {h,j,k,l}
    bspc node -p {west,south,north,east}

# Pre-select the ratio.
super + ctrl + {1-9}
    bspc node -o 0.{1-9}

# Cancel the pre-selection for the focused node.
super + ctrl + space
    bspc node -p cancel

# Cancel the pre-selection for the focused desktop.
super + ctrl + shift + space
    bspc query -N -d | xargs -I id -n 1 bspc node id -p cancel

#------------------------------------------------------------------------------
# Move/resize.
#------------------------------------------------------------------------------
# Expand a window by moving one of its side outward.
super + alt + {h,j,k,l}
    bspc node -z {left -20 0,bottom 0 20,top 0 -20,right 20 0}

# Contract a window by moving one of its side inward.
super + alt + shift + {h,j,k,l}
    bspc node -z {right -20 0,top 0 20,bottom 0 -20,left 20 0}

# Move a floating window.
super + {Left,Down,Up,Right}
    bspc node -v {-20 0,0 20,0 -20,20 0}

D systemd/backup-host.service => systemd/backup-host.service +0 -5
@@ 1,5 0,0 @@
[Unit]
Description=Backup home directory using Borg

[Service]
ExecStart=%h/dev/workspace/bin/backup-host

D systemd/backup-host.timer => systemd/backup-host.timer +0 -9
@@ 1,9 0,0 @@
[Unit]
Description=Backup home directory weekly

[Timer]
OnCalendar=Mon,Thu 12:00
Persistent=true

[Install]
WantedBy=timers.target

D tmux/.tmux.conf => tmux/.tmux.conf +0 -71
@@ 1,71 0,0 @@
#------------------------------------------------------------------------------
# Key-bindings
#------------------------------------------------------------------------------
unbind-key C-b
set-option -g prefix C-a
bind-key C-a send-prefix

unbind-key !
bind-key ! respawn-pane -k

unbind-key Space
bind-key Space select-layout -E

#------------------------------------------------------------------------------
# Copy mode configuration
#------------------------------------------------------------------------------
# Re-map copy mode keys so they resemble Vim-style key-bindings. Copy/paste
# functionality sends output/takes input from xclip so that we can interact
# with the system keyboard and Vim.
#------------------------------------------------------------------------------
bind-key Escape copy-mode

set-window-option -g mode-keys vi

bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T copy-mode-vi C-v send-keys -X rectangle-toggle
bind-key -T copy-mode-vi y send-keys -X copy-pipe \
"xclip -in -filter -selection primary | xclip -in -selection clipboard"

unbind-key p
bind-key p run-shell "xclip -out | tmux load-buffer - && tmux paste-buffer"
bind-key P run-shell "xclip -sel clip -out | tmux load-buffer - && tmux paste-buffer"

#------------------------------------------------------------------------------
# General configuration
#------------------------------------------------------------------------------
# Notify us other windows have activity.
set-option -g visual-activity on
# Shorten the wait after hitting Escape.
set-option -g escape-time 200
# Extend the scrollback limit.
set-option -g history-limit 8192
# Force tmux to use the correct shell.
set-option -g default-terminal "st-256color"
# Use non-login shells in tmux.
set-option -g default-command "/usr/bin/bash"

#------------------------------------------------------------------------------
# Apperance customizations
#------------------------------------------------------------------------------
# Status bar options.
set-option -g status-position bottom
set-option -g status-justify right

set-option -g status-style "bg=#dadada"
set-option -ag status-style "fg=#4e4e4e"

set-option -g status-left-length 40
set-option -g status-left " #S · #I · #P · #F "
set-option -g status-left-style "fg=#4e4e4e"

set-option -g status-right ""

# Window options.
set-window-option -g automatic-rename on
set-window-option -g window-status-format " #W "
set-window-option -g window-status-current-format " #[underscore]#W#[none] "

# Pane options.
set-window-option -g pane-border-style "fg=#c8c8c8"
set-window-option -g pane-active-border-style "fg=#9e9e9e"

D tmux/default.yml => tmux/default.yml +0 -13
@@ 1,13 0,0 @@
---
session_name: default
windows:
    - window_name: "*"
      layout: even-horizontal
      panes:
          - focus: true
    - window_name: comms
      layout: even-horizontal
      panes:
          - shell_command: aerc
          - shell_command: irssi
...

M vim/.vimrc => vim/.vimrc +39 -113
@@ 1,40 1,27 @@
scriptencoding utf-8
set encoding=utf-8

" Turn off Vi compatibility.
" Turn off Vi compatibility
set nocompatible

"----------------------------------------------------------------------
" Plugin registration
"----------------------------------------------------------------------
" We use vim-plug to help manage our plugins.
"----------------------------------------------------------------------
call plug#begin(expand('~/.vim/plugged'))

" Color scheme.
Plug 'junegunn/seoul256.vim'

" Fuzzy finder.
Plug 'junegunn/fzf'
Plug 'junegunn/fzf.vim'

" Dynamic working directory.
Plug 'airblade/vim-rooter'

" Configure editor according to .editorconfig prescense.
Plug 'editorconfig/editorconfig-vim'

" Distraction-free writing.
Plug 'junegunn/goyo.vim'
Plug 'junegunn/limelight.vim'
" Workaround to fix Vim clipboard for Wayland
" https://github.com/vim/vim/issues/5157
Plug 'jasonccox/vim-wayland-clipboard'

" Modify surrounding symbols.
Plug 'tpope/vim-surround'
Plug 'junegunn/fzf'
Plug 'junegunn/fzf.vim'

" Markdown syntax highlighting
Plug 'plasticboy/vim-markdown'
Plug 'tpope/vim-surround'

" GLSL syntax highlighting
Plug 'tikhomirov/vim-glsl'

call plug#end()


@@ 42,31 29,26 @@ call plug#end()
"----------------------------------------------------------------------
" General configuration
"----------------------------------------------------------------------
" Enable file-format specific plugin and indentation changes.
" Enable file-format specific plugin and indentation changes
filetype plugin on
filetype indent on

set history=8192

" Some general options.
" General options
set ruler
set cursorline
set colorcolumn=72,80,100
set laststatus=2  " Always show status line.
set showmatch " Show matching braces.
set nofoldenable " Folding makes things unreadable.
set autoread " Re-read a file if it has been changed.
set showcmd " Show current command.
set noerrorbells " Disable warning sounds.
set visualbell " Enable visual warnings.

" Formatting options.
set colorcolumn=80
set laststatus=2 " Always show status line
set showmatch    " Show matching braces
set nofoldenable " Folding makes things unreadable
set autoread     " Re-read a file if it has been changed
set showcmd      " Show current command
set noerrorbells " Disable warning sounds
set visualbell   " Enable visual warnings

" Formatting options
set autoindent
set noexpandtab
set shiftwidth=4
set softtabstop=4
set tabstop=4
set textwidth=80
" Vim built-in formatting options (see `:help gq`).
" Note that 'n' and '2' don't play well together.
let &formatoptions = 'tcqjn'


@@ 79,33 61,33 @@ augroup relativenumber_toggle
	autocmd BufLeave,FocusLost,InsertEnter * set norelativenumber
augroup END

set undofile " Persistent undo.
set undofile " Persistent undo
let &undodir = expand('~/.vim/undo')
let &dir = expand('~/.vim/swap')

" Let Vim know we have 256 color support.
" Let Vim know we have 256 color support
set t_Co=256

" Enable syntax highlighting.
" Enable syntax highlighting
syntax on
let g:seoul256_srgb = 1
colorscheme seoul256-light
set background=light

" Show invisible characters, but disable syntax highlighting for them.
" Show invisible characters, but disable syntax highlighting for them
set list
set listchars=tab:│\ ,eol:¬
set listchars=tab:⇥\ ,eol:¬,trail:⋅
highlight NonText cterm=NONE
highlight SpecialKey cterm=NONE

" https://github.com/vim/vim/issues/406
let c_no_curly_error = 1

" Highlight the search as we are typing.
" Highlight search as we are typing
set incsearch
set hlsearch

" Auto-completion options.
" Auto-completion options
set completeopt=menu,menuone,preview

augroup filetype_detection


@@ 114,79 96,23 @@ augroup filetype_detection
	autocmd BufNewFile,BufReadPost .clang-format set filetype=yaml
augroup END

" Autocorrect common spelling mistakes
iabbrev teh the
iabbrev waht what

"------------------------------------------------------------------------------
" Key-bindings
"------------------------------------------------------------------------------
let mapleader = ','

" 'Self-documenting' key-bindings.
" http://joshldavis.com/2015/08/22/self-documenting-vim-mappings/
nmap <Leader><Tab> :echo 'Fuzzy-search Git files' <Bar> :GFiles<CR>
nmap <Leader>q :echo 'Fuzzy-search all files' <Bar> :Files<CR>
nmap <Leader>w :echo 'Fuzzy-search open buffers' <Bar> :Buffers<CR>
nmap <Leader>t :echo 'Fuzzy-search tags' <Bar> :Tags<CR>
nmap <Leader>T :echo 'Swap between multiple tag definitions' <Bar> :ts<CR>

nmap <Leader>g :echo 'Enter distraction-free writing' <Bar> :Goyo<CR>
nmap <Leader>G :echo 'Exit distraction-free writing' <Bar> :Goyo!<CR>
nmap <Leader>c :echo 'Un-highlight all search results' <Bar> :nohlsearch<CR>
nmap <Leader>a :echo 'Close all open buffers' <Bar> :bufdo bdelete<CR>
nmap <Leader>A :echo 'Force close all open buffers' <Bar> :bufdo! bdelete<CR>
" fzf shortcuts
nmap <Leader>g :GFiles<CR>
nmap <Leader>f :Files<CR>
nmap <Leader>b :Buffers<CR>
nmap <Leader>t :Tags<CR>

"------------------------------------------------------------------------------
" Abbreviations
"------------------------------------------------------------------------------
" Autocorrect common spelling mistakes.
iabbrev teh the
iabbrev waht what

"------------------------------------------------------------------------------
" Plugin-specific configuration
"------------------------------------------------------------------------------
" Configuration for fzf.
" Customize fzf colors to match color scheme.
let g:fzf_colors = {
			\ 'fg': ['fg', 'Normal'],
			\ 'bg': ['bg', 'Normal'],
			\ 'hl': ['fg', 'Comment'],
			\ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
			\ 'bg+': ['bg', 'CursorLine', 'CursorColumn'],
			\ 'hl+': ['fg', 'Statement'],
			\ 'info': ['fg', 'PreProc'],
			\ 'border': ['fg', 'Ignore'],
			\ 'prompt': ['fg', 'Conditional'],
			\ 'pointer': ['fg', 'Exception'],
			\ 'marker': ['fg', 'Keyword'],
			\ 'spinner': ['fg', 'Label'],
			\ 'header': ['fg', 'Comment'],
			\ }

" Configuration for Goyo/Limelight.
let g:goyo_width = 100

" Enable and disable Limelight when entering/exiting Goyo.
" FIXME: This does not play well with our hybrid line number settings.
" This can be fixed using callback functions on GoyoEnter/Leave.
augroup limelight_goyo
	autocmd!
	autocmd User GoyoEnter Limelight
	autocmd User GoyoLeave Limelight!
augroup END
" Swap between multiple tag definitions
nmap <Leader>T :ts<CR>

" Configuration for Rooter.
set noautochdir
let g:rooter_change_directory_for_non_project_files = 'current'
let g:rooter_patterns = [
			\ 'tags',
			\ '.git',
			\ '.hg',
			\ '.bzr',
			\ '.svn',
			\ '.editorconfig',
			\ ]
let g:rooter_resolve_links = 1

" Configuration for vim-markdown.
let g:vim_markdown_math = 1
let g:vim_markdown_frontmatter = 1
let g:vim_markdown_strikethrough = 1
" Un-highlight all search results
nmap <Leader>c :nohlsearch<CR>

D xinit/.xinitrc => xinit/.xinitrc +0 -8
@@ 1,8 0,0 @@
#!/usr/bin/env sh

# Set desktop wallpaper
if [[ -f "$HOME"/.fehbg ]]; then
    "$HOME"/.fehbg &
fi

exec bspwm

D xinit/.xserverrc => xinit/.xserverrc +0 -2
@@ 1,2 0,0 @@
#!/usr/bin/env sh
exec /usr/bin/Xorg -nolisten tcp -nolisten local "$@" "vt""$XDG_VTNR"

A yay/config.json => yay/config.json +45 -0
@@ 0,0 1,45 @@
{
	"aururl": "https://aur.archlinux.org",
	"buildDir": "/home/rycwo/.cache/yay",
	"editor": "",
	"editorflags": "",
	"makepkgbin": "makepkg",
	"makepkgconf": "",
	"pacmanbin": "pacman",
	"pacmanconf": "/etc/pacman.conf",
	"redownload": "no",
	"rebuild": "no",
	"answerclean": "",
	"answerdiff": "",
	"answeredit": "",
	"answerupgrade": "",
	"gitbin": "git",
	"gpgbin": "gpg",
	"gpgflags": "",
	"mflags": "",
	"sortby": "votes",
	"searchby": "name-desc",
	"gitflags": "",
	"removemake": "yes",
	"sudobin": "sudo",
	"sudoflags": "",
	"requestsplitn": 150,
	"completionrefreshtime": 7,
	"maxconcurrentdownloads": 0,
	"bottomup": true,
	"sudoloop": false,
	"timeupdate": false,
	"devel": true,
	"provides": false,
	"pgpfetch": true,
	"upgrademenu": true,
	"cleanmenu": false,
	"diffmenu": true,
	"editmenu": false,
	"combinedupgrade": true,
	"useask": false,
	"batchinstall": true,
	"singlelineresults": false,
	"separatesources": true,
	"version": "11.3.0"
}