Converting the pages to markdown with sed
This commit is contained in:
parent
b585649fc4
commit
619736be2a
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
# Add spaces to == headers such as "=header="
|
||||||
|
s/^\(=\+\)\([^=]*\)\(=\+\)$/\1 \2 \3/
|
||||||
|
|
||||||
|
# Replace comments
|
||||||
|
s/# \(.*\)$/* \1/g
|
||||||
|
|
||||||
|
# Replace == headers with # headers
|
||||||
|
s/^= \(.*\) =$/# \1/g
|
||||||
|
s/^== \(.*\) ==$/## \1/g
|
||||||
|
s/^=== \(.*\) ===$/### \1/g
|
||||||
|
s/^==== \(.*\) ====$/#### \1/g
|
||||||
|
s/^===== \(.*\) =====$/##### \1/g
|
||||||
|
s/^====== \(.*\) ======$/###### \1/g
|
||||||
|
|
||||||
|
# Replace code tags
|
||||||
|
s/{{{class="brush: *\([^"]*\)"/\`\`\`\1/g
|
||||||
|
s/{{{class="\([^"]*\)"/\`\`\`\1/g
|
||||||
|
s/{{{/\`\`\`/g
|
||||||
|
s/}}}/\`\`\`/g
|
||||||
|
|
||||||
|
# Replace * bullets with - bullets
|
||||||
|
s/^\(\s*\)\*/\1-/g
|
||||||
|
|
||||||
|
# Replace partially-finished checklist items with unfinished checklist items
|
||||||
|
s/^\(\s*\)- \(\[[.oO]\]\)/\1- [ ]/g
|
||||||
|
|
||||||
|
# Replace URLs
|
||||||
|
s/\[\[\(.*\)|\(.*\)\]\]/\[\2\](\1)/g
|
||||||
|
s/\[\[\([^]]\{1,\}\)\]\]/[\1](\1.md)/g
|
||||||
|
|
||||||
|
# Replace comments
|
||||||
|
s/%% \(.*\)/<!-- \1 -->/g
|
||||||
|
|
||||||
|
# Replace TOC, Title, and draft status
|
||||||
|
/%toc.*/d
|
||||||
|
s/%title \(.*\)/# \1/g
|
||||||
|
s/%nohtml/- status: draft/g
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
newdir=./new
|
||||||
|
|
||||||
|
[[ ! -d $newdir ]] && mkdir $newdir
|
||||||
|
|
||||||
|
for i in ./*.wiki; do
|
||||||
|
newname=${i/.wiki/.md}
|
||||||
|
sed -f "$1" "$i" > "$newdir/$newname"
|
||||||
|
done
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Archived Pages
|
||||||
|
|
||||||
|
- [Audiobook RSS Feed](Audiobook RSS Feed.md)
|
||||||
|
|
||||||
|
### Configuration/Dotfiles
|
||||||
|
|
||||||
|
- [i3](i3.md) -- Moved to Sway
|
||||||
|
- [Xinitrc](Xinitrc.md) -- Moved to Sway
|
||||||
|
- [Pkglists](Pkglists.md) -- Project abandoned. I install as I go nowadays.
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Serving Audiobooks as an RSS Feed
|
||||||
|
|
||||||
|
I want to serve my library of audiobooks as an RSS feed so that I can use my favorite podcast app as the player.
|
||||||
|
|
||||||
|
Packages used:
|
||||||
|
- python-pyrss2gen: RSS generation
|
||||||
|
- python-mutagen: metadata extraction
|
|
@ -0,0 +1,187 @@
|
||||||
|
# Automated Android App Builds
|
||||||
|
|
||||||
|
Goal: Get a compiled apk of [AsteroidOS Sync](https://github.com/asteroidos/AsteroidOSSync) from the latest git commit.
|
||||||
|
|
||||||
|
I wanted to do this without untracked software clutter on my main machine, so I decided to do it in a systemd-nspawn container on my home server. The container and build turned out better than I expected, so I went ahead with automating the whole setup to check daily for new commits, building the app if there is a new commit, and dumping it in a folder outside of the container.
|
||||||
|
|
||||||
|
## Setting up systemd-nspawn
|
||||||
|
|
||||||
|
Arch makes this step super easy with the `arch-install-scripts` package:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- pacstrap -icd container/ base --ignore linux base-devel
|
||||||
|
```
|
||||||
|
|
||||||
|
- `-i`: Avoid auto-confirmation of package selections
|
||||||
|
- `-c`: Use the package cache on the host rather than the target
|
||||||
|
- `-d`: Allow installation to a non-mountpoint directory
|
||||||
|
- `container/`: Path to your desired container location
|
||||||
|
- `base --ignore linux base-devel`: Install the base and base-devel groups, ignoring the `linux` package. The kernel is not necessary inside this container, so might as well save the bandwidth
|
||||||
|
|
||||||
|
This will get you a container with the latest packages ready to spin up. After that, all you need to do is:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- systemd-nspawn -bD container/
|
||||||
|
```
|
||||||
|
|
||||||
|
This will boot the container and leave you at a login prompt. For Arch, root will be passwordless. Start here, and configure your new container for what you need. For my setup, I created an unprivileged user, added my `~/.bashrc` and `~/.vimrc`, and installed the android-sdk package from the AUR.
|
||||||
|
|
||||||
|
Next, we need to automate bringing the new container up with a systemd service. Easiest way to get a service ready for a systemd-nspawn is to use the existing systemd-nspawn@.service, and tweak it for this specific use. To get a copy of this unit and start editing it right away, run `systemctl edit --full systemd-nspawn@containername.service`. This is the end product of my unit:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- /etc/systemd/system/systemd-nspawn@asteroid.service
|
||||||
|
- This file is part of systemd.
|
||||||
|
#
|
||||||
|
- systemd is free software; you can redistribute it and/or modify it
|
||||||
|
- under the terms of the GNU Lesser General Public License as published by
|
||||||
|
- the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
- (at your option) any later version.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Container %i
|
||||||
|
Documentation=man:systemd-nspawn(1)
|
||||||
|
PartOf=machines.target
|
||||||
|
Before=machines.target
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest -U --settings=override --machine=%i -D /storage/containers/asteroid/sync-app/ --bind=/storage/containers/asteroid/output:/home/thurstylark/output
|
||||||
|
KillMode=mixed
|
||||||
|
Type=notify
|
||||||
|
RestartForceExitStatus=133
|
||||||
|
SuccessExitStatus=133
|
||||||
|
Slice=machine.slice
|
||||||
|
Delegate=yes
|
||||||
|
TasksMax=16384
|
||||||
|
|
||||||
|
- Enforce a strict device policy, similar to the one nspawn configures
|
||||||
|
- when it allocates its own scope unit. Make sure to keep these
|
||||||
|
- policies in sync if you change them!
|
||||||
|
DevicePolicy=closed
|
||||||
|
DeviceAllow=/dev/net/tun rwm
|
||||||
|
DeviceAllow=char-pts rw
|
||||||
|
|
||||||
|
- nspawn itself needs access to /dev/loop-control and /dev/loop, to
|
||||||
|
- implement the --image= option. Add these here, too.
|
||||||
|
DeviceAllow=/dev/loop-control rw
|
||||||
|
DeviceAllow=block-loop rw
|
||||||
|
DeviceAllow=block-blkext rw
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=machines.target
|
||||||
|
```
|
||||||
|
|
||||||
|
The only things changed from the original are all in `ExecStart=`:
|
||||||
|
|
||||||
|
- `-D /storage/containers/asteroid/sync-app/`: Boot the nspawn from a directory instead of from an image, and the path to that directory
|
||||||
|
- `--bind=/storage/containers/asteroid/output:/home/thurstylark/output`: Create a bind mount between the host and the container. The format is `/host/dir:/container/dir` where `/container/dir` is specified with `/` at the root of the container, not of the host.
|
||||||
|
- Removed `--network-veth` to use the networking from the host instead of creating a virtual ethernet link.
|
||||||
|
|
||||||
|
Check the systemd-nspawn manpage for more info.
|
||||||
|
|
||||||
|
To start your container, run `systemctl start systemd-nspawn@containername.service`. Confirm it's running with `machinectl list` and `systemctl status systemd-nspawn@containername.service`.
|
||||||
|
|
||||||
|
### Reference
|
||||||
|
- https://wiki.archlinux.org/index.php/Systemd-nspawn
|
||||||
|
|
||||||
|
----
|
||||||
|
## Interacting With Your New Container
|
||||||
|
|
||||||
|
When your systemd-nspawn is booted, most interaction is done using `machinectl(1)`. I will only be covering what's necessary for this setup. Check machinectl's manpage for more detailed info.
|
||||||
|
|
||||||
|
To get a shell:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- machinectl shell user@containername
|
||||||
|
```
|
||||||
|
|
||||||
|
This will bypass the login prompt, and start user's shell. If no user is specified, you will be logged in as root.
|
||||||
|
|
||||||
|
The actual building is done by a script in the container. This means we need either a) a way to execute that script from outside the container, or b) put the script on a timer within the container. Since I don't want the container running the whole time, I opted for option A. This allows the machine to be started and stopped as necessary.
|
||||||
|
|
||||||
|
To execute the script from outside the container:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- machinectl shell user@containername /path/to/script
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: This path is relative to the root of the container, not of the host.
|
||||||
|
|
||||||
|
All that's left is to make a service unit for this command. Here's how my unit stands at the time of writing:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- /etc/systemd/system/build-aos-sync.service
|
||||||
|
[Unit]
|
||||||
|
Description=Build latest commit of AsteroidOS Sync
|
||||||
|
Requires=systemd-nspawn@asteroid.service
|
||||||
|
After=systemd-nspawn@asteroid.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/bin/machinectl shell thurstylark@asteroid /home/thurstylark/buildapp.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
This unit is set up to boot our container automatically by using `Requires=` and `After=`. This way, we don't have to manage how our container is started. This also enables us to manually trigger a build by starting this unit.
|
||||||
|
|
||||||
|
The last part of the actual automation is done with a timer for our new service. It doesn't have to be super complicated, but you can tweak it how you like it:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- /etc/systemd/system/build-aos-sync.timer
|
||||||
|
[Unit]
|
||||||
|
Description=Timer for automated AsteroidOS Sync build
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=daily
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
```
|
||||||
|
|
||||||
|
This timer is set for `OnCalendar=daily`, which will trigger every day at midnight. When the timer triggers, it will start our service, which will start our container if it's not already started, then it will run our build script. More options for this timer can be found in the `systemd.timer` manpage.
|
||||||
|
|
||||||
|
----
|
||||||
|
## Build Script
|
||||||
|
|
||||||
|
The last peice of the puzzle for this is to actually compile the app in question. Before any of this can be done or tested, your Android build environment should be set up. Check the Android Building page for more info.
|
||||||
|
|
||||||
|
Here's the script I ended up with:
|
||||||
|
|
||||||
|
```prettyprint linenums
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
pkgname=asteroid-os-sync
|
||||||
|
project_root=/home/thurstylark/AsteroidOSSync
|
||||||
|
bind_mount=/home/thurstylark/output
|
||||||
|
output=$project_root/app/build/outputs/apk/app-debug.apk
|
||||||
|
|
||||||
|
build_app() {
|
||||||
|
- Reference: https://developer.android.com/studio/build/building-cmdline.html
|
||||||
|
cd $project_root
|
||||||
|
git remote update
|
||||||
|
if [ "$(git rev-parse @)" == "$(git rev-parse @{u})" ]( "$(git rev-parse @)" == "$(git rev-parse @{u})" .md); then
|
||||||
|
echo "App up to date." >&2
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
git pull origin master
|
||||||
|
rm -r app/src/main/res/values-ca-rES@valencia/
|
||||||
|
ANDROID_HOME=/opt/android-sdk ./gradlew assembleDebug
|
||||||
|
fi
|
||||||
|
|
||||||
|
copy_output
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgver() {
|
||||||
|
cd $project_root
|
||||||
|
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_output() {
|
||||||
|
cp ${output} ${bind_mount}/${pkgname}-$(pkgver).apk
|
||||||
|
}
|
||||||
|
|
||||||
|
build_app
|
||||||
|
```
|
||||||
|
|
||||||
|
This script is not incredibly intelligent, but it gets the job done. One thing to point out is the test on line 11. This if statement checks whether our local copy of the git repo is up to date. If it's up to date, the script exits with a little message. This way we are only building if there are changes to be built.
|
||||||
|
|
||||||
|
I also use `copy_output()` to rename the resulting apk with the revision number and short commit id (compiled using `pkgver()`) for clarity.
|
|
@ -0,0 +1,337 @@
|
||||||
|
# Bashrc
|
||||||
|
|
||||||
|
Source: https://git.thurstylark.com/vcsh/bashrc.git
|
||||||
|
|
||||||
|
## Profile
|
||||||
|
|
||||||
|
Bash chooses which dotfile to source based on how it gets run. If starting from a login shell, `~/.bash_profile` will get sourced, but if there's not a command in there to source your `~/.bashrc`, you may find yourself having to `exec bash` after starting bash. This can be fixed by adding the following line to your `~/.bash_profile`:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
[ -f ~/.bashrc ]( -f ~/.bashrc .md) && . ~/.bashrc
|
||||||
|
```
|
||||||
|
|
||||||
|
I also use `~/.bash_profile` for setting numlock while in a tty:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
case $(tty) in /dev/tty[0-9]*)
|
||||||
|
setleds -D +num * (numlock for X is set in ~/.xinitrc)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
```
|
||||||
|
|
||||||
|
The last thing of note in my `~/.bash_profile` is a warning:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- Temporary fix for a systemd bug related to systemd --user timers that run on login
|
||||||
|
[ -z "$DBUS_SESSION_BUS_ADDRESS" ]( -z "$DBUS_SESSION_BUS_ADDRESS" .md) && printf "%bWARNING: \$DBUS_SESSION_BUS_ADDRESS is unset! %b\n" "$(tput bold)$(tput setab 1)" "$(tput sgr0)"
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Main bashrc
|
||||||
|
|
||||||
|
Things started getting a little too expansive, so I split off relevant sections into their own files. Now all my individual utilities have their own file, making troubleshooting and adding functionality much easier. You can find info for each file and what it does in its own section on this page.
|
||||||
|
|
||||||
|
### General config
|
||||||
|
|
||||||
|
I'm not going in to detail about every line, but I'll hilight the important parts. The rest should be documented in the script itself.
|
||||||
|
|
||||||
|
First off, if we're not running bash interactively, there's no use for any of the rest of this, so just skip it.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- If not running interactively, don't do anything
|
||||||
|
[ $- != *i* ]( $- != *i* .md) && return
|
||||||
|
```
|
||||||
|
|
||||||
|
Another cool option is actually built in to bash: If you call for a directory without any command before it, just `cd` into that directory.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- If a directory is given without any command, CD into it.
|
||||||
|
shopt -s autocd
|
||||||
|
```
|
||||||
|
|
||||||
|
This is where all the other utilities, aliases, and functions get pulled in. Anything in `~/.bashrc.d/` ending in `.sh` will get pulled in.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
for f in ~/.bashrc.d/*.sh; do source "$f"; done
|
||||||
|
```
|
||||||
|
|
||||||
|
This also removes the need for the local bashrc sourcing that I [had in this file previously](https://git.thurstylark.com/vcsh/bashrc.git/tree/.bashrc?id=30c53ca7224b583ed5068038b697653810e3b94b#n45). If that functionality is needed, simply make a new script in `~/.bashrc.d/` and don't track it with `vcsh`.
|
||||||
|
|
||||||
|
Ordering can be done by adding numbers to the beginning of filenames. For example: `10-prompt.sh`. Currently, nothing that I use requires that kind of functionality.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
https://git.thurstylark.com/vcsh/bashrc.git/tree/.bashrc.d/prompt.sh
|
||||||
|
|
||||||
|
I originally built my prompt using http://bashrcgenerator.com and, while it's a nice tool for visually building a prompt, it has several limitations on what you're able to create with it. But more importantly to me, it generates a rediculously long string, defines and resets color for every single character, uses both a color and bold escape sequence to use light/bright colors, mixes raw escape sequences and subshells running tput, and as a result is utterly unreadable and unmaintainable.
|
||||||
|
|
||||||
|
So, I replaced it:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
promptsetup() {
|
||||||
|
- Color definitions for prompt
|
||||||
|
local fg_brightred='\[$(tput setaf 9)\]'
|
||||||
|
local fg_blue='\[$(tput setaf 4)\]'
|
||||||
|
local fg_magenta='\[$(tput setaf 13)\]'
|
||||||
|
local fg_cyan='\[$(tput setaf 6)\]'
|
||||||
|
local fg_brightcyan='\[$(tput setaf 14)\]'
|
||||||
|
local fg_green='\[$(tput setaf 2)\]'
|
||||||
|
local reset='\[$(tput sgr0)\]'
|
||||||
|
local hostname='\h'
|
||||||
|
local mixin
|
||||||
|
|
||||||
|
- [hh:mm][username@hostname pwd]$
|
||||||
|
|
||||||
|
- Remotely, hostname is red.
|
||||||
|
[ -n "$SSH_CLIENT" ] && hostname="${fg_brightred}\h${reset}"
|
||||||
|
|
||||||
|
- If in a python venv, add venv name in green.
|
||||||
|
[ -n "$VIRTUAL_ENV" ] && mixin=" ${fg_green}$(basename "$VIRTUAL_ENV")${reset}"
|
||||||
|
|
||||||
|
- If in a vcsh repo env, add repo name in magenta.
|
||||||
|
[ -n "$VCSH_REPO_NAME" ] && mixin=" ${fg_magenta}$VCSH_REPO_NAME${reset}"
|
||||||
|
|
||||||
|
PS1="${fg_blue}[\A]${fg_cyan}[${fg_brightcyan}\u${fg_cyan}@${hostname}${mixin} ${fg_cyan}\W]${reset}\$ "
|
||||||
|
}
|
||||||
|
|
||||||
|
promptsetup
|
||||||
|
```
|
||||||
|
|
||||||
|
I intentionally put everything in a function and call it immediately so I may use local vars for the color definitions. I didn't really want to leave them around just in case.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Aliases
|
||||||
|
|
||||||
|
https://git.thurstylark.com/vcsh/bashrc.git/tree/.bashrc.d/alias.sh
|
||||||
|
|
||||||
|
Most of these are just creature comforts and fairly self-explanitory:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
##* ALIASES ###
|
||||||
|
|
||||||
|
- Colorize all `ls` output:
|
||||||
|
alias ls='ls -AF --color=auto'
|
||||||
|
|
||||||
|
- Map "la" to `ls -la`
|
||||||
|
alias la='ls -laFh --color=auto'
|
||||||
|
|
||||||
|
- Colorize `grep` output
|
||||||
|
alias grep='grep --color=auto'
|
||||||
|
|
||||||
|
- Change layout of lsblk to include FSTYPE and remove MAJ:MIN, RM, and RO collumns.
|
||||||
|
alias lsblk='lsblk -o NAME,FSTYPE,SIZE,TYPE,MOUNTPOINT'
|
||||||
|
|
||||||
|
- Always use sudo when using nmap.
|
||||||
|
alias nmap='sudo -E nmap'
|
||||||
|
|
||||||
|
- Switch $TERM temporarily (for logging into machines that don't have tmux-256color terminfo)
|
||||||
|
alias screenterm='TERM=screen-256color'
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Colored man Pages
|
||||||
|
|
||||||
|
Some color changes in `man` are almost essential for readability for me, so here's how I achieve that:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- Enables colored Man pages:
|
||||||
|
man() {
|
||||||
|
env LESS_TERMCAP_mb=$'\E[01;31m' \
|
||||||
|
LESS_TERMCAP_md=$'\E[01;38;5;74m' \
|
||||||
|
LESS_TERMCAP_me=$'\E[0m' \
|
||||||
|
LESS_TERMCAP_se=$'\E[0m' \
|
||||||
|
LESS_TERMCAP_so=$'\E[38;5;246m' \
|
||||||
|
LESS_TERMCAP_ue=$'\E[0m' \
|
||||||
|
LESS_TERMCAP_us=$'\E[04;38;5;146m' \
|
||||||
|
man "$@"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This can also be done for any similar program that uses `less` as its pager.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Get Dell Service Tag
|
||||||
|
|
||||||
|
https://git.thurstylark.com/vcsh/bashrc.git/tree/.bashrc.d/getdst.sh
|
||||||
|
|
||||||
|
I work with Dell machines a lot, and when dealing with hardware problems, it's nice to have the service tag handy. Lucky for me, the service tag is easily retrieveable using `dmidecode(1)`, so I made a function for it.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
getdst() {
|
||||||
|
if [ "$1" = "-l" ]( "$1" = "-l" .md); then
|
||||||
|
printf "http://www.dell.com/support/home/us/en/04/product-support/servicetag/%s/configuration\n" "$(getdst)"
|
||||||
|
else
|
||||||
|
sudo dmidecode -s system-serial-number
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
As an added bonus, the `-l` option will print the url for that product's support page.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
|
||||||
|
https://git.thurstylark.com/vcsh/bashrc.git/tree/.bashrc.d/shot.sh
|
||||||
|
|
||||||
|
This function wraps `maim(1)` and `fb(1)` to simplify my most used options. It uses maim to capture either the full screen, the active window, or a mouse selection to a file, or directly to a pastebin.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
shot() {
|
||||||
|
- Usage: shot XY
|
||||||
|
local destdir="$HOME/Pictures/screenshots"
|
||||||
|
local fname
|
||||||
|
local pb="fb"
|
||||||
|
local paste msgt msgd opts
|
||||||
|
fname="shot-$(date +%F-%T).png"
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
printf "
|
||||||
|
Usage: shot XY
|
||||||
|
X: Target
|
||||||
|
Y: Destination
|
||||||
|
|
||||||
|
Valid Targets:
|
||||||
|
w Active Window
|
||||||
|
a All displays
|
||||||
|
s Mouse Selection
|
||||||
|
|
||||||
|
Valid Destinations:
|
||||||
|
f Save to file (defined in function)
|
||||||
|
p Upload to a pastebin (defined in function)
|
||||||
|
"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
- X: What to capture
|
||||||
|
case ${1:0:1} in
|
||||||
|
- Active window
|
||||||
|
w) printf "Focus target window now...\n"
|
||||||
|
opts="-i $(xdotool getactivewindow)"
|
||||||
|
msgt="active window"
|
||||||
|
;;
|
||||||
|
- All
|
||||||
|
a) msgt="all displays"
|
||||||
|
;;
|
||||||
|
- Mouse selection
|
||||||
|
s) opts="-s --noopengl"
|
||||||
|
msgt="mouse selection"
|
||||||
|
;;
|
||||||
|
|
||||||
|
-) printf "Invalid target: %s\n" "${1:0:1}"
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
- Y: Where to put the result
|
||||||
|
case ${1:1:1} in
|
||||||
|
- Save to file
|
||||||
|
f) msgd="file: $destdir/$fname"
|
||||||
|
;;
|
||||||
|
- Post to a pastebin
|
||||||
|
p) destdir=$destdir/pasted
|
||||||
|
msgd="pastebin"
|
||||||
|
paste=1;;
|
||||||
|
|
||||||
|
-) printf "Invalid destination: %s\n" "${1:1:1}"
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
- Make sure destination directory will exist
|
||||||
|
[ ! -d "$destdir" ]( ! -d "$destdir" .md) && mkdir -p "$destdir"
|
||||||
|
local fpath="${destdir}/${fname}"
|
||||||
|
|
||||||
|
- If target is active window, give a 5 second countdown before running maim
|
||||||
|
[ "$msgt" = "active window" ]( "$msgt" = "active window" .md) && countdown 5
|
||||||
|
|
||||||
|
maim "$opts" "$fpath"
|
||||||
|
printf "Captured %s -> %s\n" "$msgt" "$msgd"
|
||||||
|
|
||||||
|
- If destination is a pastebin, do the needful
|
||||||
|
[ "$paste" ]( "$paste" .md) && $pb "$fpath"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This probably isn't the most robust solution, but it works pretty well. Patches welcome.
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Countdown
|
||||||
|
|
||||||
|
https://git.thurstylark.com/vcsh/bashrc.git/tree/.bashrc.d/countdown.sh
|
||||||
|
|
||||||
|
Found this little function when I wanted to add functionality to `shot()`. It takes an integer as an argument, then counts down that number of seconds visually.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
countdown() {
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
printf "
|
||||||
|
countdown: Count down while printing progress on the terminal
|
||||||
|
|
||||||
|
Usage: countdown <seconds>
|
||||||
|
"
|
||||||
|
fi
|
||||||
|
local secs="$1"
|
||||||
|
while [ "$secs" -gt 0 ]; do
|
||||||
|
echo -ne "$secs\033[0K\r"
|
||||||
|
sleep 1
|
||||||
|
: $((secs--))
|
||||||
|
done
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This probably isn't the sanest or safest solution to the problem, but it gets the job done. Patches welcome.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## FontFind
|
||||||
|
|
||||||
|
https://git.thurstylark.com/vcsh/bashrc.git/tree/.bashrc.d/fontfind.sh
|
||||||
|
|
||||||
|
Sometimes you just need to figure out what font provides a specific character. This function provides that solution:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
fontfind() {
|
||||||
|
if [ ${#1} -gt 1 ]( -z $1 |); then
|
||||||
|
printf "E: only one character accepted"
|
||||||
|
fi
|
||||||
|
local glyph=$1
|
||||||
|
FC_DEBUG=4 pango-view -qt "$glyph" 2>&1 | awk -F \" '/family: / { m = $2 } END { print m }'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Vactivate
|
||||||
|
|
||||||
|
https://git.thurstylark.com/vcsh/bashrc.git/tree/.bashrc.d/vactivate.sh
|
||||||
|
|
||||||
|
I started needing more than one python virtualenv, and I wanted easy access to my own specific file structure. Additionally, I wanted the ability to deactivate the venv like I would exit a child shell. This is the solution that I came up with:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
vactivate() {
|
||||||
|
local path=~/.venv/$1
|
||||||
|
|
||||||
|
if [ ! -d $path ]( ! -d $path .md); then
|
||||||
|
python -m venv $path --prompt "venv: $1"
|
||||||
|
fi
|
||||||
|
source $path/bin/activate; bash; deactivate
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A caveat to this is that the prompt modification that venv usually applies is not available using this method. If a prompt modification is desired, it needs to be taken care of elsewhere. I take care of it in my prompt setup detailed [here](https://wiki.thurstylark.com/Bashrc.html#Prompt).
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Weechat
|
||||||
|
|
||||||
|
https://git.thurstylark.com/vcsh/bashrc.git/tree/.bashrc.d/weechat.sh
|
||||||
|
|
||||||
|
See: [Weechat](Weechat.md).
|
|
@ -0,0 +1,72 @@
|
||||||
|
# CGit
|
||||||
|
|
||||||
|
Current configuration can always be found at https://git.thurstylark.com/cgit.git/tree
|
||||||
|
|
||||||
|
### Push To Deploy
|
||||||
|
|
||||||
|
The remote repo is set up to deploy the entire contents of the repo to `/srv/cgit` by using the `post-receive` hook in the git repo.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
#!/bin/bash
|
||||||
|
GIT_WORK_TREE=/srv/cgit git checkout -f
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows configuration changes to be edited on a local repo, committed, then pushed to the remote to apply changes.
|
||||||
|
|
||||||
|
### About Page
|
||||||
|
|
||||||
|
Had a problem with the about page not showing when the appropriate file names are definied as readme files. Here was the problematic config:
|
||||||
|
|
||||||
|
```prettyprint linenums
|
||||||
|
|
||||||
|
#css=/cgit-css/cgit.css
|
||||||
|
#logo=/cgit-css/cgit.png
|
||||||
|
|
||||||
|
root-title=Thurstylark
|
||||||
|
root-desc=Projects and Dotfiles
|
||||||
|
|
||||||
|
source-filter=/srv/cgit/syntax-highlighting.py
|
||||||
|
about-filter=/usr/lib/cgit/filters/about-formatting.sh
|
||||||
|
|
||||||
|
enable-git-config=1
|
||||||
|
scan-path=/srv/git
|
||||||
|
|
||||||
|
enable-http-clone=1
|
||||||
|
clone-url=https://git.thurstylark.com/$CGIT_REPO_URL
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
- Search for these files in the root of the default branch of repositories
|
||||||
|
- for coming up with the about page:
|
||||||
|
#
|
||||||
|
readme=:README.md
|
||||||
|
readme=:readme.md
|
||||||
|
readme=:README.mkd
|
||||||
|
readme=:readme.mkd
|
||||||
|
readme=:README.rst
|
||||||
|
readme=:readme.rst
|
||||||
|
readme=:README.html
|
||||||
|
readme=:readme.html
|
||||||
|
readme=:README.htm
|
||||||
|
readme=:readme.htm
|
||||||
|
readme=:README.txt
|
||||||
|
readme=:readme.txt
|
||||||
|
readme=:README
|
||||||
|
readme=:readme
|
||||||
|
readme=:INSTALL.md
|
||||||
|
readme=:install.md
|
||||||
|
readme=:INSTALL.mkd
|
||||||
|
readme=:install.mkd
|
||||||
|
readme=:INSTALL.rst
|
||||||
|
readme=:install.rst
|
||||||
|
readme=:INSTALL.html
|
||||||
|
readme=:install.html
|
||||||
|
readme=:INSTALL.htm
|
||||||
|
readme=:install.htm
|
||||||
|
readme=:INSTALL.txt
|
||||||
|
readme=:install.txt
|
||||||
|
readme=:INSTALL
|
||||||
|
readme=:install
|
||||||
|
```
|
||||||
|
|
||||||
|
The solution was to move the `scan-path` directive to the end of my cgitrc. See the [cgitrc manpage](https://git.zx2c4.com/cgit/tree/cgitrc.5.txt#n392) for details.
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Chrome Search Shortcuts
|
||||||
|
|
||||||
|
| Service | Trigger | URL | Description |
|
||||||
|
|-----------------------------|---------|-----------------------------------------------------------------------------|-------------------------------------------------------|
|
||||||
|
| Arch Wiki Search | aw | https://wiki.archlinux.org/index.php?title=Special%3ASearch&search=%s&go=Go | |
|
||||||
|
| Arch Package Search | ap | https://www.archlinux.org/packages/?sort=&q=%s&maintainer=&flagged= | |
|
||||||
|
| Arch User Repository Search | aur | https://aur.archlinux.org/packages/?O=0&K=%s | |
|
||||||
|
| Arch Linux Bug Lookup | fs | https://bugs.archlinux.org/task/%s | Go directly to bug number |
|
||||||
|
| Dell Service Tag Lookup | dell | http://www.dell.com/support/home/us/en/04/product-support/servicetag/%s | Go directly to the Dell Support page of a service tag |
|
||||||
|
| ShellCheck Code Search | sc | https://github.com/koalaman/shellcheck/wiki/SC%s | Look up ShellCheck code. (sc<tab><number>) |
|
|
@ -0,0 +1,92 @@
|
||||||
|
# Formatting Cheat Sheet
|
||||||
|
|
||||||
|
# Header1
|
||||||
|
## Header2
|
||||||
|
### Header3
|
||||||
|
|
||||||
|
|
||||||
|
-bold* -- bold text
|
||||||
|
|
||||||
|
_italic_ -- italic text
|
||||||
|
|
||||||
|
~~strikeout~~ -- strikeout text
|
||||||
|
|
||||||
|
`code without syntax`
|
||||||
|
|
||||||
|
super^script^
|
||||||
|
|
||||||
|
sub,,script,,
|
||||||
|
|
||||||
|
[wiki link](wiki link.md) -- wiki link
|
||||||
|
|
||||||
|
[description](wiki link) -- wiki link with description
|
||||||
|
|
||||||
|
## Lists
|
||||||
|
|
||||||
|
- bullet list item 1
|
||||||
|
- bullet list item 2
|
||||||
|
- bullet list item 3
|
||||||
|
- bullet list item 4
|
||||||
|
- bullet list item 5
|
||||||
|
- bullet list item 6
|
||||||
|
- bullet list item 7
|
||||||
|
- bullet list item 8
|
||||||
|
- bullet list item 9
|
||||||
|
|
||||||
|
1. numbered list item 1
|
||||||
|
2. numbered list item 2
|
||||||
|
a) numbered list item 3
|
||||||
|
b) numbered list item 4
|
||||||
|
|
||||||
|
- [ ] Unchecked item 1
|
||||||
|
- [X] Checked item 2
|
||||||
|
|
||||||
|
## Definitions
|
||||||
|
|
||||||
|
Term 1:: Definition 1
|
||||||
|
Term 2::
|
||||||
|
:: Definition 2
|
||||||
|
:: Definition 3
|
||||||
|
|
||||||
|
## Tables
|
||||||
|
|
||||||
|
| Column 1 | Column 2 | Column 3 |
|
||||||
|
|-----------------------|----------------------------------------------------------------------------------|----------|
|
||||||
|
| Data 1 | Data 2 | Data 3 |
|
||||||
|
| this takes rows below | this takes the next collumn as well and will not wrap this text to the next line | > |
|
||||||
|
| \/ | Data 5 | > |
|
||||||
|
| Data 4 | | |
|
||||||
|
|
||||||
|
## Preformatted Text
|
||||||
|
|
||||||
|
Without syntax highlighting
|
||||||
|
|
||||||
|
```
|
||||||
|
Here is some text
|
||||||
|
there is some text
|
||||||
|
```
|
||||||
|
|
||||||
|
With syntax highlighting
|
||||||
|
```prettyprint lang-python linenums >
|
||||||
|
def hello(world):
|
||||||
|
for x in range(10):
|
||||||
|
print("Hello {0} number {1}".format(world, x))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Blockquotes
|
||||||
|
|
||||||
|
Text that starts with 4 or more spaces is a Blockquote.
|
||||||
|
It won't be highlighted in Vim, but will be styled
|
||||||
|
on the HTML site.
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
A line that starts with `%%` won't show up in the HTML page
|
||||||
|
|
||||||
|
<!-- This is a comment and will be skipped when rendering to HTML -->
|
||||||
|
|
||||||
|
## Horizontal line
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
# Keyboard Mapping
|
||||||
|
References:
|
||||||
|
- https://wiki.archlinux.org/index.php/Map_scancodes_to_keycodes
|
||||||
|
- https://github.com/Earnestly/pkgbuilds/blob/master/system-config/hwdb-capslock-as-control.hwdb
|
||||||
|
|
||||||
|
Maping keys is pretty simple, and if it's done at the udev level, it's universal, so it doesn't require any X or Wayland specific configuration.
|
||||||
|
|
||||||
|
As an example, I map my compose key (menu key) to right meta (aka super, logo, windows, apple, or command key), and CapsLock to left Control.
|
||||||
|
|
||||||
|
## Get Scancode
|
||||||
|
|
||||||
|
First, get the scancode(s) of the key(s) you wish to change. Easiest way is to use `evteest(1)`. For each keypress, you'll get information similar to the following:
|
||||||
|
|
||||||
|
```class='prettyprint'
|
||||||
|
Event: time 1496690003.603531, -------------- SYN_REPORT ------------
|
||||||
|
Event: time 1496690003.723467, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70065
|
||||||
|
Event: time 1496690003.723467, type 1 (EV_KEY), code 127 (KEY_COMPOSE), value 0
|
||||||
|
```
|
||||||
|
|
||||||
|
The code you will need to use in the udev hwdb config file is the `MSC_SCAN` value (in this case: 70065).
|
||||||
|
|
||||||
|
## Get Hardware ID
|
||||||
|
|
||||||
|
Next you will need the hardware Vendor and Product ids from `lsusb(1)`. These are two sets of four hexidecimal digits separated by a colon (:) printed right before the device name.
|
||||||
|
|
||||||
|
```class='prettyprint'
|
||||||
|
Bus 001 Device 005: ID 258a:1006 <keyboard name here>
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, the Vendor ID is `258a`, and the Product ID is `1006`.
|
||||||
|
|
||||||
|
## Create udev hwdb Configuration
|
||||||
|
|
||||||
|
Then create `/etc/udev/hwdb.d/61-custom-keyboard.hwdb` with the following contents:
|
||||||
|
|
||||||
|
```class='prettyprint'
|
||||||
|
evdev:input:b0003v258Ap1006*
|
||||||
|
KEYBOARD_KEY_70065=rightmeta
|
||||||
|
KEYBOARD_KEY_70039=leftctrl
|
||||||
|
```
|
||||||
|
|
||||||
|
A few notes on the format of this file:
|
||||||
|
- The format for the device identifying line for usb devices is `evdev:input:b0003v<Vendor ID>p<ProductID>*`.
|
||||||
|
- If `<Product ID>` and `<Vendor ID>` contain letters, they must be capitalized
|
||||||
|
- These scancodes can be quite device-specific, so it is wise to be specific to *at least* the vendor and product IDs
|
||||||
|
- There are methods for identifying atk keyboards as well. Check the Arch Wiki page listed in the references above for more info
|
||||||
|
- Defining a key to change is done with `KEYBOARD_KEY_<scancode>=<new keycode>`
|
||||||
|
- `<scancode>` is the code we pulled from evtest earlier
|
||||||
|
- `<new keycode>` is the keycode we want to emit when the key is pressed. Names of keycodes are listed in `/usr/include/linux/input-event-codes.h`, and should be all lowercased in your udev config.
|
||||||
|
- The filename `61-custom-keyboard.hwdb` is somewhat arbitrary, but make sure that you order your file *after* the existing `60-keyboard.hwdb`.
|
||||||
|
|
||||||
|
## Update Hardware Database Index
|
||||||
|
|
||||||
|
After changing the config files, the hwdb needs to be rebuilt:
|
||||||
|
|
||||||
|
```class='prettyprint'
|
||||||
|
- systemd-hwdb update
|
||||||
|
```
|
||||||
|
|
||||||
|
To start using this new hwdb, either reboot or tell udev to reload:
|
||||||
|
|
||||||
|
```class='prettyprint'
|
||||||
|
- udevadm trigger
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that this will only work for adding or modifying existing key mappings. Deleted key mappings are kept in the kernel until a reboot.
|
||||||
|
|
||||||
|
## Testing the New Mappings
|
||||||
|
|
||||||
|
A simple test can be run before trying the keys directly:
|
||||||
|
|
||||||
|
```class='prettyprint'
|
||||||
|
- udevadm info /dev/input/by-path/*-usb-*-kbd | grep KEYBOARD_KEY
|
||||||
|
```
|
|
@ -0,0 +1,93 @@
|
||||||
|
# LetsEncrypt
|
||||||
|
|
||||||
|
## Certbot Usage
|
||||||
|
|
||||||
|
Create a cert using the interactive menu:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- certbot certonly
|
||||||
|
```
|
||||||
|
|
||||||
|
## Automating Renewal
|
||||||
|
|
||||||
|
LetsEncrypt Certs are good for a max of 90 days, so automating renewal is a must.
|
||||||
|
|
||||||
|
Do a dry-run renewal with certbot:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- certbot renew --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
This will test, and possibly renew all certs that certbot knows about
|
||||||
|
|
||||||
|
Now you can use `certbot renew --quiet` for scripting this renewal. I do mine with a simple systemd script:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- /etc/systemd/system/certbot.service
|
||||||
|
[Unit]
|
||||||
|
Description=Let's Encrypt renewal
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/bin/certbot renew --quiet --agree-tos
|
||||||
|
ExecStartPost=/bin/systemctl reload httpd.service
|
||||||
|
```
|
||||||
|
|
||||||
|
## Apache Configuration
|
||||||
|
|
||||||
|
There's a couple of considerations when using ssl certs with Apache. The first is to enable the appropriate modules in httpd.conf:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
LoadModule ssl_module modules/mod_ssl.so
|
||||||
|
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
|
||||||
|
```
|
||||||
|
|
||||||
|
Also, make sure to configure apache to listen on port 443:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
Listen 443
|
||||||
|
```
|
||||||
|
|
||||||
|
That will get the basic framework ready for your virtualhost definition. Here is a very simple virtualhost configuration:
|
||||||
|
|
||||||
|
```prettyprint linenums
|
||||||
|
<VirtualHost wiki.thurstylark.com:80>
|
||||||
|
ServerName wiki.thurstylark.com
|
||||||
|
|
||||||
|
DocumentRoot "/srv/wiki/"
|
||||||
|
<Directory "/srv/wiki/">
|
||||||
|
AllowOverride None
|
||||||
|
Options None
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
- Redirect all except the '.wellk-known' path to https.
|
||||||
|
- This allows automated renewal of ssl certs by certbot
|
||||||
|
RedirectMatch permanent ^/(?!\.well-known)(.*) https://wiki.thurstylark.com/$1
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
|
||||||
|
<VirtualHost wiki.thurstylark.com:443>
|
||||||
|
ServerName wiki.thurstylark.com
|
||||||
|
ServerAdmin thurstylark@gmail.com
|
||||||
|
|
||||||
|
DocumentRoot "/srv/wiki/"
|
||||||
|
<Directory "/srv/wiki/">
|
||||||
|
AllowOverride None
|
||||||
|
Options None
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
SSLEngine on
|
||||||
|
SSLCertificateChainFile "/etc/letsencrypt/live/wiki.thurstylark.com/fullchain.pem"
|
||||||
|
SSLCertificateKeyFile "/etc/letsencrypt/live/wiki.thurstylark.com/privkey.pem"
|
||||||
|
</VirtualHost>
|
||||||
|
```
|
||||||
|
|
||||||
|
A couple things to note here: First, this defines two virtualhosts, one for port 80 and one for port 443. This is in order to redirect _all_ traffic to HTTPS except for a very small exception.
|
||||||
|
|
||||||
|
This exception is what you see on line 12 in the code above. Only `*/.well-known/*` is not redirected because this is the dir that certbot uses for domain validation. Certbot will only validate over http, and will fail if given a 301 redirect. This allows validation to complete successfuly without a configuration change, thus aiding our automation efforts. Everything else gets a 301 redirect to HTTPS. Be sure to define `DocumentRoot` with the correct location for *both* VirtualHosts, or certbot will fail to renew things correctly. (found this one out the hard way)
|
||||||
|
|
||||||
|
Lines 28-29 configure Apache to look for the necessary files in the right places. The locations listed here are actually symlinks to the real files, which are kept in an archive. These links are maintained by certbot automagically.
|
||||||
|
|
||||||
|
To obtain new certs for a subdomain, copy this config to `/etc/httpd/conf/extra/`, update the config with the appropriate subdomain name, comment out lines 5-29 to disable the redirect and ssl configuration, and add an include in the main httpd.conf. Once that is all set up, you can run certbot to obtain new certs. Once certbot is finished, you can remove the comments, restart httpd, and begin testing.
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Links of Infamy
|
||||||
|
|
||||||
|
- [How to properly run a community.](https://wiki.archlinux.org/index.php/Code_of_conduct)
|
||||||
|
- [How to properly automate yourself out of a job.](https://github.com/NARKOZ/hacker-scripts)
|
||||||
|
- [How to properly file a bug report.](https://github.com/chrislgarry/Apollo-11/issues/3)
|
||||||
|
- [How to properly troubleshoot networking equipment.](https://tools.ietf.org/html/rfc2321)
|
||||||
|
- [How to properly manage your distro's infrastructure.](http://web.archive.org/web/20150409040851/https://manjaro.github.io/expired_SSL_certificate/)
|
||||||
|
- [How to properly learn from your mistakes.](https://web.archive.org/web/20160811103932/https://manjaro.github.io/SSL-Certificate-Expired/)
|
||||||
|
- [How to properly install Gentoo](http://www.bash.org/?464385)
|
||||||
|
- [How to properly answer useless questions that get asked repeatedly.](http://stackoverflow.com/a/1732454)
|
||||||
|
- [How to properly appreciate the number five.](https://github.com/jackdcrawford/five)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# On Labels
|
||||||
|
|
||||||
|
### A label is not a template for behavior. It is a tool used for describing your specific brand of awesome to others. You are you, pick a label that fits (or don't, whatever)
|
||||||
|
|
||||||
|
That is to say: I am secure in the label that I've chosen, not because *I* can fit within *the label*, but because *the label* fits *me.* I am the only one in the world qualified to make any judgments about my sexuality, because I am the only one in the world who lives my life, feels my emotions, and experiences my attraction The *only* reason I have chosen to use a one-word label for such a large, complicated part of my person, is because it provides a useful short-hand.
|
||||||
|
|
||||||
|
However, this absolutely doesn't mean labels have no usefulness beyond communicating complicated concepts in a succinct way. In an external sense, labels provide some sense of community in a world where people are often denied the opportunity to internalize these concepts from a young age; Finding this community provides legitimacy, validation, and support where otherwise one would be left to deal with their identity completely alone.
|
||||||
|
|
||||||
|
But, for the purposes of one's *internal* struggle: You are who you are, and whatever that ends up looking like for you, it can be explored and discovered with or without the participation of others. For some people, it helps to have some experience to consider, but there are just as many who have come to their conclusions completely on their own.
|
||||||
|
|
||||||
|
### IMO: Begin by finding the truth about yourself, and then you can figure out how to communicate that to others.
|
||||||
|
|
||||||
|
Or don't. I don't live your life :)
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Password Store Setup
|
||||||
|
|
||||||
|
This is a quick reference for setting up `pass` on a new filesystem.
|
||||||
|
|
||||||
|
1. Install `pass` via the most official means possible
|
||||||
|
2. Import secret key to gpg keyring
|
||||||
|
3. Initialize the password store with the key ID
|
||||||
|
```class='prettyprint'
|
||||||
|
pass init <keyid>
|
||||||
|
```
|
||||||
|
4. Initialize the git repo inside the password store
|
||||||
|
```class='prettyprint'
|
||||||
|
pass git init
|
||||||
|
```
|
||||||
|
5. Set remote origin
|
||||||
|
```class='prettyprint'
|
||||||
|
pass git remote add origin user@site.com:pass.git
|
||||||
|
```
|
||||||
|
6. Fetch origin
|
||||||
|
```class='prettyprint'
|
||||||
|
pass git fetch origin
|
||||||
|
```
|
||||||
|
7. Reset hard to origin/master (overwriting anything that existed in the password store thus far)
|
||||||
|
```class='prettyprint'
|
||||||
|
pass git reset --hard origin/master
|
||||||
|
```
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Pkglists
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
https://git.thurstylark.com/vcsh/pkglists.git/
|
||||||
|
https://git.thurstylark.com/vcsh/systemd-user.git/
|
||||||
|
https://github.com/gs93/pakbak
|
||||||
|
|
||||||
|
These used to be actual lists created by [an admittedly terrible script](https://git.thurstylark.com/vcsh/pkglists.git/tree/.pkglists/pkglistbu.sh?id=62cc7e34c1354900cf7cc58480d9b4db2cd7309a) that was run nightly by a systemd --user timer, but now I backup `pacman`'s whole local database whenever there's a change using pakbak and `systemd.path` units.
|
||||||
|
|
||||||
|
## Pakbak
|
||||||
|
|
||||||
|
Pakbak is pretty straightforward: You configure where you want the backups stored, the ammount of backups you want to keep, and then enable `pakbak.path`. This will trigger `pacbak.service` whenever there is a change to `/var/lib/pacman/local` in the filesystem, `pakbak.path` triggers `pakbak.service`, which runs `/usr/lib/systemd/scripts/pakbak`. The pakbak script checks for pacman's lock file before continuing, then creates a tar archive of `/var/lib/pacman/local`.
|
||||||
|
|
||||||
|
If later access is needed, untar the archive, and point pacman at that dir (e.g.: to get the package lists from an unrecoverable system). The archive includes the dirs leading up to the actual database, so if simple recovery is the goal, just untar at `/`. For accessing the database in other situations, it might be prudent to add `--strip-components=3` in order to get just the `local` subdir.
|
||||||
|
|
||||||
|
### Config
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
|
||||||
|
- Backup the database to this folder
|
||||||
|
target_folder=/home/thurstylark/.pkglists/$(hostname)/
|
||||||
|
|
||||||
|
- Define how long backups should be kept
|
||||||
|
- Can be a number of days or empty to disable
|
||||||
|
keep_days=
|
||||||
|
|
||||||
|
- Define how many backups should be kept
|
||||||
|
- If more backup are found, the oldest are deleted
|
||||||
|
- Can be a number of file or empty to disable
|
||||||
|
keep_number=1
|
||||||
|
```
|
||||||
|
|
||||||
|
This will keep only one copy of the database around, and delete all the others. Since they are being committed to a git repo, there's no need to keep several copies to have access to the history.
|
||||||
|
|
||||||
|
|
||||||
|
## Backing up
|
||||||
|
|
||||||
|
Once pakbak has created the archive, it is added, committed, and pushed to a vcsh git repo by a couple of systemd --user services. This is triggered by any change to the directory that pakbak writes its output to for that host. Activation of this process is handled by `pkglists-commit.path`:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
[Unit]
|
||||||
|
Description=Path activation for pkglists-commit.service
|
||||||
|
|
||||||
|
[Path]
|
||||||
|
PathChanged=%h/.pkglists/%H
|
||||||
|
MakeDirectory=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
```
|
||||||
|
|
||||||
|
This unit watches `$HOME/.pkglists/$HOSTNAME` for changes, and on any activity, activates `pkglists-commit.service`:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
[Unit]
|
||||||
|
Description=Add, commit, and push pacman db backups
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=no
|
||||||
|
ExecStartPre=/usr/bin/bash -c 'wait $(pgrep pakbak)'
|
||||||
|
ExecStartPre=/usr/bin/vcsh pkglists pull
|
||||||
|
ExecStartPre=/usr/bin/vcsh pkglists add -A %h/.pkglists/%H/*
|
||||||
|
ExecStartPre=/usr/bin/vcsh pkglists commit -m "Auto-commiting %H pacman db"
|
||||||
|
ExecStart=/usr/bin/vcsh pkglists push
|
||||||
|
```
|
||||||
|
|
||||||
|
This service waits for pakbak to complete, pulls the pkglists repo, adds any changes to `$HOME/.pkglists/$HOSTNAME`, commits to the repo, then pushes. Thanks to `git-add`'s `-A` option, the add step also includes removal, so that git will remove the old database from the branch, which avoids the possibility of having multiple databases exist when pulling from or cloning the repo.
|
||||||
|
|
||||||
|
This is where the main magic happens that allows automatic distributed backups. For each host that has this set up, they also are housing the backups. The origin branch is _technically_ the canonical master, but since this is git, recovery is very easy to access from any machine. Also, since the trigger is literally any time pacman's local database changes (read: installation or removal of a package), the chances of all the clients having the latest revision of the repo becomes much higher.
|
||||||
|
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
- I'm not a big fan of using my own `systemd.path` unit since one is already provided by pakbak, but since A) this process deals with files in a home folder, and B) there isn't any forseeable situation where a `systemd --user` instance _won't_ be running when the database gets updated, I opted for `systemd --user` units to manage this part of the solution, and `--user` units can't depend on `--system` units. This could easily be fixed by installing a copy of pakbak's units to `/usr/lib/systemd/user/` in the `PKGBUILD` and running it from there.
|
||||||
|
- All of this could probably be replaced with my own `systemd --user` units or a pacman hook, but for the moment, I'm more concerned with getting it working.
|
|
@ -0,0 +1,15 @@
|
||||||
|
= Ramblings =
|
||||||
|
Sometimes I just need to write shit down.
|
||||||
|
|
||||||
|
|
||||||
|
## LGBTQ+
|
||||||
|
- [On Labels](On Labels.md)
|
||||||
|
|
||||||
|
|
||||||
|
### On Gender
|
||||||
|
- [Am I faking being trans?](am-i-faking-gender)
|
||||||
|
|
||||||
|
### On Sexuality
|
||||||
|
- [Does experimenting make you any less straight?](experimenting-with-sexuality)
|
||||||
|
- [Should I come out while still questioning?](coming-out-while-questioning) -- Adolescence, fluidity, and communicating your truth
|
||||||
|
- [Do people actually desire physical affection?](desiring-physical-affection) -- Asexuality, relationships, and wtf is normalcy anyways?
|
|
@ -0,0 +1,74 @@
|
||||||
|
# SSH
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## User-Specific Client Config
|
||||||
|
|
||||||
|
Most directives that can be set in the system-wide client configuration can be set by each user in `~/.ssh/config`. This snippit contains a collection of my most used options:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
SendEnv LC_* * Send all LC env vars to the host
|
||||||
|
AddKeysToAgent yes * If asked to unlock a password-protected private
|
||||||
|
- key, automatically add that key to the ssh-agent
|
||||||
|
- so you no longer need to reenter the password
|
||||||
|
- again this session
|
||||||
|
|
||||||
|
- Example Host Definition
|
||||||
|
Host foo * Arbitrary String. Use this definition by running `ssh foo`
|
||||||
|
HostName foo.bar.com * Actual DNS Hostname or IP address of the server
|
||||||
|
Port 12345 * Port number to connect to
|
||||||
|
User thurstylark * Username on the server to connect as
|
||||||
|
IdentityFile ~/.ssh/id_rsa * Private key to use for authentication
|
||||||
|
ServerAliveInterval 300 * Interval in seconds before a keepalive packet is sent to the server
|
||||||
|
ServerAliveCountMax 3 * Declare the connection dead after no response to this many keepalive packets
|
||||||
|
HostKeyAlgorithms ssh-dss * Use ssh-dss for host-key algorithm checking (ssh-dss is insecure. Use something else)
|
||||||
|
KexAlgorithms +kex * Add 'kex' to the list of Key Exchange Algorithms available for use.
|
||||||
|
StrictHostKeyChecking no * Turn off Strict Host Key Checking for only this host (insecure)
|
||||||
|
UserKnownHostsFile /dev/null * Discard this hosts host key instead of storing in ~/.ssh/known_hosts (not recommended)
|
||||||
|
VisualHostKey yes * Always use randomart in place of host key sums
|
||||||
|
```
|
||||||
|
|
||||||
|
### Directive Notes
|
||||||
|
|
||||||
|
- `Host`
|
||||||
|
- Can also refer to an actual hostname. See "Host-Specific Keys" below.
|
||||||
|
- `ServerAliveInterval` and `ServerAliveCountMax`
|
||||||
|
- It's common for a firewall to cause problems keeping connections open, so tweaking these settings can help. See "Broken Pipe Remedy" below.
|
||||||
|
- `HostKeyAlgorithms`
|
||||||
|
- ssh-dss is less secure than the alternatives/defaults. Only use this if necessary.
|
||||||
|
- `KexAlgorithms`
|
||||||
|
- I use this to add `diffie-hellman-group1-sha1` to the available Key Exchange Algorithms for connecting to older hardware that doesn't accept any currently allowed kex algorithms. Diffie Hellman is quite insecure, so please use caution.
|
||||||
|
- `StrictHostKeyChecking`
|
||||||
|
- Several servers I connect to are descrete servers, but they all are accessed through a single IP Address with a randomized port number. This allows me to continue connecting to the host without stopping to delete a line from `~/.ssh/known_hosts` before connecting.
|
||||||
|
|
||||||
|
|
||||||
|
### Host-Specific Keys
|
||||||
|
|
||||||
|
User-specific ssh configs make it stupid easy to create several keys for several different uses. For instance, this allows you to have a separate key for each service that you use, and allows you less headache should one key be compromised.
|
||||||
|
|
||||||
|
For example: Github allows you to push to your remote repositories over ssh by adding a public key to your account. Ideally, you should create a keypair for this specific purpose, and name it something like 'github'. Then you can add something like this to your `~/.ssh/config`:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
host github.com
|
||||||
|
IdentityFile ~/.ssh/github
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, when your repo's origin url is set to something like `git@github.com:username/reponame.git`, ssh will automatically use your github key instead of needing to specify it in the command, or using your username and password with HTTPS every time.
|
||||||
|
|
||||||
|
### Broken Pipe Remedy
|
||||||
|
|
||||||
|
Often times a firewall or inconsistent connection can cause an ssh connection to be closed prematurely and give a "Write Failed: broken pipe" error message. Some firewalls are configured to close connections that have sent no data after a certain interval, thus causing a broken pipe error when the connection was otherwise healthy. This can usually be solved by sending data through the connection before that interval is up, thus resetting the firewall's timer.
|
||||||
|
|
||||||
|
The `ServerAliveInterval` option sends a keepalive packet if no data has been received within the interval specified. All the keepalive packet does is request a response from the server to verify the connection is still good. By default, this option is disabled.
|
||||||
|
|
||||||
|
Additionally, the `ServerAliveCountMax` option specifies the number of keepalive packets that may be sent without a response before ssh terminates the connection. By default this is set to `3`, but if your connection is unreliable, you can set this higher to give your server a better chance at responding the next time a keepalive packet is sent.
|
||||||
|
|
||||||
|
It is important to note that messages sent by the `TTYKeepAlive` option are not sent through the encrypted channel and can be spoofed, but the "server alive" messages are sent through the encrypted channel and cannot be spoofed. Do not use `TTYKeepAlive` messages for determining the quality or security of a connection! See `ssh-config(5)` for more info.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## SSH Host Configuration
|
||||||
|
|
||||||
|
### Google Authenticator
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Stupid Crestron Quirks
|
||||||
|
|
||||||
|
Crestron can be stupid sometimes. These are the undocumented ways.
|
||||||
|
|
||||||
|
## When creating a SIMPL Windows program for a 2 Series DMPS, DO NOT select the control system at program creation
|
||||||
|
|
||||||
|
When you create a new SIMPL Windows program, you get the option to select which control system this program is being created for. Without selecting this option, you won't be able to connect any of your logic to any of the hardware, and your program won't do anything useful. You *can* create a program without a control system, but this is usually to create a SIMPL Macro, which is then completed and added to a different SIMPL program. All this to say, a SIMPL Windows program without a control system at the top of the hardware tree is not useful on its own.
|
||||||
|
|
||||||
|
So, when I create a program that's supposed to run on a 2 Series DMPS (model `DMPS-*`, not `DMPS3-*`), and I understand all the above, naturally I select the model number of the control system I'm writing a program for.
|
||||||
|
|
||||||
|
The program gets created, and I get started creating the program. I get hung up on the part of the program that deals with switching video and audio sources, so I naturally look at the help file for the device that I'm trying to control. It's probably the most unhelpful help file in the history of helping people.
|
||||||
|
|
||||||
|
Here's where it's valuable to understand a little about the hardware. Crestron has a long history of design-recycling masquerading as backwards-compatibility. Basically, whenever they create a new product, they take an existing product and its tech, modify it to do what they want to market, and throw it out there. In this case, they took a 2 Series processor and a paired-down DM chassis, shoehorned them into the same case, and rushed it to market. The result is a disjointed attempt at providing the advertized functionality. Instead of providing the programmer with the appropriate controls for input switching in the hardware tree (you know, where you control the hardware), they instead had a whole bunch of undocumented nonsense nodes in a jumble of confusing unreadable card-based slot structure, and then a macro (yes, quite literally like the macro that I alluded to earlier), which connects itself to all the right spots in the hardware tree, and provides a littany of **actually useful** controls in the logic tree.
|
||||||
|
|
||||||
|
The perceptive reader might ask how such a macro does the attaching by itself (as the attaching of signals is usually the exclusive job of the Crestron programmer/dealer). Well, the answer came to me after 45 minutes of troubleshooting on my own and with my manager, and then after an hour-long phone call with Crestron True Blue support: I created the program wrong.
|
||||||
|
|
||||||
|
See, if you select a 2 Series DMPS at program creation, this macro doesn't get automatically added and connected to the appropriate places in order to be useful. Instead you have to create the program with no control system, then add the control system in configure mode. Apparently there is some sort of script that bootstraps the module to the hardware, and if you add the control system to the project at program creation, this script doesn't get to run, and your program is SOL. And since I had put the switching problem aside and finished creating the rest of the program, the tech on the phone had to tell me that I had to create a new program from scratch, and copy/pase my code into my new project to get it to work.
|
||||||
|
|
||||||
|
Now, I'm hesitant to rag solely on Crestron's developers for this convoluted mess of what-the-fuckery, but this situation does make it obvious that there is definitely a cultural reluctance to modernize and refactor their systems for the good of the programmers that have to put these systems together for *their* customers. Further, I'm sure that the decision to base their control systems on Windows CE and .NET Compact Framework 3.5 was not made by the developers, and they are certainly making the best of the hand they're dealt (especially now that their current control systems are running on these discontinued products). I think the blame for this particular circuis goes to their exec team who didn't give enough time to make this project the right way. It's a classic case of a product being rushed to market, but here's the important part: It seems that way only from the perspective of the *programmer*.
|
||||||
|
|
||||||
|
See, if there's anything that I would commend Crestron's Dev team for, it would be stability. It takes a lot to get a big system with hundreds of finicky pieces to work together just right, but by god, once you get it right, it will do the exact same thing in the exact same way every freakin time until the hardware gives out. This is no small feat, and I recognize that for what it is. I take issue with all the other cruft and bullshittery that collects after years and years of the "Backwards Compatibility and Stability above all" doctrine. It's a doctrine that creates a focus on marketing and sales above product quality. From the end-user's perspective, the product works as desired, but this is at the cost of programming time due to the complexity of these systems and the necessity of a programmer with the appropriate experience. All part of the bill that the customer has to pay.
|
||||||
|
|
||||||
|
And this is one of the many reasons Crestron can be stupid.
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Tasks
|
||||||
|
|
||||||
|
## General
|
||||||
|
|
||||||
|
## Wiki
|
||||||
|
|
||||||
|
### Pages
|
||||||
|
- [ ] Thurstylark-VPS
|
||||||
|
- [ ] Cgit
|
||||||
|
- [ ] Apache
|
||||||
|
|
||||||
|
### Template
|
||||||
|
- [ ] Figure out TOC
|
||||||
|
- [ ] Finish building out navbar
|
||||||
|
- [ ] Change page title to "Thurstylark Wiki -- %title%"
|
||||||
|
- [ ] Breadcrumbs?
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Thurstylark-VPS
|
||||||
|
|
||||||
|
Just a little Linode VPS running Arch, but it's a powerful little sucker.
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
- [Cgit](Cgit.md)
|
||||||
|
- Apache
|
||||||
|
- [Weechat](Weechat.md)
|
||||||
|
- Custom Repo
|
|
@ -0,0 +1,142 @@
|
||||||
|
# Vimwiki
|
||||||
|
|
||||||
|
Source: https://git.thurstylark.com/vimwiki.git/
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- All content is stored in a git repo as vimwiki content (to avoid having to sync HTML content as well)
|
||||||
|
- All content automatically converted to HTML and moved to the appropriate directory when the git repo is pushed
|
||||||
|
- [Template](https://git.thurstylark.com/vimwiki.git/tree/html-template/index.html) based on bootstrap, so theming/building the template is easy peasy
|
||||||
|
|
||||||
|
## Table tweaks
|
||||||
|
|
||||||
|
Tables without any styles are gross, so let's use the styles from Bootstrap. Problem is that Vimwiki doesn't provide a way to add a class to a table element, so we'll do it with JQuery:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
<head>
|
||||||
|
...
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("table").addClass("table table-condensed table-hover");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
...
|
||||||
|
</head>
|
||||||
|
```
|
||||||
|
|
||||||
|
This adds `.table`, `.table-condensed`, and `.table-hover` classes to every table element in the whole document. Don't see why it should be any other way for the moment.
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
- http://stackoverflow.com/a/39897883
|
||||||
|
- http://www.w3schools.com/jquery/jquery_syntax.asp
|
||||||
|
|
||||||
|
## HTML Checkboxes
|
||||||
|
|
||||||
|
By default, there is no difference between how a non-checkbox list item, unchecked list item, and a checked list item are displayed when exported to HTML.
|
||||||
|
|
||||||
|
There are 5 states of a checkbox, 0-4, and they each represent a different level of completeness. This is mainly for checklist items with children.
|
||||||
|
|
||||||
|
Checkbox states:
|
||||||
|
|
||||||
|
| State * | % Complete | li class | Unicode character | Escape sequence | HTML code |
|
||||||
|
|---------|------------|----------|-------------------|-----------------|------------|
|
||||||
|
| 0 | 0% | `done0` | ◯ | `\u25EF` | `◯` |
|
||||||
|
| 1 | 1-33% | `done1` | ◔ | `\u25D4` | `◔` |
|
||||||
|
| 2 | 34-66% | `done2` | ◑ | `\u25D1` | `◑` |
|
||||||
|
| 3 | 67-99% | `done3` | ◕ | `\u25D5` | `◕` |
|
||||||
|
| 4 | 100% | `done4` | ✔ | `\u2714` | `✔` |
|
||||||
|
|
||||||
|
Now, in order to use these in our HTML, we just have to write a style for `ul li.doneX:before` in our header like so:
|
||||||
|
|
||||||
|
```prettyprint linenums >
|
||||||
|
<style>
|
||||||
|
ul li.done0:before {content: '\25EF';}
|
||||||
|
ul li.done1:before {content: '\25D4';}
|
||||||
|
ul li.done2:before {content: '\25D1';}
|
||||||
|
ul li.done3:before {content: '\25D5';}
|
||||||
|
ul li.done4:before {content: '\2714';}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Now here's a few test lists:
|
||||||
|
|
||||||
|
- [ ] Unfinished item
|
||||||
|
- [X] Finished item
|
||||||
|
- [ ] Parent item 1
|
||||||
|
- [X] Child item 1
|
||||||
|
- [ ] Child item 2
|
||||||
|
- [ ] Child item 3
|
||||||
|
- [ ] Child item 4
|
||||||
|
- [ ] Parent item 2
|
||||||
|
- [X] Child item 1
|
||||||
|
- [X] Child item 2
|
||||||
|
- [ ] Child item 3
|
||||||
|
- [ ] Child item 4
|
||||||
|
- [ ] Parent item 3
|
||||||
|
- [X] Child item 1
|
||||||
|
- [X] Child item 2
|
||||||
|
- [X] Child item 3
|
||||||
|
- [ ] Child item 4
|
||||||
|
- [X] Parent item 4
|
||||||
|
- [X] Child item 1
|
||||||
|
- [X] Child item 2
|
||||||
|
- [X] Child item 3
|
||||||
|
- [X] Child item 4
|
||||||
|
- [ ] Parent item 5
|
||||||
|
- [ ] Child item 1
|
||||||
|
- [ ] Child item 2
|
||||||
|
- [ ] Child item 3
|
||||||
|
- [ ] Child item 4
|
||||||
|
|
||||||
|
## Push to Deploy
|
||||||
|
|
||||||
|
The easiest way to manage this wiki, and also allow it to be hosted, is to commit all the wiki documents to a repo, and script the deployment to the wiki's webroot using git's post-receive hook. The origin remote repo also hosts the http server, so it makes things simple. Less simple because it requires a vim plugin to compile the HTML files, but it's still doable.
|
||||||
|
|
||||||
|
First part of this solution is the vimrc for the remote machine. This sets the destination for the final html files, the origin wiki files, and the html template page.
|
||||||
|
|
||||||
|
```prettyprint linenums
|
||||||
|
set nocompatible
|
||||||
|
filetype plugin on
|
||||||
|
syntax on
|
||||||
|
let g:vimwiki_list = [{
|
||||||
|
\ 'path': '/tmp/vimwiki/',
|
||||||
|
\ 'path_html': '/srv/wiki/',
|
||||||
|
\ 'template_path': '/tmp/vimwiki/html-template',
|
||||||
|
\ 'template_default': 'index',
|
||||||
|
\ 'template_ext': '.html'}]
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: lines 1-3 are required for vimwiki to work correctly with the post-receive hook. The rest of the config are options for vimwiki directly.
|
||||||
|
|
||||||
|
The post-receive hook is a fairly simple bash script. This script is located at `~/git/vimwiki.git/hooks/post-receive`, and is run every time the repo receives a push from downstream.
|
||||||
|
|
||||||
|
```prettyprint linenums
|
||||||
|
#!/bin/bash
|
||||||
|
mkdir /tmp/vimwiki
|
||||||
|
export GIT_WORK_TREE=/tmp/vimwiki
|
||||||
|
|
||||||
|
export GIT_DIR=/home/thurstylark/git/vimwiki.git
|
||||||
|
|
||||||
|
git checkout -f
|
||||||
|
|
||||||
|
vim -u /tmp/vimwiki/html-template/srv-vimrc -c VimwikiAll2HTML -c q /tmp/vimwiki/index.wiki
|
||||||
|
|
||||||
|
cp /tmp/vimwiki/html-template/slate.bootstrap.css /srv/wiki/
|
||||||
|
|
||||||
|
rm -rf /tmp/vimwiki
|
||||||
|
```
|
||||||
|
|
||||||
|
It first makes a directory under /tmp for the contents of the repo, sets `$GIT_WORK_TREE` and `$GIT_DIR`, and does a `git checkout` for all the files in the repo.
|
||||||
|
|
||||||
|
Line 9 is where the magic happens. This line runs vim with the vimrc from above, and runs the `:VimwikiAll2HTML` command.
|
||||||
|
|
||||||
|
Next, the script copies over the one CSS file that I need to host myself, and lastly, it cleans up the temp dir.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
- [X] Commit to a repository
|
||||||
|
- [X] Setup remote to host
|
||||||
|
- [X] Setup remote to automatically `:VimwikiAll2HTML` after it's been pushed to
|
||||||
|
- [X] Document push to deploy
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
# Weechat
|
||||||
|
|
||||||
|
Current configuration can always be found at https://git.thurstylark.com/vcsh/weechat.git
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
- Not dependent on graphical session (terminal-based client)
|
||||||
|
- Use only one nick during normal operation
|
||||||
|
- Use multiple computers interchangeably at random
|
||||||
|
- Do not require a close/quit process to move between workstations
|
||||||
|
- Reduce the ammount of join/part messages caused by me
|
||||||
|
- Be reachable through IRC as much as possible (stay online)
|
||||||
|
- Have the ability to use a mobile app at will
|
||||||
|
|
||||||
|
The best option so far is weechat run in a multiplexer like tmux.
|
||||||
|
|
||||||
|
----
|
||||||
|
## Starting Weechat
|
||||||
|
|
||||||
|
Easiest way to get this done is to start weechat at boot with a systemd system service:
|
||||||
|
|
||||||
|
```prettyprint linenums
|
||||||
|
[Unit]
|
||||||
|
Description=Start Weechat as relay and client
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=forking
|
||||||
|
User=thurstylark
|
||||||
|
Group=thurstylark
|
||||||
|
ExecStart=/usr/bin/tmux -f /home/thurstylark/.config/srv-tmux.conf new-session -ds weechat weechat
|
||||||
|
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
- When starting tmux with `new-session -d` as its command, tmux forks to the background, thus requiring `Type=forking` in order to let systemd keep track of the process.
|
||||||
|
- I run this service as my user and group, because I use the default locations for weechat config: `~/.weechat/`. This greatly simplifies weechat configuration.
|
||||||
|
- tmux configuration needs to be passed to tmux by using `-t /path/to/config`. Full path is used just to be thorough.
|
||||||
|
|
||||||
|
----
|
||||||
|
## Configuring tmux
|
||||||
|
|
||||||
|
tmux needs a configuration to disable the status bar, visual bell, and other things that won't be useful in this setup.
|
||||||
|
|
||||||
|
```prettyprint linenums
|
||||||
|
set -g default-terminal "screen-256color"
|
||||||
|
|
||||||
|
set-option -g assume-paste-time 1
|
||||||
|
set-option -g base-index 1
|
||||||
|
set-option -g pane-base-index 1
|
||||||
|
set-option -g default-command ""
|
||||||
|
set-option -g default-shell "/bin/bash"
|
||||||
|
set-option -g destroy-unattached off
|
||||||
|
set-option -g detach-on-destroy on
|
||||||
|
set-option -g display-panes-active-colour red
|
||||||
|
set-option -g display-panes-colour blue
|
||||||
|
set-option -g display-panes-time 1000
|
||||||
|
set-option -g display-time 750
|
||||||
|
set-option -g history-limit 10000
|
||||||
|
set-option -g word-separators " -_@"
|
||||||
|
set-option -g renumber-windows off
|
||||||
|
set-option -g repeat-time 500
|
||||||
|
set-option -g set-remain-on-exit off
|
||||||
|
set-option -g set-titles off
|
||||||
|
set-option -g set-titles-string "#S:#I:#W - "#T" #{session_alerts}"
|
||||||
|
set-option -g status off
|
||||||
|
|
||||||
|
- Change prefix to C-a
|
||||||
|
set-option -g prefix C-a
|
||||||
|
|
||||||
|
set-option -g status-style fg=black,bg=cyan
|
||||||
|
set-option -g message-command-style fg=green,bg=black
|
||||||
|
set-option -g message-style fg=white,bg=red
|
||||||
|
set-option -g update-environment "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY"
|
||||||
|
|
||||||
|
- Set audible bell on, and visual bell off because it is slooooowwwww
|
||||||
|
set-option -g bell-action any
|
||||||
|
set-option -g bell-on-alert on
|
||||||
|
set-option -g visual-bell off
|
||||||
|
set-option -g visual-silence off
|
||||||
|
set-option -g visual-activity off
|
||||||
|
|
||||||
|
- Pane active colors
|
||||||
|
set-option -g pane-active-border-style fg=cyan,bright
|
||||||
|
|
||||||
|
- Pane inactive colors
|
||||||
|
set-option -g pane-border-style fg=colour8
|
||||||
|
|
||||||
|
- Use C-a,Shift-R to reload configuration
|
||||||
|
bind R source-file ~/.tmux.conf \; display-message "Config reloaded..."
|
||||||
|
|
||||||
|
- Use C-a,a to send prefix to nested session
|
||||||
|
bind-key a send-prefix
|
||||||
|
|
||||||
|
- Use Alt-arrow keys without prefix key to switch panes
|
||||||
|
bind -n M-Left select-pane -L
|
||||||
|
bind -n M-Right select-pane -R
|
||||||
|
bind -n M-Up select-pane -U
|
||||||
|
bind -n M-Down select-pane -D
|
||||||
|
- Do the same for HJKL
|
||||||
|
bind -n M-h select-pane -L
|
||||||
|
bind -n M-l select-pane -R
|
||||||
|
bind -n M-k select-pane -U
|
||||||
|
bind -n M-j select-pane -D
|
||||||
|
|
||||||
|
- No delay for escape key press
|
||||||
|
set -sg escape-time 0
|
||||||
|
|
||||||
|
- Various copy mode tweaks
|
||||||
|
bind-key -t vi-copy Home start-of-line
|
||||||
|
bind-key -t vi-copy End end-of-line
|
||||||
|
- Sync copy mode and PRIMARY selection
|
||||||
|
bind-key -t vi-copy MouseDragEnd1Pane copy-pipe "xsel -i -p -b"
|
||||||
|
bind-key -t vi-copy Enter copy-pipe "xsel -i -p -b"
|
||||||
|
bind-key -t vi-copy y copy-pipe "xsel -i -p -b"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
I will usually use this within yet another tmux session, so I end up needing to set up some key bindings to control the differrent sessions
|
||||||
|
|
||||||
|
- `C-a a`: Send prefix to the terminal
|
||||||
|
- `C-a a d`: Disconnect the nested session from this client.
|
||||||
|
- `C-a a :`: Get command prompt on nested session
|
||||||
|
|
||||||
|
----
|
||||||
|
## Weechat Relay
|
||||||
|
|
||||||
|
Here are all the options related to weechat relay:
|
||||||
|
|
||||||
|
```prettyprint linenums
|
||||||
|
[cmd] (alias.conf)
|
||||||
|
alias.cmd.norelay = "/buffer set localvar_set_relay hard-hide"
|
||||||
|
[look] (relay.conf)
|
||||||
|
relay.look.auto_open_buffer = off (default: on)
|
||||||
|
relay.look.raw_messages = 256
|
||||||
|
[color] (relay.conf)
|
||||||
|
relay.color.client = cyan
|
||||||
|
relay.color.status_active = lightblue
|
||||||
|
relay.color.status_auth_failed = lightred
|
||||||
|
relay.color.status_connecting = yellow
|
||||||
|
relay.color.status_disconnected = lightred
|
||||||
|
relay.color.status_waiting_auth = brown
|
||||||
|
relay.color.text = default
|
||||||
|
relay.color.text_bg = default
|
||||||
|
relay.color.text_selected = white
|
||||||
|
[network] (relay.conf)
|
||||||
|
relay.network.allow_empty_password = off
|
||||||
|
relay.network.allowed_ips = ""
|
||||||
|
relay.network.bind_address = "127.0.0.1" (default: "")
|
||||||
|
relay.network.clients_purge_delay = 0
|
||||||
|
relay.network.compression_level = 6
|
||||||
|
relay.network.ipv6 = off (default: on)
|
||||||
|
relay.network.max_clients = 5
|
||||||
|
relay.network.password = "letmein" (default: "")
|
||||||
|
relay.network.ssl_cert_key = "%h/ssl/relay.pem"
|
||||||
|
relay.network.ssl_priorities = "NORMAL:-VERS-SSL3.0"
|
||||||
|
relay.network.websocket_allowed_origins = ""
|
||||||
|
[irc] (relay.conf)
|
||||||
|
relay.irc.backlog_max_minutes = 1440
|
||||||
|
relay.irc.backlog_max_number = 256
|
||||||
|
relay.irc.backlog_since_last_disconnect = on
|
||||||
|
relay.irc.backlog_since_last_message = off
|
||||||
|
relay.irc.backlog_tags = "irc_privmsg"
|
||||||
|
relay.irc.backlog_time_format = "[%H:%M] "
|
||||||
|
[port] (relay.conf)
|
||||||
|
relay.port.weechat = 9001 (default: 0)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
- `alias.cmd.norelay = "/buffer set localvar_set_relay hard-hide`
|
||||||
|
- Creates the `/norelay` command which is used to hide a buffer from being relayed to any relay client. This is mainly for stopping a buffer from alerting me on mobile.
|
||||||
|
- `relay.look.auto_open_buffer = off`
|
||||||
|
- Keeps weechat from opening a buffer with superfluous information every time a client connects or disconnects
|
||||||
|
- `relay.network.bind_address = "127.0.0.1"`
|
||||||
|
- Weechat will only accept relay connections from localhost. This means any relay client that wishes to connect will need to tunnel over ssh first, then connect to the relay. Luckily for me, weechat-android does this natively.
|
||||||
|
- `relay.port.weechat = 9001`
|
||||||
|
- The relay client will want to know this.
|
||||||
|
|
||||||
|
### Reference
|
||||||
|
|
||||||
|
- https://weechat.org/files/doc/stable/weechat_user.en.html#relay_plugin
|
||||||
|
|
||||||
|
----
|
||||||
|
## Workstation Client
|
||||||
|
|
||||||
|
By far, the most use of weechat will be from a workstation. With this setup, the only requirements of the client is ssh or mosh. I prefer mosh in this case because of it's reconnect capabilities, making it much less painful to keep a session running on a mobile workstation.
|
||||||
|
|
||||||
|
Also, the easiest way to launch this connection is to run literally `weechat`, so I set up a couple aliases for this in my `~/.bashrc` (found [here](https://git.thurstylark.com/vcsh/bashrc.git/tree/.bashrc)):
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- If you don't have weechat installed, connect to the existing tmux session through mosh
|
||||||
|
[ ! -s /usr/bin/weechat ]( ! -s /usr/bin/weechat .md) && alias weechat='mosh vps -- tmux attach -dt weechat'
|
||||||
|
- If you are thurstylark-vps, connect to the existing tmux session locally
|
||||||
|
[ "$HOSTNAME" = "thurstylark-vps" ]( "$HOSTNAME" = "thurstylark-vps" .md) && alias weechat='tmux attach -dt weechat'
|
||||||
|
```
|
||||||
|
|
||||||
|
This gets run when bash starts, so this allows me to use the same `~/.bashrc` on the client and the server. More details on the Bash page.
|
||||||
|
|
||||||
|
The only thing not noted is that if the client has weechat installed (to /usr/bin/weechat) and `$HOSTNAME` is not "thurstylark-vps", an alias for 'weechat' will not be created, and weechat will launch normally.
|
||||||
|
|
||||||
|
[Configuration](Configuration.md) that allows one to use an arbitrary string as a hostname for ssh/mosh can be found on the ssh config page.
|
|
@ -0,0 +1,124 @@
|
||||||
|
# Xinitrc
|
||||||
|
|
||||||
|
Source: https://git.thurstylark.com/vcsh/xinitrc.git
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Preamble
|
||||||
|
|
||||||
|
The first few lines of my Xinitrc are from `/etc/X11/xinit/xinitrc`. They pull in different X configuration, and also run any scripts from `/etc/X11/xinit/xinitrc.d/`.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Screen Locker
|
||||||
|
|
||||||
|
-WARNING*: [(in fact, you might want to consider even using X11 in the first place...)](http://blog.martin-graesslin.com/blog/2015/01/why-screen-lockers-on-x11-cannot-be-secure/|Screen lockers on X11 are absolutely not secure]]!! Do not use a screen locker if you require high security!! [[http://theinvisiblethings.blogspot.com/2011/04/linux-security-circus-on-gui-isolation.html)
|
||||||
|
|
||||||
|
I lock my desktop using a combination of `i3lock(1)` and `xautolock(1)` with some help from `xset(1)` to change dpms timeout before and after locking:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
screen_locker="xset dpms 0 0 10 dpms force off; i3lock --nofork -befc 000000; xset dpms 0 0 0"
|
||||||
|
locktime=30 * Default screen lock timeout in minutes
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
- Automatically lock after $locktime minutes using i3lock
|
||||||
|
xautolock -time $locktime -locker "$screen_locker" -detectsleep &
|
||||||
|
```
|
||||||
|
|
||||||
|
The locker is defined in `$screen_locker`, then used later along with `$locktime` to start `xautolock(1)`. When `$screen_locker` is run, the following happens:
|
||||||
|
|
||||||
|
1. DPMS timeout is set to 10 seconds
|
||||||
|
2. DPMS forces the display off now
|
||||||
|
3. i3lock is run with these options:
|
||||||
|
- `--nofork`: Don't fork to the background
|
||||||
|
- `-b`: Beep on incorrect password attempt
|
||||||
|
- `-e`: Ignore empty password
|
||||||
|
- `-f`: Show number of failed attempts, if any
|
||||||
|
- `-c 000000`: Background color should be `#000000`
|
||||||
|
4. When i3lock exits, DPMS timeout is set to 0 for never
|
||||||
|
|
||||||
|
Whenever I wish to lock the screen, I need only run `xautolock -locknow` making sure that `$DISPLAY` is set correctly. For example, my [i3](i3.md) config is set up to run that command for `Ctrl+Alt+l`.
|
||||||
|
|
||||||
|
Also note that the definition of `$screen_locker` and `$locktime` are separated from the invocation of `xautolock(1)` by all the host-specific configuration. This is to allow setting `$locktime` on a host-by-host basis. Given the first step of the locker is to use DPMS to turn the display off, this effectively sets the display sleep timeout to `$locktime`.
|
||||||
|
|
||||||
|
As far as power saving options go, `$screen_locker` _could_ be a little more general by using a variable for the last invocation of `xset(1)`, but I don't have a need for it.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Srandrd
|
||||||
|
|
||||||
|
All display output configuration, touchscreen configuration, or any other configuration that should change based on display connectivity takes place in the `srandrd(1)` configuration. In fact, `~/.xinitrc` will completely abort if srandrd isn't installed. This makes display layouts and touchscreen easier to maintain in the long run.
|
||||||
|
|
||||||
|
The "configuration" can be any executable file which will be run with the environment variable `$SRANDRD_ACTION` set to a string formatted as `<output> <connected|disconnected|unknown>`, where `<output>` is the name of the output according to `xrandr(1)`. I use a bash script for this purpose.
|
||||||
|
|
||||||
|
### Script Summary
|
||||||
|
|
||||||
|
This script is set up to be one monolithic "configuration" for multiple hosts by using a case statement that tests against `$(hostname)` before attempting to handle `$SRANDRD_ACTION`. If multiple configuration files become necessary at some point, it would be trivial to break out each host's configurations into their own files and do something similar to `source ~/.config/srandrd/$(hostname).conf`, but it's not necessary for the time being.
|
||||||
|
|
||||||
|
Once the hostname is determined, I begin by setting a few variables with host-specific information. Setting these variables before handling `$SRANDRD_ACTION` is beneficial for situations where a software or hardware change might change any one of these values, in which case, the information will only need to be updated in one place instead of several places throughout the script.
|
||||||
|
|
||||||
|
Finally, `$SRANDRD_ACTION` is handled with a case statement. This section of the script can be arbitrarily complicated, but for my simple usage, every output that needs to be handled needs both a connected and disconnected case defined. In the most complicated case, I do 3 things: Run `xrandr(1)` to configure outputs, configure the touchscreen with `xinput(1)`, and set PulseAudio's default sink with `pacmd(1)`.
|
||||||
|
|
||||||
|
### Touchscreen Configuration
|
||||||
|
|
||||||
|
When using a touchscreen with multiple monitors, it is possible that the touchscreen will be mapped to cover the entire canvas instead of only the display to which it is attached. This results in situations where touch events on one side of the display will be close to accurate, but touch events on the other side of the display begin to manipulate the cursor on the 2nd display.
|
||||||
|
|
||||||
|
This is fairly easy to rectify using `xinput --map-to-output <device id> <output name>` where `<device id>` is the id number of the touchscreen as reported by `xinput list`, and `<output name>` is the xrandr name of the output you wish to map the touchscreen to.
|
||||||
|
|
||||||
|
This may seem easy enough to script by finding the device id once, then adding an appropriate line in `~/.xinitrc`, but the device id is not static, and may change between boots.
|
||||||
|
|
||||||
|
For this reason, it is more appropriate to match against an attribute of the device that will not change. In the case of `xinput(1)`, the best option for this situation is the device name. The device id can easily be found by running `xinput list --id-only <device name>`. This can easily be strung together with a subshell to do everything on one line. For instance, if you wish to map a device named `ELAN Touchscreen` to an output named `eDP-1`, the resulting line might look like the following:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
xinput --map-to-output $(xinput list --id-only "ELAN Touchscreen") eDP-1
|
||||||
|
```
|
||||||
|
|
||||||
|
This command must be run after every time the display configuration changes, so it is possible that the command will need to exist several times in the `srandrd(1)` configuration. Since the only unique pieces of information between hosts will be the device name and the output name, it is easier to use a function instead of duplicating the same line over and over:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
maptouchscreen() {
|
||||||
|
- maptouchscreen <name> <output>
|
||||||
|
local name="$1" * <name> should be a full name from the output of `xinput list`
|
||||||
|
local output="$2" * <output> should be an xrandr output name
|
||||||
|
xinput --map-to-output $(xinput list --id-only "$name") "$output"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows you to replace any instance of the full `xinput(1)` command with `maptouchscreen <device name> <output>`.
|
||||||
|
|
||||||
|
-Note:* If there are spaces in the device name, bash will glob the crap out of it, so be sure to double quote the device name when calling `maptouchscreen()`.
|
||||||
|
|
||||||
|
### PulseAudio Default Sink
|
||||||
|
|
||||||
|
I want the default PulseAudio sink to change to HDMI when HDMI is plugged in, and back to analog when disconnected.
|
||||||
|
|
||||||
|
Changing the default sink in pulse is as easy as running `pacmd set-default-sink <sink id>` where `<sink id>` is the id of the desired sink. Unfortunately, this is another situation where the id might change unexpectedly. We also don't have an easy interface to determine the id number from a name like we did with `xinput(1)`, so we're forced to parse the output of `pactl list sinks short` like so:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
pacmd set-default-sink $(pactl list sinks short | grep "hdmi" | grep -o "^\S\+")
|
||||||
|
```
|
||||||
|
|
||||||
|
This command lists all sinks in short form, then greps for a line containing "hdmi", uses grep to only print the first character (the sink id), then sets the default sink with `pacmd(1)`. Since this will also need to be run any time the display configuration changes, a function is, again, appropriate:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
setpasink() {
|
||||||
|
- setpasink <name>
|
||||||
|
- Find a unique string in the output of `pacmd list short` to use for <name>
|
||||||
|
pacmd set-default-sink $(pactl list sinks short | grep "$1" | grep -o "^\S\+")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows you to change the default PulseAudio sink with `setpasink <name>` where `<name>` is any arbitrary string that is unique to the line that corresponds to the desired sink in the output of `pactl list sinks short`.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## NumLock
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## ssh-agent
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
# Am I Faking Being Trans?
|
||||||
|
|
||||||
|
This began life as a reply to someone on /r/questioning, but I later came to realize that I was actually writing to myself.
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
(paraphrasing to anonymize)
|
||||||
|
|
||||||
|
OP expressed that they had recently begun feeling like he/him didn't quite fit, and had started talking to their non-binary friends about their feelings. Unfortunately, OP received some pushback from those friends because, they had felt NB all their life, and the process of discovery for them was mainly focussed on finding the language to express as much, so these friends began assuming that OP was faking it.
|
||||||
|
|
||||||
|
OP's main question was: Is it possible that I'm just faking how I feel? That they're right and I'm just making it up in my mind to fit in with my friends?
|
||||||
|
|
||||||
|
## Response
|
||||||
|
|
||||||
|
Labels aren't a template for behavior. They're a tool used to communicate your particular flavor of awesome to others. You are you, pick a label that fits (or don't, whatever).
|
||||||
|
|
||||||
|
There are 7 billion unique people on this earth, and we haven't developed mind-reading tech yet, so that leaves *you* as the only person who is physically capable of living your life, feeling your emotions, and experiencing your gender. Nobody else knows exactly what's going on in your head, and the only way we can learn is if you tell us.
|
||||||
|
|
||||||
|
That doesn't always happen perfectly, though. Sometimes the right words don't exist, sometimes the words come out wrong, sometimes both of those go exactly right, and the other party ends up misinterpreting what was said... This can affect what others understand about what you're trying to communicate, but none of that changes this one simple fact:
|
||||||
|
|
||||||
|
### *You* are the ultimate source of information about *yourself*
|
||||||
|
|
||||||
|
So, are you cis? How the fuck should I know? I don't live your life. You're cis if you say so. You're bi if you say so. You are who you say you are, because nobody else has a better source of information about you than you do.
|
||||||
|
|
||||||
|
Put another way: What if you're faking being *cis?* What if you were never cis from the get-go, but you've been "faking it" as your assigned gender for your whole life because that's all that you've been allowed to think until now? What if this means that, since you have no experience with a label that accurately reflects your gender identity (internal), you therefore don't know what it's like to *not* fake your gender expression (external)? What if it feels like or sounds like "faking it" because you've been faking an *incorrect* gender this whole time, and simply don't know what it feels like to truly identify with your label because it was given to you at birth based on your genitals instead of you choosing your label based on how accurately it reflects your reality?
|
||||||
|
|
||||||
|
### Change is life
|
||||||
|
|
||||||
|
Additionally: Human nature is to change, and neither sexuality or gender are exempt from that by any means. Knowing for certain that one label fits you for any amount of time does not mean that you're stuck with it until you die. Changing your label is just as valid as changing your haircut or your clothes. Both of these are also external expressions of internal taste in style, why would the rules for your taste in romance or sex be any different?
|
||||||
|
|
||||||
|
If your gender changes, and you decide to change your labels to match, that's it. Any resistance you receive for communicating this information to others is laughably pointless. What are they gonna do, try to *persuade* your experience into compliance??
|
||||||
|
|
||||||
|
### Communicating your truth
|
||||||
|
|
||||||
|
Remember, You aren't responsible for how others react to information that you provide. You are simply putting it out there, and any reaction to that news is ultimately a reflection of *their* thoughts and emotions through the lens of *their* experience and bias. Your life and experience isn't affected by whether they choose to respect you by accepting information from the primary source (you) as truth, or if they choose to live in their own reality by denying it. You continue to be you, they continue to be them, and the planet continues to spin.
|
||||||
|
|
||||||
|
I realize that you may not be in a place to directly confront your friends about how they discuss sexuality and gender, but I would encourage you to push back on the idea that you're "faking" something. You are welcome to accept others' perspective, but *they* are as much of an authority on *your* gender as *you* are on *theirs.* Just because they know what it's like to experience *their* gender doesn't mean that they know what it's like to experience *your* gender.
|
||||||
|
|
||||||
|
The short version of this story is this: Your friends have shared information about their experience that they expect *you* to respect, but they did not to afford *you* the same respect when you decided to express similar information. That's rude and inconsiderate, and it's perfectly appropriate for you to ~~ask~~ ~~expect~~ *demand* them to respect your gender expression (however fluid or unresolved it might be), just the same as *they* have asked of *you*.
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Should I Come Out While Still Questioning?
|
||||||
|
|
||||||
|
This began life as a reply to someone on /r/questioning, but decided to archive it for myself.
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
(Paraphrasing to anonymize)
|
||||||
|
|
||||||
|
OP is female, and 17 at the time of writing. She had been questioning her sexuality for a while, has privately used a few different labels along the way,but still remained kind of confused about her identity. She had planned on coming out to her family once sure of her labels, but she's slowly coming to the realization that this might take some many years to fully flesh out. She wants to be open about her sexuality to friends and family, but even though they are generally supportive of the LGBTQ+ community, she feels it may still be complicated to explain certain concepts to some individuals.
|
||||||
|
|
||||||
|
OP's main question: "Is it a possibility to come out although I'm not sure of my labels yet? At the moment, I would most likely come out as simply "not heterosexual" and questioning. Also, since I'm fairly nervous about this, would it be ok to do this in writing, or should I only do this face-to-face? Should I wait until I've stopped questioning?"
|
||||||
|
|
||||||
|
## Response
|
||||||
|
|
||||||
|
IMO, identifying as questioning is such a power move.
|
||||||
|
|
||||||
|
"Good luck trying to shove me in one of your stupid boxes while even *I* don't know what the hell is going on in here!"
|
||||||
|
|
||||||
|
Labels can be tricky when the landscape seems to keep shifting like this, but I have two main ideas on this front:
|
||||||
|
|
||||||
|
### 1. On Adolescence
|
||||||
|
|
||||||
|
Teen years suck in countless ways, but they also come with a neat perk: ***Nobody expects you to have your shit together yet.*** Those younger than you will look up to you by default, those older than you have been through it and understand, and your peers are busy dealing with their own shit. You have the benefit of a few years of life with bumpers where you're ~~allowed~~ *expected* to figure out who you are, often via trial-and-error.
|
||||||
|
|
||||||
|
Salty adults can complain all they want about a teenager going through a "phase," but we only call it that because when we try to remember our *own* teenage years, it reminds us of all the ways that our teenage selves needed improvement in order to become who we are today. It's human nature to change and adapt, and teen/early adult years are often one's first and most substantial opportunity to make those changes based on *internal* motivation as opposed to *external* motivation like a parent, guardian, teacher, etc.
|
||||||
|
|
||||||
|
Guess what: When a human with little life experience and a newly-discovered personal agency is given the opportunity to make changes to themselves, they make uninformed decisions. Every single adult on this planet has made a bad decision in their teenage years, and learned from it. C'est la vie. The important part of this process is that when we make a misstep like this, we come out of it with lessons about what not to do next time. This is how adults are forged from the pressure-cooker of puberty, and we all go through it, whether we want to acknowledge that reality or not.
|
||||||
|
|
||||||
|
The only reason that adults label this as a "phase" is because when adults cast their mind back to their own lessons, they come to the incorrect conclusion that they *shouldn't have made that decision in the first place.* This makes a little sense when considering that this conclusion *is* the lesson they took from the experience, but how else were they to learn that lesson if not for experience? Life doesn't come with a manual or textbook to learn from, so how else are teenagers supposed to figure out how they want to dress or who they want to hang out with, or what they want to do with their life??
|
||||||
|
|
||||||
|
We *all* learn via experience during puberty, and your parents are no exception.
|
||||||
|
|
||||||
|
=== 2. On Labels and Questioning ===
|
||||||
|
|
||||||
|
-A label is not a template for behavior. It's a tool used to communicate you particular brand of awesome to others.* You are you, pick a label that fits. (or don't, whatever)
|
||||||
|
|
||||||
|
This isn't to say that labels are unimportant, though. At the very least labels provide a useful shorthand for things that are complicated or abstract (see: bisexuality vs pansexuality), so there's definitely an argument for their practicality. The point is that *your you-ness* should inform your label choice, and not the other way around.
|
||||||
|
|
||||||
|
This is why I think identifying as questioning is so cool. You can't get any more honest than openly admitting that you don't know shit and are still figuring it out :D
|
||||||
|
|
||||||
|
Alright, out of my soliloquy, and back to your thing :P
|
||||||
|
|
||||||
|
### Communicating Your Truth
|
||||||
|
|
||||||
|
Is it a possibility to come out although I am not sure of my labels yet?
|
||||||
|
|
||||||
|
As each person on earth is wholely unique, I would argue that there's currently around 7 billion different possible sexualities out there. Who you are, who you like, and the reasoning/motivation for any of these things are fully unique to you alone, which means that you happen to be *literally the only human on the face of the planet* with enough information to determine what label fits you best.
|
||||||
|
|
||||||
|
This goes both ways, too. You are the only one who can determine which labels *do* fit, but the same goes for labels that *don't* fit. If heterosexuality no longer fits you, that conclusion is equally entirely valid.
|
||||||
|
|
||||||
|
On that same coin, choosing to use no labels is just as valid, and so is picking a label but choosing to keep it private.
|
||||||
|
|
||||||
|
should I wait until I stopped questioning?
|
||||||
|
|
||||||
|
No. All humans change, and sexuality is not exempt. If you're feeling strongly about letting people know your labels, then that's a good enough reason in itself. If your attraction happens to change later on, that change is also valid, as is your choice of new labels
|
||||||
|
|
||||||
|
do you think that I should use a letter to come out?
|
||||||
|
|
||||||
|
IMO, whether you end up using it or not, write the letter anyways. When I have tangled, shifting, or abstract thoughts that don't lend themselves to easy explanation, I find that the process of taking hold of them and translating them into words helps *my own* understanding. Even if nobody reads what I write, I come away with a better idea of what I'm feeling, which parts are the most important to communicate, and how they can be worded.
|
||||||
|
|
||||||
|
If you end up with a letter you're happy with, I think it's a great way to deal with the nerves involved with face-to-face convos. A letter involves a great deal more time and effort than just words on a page, and I think your parents will definitely understand that :)
|
||||||
|
|
||||||
|
Above all else, remember that the way others respond to this information is ultimately filtered through *their* emotions, and is more of a reflection of *their* perspective. Whether the result is positive or negative, you are simply putting the information out there (as is your prerogative), and it is *their* responsibility to deal with it. There can be wider practical concerns (cases where parental withdrawal is likely, for instance), but on the general social front: you are not responsible for how other people handle the information you provide.
|
||||||
|
|
||||||
|
However you choose to come out, I wish you all the best :)
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Contact Info
|
||||||
|
|
||||||
|
| Service | |
|
||||||
|
|----------------|-----------------------|
|
||||||
|
| Email | thurstylark@gmail.com |
|
||||||
|
| IRC (Freenode) | thurstylark |
|
||||||
|
| Twitter | @thurstylark |
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Do People Actually Desire Physical Affection?
|
||||||
|
|
||||||
|
This began life as a reply to someone on /r/questioning, but decided to archive it for myself.
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
(paraphrasing to anonymize)
|
||||||
|
|
||||||
|
OP has just started their first romantic relationship with someone they have quite a bit in common with. OP enjoys spending time with their partner, but didn't feel anything special during their first kiss. OP would be fine with kissing them again if requested, but it's not something they felt that they would specifically desire or seek out.
|
||||||
|
|
||||||
|
OP recognizes that they generally don't quite understand romance or attraction, so being in a relationship is somewhat difficult already, but in an effort to understand their partner better, they wanted other perspectives.
|
||||||
|
|
||||||
|
OP's main question: "Do 'regular' people actually desire physical affection? Like, do they look at their partner and feel a physical urge to touch/kiss them, or does it originate in some concious 'I want to touch/kiss them' thought that then begets an action?"
|
||||||
|
|
||||||
|
## Response
|
||||||
|
|
||||||
|
Do people actually desire physical affection?
|
||||||
|
|
||||||
|
For me, 'yes' isn't strong enough.
|
||||||
|
|
||||||
|
I don't just desire physical affection, I *need it*. In fact, I sometimes don't feel as if my feelings are properly expressed *without* employing physical affection. Past that, I can get irritable, depressed, and lonely during prolonged periods without it. It affects my mood on a deep level, and it's something I need in order to function properly. I don't think I could stay in a monogamous relationship that lacked physical affection.
|
||||||
|
|
||||||
|
### "Regular" people
|
||||||
|
|
||||||
|
BUT, if that's something you don't desire or need, then that isn't weird, it's just a part of your particular flavor of awesome. "Normal" or "regular" people aren't a thing, and I discourage anyone from trying to compare themselves to a baseline human configuration of wants and needs. Evolution-based life doesn't operate like that. Evolution is dependent on randomness, uniqueness, and mutations, then it keeps the useful ones around over time.
|
||||||
|
|
||||||
|
To this end, I encourage you to ask yourself: Where your idea of "normal" comes from? From your parents? Peers? Media? A combination?
|
||||||
|
|
||||||
|
Also, what is to be gained by people who reinforce this notion of "normal"? Do they earn money from it? Do they feel accepted or powerful by being (or claiming to be) a part of the "normal" group? Do they use it to otherize those who don't fit in the "normalcy" they so enjoy?
|
||||||
|
|
||||||
|
There's deep introspection down that path, so here's a lighter take: I don't have to understand you to respect you, but more importantly, *I don't have to understand you for you to deserve my respect.* You don't deserve respect because you fit in my definition of "respectable person", you deserve my respect because you are a human.
|
||||||
|
|
||||||
|
For example: I don't understand what it is to live in an existence where physical affection does nothing for me, but that's ok. My inability to empathize fully with your situation is not a failing on my part, and especially not on yours. I have to accept that yours is a perspective that I will never fully grasp, but also that ***you are still valid***. If someone is unable to *respect* you, that's a them thing, not a you thing.
|
||||||
|
|
||||||
|
### The nature of relationships
|
||||||
|
|
||||||
|
Above all, don't feel like you have to push yourself to do things that you're not comfortable with. In our current society, there is definitely a tendency to push for obtaining romantic relationships and putting them on an ever-escalating path towards monogamous marriage (most commonly referred to as the [Relationship Escalator](https://medium.com/@agahran/why-step-off-the-relationship-escalator-d5b033b1ccb2)).
|
||||||
|
|
||||||
|
There's a societal expectation that you date to marry forever and that's the best path for everyone, but it doesn't have to be that way. You are a unique person, your partner is a unique person, but also, the relationship between you and your partner is a unique entity of its own. Just as you don't have any responsibility to look or act or be a certain way, your relationships with others don't have to look a certain way.
|
||||||
|
|
||||||
|
All that to say: If physical affection is something that you don't want or need to be included in your relationship with another person, then by all means, you shouldn't feel obligated to shoehorn it in. Human relationships are best when they're mutually beneficial, and beneficial relationships tend to be stifled when one forces themselves to be someone they're not for the sake of the relationship.
|
||||||
|
|
||||||
|
That is my perspective, but don't take my word for everything. Try things out, figure out what works best for *you*. I greatly appreciate that you specifically expressed your desire for other perspectives. That is a valuable and [seemingly] rare trait, and you should be proud of that. Keep following that curiosity and openness.
|
||||||
|
|
||||||
|
If you would like more perspective, I would take a look at /r/asexuality, /r/demisexuality, and any other subs that may interest you from their sidebars and wikis. Follow your nose, ask questions, and read about the experience of others.
|
||||||
|
|
||||||
|
### Learning from the Polyamorous community
|
||||||
|
|
||||||
|
Also, while I am not directly recommending polyamory for your situation, a lot of understanding can be gained from that community about the nature of relationships. It was certainly a catalyst for shifting my own perspectives when it came to relationships. /r/polyamory, and the resources documented there is a good place to start. Decide whether it's for you or not, but I would recommend checking it out, if only in the interest of gaining new outside perspectives.
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Does Experimenting Make You Any Less Straight?
|
||||||
|
|
||||||
|
## No.
|
||||||
|
|
||||||
|
End of story. Full stop. Thanks for playing!
|
||||||
|
|
||||||
|
### Wait, Really?
|
||||||
|
|
||||||
|
Yes, really.
|
||||||
|
|
||||||
|
-You* are the only one who can define your sexuality. Sometimes people just know, sometimes they have to try things out before they are sure. Both are valid methods, and their results are genuine. Just because you experimented doesn't make the results any less valid. It doesn't matter if you kissed someone, or slept with someone and enjoyed it. If you say you're straight, then you're straight.
|
||||||
|
|
||||||
|
Labels aren't a template for behavior. Labels are a tool used to communicate your specific flavor of awesome to others. Likewise, behavior doesn't define your labels either. You do.
|
|
@ -0,0 +1,142 @@
|
||||||
|
# i3 Configuration
|
||||||
|
|
||||||
|
Source: https://git.thurstylark.com/vcsh/i3.git
|
||||||
|
|
||||||
|
## j4-make-config
|
||||||
|
|
||||||
|
The final config that actually is read by i3 is created using j4-make-config. This is done in the [Xinitrc](Xinitrc.md).
|
||||||
|
|
||||||
|
Simple usage:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
j4-make-config -a $(hostname).config archlinux
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates `~/.config/i3/config` by merging `~/.config/i3/config.base` and `~/.config/i3/$HOSTNAME.config`, and adds the 'archlinux' theme (included with j4-make-config). Optionally, you can add `-r` to tell i3 to reload the config after `j4-make-config` has completed.
|
||||||
|
|
||||||
|
Since using `j4-make-config`, the command for reloading the config has been changed to the following:
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- rebuild and reload the configuration file
|
||||||
|
bindsym $mod+Shift+c exec "j4-make-config -r -a $HOSTNAME.config archlinux"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reference
|
||||||
|
|
||||||
|
https://github.com/okraits/j4-make-config
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Media Keys
|
||||||
|
|
||||||
|
### Volume
|
||||||
|
|
||||||
|
This differs depending on if you're using ALSA or Pulseaudio. Thus, I include these instructions in the host-specific configs instead of the base config
|
||||||
|
|
||||||
|
ALSA:
|
||||||
|
```prettyprint
|
||||||
|
- Alsa Volume controls
|
||||||
|
bindsym XF86AudioRaiseVolume exec --no-startup-id amixer set Master 5%+ #increase sound volume
|
||||||
|
bindsym XF86AudioLowerVolume exec --no-startup-id amixer set Master 5%- #decrease sound volume
|
||||||
|
bindsym XF86AudioMute exec --no-startup-id amixer set Master toggle * mute sound
|
||||||
|
```
|
||||||
|
|
||||||
|
PulseAudio:
|
||||||
|
```prettyprint
|
||||||
|
- PulseAudio Volume controls
|
||||||
|
bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +5% #increase sound volume
|
||||||
|
bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -5% #decrease sound volume
|
||||||
|
bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle * mute sound
|
||||||
|
```
|
||||||
|
|
||||||
|
### Brightness
|
||||||
|
|
||||||
|
Brightness can be universal unless the utility for changing brightness differs between machines, so this snippit lives in the base config.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- Sreen brightness controls (requires light(1) from the AUR)
|
||||||
|
bindsym XF86MonBrightnessUp exec light -A 10 * increase screen brightness
|
||||||
|
bindsym XF86MonBrightnessDown exec light -U 10 * decrease screen brightness
|
||||||
|
```
|
||||||
|
|
||||||
|
### Playhead Control
|
||||||
|
|
||||||
|
This also is universal if the same tool is being used across hosts. I use `playerctl` mainly for its compatibility with Spotify's Linux client.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- Music Player controls
|
||||||
|
bindsym XF86AudioPlay exec --no-startup-id playerctl play-pause
|
||||||
|
bindsym XF86AudioNext exec --no-startup-id playerctl next
|
||||||
|
bindsym XF86AudioPrev exec --no-startup-id playerctl previous
|
||||||
|
```
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
https://wiki.archlinux.org/index.php/Extra_keyboard_keys
|
||||||
|
https://wiki.archlinux.org/index.php/Advanced_Linux_Sound_Architecture#Keyboard_volume_control
|
||||||
|
https://wiki.archlinux.org/index.php/PulseAudio#Keyboard_volume_control
|
||||||
|
https://wiki.archlinux.org/index.php/Backlight
|
||||||
|
https://wiki.archlinux.org/index.php/Spotify#Global_media_hotkeys
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Screen Locker
|
||||||
|
|
||||||
|
The screen locker is already set up in [Xinitrc](Xinitrc.md), so all that is necessary in the i3 config is to set the key combination that should spawn `xautolock -locknow`.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
- Ctrl+Alt+L to lock the screen
|
||||||
|
- Locker is set in ~/.xinitrc
|
||||||
|
bindsym Mod1+Control+l exec "xautolock -locknow"
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## i3Bar
|
||||||
|
|
||||||
|
This is another host-specific configuration, since `bar {}` has host-specific options apart from just the i3status config. It also includes the `j4-make-config` theme placeholder, since the theme definitions for the bar are separate from the main config.
|
||||||
|
|
||||||
|
I'll only demonstrate the most complicated of my current i3bar configuration. The rest can be viewed on the git repo.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
bar {
|
||||||
|
status_command i3status -c ~/.config/i3/status/$HOSTNAME.config
|
||||||
|
tray_output primary
|
||||||
|
output eDP1 * Which display should i3bar be bound to?
|
||||||
|
- $i3-theme-bar
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## i3Status
|
||||||
|
|
||||||
|
Most of the i3Status configuration is pretty standard, and is well documented by [the upstream docs](https://i3wm.org/i3status/manpage.html), so I'll only document the specific directives I crafted/modified myself
|
||||||
|
|
||||||
|
### Volume
|
||||||
|
|
||||||
|
This directive chooses ALSA by default, PulseAudio can be specified by adding `device = "pulse"` to the end of this directive.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
volume master {
|
||||||
|
format = "🔈%volume" * U+1F508
|
||||||
|
format_muted = "🔇" * U+1F507
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### SPVPN
|
||||||
|
|
||||||
|
This is a simple pidfile watcher used with one of my [VPN](VPN.md) configurations that gets started with systemd.
|
||||||
|
|
||||||
|
```prettyprint
|
||||||
|
run_watch SPVPN {
|
||||||
|
pidfile = "/var/run/spvpn@*.pid"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Nagbar
|
||||||
|
|
||||||
|
The nagbar is intensely annoying to encounter mainly because you can only use the mouse for interacting with it. It has been removed from my config altogether, and I plan on replacing it with dmenu in the future.
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Thurstylark's Knowledge Base
|
||||||
|
|
||||||
|
Half brain dump, half documentation practice.
|
||||||
|
|
||||||
|
### Projects
|
||||||
|
|
||||||
|
- [Vimwiki](Vimwiki.md) -- This very wiki, and how it's hosted
|
||||||
|
- [Cgit](Cgit.md) -- Configuration and hosting of https://git.thurstylark.com/
|
||||||
|
|
||||||
|
### Configuration/Dotfiles
|
||||||
|
|
||||||
|
- [Bashrc](Bashrc.md)
|
||||||
|
- [SSH](SSH.md)
|
||||||
|
- [Chrome Search Shortcuts](Chrome Search Shortcuts.md)
|
||||||
|
|
||||||
|
### Reference
|
||||||
|
|
||||||
|
- [Thurstylark-VPS](Thurstylark-VPS.md) -- All the services and little tweaks unique to my VPS
|
||||||
|
- [LetsEncrypt](LetsEncrypt.md) -- Usage of certbot, and relevant info for Apache configuration
|
||||||
|
- [Keyboard Mapping](Keyboard Mapping.md) -- Changing keyboard mapping at the hwdb level
|
||||||
|
- [Password-Store setup](Password-Store setup.md)
|
||||||
|
- [Formatting Cheat Sheet](Formatting Cheat Sheet.md)
|
||||||
|
|
||||||
|
### Misc.
|
||||||
|
|
||||||
|
- [Links Of Infamy](Links Of Infamy.md) -- A link dump of things I find truly amazing
|
||||||
|
- [Stupid Crestron Quirks](Stupid Crestron Quirks.md) -- Crestron can be stupid. Here are some examples
|
||||||
|
- [Ramblings](Ramblings.md) -- Non-technical musings, rants, or other such tomfoolery
|
||||||
|
- [Archive](Archive.md) -- Pages that aren't of much active use, but worth keeping around
|
||||||
|
|
||||||
|
|
||||||
|
### [Contact Info](contact)
|
|
@ -0,0 +1,48 @@
|
||||||
|
# VA GST Testing
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- [ ] Finish info gathering script
|
||||||
|
- [ ] Add test cases for 30FPS for existing cases
|
||||||
|
- [ ] Implement special groups
|
||||||
|
- [ ] Create parse script
|
||||||
|
- [ ] pyparsing
|
||||||
|
- [ ] general info
|
||||||
|
- [ ] data
|
||||||
|
- [ ] matplotlib
|
||||||
|
- [ ] Package va264enc for independent install
|
||||||
|
- [ ] Debian
|
||||||
|
- [ ] Arch
|
||||||
|
- [ ] Create netboot image
|
||||||
|
- [ ] Debian
|
||||||
|
- [ ] Arch
|
||||||
|
|
||||||
|
|
||||||
|
## Situations
|
||||||
|
|
||||||
|
- 1280x720 @30-@60 x1-x10
|
||||||
|
- 640x360 @30-@60 x1-x10
|
||||||
|
- Group 1
|
||||||
|
- 1280x720 @30 x1
|
||||||
|
- 1280x720 @30 x6
|
||||||
|
- Group 2
|
||||||
|
- 1280x720 @60 x1
|
||||||
|
- 1280x720 @60 x6
|
||||||
|
|
||||||
|
## Parser Output
|
||||||
|
|
||||||
|
- General info
|
||||||
|
- OS
|
||||||
|
- Kernel Version
|
||||||
|
- CPU generation
|
||||||
|
- Memory
|
||||||
|
- LibVA version
|
||||||
|
- VA-API version
|
||||||
|
- Gfx Driver version
|
||||||
|
- Render time per frame
|
||||||
|
- mean
|
||||||
|
- median
|
||||||
|
- mode
|
||||||
|
- max
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue