Dotfiles bankruptcy and rewrite! All hail, v2.0

This commit is contained in:
Henrik Lissner 2017-12-06 01:39:10 -05:00
parent d2da342f62
commit bd9e49aa09
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
640 changed files with 7650 additions and 6206 deletions

View file

@ -1,12 +0,0 @@
case $OSTYPE in
darwin*)
alias dkm='docker-machine'
alias dki='eval $(docker-machine env)'
;;
linux*)
alias docker='sudo docker'
;;
esac
alias dk='docker'
alias dkc='docker-compose'

View file

@ -1,12 +0,0 @@
#!/usr/bin/env bash
case $OSTYPE in
darwin*)
brew cask install virtualbox
brew install docker docker-compose docker-machine
;;
linux*)
if [[ -f /etc/arch-release ]]; then
sudo pacman --needed --noconfirm -S docker docker-compose
fi
esac

View file

@ -1,28 +0,0 @@
#!/usr/bin/env bash
# Pipes input to the weechat fifo (strips commented lines
# and prepends * to commands).
fifos=$(echo "$HOME/.weechat/weechat_fifo_*")
if [[ -z "$fifos" ]]; then
>&2 echo "No FIFOs. Is weechat running?"
exit 1
fi
rd() {
if [ -t 0 ]; then
cat $@
else
while read -r line; do
echo $line
done
fi | sed '/^ *\(#\|$\)/ d;s/^/*/g'
}
if [[ "$1" = "-d" ]]; then
shift
rd $@
else
rd $@ > $HOME/.weechat/weechat_fifo_*
fi

View file

@ -1,17 +0,0 @@
#!/usr/bin/env bash
case $OSTYPE in
darwin*)
brew install weechat
;;
linux*)
if [[ -d /etc/arch-release ]]; then
sudo pacman --needed --noconfirm -S weechat
elif [[ -d /etc/debian_version ]]; then
# TODO Untested
sudo apt-get install -y weechat
fi
esac
# NOTE: init.sh needs to be run separately, afterward
echo "Don't forget to run weechat/scripts/init.sh while weechat is open"

View file

@ -1,27 +0,0 @@
#!/usr/bin/env bash
if ! pgrep weechat >/dev/null; then
>&2 echo "Weechat isn't running, or fifo is off: /fifo enable"
exit 1
fi
if [[ -f ~/.private/config/irc.conf ]]; then
# ...otherwise, configure it!
CWD=$(cd $(dirname $0) && pwd -P)
wee "/secure passphrase $(pass irc/master)"
wee "/secure set username vnought"
wee "/secure set freenode $(pass irc/freenode.net | head -n1)"
wee "/secure set snoonet $(pass irc/snoonet.org | head -n1)"
wee "/secure set oftc $(pass irc/oftc.net | head -n1)"
wee "/secure set afternet $(pass irc/afternet.net | head -n1)"
wee "/secure set pushover_key $(pass api/pushover/key)"
wee "/secure set pushover_api $(pass api/pushover/api)"
wee "$CWD/../plugins.txt"
wee "$CWD/../settings.txt"
wee "$CWD/../servers.txt"
else
>&2 echo "Couldn't find secrets!"
exit 1
fi

12
.gitignore vendored
View file

@ -1,12 +0,0 @@
.enabled.d/*
*.log
*.pid
*.db
shell/+tmux/.tmux/plugins/
shell/+tmux/.tmuxifier/
shell/+mpd/.config/mpd/mpd.*
shell/+mpd/.config/mpd/mpdstate
+weechat/.weechat/*

105
README.md
View file

@ -1,69 +1,72 @@
[![MIT](https://img.shields.io/badge/license-MIT-green.svg?style=flat-square)](./LICENSE)
# Mein dotfiles
# Henrik's dotfiles
A tidy `$HOME` is a tidy mind.
<img src="http://i.giphy.com/ZHlGzvZb130nm.gif" align="right" />
![Oct-2017 Screenshot of Arch Linux](assets/screenshots/OCT2017.png)
Fuel for my madness. Designed for Arch Linux, MacOS, and various remotes I
frequent.
My dotfiles are organized into 2-level topics (e.g. `shell/zsh`), and strive for
minimum `$HOME` presence (adhering to XDG standards as much as possible).
It is organized into topics, some with their own READMEs. Check them out for
more targeted information. The `./bootstrap` script is used to deploy and update
them.
+ Arch Linux
+ wm: bspwm
+ shell: zsh
+ font: kakwafont
+ bar: polybar
## Bootstrap
## Quick start
`bootstrap` is my idempotent dotfile deployment script.
`bash <(curl -s https://raw.githubusercontent.com/hlissner/dotfiles/master/bootstrap.sh)`
e.g. `./bootstrap os/+arch shell/+{zsh,tmux} dev/+pyenv`
## Overview
```
Usage: bootstrap [-iuldypLSU] [topic1[ topic2[ ...]]]
```sh
# general
bin/ # global scripts
assets/ # wallpapers, sounds, screenshots, etc
Options:
-i Don't run install scripts
-u Don't run update scripts
-l Don't symlink dotfiles
-d Do a dry run (only output commands, no changes)
-y Overwrite conflicts (no prompts)
-p Prompt on file conflict (to overwrite)
-L Refresh links; the same as -ui
-S Server mode; only install the bare minimum
-U Update mode; run update scripts only
# categories
base/ # provisions my system with the bare essentials
dev/ # relevant to software development & programming in general
editor/ # configuration for my text editors
misc/ # for various apps & tools
shell/ # shell utilities, including zsh + bash
```
Here's a simplified break down of what it does:
## Dotfile management
```bash
# 1. Symlinks dotfiles to $HOME
ln -sfv $topic/.* ~/
ln -sfv $topic/.{config,local}/* ~/.{config,local}/
```
Usage: deploy [-acdlLit] [TOPIC...]
# 2. Track enabled topics in ~/.dotfiles/.enabled.d.
if [[ -e ~/.dotfiles/.enabled.d/$topic ]]; then
# 3a. If topic is already enabled, run update script
$topic/update
-a Target all enabled topics (ignores TOPIC args)
-c Afterwards, remove dead symlinks & empty dot-directories in $HOME.
Can be used alone.
-d Unlink and run `./_init clean` for topic(s)
-l Only relink topic(s) (implies -i)
-L List enabled topics
-i Inhibit install/update/clean init scripts
-t Do a test run; do not actually do anything
```
e.g.
+ `deploy base/arch shell/{zsh,tmux}`: enables base/arch, shell/zsh, & shell/tmux
+ `deploy -d shell/zsh`: disables shell/zsh & cleans up after it
+ `deploy -l shell/zsh`: refresh links for shell/zsh (inhibits init script)
Here's a breakdown of what the script does:
``` sh
cd $topic
if [[ -L $DOTFILES_DATA/${topic//\//.}.topic ]]; then
./_init update
else
# 3b. Otherwise, run install script
ln -sfv $topic ~/.dotfiles/.enabled.d/
$topic/install
ln -sfv $DOTFILES/$topic $DOTFILES_DATA/${topic//\//.}.topic
./_init install
./_init link
fi
```
## Clean
## Relevant projects
`clean` deletes broken symlinks in `$HOME`. If passed `-u`, it will remove all
symlinks in `.enabled.d/`, marking all topics as "disabled".
```
Usage: clean [-du]
Options:
-d Do a dry run (only output commands, no changes)
-u Uninstall all enabled topics
```
## Other Relevant Configs
+ [Vim](https://github.com/hlissner/.vim) (pulled in by the `editor/vim` topic)
+ [Emacs](https://github.com/hlissner/.emacs.d) (pulled in by the `editor/emacs` topic)
+ [doom-emacs](https://github.com/hlissner/doom-emacs) (pulled by `editor/emacs`)
+ [.vim](https://github.com/hlissner/.vim) (pulled by `editor/{neo,}vim`)

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 KiB

BIN
assets/sounds/ding.ogg Normal file

Binary file not shown.

BIN
assets/sounds/startup.ogg Normal file

Binary file not shown.

BIN
assets/sounds/updates.ogg Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 KiB

111
base/arch/Xresources Normal file
View file

@ -0,0 +1,111 @@
!! OCT-2017
!! Colors
#define blk #141517
#define bblk #969896
#define red #cc6666
#define bred #de935f
#define grn #b5bd68
#define bgrn #757d28
#define ylw #f0c674
#define bylw #f9a03f
#define blu #81a2be
#define bblu #2a8fed
#define mag #b294bb
#define bmag #bc77a8
#define cyn #8abeb7
#define bcyn #a3685a
#define wht #c5c8c6
#define bwht #ffffff
#define bg blk
#define fg wht
*.foreground: fg
*.background: bg
*.cursorColor: mag
*.color0: blk
*.color8: bblk
*.color1: red
*.color9: bred
*.color2: grn
*.color10: bgrn
*.color3: ylw
*.color11: bylw
*.color4: blu
*.color12: bblu
*.color5: mag
*.color13: bmag
*.color6: cyn
*.color14: bcyn
*.color7: wht
*.color15: bwht
! greys
*.color234: #1d2021
*.color235: #282828
*.color236: #32302f
*.color237: #3c3836
*.color239: #504945
*.color240: #544c49
*.color241: #665c54
!! Settings
! font rendering
Xft.hinting: 0
Xft.antialias: 1
Xft.autohint: 1
Xft.hintstyle: hintslight
Xft.lcdfilter: lcddefault
Xft.rgba: rgb
! cursor
Xcursor.theme: default
Xcursor.size: 32
! emacs
Emacs.toolBar: 0
Emacs.menuBar: 0
Emacs.verticalScrollBars: off
! urxvt
URxvt*.background: [96]blk
URxvt*.termName: xterm-256color
URxvt*.geometry: 81x20
URxvt*.buffered: true
URxvt*.cursorBlink: true
URxvt*.underlineColor: grey
URxvt*.depth: 32
URxvt*.borderless: 1
URxvt*.lineSpace: 1
URxvt*.letterSpace: 0
URxvt.iso14755: false
URxvt.iso14755_52: false
URxvt*.internalBorder: 14
URxvt*.scrollBar: false
URxvt*.saveLines: 5000
URxvt*.loginShell: false
URxvt.perl-ext-common: default,matcher
URxvt*.matcher.button: 1
URxvt*.matcher.rend.0: Uline Bold fg5
URxvt*.url-launcher: firefox
!URxvt.keysym.Shift-Control-C: perl:clipboard:copy
!URxvt.keysym.Shift-Control-V: perl:clipboard:paste
URxvt.clipboard.autocopy: true
URxvt*.font: xft:kakwa kakwafont:pixelsize=12
urxvt-scratch.font: xft:Misc Tamsyn:pixelsize=16
urxvt-fuzzy.font: xft:Misc Tamsyn:pixelsize=18
urxvt-fuzzy.boldFont: xft:Misc Tamsyn:pixelsize=18
urxvt-fuzzy.lineSpace: 4
urxvt-stream.lineSpace: 0
urxvt-stream.letterSpace: -1
urxvt-stream.font: xft:Fira Mono:pixelsize=17
! URxvt*.lineSpace: 0
! URxvt*.letterSpace: -1
! URxvt*.font: xft:Fira Mono:pixelsize=14
! urxvt-scratch.font: xft:Fira Mono:pixelsize=18
! urxvt-fuzzy.font: xft:Fira Mono:pixelsize=20

84
base/arch/_init Executable file
View file

@ -0,0 +1,84 @@
#!/usr/bin/env zsh
source ${0:A:h}/../../deploy
install() {
if ! nc -z 8.8.8.8 53 >/dev/null 2>&1; then
>&2 echo "No internet connection"
return 1
elif ! sudo pacman -Syu --noconfirm; then
>&2 echo "Could not update pacman"
return 2
fi
# Core essentials
sudo pacman --needed --noconfirm -S wget git curl tree rsync dnsutils
# Set up pacaur (AUR helper)
if ! _is_callable pacaur; then
TEMP="$(mktemp -d)"
pushd $TEMP
for pkg in cower pacaur; do
if [[ ! "$(pacman -Qs $pkg)" ]]; then
curl -o PKGBUILD https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=$pkg && \
makepkg PKGBUILD --needed --noconfirm --skippgpcheck -sri
fi
done
popd
rm -rf $TEMP
if ! _is_callable pacaur; then
>&2 echo "Pacaur was not successfully installed"
return 3
fi
fi
pacaur --needed --noconfirm --noedit -S \
wget curl ripgrep the_silver_searcher bc cronie youtube-dl \
xorg-server xorg-xinit xorg-xlsfonts xorg-xfd xdotool \
lightdm lightdm-mini-greeter \
bspwm sxhkd compton dunst xcb-proto polybar libnotify \
rvxt-unicode rvxt-unicode-terminfo \
slop feh maim ffmpeg zbar \
keybase-bin pass pass-otp \
neofetch glances inxi dfc \
ttf-fira-{mono,sans} ttf-font-awesome tamsym-font siji-git \
adwaita-icon-theme adwaita-slim-gtk-theme
# install crontab
sudo systemctl enable cronie
crontab ./crontab
# raise inotify limit
sudo tee -a /etc/sysctl.d/99-sysctl.conf <<<"fs.inotify.max_user_watches=524288"
# set up lightdm + minigreeter
sudo systemctl enable lightdm
sudo sed -i \
-e "s@^#?\(greeter-session=\).+@\1lightdm-mini-greeter@" \
-e "s@^#?\(user-session=\).+@\1bspwm@" \
/etc/lightdm/lightdm.conf
sudo sed -i \
-e "s@^\(user = \).+@\1${USER}@" \
-e "s@^\(show-password-label = \).+@\1false@" \
-e "s@^\(background-color = \).+@\1\"#000000\"@;" \
/etc/lightdm/lightdm-mini-greeter.conf
}
update() {
_is_callable pacaur && local pac=pacaur
${pac:-sudo pacman} -Syu --noconfirm
}
link() {
mklink xprofile ~/.xprofile
mklink config/* $XDG_CONFIG_HOME/
mklink fonts/* $XDG_DATA_HOME/fonts/
mklink -s pacman/*.hook /etc/pacman.d/hooks/
}
clean() {
rm -fv $XDG_DATA_HOME/fonts/*(@N)
sudo rm -fv /etc/pacman.d/hooks/*(@N)
}
init "$@"

22
base/arch/aliases.zsh Normal file
View file

@ -0,0 +1,22 @@
alias ls="${aliases[ls]:-ls} --color=auto --group-directories-first"
alias kb=keybase
alias sc=systemctl
alias ssc='sudo systemctl'
alias pac=pacaur
alias pacu='pacaur -Syu' # upgrade
alias pacc='pacaur -Sc' # clean pacman
alias paco='pacaur -Qtdq' # orphaned packages
alias reboot='sudo systemctl reboot'
alias shutdown='sudo systemctl poweroff'
# Clipboard pipes
if _is_callable xclip; then
alias y='xclip -selection clipboard -in'
alias p='xclip -selection clipboard -out'
elif _is_callable xsel; then
alias y='xsel -i --clipboard'
alias p='xsel -o --clipboard'
fi

37
base/arch/bin/bspc-focus Executable file
View file

@ -0,0 +1,37 @@
#!/usr/bin/env bash
# bspc-focus
# Jump to the next window in a direction. If -m is supplied, jump to the next
# monitor in that direction.
#
# Makes switching nodes more intuitive.
#
# Usage: bspc-focus [-m] (west|south|north|east)
# Example:
# + bspc-focus south
# + bspc-focus -m west
set -e
leap=
if [[ $1 == -m ]]; then
leap=1; shift
fi
dir=$1
case $dir in west|south|north|east) ;;
*) >&2 echo "Not a valid direction: $dir"
exit 1
esac
if [[ $leap ]]; then
# jump to monitor in direction
bspc monitor -f "$dir"
else
# jump to window in direction (unless at edge of last monitor)
if ! bspc node -f "$dir.local"; then
if [[ $(bspc query -M -m "$dir") ]]; then
bspc monitor -f "$dir"
fi
fi
fi

45
base/arch/bin/bspc-swap Executable file
View file

@ -0,0 +1,45 @@
#!/usr/bin/env bash
# bspc-swap
# swaps current window with the next window in a direction. If -m is set, moves
# window to the next monitor in that direction.
#
# Makes swapping nodes more intuitive.
#
# Usage: bspc-swap (west|south|north|east) (1|0)
# Example:
# + bspc-swap south
# + bspc-swap -m west
set -e
leap=
if [[ $1 == -m ]]; then
leap=1
dir=$2
else
dir=$1
fi
case $dir in west|south|north|east) ;;
*) >&2 echo "Not a valid direction: $dir"
exit 1
esac
if [[ $leap ]]; then
# move window to monitor in direction
old_id=$(bspc query -N -n focused)
if [[ $(bspc query -M -m "$dir") ]]; then
bspc node -m "$dir"
bspc node -f "$old_id"
fi
else
# move window in direction
old_id=$(bspc query -N -n focused)
if bspc node -s "$dir.local"; then
bspc node -f "$old_id"
elif [[ $(bspc query -M -m "$dir") ]]; then
bspc node -m "$dir"
bspc node -f "$old_id"
fi
fi

3
base/arch/bin/firefox Executable file
View file

@ -0,0 +1,3 @@
#!/bin/bash
# A shim to make firefox believe HOME is elsewhere
HOME="$XDG_DATA_HOME/mozilla" exec /usr/bin/firefox "$@"

View file

@ -0,0 +1,2 @@
#!/usr/bin/env bash
DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /usr/bin/notify-send "$@"

12
base/arch/bin/inject-xcolors Executable file
View file

@ -0,0 +1,12 @@
#!/usr/bin/env bash
xcolor() {
xrdb -query | awk "/^\*\.$1:/ {print \$2}" | sed -E 's/^[^#]+//'
}
COLOR_FG=$(xcolor foreground)
COLOR_BG=$(xcolor background)
for ((i=0;i<=15;i++)); do
eval "COLOR_$i=\$(xcolor color$i)"
done

View file

@ -1,5 +1,4 @@
#!/usr/bin/env bash
# A script run by devmon/udevil when a device is mounted or unmounted, notifying me.
DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus notify-send -a "devmon" "Device change" "$2"

View file

@ -7,4 +7,8 @@ dest=${1:-$(mktemp -t recXXX.webm)}
ffmpeg -f x11grab -s "$W"x"$H" -i :0.0+$X,$Y "$dest"
# vim:set ft=sh:
if [[ -f $dest ]]; then
mv $dest .
fi
# vim:set ft=sh shiftwidth=2:

22
base/arch/bin/rsl Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Run resilio (bittorrent sync) from $HOME if it isn't running. Otherwise, open
# its gui in the browser.
if command -v xdg-open >/dev/null; then
open=xdg-open
elif command -v open >/dev/null; then
open=open
elif [[ $BROWSER ]]; then
open=firefox
else
>&2 echo "No program to open urls with"
fi
if ! pgrep rslsync >/dev/null; then
pushd $HOME >/dev/null
rslsync &
popd >/dev/null
fi
[[ -t 0 ]] && $open http://localhost:8888/gui/

View file

@ -0,0 +1,4 @@
#!/usr/bin/env bash
xdotool search --onlyvisible --classname urxvt-fuzzy windowkill
xdotool search --classname urxvt-fuzzy windowmap \
|| urxvt -name urxvt-fuzzy -geometry 100x16 -e $SHELL -c fzf-apps

View file

@ -0,0 +1,29 @@
#!/usr/bin/env zsh
#
# Opens fzf-pass in a transient popup window and temporary tmux session,
# recreating this window if necessary.
#
# Get firefox's current url; requires "Hostname in title" plugin for firefox
win=$(xdotool getactivewindow)
if [[ $win ]]; then
winname=$(xdotool getwindowname $win)
if [[ $winname =~ " - Mozilla Firefox$" ]]; then
url=${winname% - Mozilla*}
url=${url##* - }
while (( ${#url//[^.]/} > 1 )); do
url=${url#*.}
done
fi
fi
# Present the popup
xdotool search --onlyvisible --classname urxvt-fuzzy windowkill
bspc monitor -f primary
urxvt -name urxvt-fuzzy \
-geometry 100x16 \
-e $SHELL \
-c "fzf-pass $@ $url"
[[ $win ]] && xdotool windowactivate $win

View file

@ -0,0 +1,18 @@
#!/usr/bin/env bash
SCRID=urxvt-scratch
focused=$(xdotool getactivewindow)
scratch=$(xdotool search --onlyvisible --classname $SCRID)
if [[ $scratch ]]; then
if [[ $focused == $scratch ]]; then
tmux kill-session -t scratch
else
xdotool windowactivate $scratch
fi
else
bspc monitor -f primary
urxvt -name $SCRID \
-geometry 100x26 \
-e bash \
-c 'tmux new-session -A -s scratch -n scratch'
fi

25
base/arch/bin/vol Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env bash
if (($# == 0)); then
data=$(amixer get Master)
vol=$(echo "$data" | sed -n 's/^.*\[\([0-9]\+\)%.*$/\1/p' | uniq)
state=$(echo "$data" | grep '\[on\]')
[[ $state ]] && echo $vol || echo 0
exit
fi
case $1 in
[0-9]*) amixer set Master $1 ;;
[+-]) amixer set Master 5%$1 ;;
*mute) amixer set Master $1 ;;
toggle) amixer set Master toggle ;;
*) >&2 echo "Invalid command"
exit 1
;;
esac
# community/xosd
if command -v osd_cat >/dev/null; then
killall -9 -q osd_cat &>/dev/null
osd_cat --font="10x20" --delay=2 --color=white --align=center --pos=bottom --barmode=percentage --percentage $($0) &
fi

View file

@ -0,0 +1,8 @@
#!/usr/bin/env zsh
export MONITOR=$(xrandr -q | grep 'primary' | cut -d' ' -f1)
bspc config -m $MONITOR window_gap 4
bspc config -m $MONITOR bottom_padding 158
bspc config -m $MONITOR top_padding 0
bspc config -m $MONITOR left_padding 0
bspc config -m $MONITOR right_padding 0

View file

@ -1,18 +1,27 @@
#!/usr/bin/bash
#!/usr/bin/env zsh
#
# Appearance
# Displays
#
declare -A COLOR
END=15
for ((i=0;i<=END;i++)); do
COLOR[$i]=$(xrdb -query | awk "/^\*\.color$i:/ {print \$2}")
export MONITOR=$(xrandr -q | grep 'primary' | cut -d' ' -f1)
export MONITORS=( $(xrandr -q | grep ' connected' | cut -d' ' -f1) )
MONITOR=${MONITOR:-${MONITORS[0]}}
# Multiple workspaces for main monitor, but only one for others
bspc monitor $MONITOR -d {1,2,3,4,5}
for mon in ${MONITORS[@]/${MONITOR}}; do
bspc monitor $mon -d $mon/1
done
bspc config normal_border_color "${COLOR[0]}"
bspc config active_border_color "${COLOR[0]}"
bspc config focused_border_color "${COLOR[4]}"
if ! pgrep polybar >/dev/null; then
$XDG_CONFIG_HOME/polybar/run.sh
fi
#
# Aesthetics
#
bspc config split_ratio 0.50
bspc config gapless_monocle true
@ -28,57 +37,33 @@ bspc config pointer_action3 resize_corner
bspc config remove_disabled_monitors false
bspc config remove_unplugged_monitors true
# bspc config normal_border_color "$COLOR_0"
# bspc config active_border_color "$COLOR_0"
# bspc config focused_border_color "$COLOR_0"
bspc config border_width 0
# bspc config window_gap 16
# bspc config top_padding 32
# bspc config bottom_padding 34
# bspc config left_padding 32
# bspc config right_padding 32
bspc config window_gap 1
bspc config window_gap 8
bspc config top_padding 0
bspc config bottom_padding 0
bspc config left_padding 0
bspc config right_padding 0
bspc config -m $MONITOR window_gap 22
bspc config -m $MONITOR bottom_padding 36
bspc config -m $MONITOR top_padding 0
bspc config -m $MONITOR left_padding 0
bspc config -m $MONITOR right_padding 0
#
# Displays
#
nmon=$(bspc query -M | wc -l)
primary=$(bspc query -M -m prmary)
host=$(hostname)
case $host in
triton*)
MONITOR=DVI-I-1
[[ $nmon > 1 ]] && bspc monitor HDMI-0 -d HDMI-0/1
[[ $nmon > 2 ]] && bspc monitor DVI-D-0 -d DVI-D-0/1
;;
proteus*)
MONITOR=LVDS-0
;;
halimede*)
MONITOR=DVI-I-1
[[ $nmon > 1 ]] && bspc monitor DVI-D-0 -d DVI-D-0/1
;;
esac
if [[ $MONITOR ]]; then
export MONITOR
bspc config -m $MONITOR top_padding 25
bspc monitor $MONITOR -d {1,2,3,4,5}
. ~/.config/polybar/run.sh
fi
#
# Rules
#
# Reset
bspc rule -r '*'
# Floating fixes
bspc rule -a Emacs:org* state=floating
bspc rule -a 'Emacs:org*' state=floating
bspc rule -a mplayer2 state=floating
bspc rule -a mpv state=floating center=on
bspc rule -a Vlc state=floating monitor=C center=on

View file

@ -1,8 +1,9 @@
backend = "xrender";
backend = "glx";
# backend = "xrender";
glx-no-stencil = true;
glx-copy-from-front = false;
glx-no-rebind-pixmap = true;
glx-swap-method = "undefined";
# glx-swap-method = "undefined";
# Set VSync method. VSync methods currently available:
# + none: No VSync
@ -18,7 +19,8 @@ glx-swap-method = "undefined";
# + opengl-mswc: Try to VSync with MESA_swap_control OpenGL extension. Basically the
# same as opengl-swc above, except the extension we use.
# (Note some VSync methods may not be enabled at compile time.)
vsync = "none";
vsync = "opengl-mswc";
# vsync = "none";
# Limit compton to repaint at most once every 1 / refresh_rate second to boost
# performance. This should not be used with --vsync drm/opengl/opengl-oml as they
@ -55,19 +57,20 @@ detect-client-leader = false;
#
########################################
shadow = false;
shadow = true;
no-dock-shadow = true;
no-dnd-shadow = true;
clear-shadow = true;
shadow-radius = 4;
shadow-offset-x = -3;
shadow-offset-y = -3;
shadow-opacity = 0.6;
shadow-offset-y = 0;
shadow-opacity = 0.15;
# shadow-red
# shadow-green
# shadow-blue
shadow-exclude = [
"n:e:Notification",
"class_i = 'Dunst'",
"class_i = 'presel_feedback'",
"g:e:Conky"
];
@ -83,13 +86,12 @@ shadow-ignore-shaped = true;
menu-opacity = 1;
active-opacity = 1;
inactive-opacity = 1.0;
inactive-opacity = 1;
# frame-opacity = 1.0;
inactive-dim = 0.15;
inactive-opacity-override = false;
opacity-rule = [
"80:class_g = 'Bspwm' && class_i = 'presel_feedback'",
"96:class_g = 'URxvt'"
"80:class_g = 'Bspwm' && class_i = 'presel_feedback'"
];
alpha-step = 0.06

View file

@ -1,40 +1,39 @@
[global]
alignment = left
allow_markup = yes
markup = full
bounce_freq = 0
browser = /usr/bin/firefox -new-tab
dmenu = /usr/bin/rofi -dmenu -p dunst:
follow = none
font = Fira Sans 12
format = "<b>%s</b>\n%b"
font = UW Ttyp0 10
# font = Misc Tamsyn 12
format = "%s\n%b"
# geometry [{width}]x{height}][+/-{x}+/-{y}]
geometry = "375x22-10+36"
geometry = "345x15-21+21"
history_length = 20
horizontal_padding = 20
horizontal_padding = 16
idle_threshold = 120
ignore_newline = no
indicate_hidden = yes
line_height = 0
monitor = 0
padding = 18
separator_color = frame
separator_height = 1
padding = 12
separator_color = "#18191b"
separator_height = 2
show_age_threshold = 60
show_indicators = yes
shrink = no
sort = yes
startup_notification = false
sticky_history = yes
transparency = 0
transparency = 1
word_wrap = yes
# Align icons left/right/off
icon_position = right
# Paths to default icons.
icon_folders = /usr/share/icons/hicolor/32x32/apps/:/usr/share/icons/Adwaita/32x32/actions/
[frame]
width = 4
color = "#98C379"
frame_width = 0
frame_color = "#131416"
[shortcuts]
context = ctrl+shift+period
@ -42,17 +41,17 @@
[urgency_low]
# IMPORTANT: colors have to be defined in quotation marks.
# Otherwise the "#" and following would be interpreted as a comment.
background = "#282c34"
foreground = "#bbc2cf"
timeout = 10
background = "#0a0b0c"
foreground = "#b5bd68"
timeout = 8
[urgency_normal]
background = "#282c34"
foreground = "#bbc2cf"
timeout = 20
background = "#b5bd68"
foreground = "#131416"
timeout = 14
[urgency_critical]
background = "#2B0000"
foreground = "#bbc2cf"
background = "#cc6666"
foreground = "#131416"
timeout = 0

View file

@ -0,0 +1,11 @@
[Filechooser Settings]
LocationMode=path-bar
ShowHidden=false
ShowSizeColumn=true
GeometryX=1200
GeometryY=0
GeometryWidth=1010
GeometryHeight=664
SortColumn=name
SortOrder=ascending
StartupMode=recent

View file

@ -0,0 +1,2 @@
include "/usr/share/themes/Adwaita-Slim-Dark/gtk-2.0/gtkrc"
# include "/usr/share/themes/Arc-Dark/gtk-2.0/gtkrc"

View file

@ -0,0 +1,2 @@
file:///home/hlissner
file:///home/hlissner/work

View file

@ -0,0 +1,4 @@
[Settings]
gtk-theme-name = Adwaita-Slim-Dark
gtk-icon-theme-name = Adwaita-Slim-Dark
gtk-application-prefer-dark-theme = true

View file

@ -0,0 +1,342 @@
;=====================================================
;
; To learn more about how to configure Polybar
; go to https://github.com/jaagr/polybar
;
; The README contains alot of information
;
;=====================================================
[colors]
bg = ${xrdb:background}
fg = ${xrdb:foreground}
black = ${xrdb:color0}
bblack = ${xrdb:color8}
red = ${xrdb:color1}
bred = ${xrdb:color9}
green = ${xrdb:color2}
bgreen = ${xrdb:color10}
yellow = ${xrdb:color3}
byellow = ${xrdb:color11}
blue = ${xrdb:color4}
bblue = ${xrdb:color12}
magenta = ${xrdb:color5}
bmagenta = ${xrdb:color13}
cyan = ${xrdb:color6}
bcyan = ${xrdb:color14}
white = ${xrdb:color7}
bwhite = ${xrdb:color15}
bg-alt = #0F1013
fg-alt = #25282a
icons = #555856
alert = ${colors.red}
[global/wm]
margin-top = 0
margin-bottom = 35
[bar/main]
monitor = ${env:MONITOR}
enable-ipc = true
wm-restack = bspwm
# REQUIRED to move the window with hideit.sh
override-redirect = true
background =
foreground = ${colors.fg}
width = 100%
height = 24
offset-x = 0
offset-y = 16
bottom = 1
overline-size = 0
overline-color = #f00
underline-size = 0
underline-color = #00f
border-bottom-size = 0
padding-left = 4
padding-right = 4
module-margin-left = 0
module-margin-right = 0
font-0 = "Misc Tamsyn:pixelsize=12;2"
font-1 = "Wuncon Siji:pixelsize=12;2"
font-2 = "siji:pixelsize=10;2"
modules-left = volume pad cpu memory pad pkg mail
modules-center = bspwm
modules-right = battery wlan app-rslsync app-redshift pad date
;tray-position = center
;tray-padding = 2
;tray-transparent = true
;tray-background = #0063ff
[module/bspwm]
type = internal/bspwm
pin-workspaces = true
enable-click = true
ws-icon-0 = 1;
ws-icon-1 = 2;
ws-icon-2 = 3;
ws-icon-3 = 4;
ws-icon-4 = 5;
ws-icon-default = x
format = <label-state> <label-mode>
label-padding = 1
label-focused = %icon%
label-focused-background = #33000000
label-focused-foreground = ${colors.green}
; label-focused-underline = ${colors.magenta}
; label-focused-foreground = ${xrdb:color2}
label-focused-padding = 1
label-occupied = %icon%
label-occupied-foreground = ${colors.icons}
label-occupied-padding = 1
; label-urgent = %icon%
label-urgent-foreground = ${colors.red}
; label-urgent-background = ${colors.alert}
label-urgent-padding = 1
label-empty = %icon%
label-empty-foreground = ${colors.fg-alt}
label-empty-padding = 1
[module/date]
type = internal/date
interval = 5
label = %date% %time%
date = %A, %h %d
date-alt = %Y-%m-%d
time = %I:%M %p
time-alt = %H:%M:%S
format-prefix = ""
format-prefix-padding = 1
; format-prefix-background = ${colors.bg-alt}
format-prefix-foreground = ${colors.icons}
; format-underline = ${xrdb:color4}
[module/xwindow]
type = internal/xwindow
label = %title:0:80:...%
label-padding-left = 2
; [module/mpd]
; type = internal/mpd
; host = /home/hlissner/.config/mpd/mpd.sock
;
; format-online = <label-song> <toggle>
; format-padding = 5
;
; label-song-maxlen = 45
; label-song-ellipsis = true
;
; icon-prev = 
; icon-seekb = 
; icon-stop = 
; icon-play = 
; icon-pause = 
; icon-next = 
; icon-seekf = 
;
; icon-random = 
; icon-repeat = 
;
; toggle-on-foreground = ${colors.fg}
; toggle-off-foreground = #66
[module/cpu]
type = internal/cpu
interval = 2
format = <bar-load>
format-prefix = ""
format-foreground = ${colors.icons}
; format-underline = #f90000
; label = %percentage%%
format-padding = 1
bar-load-indicator =
bar-load-width = 6
bar-load-foreground-0 = ${colors.green}
bar-load-foreground-1 = ${colors.green}
bar-load-foreground-2 = ${colors.yellow}
bar-load-foreground-3 = ${colors.red}
bar-load-foreground-4 = ${colors.red}
bar-load-fill = |
bar-load-empty = ¦
bar-load-empty-foreground = ${colors.fg-alt}
[module/memory]
type = internal/memory
interval = 3
format = <bar-used>
format-prefix = ""
format-prefix-foreground = ${colors.icons}
; format-underline = #4bffdc
; label = %percentage_used%%
format-padding-left = 1
; Only applies if <bar-used> is used
bar-used-indicator =
bar-used-width = 6
bar-used-foreground-0 = ${colors.green}
bar-used-foreground-1 = ${colors.green}
bar-used-foreground-2 = ${colors.yellow}
bar-used-foreground-3 = ${colors.red}
bar-used-foreground-4 = ${colors.red}
bar-used-fill = |
bar-used-empty = ¦
bar-used-empty-foreground = ${colors.fg-alt}
[module/wlan]
type = internal/network
interface = ${env:WLP:wlp3s0}
interval = 3.0
format-connected = <ramp-signal>
format-disconnected = !
format-disconnected-foreground = ${colors.red}
; label-connected =
; label-disconnected = !
; label-disconnected-foreground = ${colors.red}
ramp-signal-0 = 
ramp-signal-0-foreground = ${colors.yellow}
ramp-signal-1 = 
ramp-signal-1-foreground = ${colors.yellow}
ramp-signal-2 = 
ramp-signal-2-foreground = ${colors.yellow}
ramp-signal-3 = 
ramp-signal-3-foreground = ${colors.icons}
ramp-signal-4 = 
ramp-signal-4-foreground = ${colors.icons}
; [module/eth]
; type = internal/network
; interface = ${env:ETH:enp2s0}
; interval = 4.0
;
; ; format-connected-underline = #55aa55
; ; format-connected-prefix = " "
; format-connected-foreground-foreground = ${colors.fg-alt}
; label-connected = %local_ip%
;
; format-disconnected-underline = ${self.format-connected-underline}
; label-disconnected = %ifname% disconnected
; label-disconnected-foreground = ${colors.fg-alt}
[module/volume]
type = internal/volume
; format-volume = <label-volume> <bar-volume>
format-volume = <ramp-volume> <bar-volume>
; label-volume = " "
label-volume-foreground = ${colors.fg}
; format-muted-prefix = " "
format-muted-foreground = ${colors.red}
label-muted = 
bar-volume-width = 8
bar-volume-foreground-0 = ${colors.blue}
bar-volume-foreground-1 = ${colors.blue}
bar-volume-foreground-2 = ${colors.blue}
bar-volume-foreground-3 = ${colors.blue}
bar-volume-foreground-4 = ${colors.blue}
bar-volume-foreground-5 = ${colors.blue}
bar-volume-foreground-6 = ${colors.blue}
bar-volume-gradient = false
bar-volume-indicator = |
bar-volume-indicator-font = 2
bar-volume-indicator-foreground = #ff
bar-volume-fill = ─
bar-volume-fill-font = 2
bar-volume-empty = ─
bar-volume-empty-font = 2
bar-volume-empty-foreground = ${colors.fg-alt}
; Only applies if <ramp-volume> is used
ramp-volume-0 = 
ramp-volume-1 = 
ramp-volume-2 = 
[module/battery]
type = internal/battery
battery = BAT0
adapter = ADP1
full-at = 98
format-charging = <animation-charging> <label-charging>
format-charging-underline = #ffb52a
format-discharging = <ramp-capacity> <label-discharging>
format-discharging-underline = ${self.format-charging-underline}
format-full-prefix = " "
format-full-prefix-foreground = ${colors.fg-alt}
format-full-underline = ${self.format-charging-underline}
ramp-capacity-0 = 
ramp-capacity-1 = 
ramp-capacity-2 = 
ramp-capacity-foreground = ${colors.fg-alt}
animation-charging-0 = 
animation-charging-1 = 
animation-charging-2 = 
animation-charging-foreground = ${colors.fg-alt}
animation-charging-framerate = 750
;=====================================================
; Custom scripts
;=====================================================
[module/pad]
type = custom/text
content = " "
content-foreground = ${colors.fg-alt}
[module/pkg]
type = custom/ipc
hook-0 = ~/.config/polybar/modules/updates
initial = 1
click-left = polybar-msg -p %pid% hook pkg 1
format-padding = 1
[module/mail]
type = custom/ipc
hook-0 = ~/.config/polybar/modules/mail
initial = 1
click-left = polybar-msg -p %pid% hook mail 1
format-padding-right = 1
[module/app-redshift]
type = custom/script
exec = echo 1
exec-if = pgrep -x redshift
format = ""
format-foreground = ${colors.icons}
interval = 2
[module/app-rslsync]
type = custom/script
exec = echo 1
exec-if = pgrep -x rslsync
format = ""
format-foreground = ${colors.icons}
interval = 60
; vim:ft=dosini

View file

@ -2,8 +2,6 @@
# Specifying the icon(s) in the script
# This allows us to change its appearance conditionally
icon=""
pgrep -x redshift &> /dev/null
if [[ $? -eq 0 ]]; then
temp=$(redshift -p 2>/dev/null | grep temp | cut -d' ' -f3)

View file

@ -0,0 +1,92 @@
#!/usr/bin/env python3
import imaplib
import os
import sys
import socket
from subprocess import Popen
CONFIG_FILE = os.path.expanduser("~/.secrets/email")
CACHE_FILE = "/tmp/polybar-mail"
ICON = ""
try:
import gnupg
from pathlib import Path
except ImportError:
print("%{{F{}}}*".format("#555856", ICON))
sys.exit(1)
#
def internet_is_on():
try:
host = socket.gethostbyname("www.google.com")
socket.create_connection((host, 80), 2)
return True
except:
pass
return False
def unread_count(address, password):
imap = imaplib.IMAP4_SSL('imap.gmail.com', 993)
imap.login(address, password)
imap.select('INBOX')
status, resp = imap.search(None, 'UNSEEN')
imap.close()
imap.logout()
return len(resp[0].split())
def ding():
Popen(["{}/bin/ding".format(os.getenv("DOTFILES", os.expanduser("~/.dotfiles")))])
#
def main():
try:
if not internet_is_on():
raise IOError("Internet is off")
secrets = Path(CONFIG_FILE)
if not secrets.exists():
raise IOError("Can't find secrets")
gpg = gnupg.GPG()
gpgdata = gpg.decrypt(secrets.read_bytes())
if not gpgdata.ok:
raise IOError("Couldn't decrypt secrets")
accounts = [line.split(':') for line in gpgdata.data.decode('utf-8').strip().split('\n')]
last_total = 0
cache = Path(CACHE_FILE)
if cache.exists():
cache_text = cache.read_text()
last_total = int(cache.read_text())
total = 0
for addr, pwd in accounts:
total += unread_count(addr, pwd)
if total != last_total:
ding()
if total != 0:
print("%{{F{}}}{}{}".format("#f0c674", ICON, total))
else:
print("%{{F{}}}{}".format("#555856", ICON))
cache.write_text(str(total))
except IOError as e:
print("ERROR: {}".format(e), file=sys.stderr)
print("%{{F{}}}{}!".format("#cc6666", ICON))
sys.exit(1)
#
if __name__ == '__main__':
if sys.argv[1:]:
print("%{{F{}}}{}".format("#555856", ICON))
else:
main()

View file

@ -0,0 +1,22 @@
#!/usr/bin/env zsh
icon=""
if [[ $1 == "1" ]]; then
echo "%{F#555856}${icon}%{F-}"
exit
fi
pac=$(checkupdates | wc -l)
aur=$(cower -u | wc -l)
[[ -f /tmp/polybar-updates ]] && last=$(</tmp/polybar-updates)
check=$((pac + aur))
if [[ "$check" != "0" ]]; then
echo "%{F#b5bd68}${icon}$pac+$aur%{F-}"
if [[ $last != "$pac$aur" ]]; then
notify-send "$((pac+aur)) updates available"
aplay -N -q $DOTFILES_ASSETS/sounds/updates.ogg
echo "$pac$aur" >/tmp/polybar-updates
fi
else
echo "%{F#555856}${icon}%{F-}"
fi

11
base/arch/config/polybar/run.sh Executable file
View file

@ -0,0 +1,11 @@
#!/usr/bin/env zsh
killall -q polybar
while _is_running polybar; do sleep 1; done
source "${0:A:h}/../../bin/inject-xcolors"
pushd ~ >/dev/null
polybar main >>$XDG_DATA_HOME/polybar.log 2>&1 &
popd >/dev/null
echo "Polybar launched..."

View file

@ -0,0 +1,141 @@
#
# wm independent hotkeys
#
# terminal emulator
mod4 + ctrl + Return
urxvt
mod4 + ctrl + shift + Return
urxvt -name urxvt-stream
mod4 + grave
urxvt-scratch-window
mod4 + space
urxvt-app-launcher
mod4 + backslash
urxvt-pass-manager
mod4 + mod1 + backslash
firefox-current
# urxvt-pass-manager -r
# reload sxhkd
mod4 + ctrl + shift + Escape
ding; pkill -USR1 -x sxhkd
#
# Media keys
#
Print
maim -s ~/screenshots/$(date +%F-%T).png && notify-send "Screenshot saved"
mod4 + Print
maim ~/screenshots/$(date +%F-%T).png && notify-send "Fullscreen screenshot saved"
mod4 + shift + Print
maim -d 3 ~/screenshots/$(date +%F-%T).png && notify-send "Screenshot saved"
Pause
mpc -q toggle # play/pause music
mod4 + {Pause,XF86Eject}
zzz # sleep display
mod4 + shift + Pause
zzz -f # sleep computer
# Media Keys
XF86Audio{Play,Pause}
mpc -q toggle
XF86Audio{Prev,Next}
mpc -q {prev,next}
XF86Audio{LowerVolume,RaiseVolume}
vol {-,+}
XF86AudioMute
vol toggle
mod4 + {Down,Up}
vol {-,+}
mod4 + {Left,Right}
mpc {prev,next}
#
# bspwm hotkeys
#
# quit bspwm normally
mod4 + alt + Escape
bspc quit
# close and kill
mod4 + {_,shift + }q
bspc node -{c,k}
#
# state/flags
#
mod4 + {ctrl,shift + } f
{bspc desktop -l next,bspc node -t \~floating}
mod4 + shift + p
bspc node -t \~pseudo_tiled
# set the node flags
mod4 + ctrl + {x,y,z}
bspc node -g {locked,sticky,private}
#
# focus/swap
#
# focus/swap the node in the given direction
mod4 + {_,ctrl +}{h,j,k,l}
bspc-focus {_,-m }{west,south,north,east}
mod4 + shift + {_,ctrl +}{h,j,k,l}
bspc-swap {_,-m }{west,south,north,east}
# focus the node for the given path jump
mod4 + {p,b,comma,period}
bspc node -f @{parent,brother,first,second}
# focus monitor or send to the given desktop
mod4 + bracket{left,right}
bspc desktop -f focused#{prev,next}.local
mod4 + ctrl + {_,shift +}{1-9,0}
bspc {desktop -f,node -d} {1-9,10}
#
# preselect
#
# preselect the direction
mod4 + mod1 + ctrl + {h,j,k,l}
bspc node -p {west,south,north,east}
# preselect the ratio
mod4 + mod1 + ctrl + {1-9}
bspc node -o 0.{1-9}5
# cancel the preselection for the focused node
mod4 + mod1 + ctrl + space
bspc node -p cancel
# cancel the preselection for the focused desktop
#mod4 + alt + shift + space
# bspc query -N -d | xargs -I id -n 1 bspc node id -p cancel
# expand the tiled space in the given direction
#mod4 + alt + {h,j,k,l}
# bspc node {@west -r -,@south -r +,@north -r -,@east -r +}64
#
## contract the tiled space in the given direction
#mod4 + alt + ctrl + {h,j,k,l}
# bspc node {@east -r -,@north -r +,@south -r -,@west -r +}64
# move a floating window
#mod4 + alt + {Left,Down,Up,Right}
# xdo move {-x -,-y +,-y -,-x +}40
#mod4 + alt + ctrl + {Left,Down,Up,Right}
# xdo resize {-w -,-h -,-h -,-w -}40

View file

@ -9,9 +9,9 @@
# m hr d m w cmd
# 0 * * * * ...
# Lemonbar
# 0,30 * * * * DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus ~/.config/panel/panel-notify :updates
# */2 * * * * DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus ~/.config/panel/panel-notify :mail
# Polybar
0,30 * * * * polybar-msg hook pkg 1
0 * * * * polybar-msg hook pkg 1
*/5 * * * * polybar-msg hook mail 1
# Personal
0 * * * * DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus notify-send "It is $(date +\%H:\%M)"

14
base/arch/env.zsh Normal file
View file

@ -0,0 +1,14 @@
export GNUPGHOME="$XDG_CONFIG_HOME/gpg"
export GTK2_RC_FILES="${0:A:h}/config/gtk-2.0/gtkrc"
export TERMINFO="$XDG_CONFIG_HOME/terminfo"
export BROWSER=firefox
export URXVT_PERL_LIB="$XDG_CONFIG_HOME/urxvt"
_is_running ssh-agent || {
ssh-agent -s >"$XDG_RUNTIME_DIR/ssh-agent-env"
}
_is_running gpg-agent || {
gpg-agent --daemon >"$XDG_RUNTIME_DIR/gpg-agent-env"
}
_source "$XDG_RUNTIME_DIR/ssh-agent-env" >/dev/null
_source "$XDG_RUNTIME_DIR/gpg-agent-env" >/dev/null

View file

@ -0,0 +1,3 @@
2
kakwafont-12-b.pcf.gz -kakwa-kakwafont-medium-r-bold--12-120-72-72-c-60-iso8859-1
kakwafont-12-n.pcf.gz -kakwa-kakwafont-medium-r-normal--12-120-72-72-c-60-iso8859-1

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,16 @@
#!/usr/bin/env bash
if command -v aseprite >/dev/null; then
echo "Aseprite is already installed"
exit 1
fi
set -e
pacaur --needed --noconfirm --noedit -S ninja cmake libxcursor
rm -rf /tmp/aseprite
if git clone --recursive https://github.com/aseprite/aseprite /tmp/aseprite; then
mkdir /tmp/aseprite/build && cd /tmp/aseprite/build
cmake -DCMAKE_INSTALL_PREFIX=/usr -G Ninja ..
ninja aseprite
ninja install
fi

View file

@ -0,0 +1,10 @@
#!/usr/bin/env bash
if ! grep -e '^[multilib]' /etc/pacman.conf >/dev/null; then
echo "[multilib]\nInclude = /etc/pacman.d/mirrorlist" | \
sudo tee -a /etc/pacman.conf
sudo pacman -Sy
fi
sudo pacman --needed -S steam

View file

@ -0,0 +1,8 @@
#!/usr/bin/env zsh
sudo pacman --noconfirm --needed -S udevil devmon
sudo systemctl enable devmon@$USER
sudo systemctl start devmon@$USER
ARCH=$(cd "${0:A:h}/.." && pwd)
sudo sed -i "s@^# \(success_exec =\)@\1 $ARCH/bin/notify-mount@" /etc/udevil/udevil.conf

43
base/arch/xprofile Normal file
View file

@ -0,0 +1,43 @@
#!/bin/bash
DOTS=~/.dotfiles
source $DOTS/env
# A tidy $HOME is a tidy mind
export XAUTHORITY="$XDG_RUNTIME_DIR/Xauthority"
[[ -e ~/.Xauthority ]] && mv -f ~/.Xauthority "$XAUTHORITY"
#
ARCH=$DOTS/base/arch
[[ -f $ARCH/Xresources ]] && xrdb $ARCH/Xresources
[[ -f $ARCH/Xmodmap ]] && xmodmap $ARCH/Xmodmap
# set wallpaper
[[ -e ~/wallpaper ]] && feh --no-fehbg --image-bg black --bg-center ~/wallpaper
# Let me know
paplay $DOTFILES_ASSETS/sounds/startup.ogg &
# autostart programs
{
run() {
if _is_callable "$1" && ! _is_running "$1"; then
"$@"
fi
}
# essentials
run sxhkd & # keyboard daemon
run dunst & # notifications
# non-essentials
{
sleep 2
run mpd & # music server
run redshift & # screen temperature based on time-of-day
run rslsync & # resilio sync
run compton & # perdy effects + transparency
# If sxhkd isn't running by now, something is wrong
_is_running sxhkd || urxvt &
} &
} 2>&1 >$XDG_DATA_HOME/xsession-errors.log

35
base/macos/_init Executable file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env zsh
source ${0:A:h}/../../deploy
install() {
# Install homebrew
if ! _is_callable brew; then
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
fi
brew install \
wget curl tree coreutils bash \
the_silver_searcher ripgrep ffmpeg keybase \
neofetch youtube-dl
# pass-otp
brew install pass oath-toolkit
if _ensure_repo tadfisher/pass-otp /tmp/pass-otp; then
cd /tmp/pass-otp
make install PREFIX=/usr/local
fi
}
update() {
if _is_callable brew; then
brew update && brew upgrade && brew cleanup
else
echo-fail "homebrew not detected"
fi
}
# link() {}
# clean() {}
init "$@"

View file

@ -1,16 +1,14 @@
alias ls="gls --color=auto --group-directories-first"
alias date='gdate'
alias date=gdate
alias y='pbcopy'
alias p='pbpaste'
alias y=pbcopy
alias p=pbpaste
alias br='brew'
alias br=brew
alias bru='brew update && brew upgrade && brew cleanup'
alias brc='brew cask'
alias localip="ipconfig getifaddr en1"
# OS X has no `md5sum`, so use `md5` as a fallback
is-callable md5sum || alias md5sum="md5"
is-callable md5sum || alias md5sum="md5"
# OS X has no `sha1sum`, so use `shasum` as a fallback
is-callable sha1sum || alias sha1sum="shasum"

0
os/+macos/bin/timelapse → base/macos/bin/timelapse Executable file → Normal file
View file

View file

View file

@ -1,3 +1,4 @@
export GNUPGHOME="$XDG_CONFIG_HOME/gpg"
export BROWSER='open'
# export CC=/usr/bin/clang

View file

@ -3,10 +3,10 @@
# Converts a number from one base to another. DEST_RADIX is optional and
# defaults to 10.
#
# Usage: base [SRC_RADIX] [NUMBER] [DEST_RADIX]
# Usage: base SRC_RADIX NUMBER DEST_RADIX
# Examples:
# + base 2 110 #=> 6
# + base 2 110 10 #=> 6
# + base 16 FF #=> 6
# + base 2 110 #=> 6 (110_2 => 6_10)
# + base 10 9 8 #=> 11 (9_10 => 11_8)
# + base 16 FF #=> 255 (FF_16 => 255_10)
bc <<< "obase=${3:-10};ibase=$1;$2"

View file

23
bin/colors Executable file
View file

@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Prints a bunch of color codes to the terminal to demonstrate what's available.
# Each line is the color code of one forground color, out of 17 (default + 16
# escapes), followed by a test use of that color on all nine background colors
# (default + 8 escapes).
T=niX # The test text
echo -e "\n 40m 41m 42m 43m\
44m 45m 46m 47m";
for FGs in ' m' ' 1m' ' 30m' '1;30m' ' 31m' '1;31m' ' 32m' \
'1;32m' ' 33m' '1;33m' ' 34m' '1;34m' ' 35m' '1;35m' \
' 36m' '1;36m' ' 37m' '1;37m';
do FG=${FGs// /}
echo -en " $FGs \033[$FG $T "
for BG in 40m 41m 42m 43m 44m 45m 46m 47m;
do echo -en "$EINS \033[$FG\033[$BG $T \033[0m";
done
echo;
done
echo

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash
DEFAULT="$HOME/.dotfiles/sounds/${1:-Titan.ogg}"
#!/usr/bin/env zsh
DEFAULT="$DOTFILES_ASSETS/sounds/${1:-Titan.ogg}"
case $OSTYPE in
darwin*) afplay "$DEFAULT" ;;
linux*) paplay "$DEFAULT" ;;
darwin*) afplay $DEFAULT ;;
linux*) paplay $DEFAULT ;;
esac

View file

@ -1,3 +1,3 @@
#!/usr/bin/env bash
# make sure your .curlrc doesn't set a real useragent
# NOTE make sure your .curlrc doesn't set a real useragent
curl http://wttr.in/${1:-toronto}

View file

@ -1,9 +1,9 @@
#!/usr/bin/env bash
# Helper for encrypting/decrypting folders with gpg and tar.
# Encrypt/decrypt and compress folders with gpg+tar.
# Usage:
# clump foldername # packs
# clump foldername.clump # unpacks
# clump foldername # packs
# clump foldername.clump # unpacks
set -e
if (($# == 0)); then

View file

@ -8,7 +8,6 @@ import argparse
import fileinput
import html
from html.entities import entitydefs
from pathlib import Path
ENTITIES = {value: key for key, value in entitydefs.items()}
@ -28,16 +27,10 @@ def decode(text):
if __name__ == '__main__':
opts = argparse.ArgumentParser(description="Encodes (or decodes) HTML entities in text.")
opts.add_argument('file', nargs="?", help="File to encode/decode")
opts.add_argument('file', type=str, nargs="*", help="File to encode/decode")
opts.add_argument('-d', '--decode', action='store_true', help="Decode the given files/input")
args = opts.parse_args()
if "file" in args and args.file:
text = Path(args.file).read_text()
else:
text = "\n".join([line for line in fileinput.input()]).strip()
if args.decode:
print(decode(text))
else:
print(encode(text))
text = [line for line in fileinput.input(args.file)]
action = decode if args.decode else encode
print(action("\n".join(text).strip()))

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/usr/bin/env zsh
# A simple script that losslessly optimizes image files given to it.
#
@ -13,57 +13,59 @@
# GIFs: gifsicle
set -e
unset CDPATH
LOSSY=
usage() {
cat <<EOL
Usage: ${0##*/} [-lh] IMAGE [IMAGE2 [IMAGE3 [...]]]
cat <<EOL
Usage: ${0:A:t} [-lh] IMAGE [IMAGE2 [IMAGE3 [...]]]
-l enable lossy compression
-h this help
-l enable lossy compression
-h this help
EOL
}
while getopts hl opt; do
case $opt in
h) usage; exit;;
l) LOSSY=1;;
:) >&2 echo "$OPTARG requires an argument"; usage; exit 1;;
*) >&2 echo "Not a valid arg: $opt"; usage; exit 1;;
esac
case $opt in
h) usage; exit;;
l) LOSSY=1;;
:) >&2 echo "$OPTARG requires an argument"; usage; exit 1;;
*) >&2 echo "Not a valid arg: $opt"; usage; exit 1;;
esac
done
shift $((OPTIND-1))
_filesize() {
case $OSTYPE in
darwin*) stat -c%s "$1" ;;
*) stat --printf="%s" "$1" ;;
esac
case $OSTYPE in
darwin*) stat -c%s "$1" ;;
*) stat --printf="%s" "$1" ;;
esac
}
for file in $@; do
if [[ -d $file ]]; then
imgoptim $file/*
elif [[ -f $file ]]; then
pre_size=$(_filesize "$file")
case ${file##*.} in
png)
[[ $LOSSY ]] && pngquant $file
optipng -nc -nb -o7 $file
;;
gif)
gifsicle --batch --optimize=3 "$file"
;;
jpg|jpeg)
[[ $LOSSY ]] && jpegoptim --max=90 "$file"
jpegtran -copy none -optimize -progressive -outfile "$file" "$file"
;;
*) printf "Unrecognized file '$file': ignored"
;;
esac
post_size=$(_filesize "$file")
perc=$(echo "((${pre_size} - ${post_size}) / ${pre_size}) * 100" | bc -l)
printf "* %s: %d => %d (%.2f%% reduction)\n" "$file" "${pre_size}" "${post_size}" "$perc"
fi
if [[ -d $file ]]; then
imgoptim $file/*
elif [[ -f $file ]]; then
pre_size=$(_filesize "$file")
case ${file##*.} in
png)
[[ $LOSSY ]] && pngquant $file
optipng -nc -nb -o7 $file
;;
gif)
gifsicle --batch --optimize=3 "$file"
;;
jpg|jpeg)
[[ $LOSSY ]] && jpegoptim --max=90 "$file"
jpegtran -copy none -optimize -progressive -outfile "$file" "$file"
;;
*)
printf "Unrecognized file '$file': ignored"
;;
esac
post_size=$(_filesize "$file")
perc=$(echo "((${pre_size} - ${post_size}) / ${pre_size}) * 100" | bc -l)
printf "* %s: %d => %d (%.2f%% reduction)\n" "$file" "${pre_size}" "${post_size}" "$perc"
fi
done

View file

@ -1,19 +1,18 @@
#!/bin/sh
#!/usr/bin/env bash
# Read a file with possible syntax coloring applied
case "$1" in
*.awk|*.groff|*.java|*.js|*.m4|*.php|*.pl|*.pm|*.pod|*.sh|\
*.awk|*.groff|*.java|*.js|*.m4|*.php|*.pl|*.pm|*.pod|*.sh|\
*.ad[asb]|*.asm|*.inc|*.[ch]|*.[ch]pp|*.[ch]xx|*.cc|*.hh|\
*.lsp|*.l|*.pas|*.p|*.xml|*.xps|*.xsl|*.axp|*.ppd|*.pov|\
*.diff|*.patch|*.py|*.rb|*.sql|*.ebuild|*.eclass)
pygmentize -f 256 "$1";;
.bashrc|.bash_aliases|.bash_environment)
pygmentize -f 256 -l sh "$1"
;;
*)
grep "#\!/bin/bash" "$1" > /dev/null
if [ "$?" -eq "0" ]; then
pygmentize -f 256 -l sh "$1"
else
exit 1
fi
pygmentize -f 256 "$1" ;;
.bashrc|.bash_aliases|.bash_environment)
pygmentize -f 256 -l sh "$1" ;;
*)
if ! grep "#\!/.+[/ ](ba|z)?sh" "$1" >/dev/null; then
exit 1
fi
pygmentize -f 256 -l sh "$1"
esac

View file

@ -15,37 +15,37 @@ Report bugs to <sorin.ionescu@gmail.com>.
EOF
fi
if [[ $1 = -v || $1 = --verbose ]]; then
verbose=0
shift
if [[ $1 == -v || $1 == --verbose ]]; then
verbose=0
shift
fi
while (($# > 0)); do
if [[ ! -s $1 ]]; then
>&2 echo "$0: file not valid: $1"
shift
continue
fi
case ${1:l} in
*.tar.gz|*.tgz) tar t${verbose:+v}vzf "$1" ;;
*.tar.bz2|*.tbz|*.tbz2) tar t${verbose:+v}jf "$1" ;;
*.tar.xz|*.txz) tar --xz --help &> /dev/null \
&& tar --xz -t${verbose:+v}f "$1" \
|| xzcat "$1" | tar t${verbose:+v}f - ;;
*.tar.zma|*.tlz) tar --lzma --help &> /dev/null \
&& tar --lzma -t${verbose:+v}f "$1" \
|| lzcat "$1" | tar x${verbose:+v}f - ;;
*.tar) tar t${verbose:+v}f "$1" ;;
*.zip) unzip -l${verbose:+v} "$1" ;;
*.rar) unrar &> /dev/null \
&& unrar ${${verbose:+v}:-l} "$1" \
|| rar ${${verbose:+v}:-l} "$1" ;;
*.7z) 7za l "$1" ;;
*) >&2 echo "$0: cannot list: $1"
success=1
;;
esac
if [[ ! -s $1 ]]; then
>&2 echo "$0: file not valid: $1"
shift
continue
fi
case ${1:l} in
*.tar.gz|*.tgz) tar t${verbose:+v}vzf "$1" ;;
*.tar.bz2|*.tbz|*.tbz2) tar t${verbose:+v}jf "$1" ;;
*.tar.xz|*.txz) tar --xz --help &> /dev/null \
&& tar --xz -t${verbose:+v}f "$1" \
|| xzcat "$1" | tar t${verbose:+v}f - ;;
*.tar.zma|*.tlz) tar --lzma --help &> /dev/null \
&& tar --lzma -t${verbose:+v}f "$1" \
|| lzcat "$1" | tar x${verbose:+v}f - ;;
*.tar) tar t${verbose:+v}f "$1" ;;
*.zip) unzip -l${verbose:+v} "$1" ;;
*.rar) unrar &> /dev/null \
&& unrar ${${verbose:+v}:-l} "$1" \
|| rar ${${verbose:+v}:-l} "$1" ;;
*.7z) 7za l "$1" ;;
*) >&2 echo "$0: cannot list: $1"
success=1
;;
esac
shift
done

View file

@ -14,7 +14,7 @@ set -e
PALETTE="/tmp/palette.png"
usage() {
cat <<EOL
cat <<EOL
Usage: ${0##*/} [-fsSth] SOURCE_FILE [destfile]
-f [FPS] set frames per second
@ -31,33 +31,33 @@ trap cleanup EXIT
#
fps=30
while getopts hf:s:t:S: opt; do
case $opt in
f) fps="$OPTARG" ;;
s) start="-ss $OPTARG" ;;
S) scale=",scale=$OPTARG:flags=lanczos" ;;
t) duration="-t $OPTARG" ;;
h) usage
exit
;;
:) >&2 echo "$OPTARG requires an argument"
usage
exit 1
;;
*) >&2 echo "Not a valid arg: $opt"
usage
exit 1
;;
esac
case $opt in
f) fps="$OPTARG" ;;
s) start="-ss $OPTARG" ;;
S) scale=",scale=$OPTARG:flags=lanczos" ;;
t) duration="-t $OPTARG" ;;
h) usage
exit
;;
:) >&2 echo "$OPTARG requires an argument"
usage
exit 1
;;
*) >&2 echo "Not a valid arg: $opt"
usage
exit 1
;;
esac
done
shift $((OPTIND-1))
#
if (($# == 0)); then
>&2 echo "No movie file specified"
exit
>&2 echo "No movie file specified"
exit
elif [[ ! -f $1 ]]; then
>&2 echo "$1 does not exist"
exit
>&2 echo "$1 does not exist"
exit
fi
src="$1"
@ -70,5 +70,5 @@ ffmpeg -v warning $start $duration -i "$src" -vf "$flags,palettegen=stats_mode=f
ffmpeg -v warning $start $duration -i "$src" -i "$PALETTE" -lavfi "$flags [x]; [x][1:v] paletteuse" -y "$dest"
if command -v gifsicle >/dev/null; then
gifsicle -O3 "$dest" -o "$dest"
gifsicle -O3 "$dest" -o "$dest"
fi

View file

@ -1,9 +0,0 @@
#!/usr/bin/env bash
case $OSTYPE in
darwin*)
terminal-notifier -title "$1" -message "$2"
;;
linux*)
DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus notify-send "$1" "$2"
;;
esac

36
bin/pacman-colors Executable file
View file

@ -0,0 +1,36 @@
#!/usr/bin/env bash
# ANSI color scheme script featuring PACMAN
# by pfh
#
# Initializing procedure by lolilolicon
f=3 b=4
for j in f b; do
for i in {0..7}; do
printf -v $j$i %b "\e[${!j}${i}m"
done
done
bld=$'\e[1m'
rst=$'\e[0m'
inv=$'\e[7m'
cat << EOF
$rst
$f3 ▄███████▄ $f1 ▄██████▄ $f2 ▄██████▄ $f4 ▄██████▄ $f5 ▄██████▄ $f6 ▄██████▄
$f3▄█████████▀▀ $f1▄$f7█▀█$f1██$f7█▀█$f1██▄ $f2▄█$f7███$f2██$f7███$f2█▄ $f4▄█$f7███$f4██$f7███$f4█▄ $f5▄█$f7███$f5██$f7███$f5█▄ $f6▄██$f7█▀█$f6██$f7█▀█$f6▄
$f3███████▀ $f7▄▄ ▄▄ ▄▄ $f1█$f7▄▄█$f1██$f7▄▄█$f1███ $f2██$f7█ █$f2██$f7█ █$f2██ $f4██$f7█ █$f4██$f7█ █$f4██ $f5██$f7█ █$f5██$f7█ █$f5██ $f6███$f7█▄▄$f6██$f7█▄▄$f6█
$f3███████▄ $f7▀▀ ▀▀ ▀▀ $f1████████████ $f2████████████ $f4████████████ $f5████████████ $f6████████████
$f3▀█████████▄▄ $f1██▀██▀▀██▀██ $f2██▀██▀▀██▀██ $f4██▀██▀▀██▀██ $f5██▀██▀▀██▀██ $f6██▀██▀▀██▀██
$f3 ▀███████▀ $f1▀ ▀ ▀ ▀ $f2▀ ▀ ▀ ▀ $f4▀ ▀ ▀ ▀ $f5▀ ▀ ▀ ▀ $f6▀ ▀ ▀ ▀
$bld
$f3 ▄███████▄ $f1 ▄██████▄ $f2 ▄██████▄ $f4 ▄██████▄ $f5 ▄██████▄ $f6 ▄██████▄
$f3▄█████████▀▀ $f1▄$f7█▀█$f1██$f7█▀█$f1██▄ $f2▄█$f7█ █$f2██$f7█ █$f2█▄ $f4▄█$f7█ █$f4██$f7█ █$f4█▄ $f5▄█$f7█ █$f5██$f7█ █$f5█▄ $f6▄██$f7█▀█$f6██$f7█▀█$f6▄
$f3███████▀ $f7▄▄ ▄▄ ▄▄ $f1█$f7▄▄█$f1██$f7▄▄█$f1███ $f2██$f7███$f2██$f7███$f2██ $f4██$f7███$f4██$f7███$f4██ $f5██$f7███$f5██$f7███$f5██ $f6███$f7█▄▄$f6██$f7█▄▄$f6█
$f3███████▄ $f7▀▀ ▀▀ ▀▀ $f1████████████ $f2████████████ $f4████████████ $f5████████████ $f6████████████
$f3▀█████████▄▄ $f1██▀██▀▀██▀██ $f2██▀██▀▀██▀██ $f4██▀██▀▀██▀██ $f5██▀██▀▀██▀██ $f6██▀██▀▀██▀██
$f3 ▀███████▀ $f1▀ ▀ ▀ ▀ $f2▀ ▀ ▀ ▀ $f4▀ ▀ ▀ ▀ $f5▀ ▀ ▀ ▀ $f6▀ ▀ ▀ ▀
$rst
EOF

27
bin/pass-get Executable file
View file

@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Fetches the FIELD in ENTRY. It expects pass fields to be colon-delimited.
if (( $# != 2 )); then
>&2 echo "Expected two arguments"
>&2 echo "pass get ENTRY FIELD"
exit 1
fi
entry=$1
field=$2
secrets="$(pass show $entry)"
if [[ ! $secrets ]]; then
notify-send --urgency=critical "Failed to retrieve $entry"
exit 2
fi
if [[ $field == password || -z $field ]]; then
printf "%s" "$(head -n1 <<<"$secrets")"
else
printf "%s" "$(awk -v "key=$field:" '$1 == key {print $2}' <<<"$secrets")"
fi | xsel -i -b -t 15000
#
echo "Copied $entry:$field to clipboard for 15s"

31
bin/pass-otpuri Executable file
View file

@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Generates an OTP-auth url (written for pass-otp)
#
# Example: passotpuri LABEL SECRET [QUERYSTRING]
type=totp
issuer=
while getopts tih opt; do
case $opt in
t) type="$OPTARG" ;;
i) issuer="$OPTARG" ;;
h) cat <<EOL
Usage: $0 [-iuldypLSU] [topic1] [topic2] [...]
-t Set type (defaults to totp)
-i Issuer
EOL
exit
;;
*) >&2 echo "Aborted."
exit 1 ;;
esac
done
shift $((OPTIND-1))
label="$1"
secret="$2"
args="${3:+&$3}"
echo "otpauth://$type/$label?secret=$secret&issuer=${issuer:-$label}$args"

View file

@ -10,27 +10,27 @@
# Requires: ghostscript (gs)
optimize() {
# Adapted from Alfred Klomp's shrinkpdf script
# <http://alfredklomp.com/programming/shrinkpdf/>
gs -q -dNOPAUSE -dBATCH -dSAFER \
-sDEVICE=pdfwrite \
-dPDFSETTINGS=/screen \
-dCompatibilityLevel=1.3 \
-dEmbedAllFonts=true \
-dSubsetFonts=true \
-dAutoRotatePages=/None \
-dMonoImageResolution=$3 \
-dMonoImageDownsampleType=/Bicubic \
-dGrayImageResolution=$3 \
-dGrayImageDownsampleType=/Bicubic \
-dColorImageResolution=$3 \
-dColorImageDownsampleType=/Bicubic \
-sOutputFile="$2" \
"$1"
# Adapted from Alfred Klomp's shrinkpdf script
# <http://alfredklomp.com/programming/shrinkpdf/>
gs -q -dNOPAUSE -dBATCH -dSAFER \
-sDEVICE=pdfwrite \
-dPDFSETTINGS=/screen \
-dCompatibilityLevel=1.3 \
-dEmbedAllFonts=true \
-dSubsetFonts=true \
-dAutoRotatePages=/None \
-dMonoImageResolution=$3 \
-dMonoImageDownsampleType=/Bicubic \
-dGrayImageResolution=$3 \
-dGrayImageDownsampleType=/Bicubic \
-dColorImageResolution=$3 \
-dColorImageDownsampleType=/Bicubic \
-sOutputFile="$2" \
"$1"
}
SRC="$1"
DEST="${2:--}"
DPI="${3:-72}"
src="$1"
dest="${2:--}"
dpi="${3:-72}"
optimize "$SRC" "$DEST" "$DPI" || exit $?
optimize "$src" "$dest" "$dpi" || exit $?

View file

@ -1,39 +1,57 @@
#!/usr/bin/env bash
if [[ ! -f "$HOME/.private/config/pushover.conf" ]]; then
>&2 echo "No pushover config file found (~/.private/config/pushover.conf)"
exit 1
#
# Sends a pushover notification.
#
# -t [TITLE]
# -m [MESSAGE]
# -p [PRIORITY_LEVEL]
# -u [URL]
# -U [URL_TITLE]
# -d [DEVICE]
#
set -e
unset CDPATH
secret_file=~/.secrets/pushover
if [[ ! -f $secret_file ]]; then
>&2 echo "No pushover config file found"
exit 1
fi
message=
title=
priority=
title=${2:+$1}
message=${2:-$1}
# priority=
url=
url_title=
device=
while getopts t:m:p:u:d: opt; do
case $opt in
t) title="$OPTARG" ;;
m) message="$OPTARG" ;;
p) priority="$OPTARG" ;;
u) url="$OPTARG" ;;
U) url_title="$OPTARG" ;;
d) device="$OPTARG" ;;
*) >&2 echo "Invalid option $OPTARG"
exit 1
;;
esac
case $opt in
t) title="$OPTARG" ;;
m) message="$OPTARG" ;;
# p) priority="$OPTARG" ;;
u) url="$OPTARG" ;;
U) url_title="$OPTARG" ;;
d) device="$OPTARG" ;;
*) >&2 echo "Invalid option $OPTARG"
exit 1
;;
esac
done
shift $((OPTIND-1))
. "$HOME/.private/config/pushover.conf"
#USER=...
#TOKEN=...
eval "$(gpg --decrypt $secret_file)"
curl -s \
--form-string "token=$TOKEN" \
--form-string "user=$USER" \
--form-string "title=$title" \
--form-string "message=$message" \
--form-string "url=$url" \
--form-string "url_title=$url_title" \
--form-string "device=$device" \
https://api.pushover.net/1/messages.json
--form-string "token=$TOKEN" \
--form-string "user=$USER" \
--form-string "title=$title" \
--form-string "message=$message" \
--form-string "url=$url" \
--form-string "url_title=$url_title" \
--form-string "device=$device" \
https://api.pushover.net/1/messages.json

16
bin/qrsnap Executable file
View file

@ -0,0 +1,16 @@
#!/usr/bin/env bash
# Snaps a screenshot of a QR code and decodes it.
#
# Requires: zbar, maim (on linux)
set -e
unset CDPATH
TMP=$(mktemp _qrXXX)
case $OSTYPE in
darwin*) screencapture -i -x -t png "$TMP" ;;
linux*) maim -s "$TMP" ;;
*) >&2 echo "Help!"; exit 1 ;;
esac
(( $? == 0 )) && zbarimg -q --raw "$TMP"
rm -f "$TMP"

10
bin/rehash Executable file
View file

@ -0,0 +1,10 @@
#!/usr/bin/env zsh
# Rehashes all (rb|py|nod|lua|*)env environments
for env in $XDG_CONFIG_HOME/*env(N); do
local bin=${env##*/}
if _is_callable $bin; then
echo "Rehashing $bin"
$bin rehash
fi
done

View file

@ -1,13 +1,27 @@
#!/usr/bin/env bash
#
set -e
unset CDPATH
# Find and replace by a given list of files.
#
# replace foo bar **/*.rb
find_this="$1"; shift
replace_with="$1"; shift
main() {
local search="$1"
local replace="$2"
shift 2
items=( $(ag -l --nocolor "$find_this" "$@") )
for item in ${items[@]}; do
sed -i "s/${find_this}/${replace_with}/g" "$item"
done
for item in $(ag -l --nocolor "$search" "$@"); do
sed -i "s%${search//%/\\%}%${replace//%/\\%}%g" "$item"
done
}
# Show matches
ag "$1"
# Are you sure?
read -rp "Confirm search+replace? (y/n)?" choice
case $choice in
y|Y) main "$@" ;;
*) >&2 echo "Aborted"; exit ;;
esac

View file

@ -73,10 +73,7 @@ class CurrencyCache():
return None
def _set(self, key, value):
self.cache[key] = {
'time': datetime.now().timestamp(),
'value': value
}
self.cache[key] = {'time': datetime.now().timestamp(), 'value': value}
def _request_currency_rate(url=API_URL, *args):

View file

@ -2,54 +2,54 @@
set -e
(( $# > 0 )) || exit
# Displays the time since $1 in a human readable format (e.g. 4h 25m 55s). If given a
# file, the modified time is used. If $1 == "--", then this script acts as a converter,
# converting $2 into human a readable format, e.g. since -- 72 #=> 1m 12s
# Displays the time since $1 in a human readable format (e.g. 4h 25m 55s). If
# given a file, the modified time is used. If $1 == "--", then this script acts
# as a converter, converting $2 into human a readable format, e.g. since -- 72
# #=> 1m 12s
# TODO: A help fallback
# TODO: Options parsing
# TODO: Options parsing?
# `date` on OSX does not have the --date parameter
date=date
if [[ $OSTYPE == darwin* ]]; then
date=gdate
date=gdate
elif ! command -v $date >/dev/null; then
echo "Unsupported system"
exit 1
echo "Unsupported system"
exit 1
fi
# If given a file, give time since last modification
(( $# == 1 )) && [[ -f $@ ]] && arg=reference || arg=date
(( $# == 1 )) && [[ -f $1 ]] && arg=reference || arg=date
args="$*"
if [[ $1 == -- ]]; then
t="$2"
t="$2"
else
now=$(${date} +%s)
then=$(${date} --$arg="$*" +%s)
now=$($date +%s)
then=$($date --$arg="$*" +%s)
t=$(( $now - $then ))
t=$(( now - then ))
fi
# Bash doesn't support floating point arithmetic like zsh does, therefore:
bc <<EOF
define abs(i) {
if (i < 0) return (-i)
return (i)
}
define abs(i) {
if (i < 0) return (-i)
return (i)
}
t = abs($t)
t = abs($t)
weeks = t / 60 / 60 / 24 / 7
days = t / 60 / 60 / 24 % 7
hours = t / 60 / 60 % 24
minutes = t / 60 % 60
seconds = t % 60
weeks = t / 60 / 60 / 24 / 7
days = t / 60 / 60 / 24 % 7
hours = t / 60 / 60 % 24
minutes = t / 60 % 60
seconds = t % 60
if (weeks > 0) print weeks, "w "
if (days > 0) print days, "d "
if (hours > 0) print hours, "h "
if (minutes > 0) print minutes, "m "
print seconds, "s"
if (weeks > 0) print weeks, "w "
if (days > 0) print days, "d "
if (hours > 0) print hours, "h "
if (minutes > 0) print minutes, "m "
print seconds, "s"
EOF

View file

@ -10,12 +10,12 @@
result=$(echo "$@" | aspell -a | tail -n-2)
if [[ "$result" == '*' ]]; then
echo "$@"
echo "$@"
else
words=$(echo "$result" | sed $'s/[:,] /\\\n/g' | tail -n +2)
if (( $(wc -l <<< "$words") > 1 )) && command -v 'fzf' >/dev/null; then
fzf <<< "$words"
else
echo "$words"
fi
words=$(echo "$result" | sed $'s/[:,] /\\\n/g' | tail -n +2)
if (( $(wc -l <<< "$words") > 1 )) && command -v 'fzf' >/dev/null; then
fzf <<< "$words"
else
echo "$words"
fi
fi

233
bin/sup Normal file
View file

@ -0,0 +1,233 @@
#!/usr/bin/env zsh
# Upload to various file hosts
# colors
c0=$(tput sgr0)
c1=$(tput setaf 1)
c2=$(tput setaf 2)
# filename to use for screenshots
local_temp=$(mktemp)
# screenshot functions
cap_fullscreen() {
local_file="$local_temp.png"
mv $local_temp $local_file
maim -u $local_file
}
cap_selection() {
local_file="$local_temp.png"
mv $local_temp $local_file
maim -s -u $local_file
}
cap_window() {
mv $local_temp $local_temp.png
maim -i $(xprop -root _NET_ACTIVE_WINDOW | grep -o '0x.*') --hidecursor
}
# delay
delay_seconds='0'
# hosts and shorteners
host='uguu'
shortener=
hosts='uguu teknik 0x0 mixtape ptpb lewd'
shorteners='waaai 0x0'
##
usage() {
cat <<EOF
Upload to various file hosts
Usage: ${0:A:t} [options]
Options:
-d SECS Delay the screenshot by the specified number of seconds.
-f Take a fullscreen screenshot.
-h Show this help message.
-l URL Upload the file at the provided URL.
-o Select a host to use. Can be uguu, teknik, 0x0, ptpb, mixtape or lewd.
-p PATH Custom path to save the image to. Saves the image as "%Y-%m-%d %H-%M-%S.png".
-s Take a selection screenshot.
-S Select a shortener to use. Can be waaai or 0x0.
-u FILE Upload a file.
-w Take a screenshot of the current window.
-x Do not notify dbus, update the log, or modify the clipboard.
EOF
}
delay() {
for (( i=delay_seconds; i>0; --i )); do
echo "$i..."
sleep 1
done
}
screenshot() {
if [[ $doFullscreen ]]; then
cap_fullscreen
elif [[ $doSelection ]]; then
cap_selection &>/dev/null
if ! [[ -s $local_file ]]; then
$(rm "$local_file" 2> /dev/null)
exit
fi
elif [[ $doWindow ]]; then
cap_window
elif [[ $doURL ]]; then
local urlext
if [[ -f /usr/share/mime/globs ]]; then
urlext=$(curl -sf --head "${remoteURL}" | grep 'Content-Type: ' | head -1 | grep -Po '(?<=\ )[^\;]*')
urlext=$(echo "${urlext}" | sed -e "s/\\r//")
urlext=$(cat /usr/share/mime/globs | grep "${urlext}" | sort -r | head -1 | grep -Po '(?<=\.)[^\n]*')
else
urlext="$(basename ${remoteURL})"
urlext=${urlext#*.}
fi
local_file="${local_temp}.${urlext}"
$(curl -sf "${remoteURL}" > "${local_file}")
fi
}
upload() {
for (( i = 1; i <= 3; i++ )); do
echo -n "Try #${i}... "
case "${host}" in
teknik) hostURL='https://api.teknik.io/v1/Upload' ;;
0x0) hostURL='https://0x0.st/' ;;
uguu) hostURL='https://uguu.se/api.php?d=upload-tool' ;;
ptpb) hostURL='https://ptpb.pw/' ;;
mixtape) hostURL='https://mixtape.moe/upload.php' ;;
lewd) hostURL='https://lewd.se/api.php?d=upload-tool' ;;
esac
case "${shortener}" in
waaai) shortenerURL='https://api.waa.ai/shorten' ;;
0x0) shortenerURL='http://0x0.st/' ;;
ptpb) shortenerURL='https://ptpb.pw/u'
esac
if [ "${host}" = 'uguu' ]; then
uploadResult="$(curl -sf -F file="@${local_file}" "${hostURL}")"
elif [ "${host}" = '0x0' ]; then
uploadResult="$(curl -sf -F file="@${local_file}" "${hostURL}")"
elif [ "${host}" = 'teknik' ]; then
uploadResult="$(curl -sf -F file="@${local_file}" "${hostURL}")"
uploadResult="${uploadResult##*url\":\"}"
uploadResult="${uploadResult%%\"*}"
elif [ "${host}" = 'mixtape' ]; then
uploadResult="$(curl -sf -F files[]="@${local_file}" "${hostURL}")"
uploadResult="$(echo "${uploadResult}" | grep -Eo '"url":"[A-Za-z0-9]+.*",' | sed 's/"url":"//;s/",//')"
uploadResult="$(echo "${uploadResult//\\\//\/}")"
elif [ "${host}" = 'ptpb' ]; then
uploadResult="$(curl -sf -F c="@${local_file}" "${hostURL}")"
uploadResult="${uploadResult##*url: }"
uploadResult="${uploadResult%%$'\n'*}"
elif [ "${host}" = 'lewd' ]; then
uploadResult="$(curl -sf -F file="@${local_file}" "${hostURL}")"
fi
if [ "${shortener}" = 'waaai' ]; then
tempResult="$(curl -sf -F url="${uploadResult}" "${shortenerURL}")"
shortCode="${tempResult##*short_code\":\"}"
shortCode="${shortCode%%\"*}"
shortenerResult="https://waa.ai/${shortCode}"
shortenerExtension="${tempResult##*extension\":}"
shortenerExtension="${shortenerExtension%%\}*}"
if [[ $shortenerExtension == true ]]; then
shortenerExtension=${shortenerExtension##\"}
shortenerExtension=${shortenerExtension%%\"}
shortenerResult="${shortenerResult}.${shortenerExtension}"
fi
elif [[ $shortener == '0x0' ]]; then
shortenerResult="$(curl -sf -F shorten="${uploadResult}" "${shortenerURL}")"
elif [[ $shortener == 'ptpb' ]]; then
shortenerResult="$(curl -sf -F c=@- "${shortenerURL}" <<< "${uploadResult}")"
fi
if [[ $shortener ]]; then
finalResult="$shortenerResult"
else
finalResult="$uploadResult"
fi
if [[ $? == 0 ]]; then
# copy to clipboard, log, and notify (unless $noComms is set)
if [ ! "${noComms}" ]; then
echo -n "${finalResult}" | xclip -selection primary
echo -n "${finalResult}" | xclip -selection clipboard
echo "$(date +"%D %R") | "${file}" | "${finalResult}"" >> ~/.uguush.log
notify-send 'uguu~' "${finalResult}"
fi
fi
echo "[${c2}OK${c0}]"
echo "File has been uploaded: ${finalResult}"
# if we took a screenshot, remove the temporary file
if [[ -z $doFile ]]; then
rm $local_file
fi
exit
done
}
path() {
if [[ $saveToPath == true ]]; then
cp $local_file "$pathToSave/$(basename "$local_file")"
fi
}
##
while getopts :d:fho:p:su:wxS:l: opt; do
case $opt in
d) # set delay value
delay_seconds="$OPTARG" ;;
f) # take fullscreen shot
doFullscreen='true' ;;
h) # print help
usage
exit 0 ;;
o) # set host
[[ "${hosts}" =~ "$OPTARG" ]] && host="$OPTARG" || exit 1 ;;
s) # take shot of selection
doSelection='true' ;;
u) # change $file to the specified file with -u
doFile='true'
local_file="$OPTARG" ;;
w) # take shot of current window
doWindow='true' ;;
x) # do not notify dbus, update log, or modify clipboard
noComms='true' ;;
S) # set shortener
[[ $shorteners =~ "$OPTARG" ]] && shortener="$OPTARG" || exit 1 ;;
l) # set url to upload
doURL='true'
remoteURL="${OPTARG}" ;;
p) # set path to save file
saveToPath='true'
pathToSave="${OPTARG}" ;;
*) # print help and EXIT_FAILURE
usage
exit 1 ;;
esac
done
# show usage if no arguments are given
if (( $# < 1 )); then
usage
exit 1
fi
delay
screenshot
path
upload
# if the program doesn't exit at the for-loop, the upload failed
>&2 echo 'File was not uploaded, did you specify a valid filename?'
exit 1

View file

@ -11,6 +11,7 @@ Usage: time-in Copenhagen "Toronto, ON" Vancouver
import sys
import json
import os
from base64 import b64encode
from datetime import datetime
from urllib import request
@ -23,7 +24,7 @@ URL_BASE = "https://maps.googleapis.com/maps/api/"
URL_TZ = URL_BASE + "timezone/json?location={},{}&timestamp={}"
URL_GEOCODE = URL_BASE + "geocode/json?address={}"
CACHE_FILE = "/tmp/time-in"
CACHE_FILE = "{}/timein".format(os.environ.get("XDG_CACHE_HOME") or "/tmp")
CACHE = {}

View file

@ -1,16 +1,16 @@
#!/usr/bin/env bash
# Upload file to transfer.sh
# Upload file/stdin to transfer.sh
url="https://transfer.sh"
tmpfile=$(mktemp -t transferXXX)
if [[ -t 0 ]]; then
basefile=$(basename "$1" | sed -e 's/[^a-zA-Z0-9._-]/-/g')
curl --progress-bar --upload-file "$1" "$url/$basefile" >> $tmpfile
basefile=$(basename "$1" | sed -e 's/[^a-zA-Z0-9._-]/-/g')
curl --progress-bar --upload-file "$1" "$url/$basefile" >>"$tmpfile"
else
curl --progress-bar --upload-file "-" "$url/$1" >> $tmpfile
curl --progress-bar --upload-file "-" "$url/$1" >>"$tmpfile"
fi
cat $tmpfile
rm -f $tmpfile
cat "$tmpfile"
rm -f "$tmpfile"
# vim:set ft=sh:

48
bin/uri
View file

@ -4,46 +4,34 @@
Encode/decode url strings in stdin or the given file(s).
"""
import getopt
import argparse
import fileinput
import sys
import os
try:
from urllib.parse import quote_plus, quote, unquote_plus, unquote
except ImportError:
from urllib import quote_plus, quote, unquote_plus, unquote
def usage():
"""Print out help for this script"""
print("Usage: {} [-edEDh] file1[ file2[ ...]]".format(os.path.basename(sys.argv[0])))
def main(commands):
try:
optlist, args = getopt.getopt(sys.argv[1:], 'edEDh')
sys.argv = [sys.argv[0]] + args
except getopt.GetoptError as err:
print(err)
sys.exit(1)
def main():
opts = argparse.ArgumentParser(description="Make text URI-safe by encoding/decoding input")
opts.add_argument('file', type=str, nargs='*', help='File(s) to encode/decode')
opts.add_argument('-e', '--encode', action='store_true', help='Use encoder')
opts.add_argument('-E', '--encode-plus', action='store_true', help='Use encoder, but encode spaces as pluses')
opts.add_argument('-d', '--decode', action='store_true', help='Use decoder')
opts.add_argument('-D', '--decode-plus', action='store_true', help='Use decoder, but decode pluses as spaces')
args = opts.parse_args()
action = quote
for flag, _ in optlist:
if flag in commands:
action = commands[flag]
elif flag == '-h':
usage()
sys.exit()
else:
assert False, "unhandled option"
if args.decode:
action = unquote
elif args.decode_plus:
action = unquote_plus
elif args.encode_plus:
action = quote_plus
print(action("\n".join([line for line in fileinput.input()]).strip()))
text = [line for line in fileinput.input(args.file)]
print(action("\n".join(text).strip()))
if __name__ == '__main__':
main({
"-e": quote,
"-E": quote_plus,
"-d": unquote,
"-D": unquote_plus
})
main()

46
bin/zzz
View file

@ -3,28 +3,28 @@
# If -f, then put computer to sleep.
# Otherwise, lock screen and turn off monitor.
if [[ $1 = -h ]]; then
bin=${0##*/}
echo "Usage: $bin [-f]"
echo
echo " $bin # put display to sleep"
echo " $bin -f # put computer to sleep"
elif [[ $1 = -f ]]; then
echo "Going to sleep..."
case $OSTYPE in
darwin*) pmset sleepnow ;;
linux*) systemctl suspend ;;
esac
if [[ $1 == -h ]]; then
bin=${0##*/}
echo "Usage: $bin [-f]"
echo
echo " $bin # put display to sleep"
echo " $bin -f # put computer to sleep"
elif [[ $1 == -f ]]; then
echo "Going to sleep..."
case $OSTYPE in
darwin*) pmset sleepnow ;;
linux*) systemctl suspend ;;
esac
else
echo "Shutting my eyes..."
case $OSTYPE in
darwin*) sleep 1; pmset displaysleepnow ;;
linux*)
if command -v slock >/dev/null; then
pgrep slock >/dev/null || slock &
fi
sleep 1
xset dpms force off
;;
esac
echo "Shutting my eyes..."
case $OSTYPE in
darwin*) sleep 1; pmset displaysleepnow ;;
linux*)
if command -v slock >/dev/null; then
pgrep slock >/dev/null || slock &
fi
sleep 1
xset dpms force off
;;
esac
fi

143
bootstrap
View file

@ -1,143 +0,0 @@
#!/usr/bin/env bash
# My (idempotent) dotfile deployment script.
#
# You pass the directories of "topics" to it to install them. It will:
# 1. symlink $topic/.* => ~/ and $topic/.(config|local)/* => ~/.\1/
# 2. run $topic/install the first time
# 3. run $topic/update on consecutive runs
CWD="$(cd "$(dirname "$0")" && pwd)"
pushd "$CWD" >/dev/null
set -e
shopt -s nullglob
# shellcheck source=shell/common.sh
source "shell/common.sh"
#
blue="\033[34m"
magenta="\033[35m"
green="\033[32m"
orange="\033[33m"
grey="\033[36m"
red="\033[31m"
nc="\033[0m"
#
_run() {
local cmd="${*//$DOTFILES\//}"
cmd="${cmd//$HOME/~}"
local clr=""
case $cmd in
*~/.bin/) clr="${magenta}" ;;
ln*) clr="" ;;
mkdir*) clr="${blue}" ;;
*) clr="${orange}"
esac
echo -e " $PREFIX$clr$cmd$nc"
[[ $DRYRUN ]] || { $@ 2>&1 | sed 's/^/ => /'; }
}
_link() {
if [[ -f "$2" || ( -d "$2" && -f "$2/${1##*/}" ) ]]; then
if [[ $yes ]]; then
[[ $yes = 1 ]] && choice=y || choice=n
else
read -r -n 1 -p "? ${1##*/} exists in $2 -- overwrite? [y/n] " choice
echo
fi
case $choice in
y|Y) _run rm -rf "$2"
PREFIX="${red}OVERWRITE:${nc} " _run ln -svf "$1" "$2"
;;
*) PREFIX="${red}ABORTED:${nc} " DRYRUN=1 _run ln -svf "$1" "$2"
;;
esac
else
_run ln -svf "$1" "$2"
fi
}
##
export SERVER=
install=1
link=1
update=1
yes=0
while getopts iuldypLSUh opt; do
case $opt in
d) DRYRUN=1 ;;
i) install= ;;
l) link= ;;
p) yes= ;;
u) update= ;;
y) yes=1 ;;
S) SERVER=1 ;;
U) install=
yes=0
;;
L) update=
install=
yes=0
;;
h) cat <<EOL
Usage: $0 [-iuldypLSU] [topic1] [topic2] [...]
-i Don't run install scripts
-u Don't run update scripts
-l Don't symlink dotfiles
-d Do a dry run (only output commands, no changes)
-y Overwrite conflicts (no prompts)
-p Prompt on file conflict (to overwrite)
-L Refresh links; the same as -ui
-S Server mode; only install the bare minimum
-U Update mode; run update scripts only
EOL
exit
;;
*) >&2 echo "Aborted."
exit 1 ;;
esac
done
shift $((OPTIND-1))
#
ENABLED_DIR=".enabled.d"
for topic in "${@:-$(ls -1 "$ENABLED_DIR" | sed 's%_%/%')}"; do
[[ -d $topic ]] || continue
echo -e "${green}${topic}${nc}"
tpath="$CWD/$topic"
if [[ $link ]]; then
# Symlink dotfiles from topics (2 levels deep) + parent (1 level deep)
for file in "$tpath"{,../}/.[a-zA-Z]*; do
if [[ -d "$file" && "${file##*/}" == .@(config|local) ]]; then
for subfile in "$file"/*; do
base="$HOME/${file##*/}/"
[[ -d $base ]] || _run mkdir -p "$base"
_link "$subfile" "$base"
done
elif [[ -e $file ]]; then
_link "$file" "$HOME/"
fi
done
fi
# Link topic to .enabled.d
linkpath="${ENABLED_DIR}/${topic//\//_}"
if [[ -h "$linkpath" ]]; then
[[ "$update" && -x ${linkpath}/update ]] && _run "$tpath/update"
else
# Register topic as 'enabled'
_run ln -svf "$tpath" "$linkpath"
# Run install script
[[ "$install" && -x ${linkpath}/install ]] && _run "$tpath/install"
fi
done
popd >/dev/null
# vim:set ft=sh:

41
bootstrap.sh Executable file
View file

@ -0,0 +1,41 @@
#!/usr/bin/env bash
# dotfiles bootstrapper
#
# Installs zsh & git, then clones this repo to ~/.dotfiles. This script is
# intended to be run remotely, via curl:
#
# bash <(curl -s https://raw.githubusercontent.com/hlissner/dotfiles/master/bootstrap.sh)
export DOTFILES=~/.dotfiles
set -e
_msg() { printf "\r\033[2K\033[0;32m[ .. ] %s\033[0m\n" "$*"; }
_uncallable() { ! command -v "$1" >/dev/null; }
if _uncallable zsh || _uncallable git; then
# NOTE Macos has both already
_msg "Installing git and/or zsh"
if [[ -f /etc/arch-release ]]; then
sudo pacman --needed --noconfirm -S git zsh
elif [[ -f /etc/debian_version ]]; then
sudo apt-get update && sudo apt-get install -y git zsh
fi
fi
if [[ ! -d ~/.dotfiles ]]; then
_msg "Deploying dotfiles repository..."
if [[ $USER == hlissner ]]; then
dfrepo=git@github.com:hlissner/dotfiles.git
else
dfrepo=https://github.com/hlissner/dotfiles
fi
git clone --recursive "$dfrepo" "$DOTFILES"
fi
#
_msg
_msg "And done!"
_msg
_msg "Use $DOTFILES/deploy to install your dotfiles, I suggest you begin"
_msg "with 'base/arch' or 'base/macos'."

45
clean
View file

@ -1,45 +0,0 @@
#!/usr/bin/env bash
# A symlink cleanup script.
#
# Usage: clean [-du]
#
# Options:
# -d Do a dry run (only output commands, no changes)
# -u Uninstall all enabled topics
_run() {
if [[ $DRYRUN ]]; then
echo "$@"
else
$@
fi
}
uninstall=
while getopts du opt; do
case $opt in
d) DRYRUN=1 ;;
u) uninstall=1 ;;
*) >&2 echo "Invalid argument: $OPTARG"
exit 1
;;
esac
done
shift $((OPTIND-1))
# Remove enabled topics
if [[ $uninstall ]]; then
_run rm -v "$(cd "$(dirname "$0")" && pwd -P)"/.enabled.d/*
fi
# Remove dead links
shopt -s nullglob
links=( $HOME/.* $HOME/.*/* )
for link in "${links[@]}"; do
if [[ -h "$link" && ! -e "$link" ]]; then
_run rm -vf "$link"
fi
done
# vim:set ft=sh:

199
deploy Executable file
View file

@ -0,0 +1,199 @@
#!/usr/bin/env zsh
# Dotfile manager
#
# By Henrik Lissner <henrik@lissner.net>
# https://github.com/hlissner/dotfiles
#
# Requires: git, zsh
source "${0:A:h}/env"
SEP='.'
# helpers
function echo-debug { echo "$@" | sed -e "s%$HOME%~%g" -e "s%$DOTFILES%.%g"; }
function echo-info { printf "\r\033[2K\033[0;34m[ .. ]\033[0m %s\n" "$*"; }
function echo-skip { printf "\r\033[2K\033[38;05;240m[SKIP]\033[0m %s\n" "$*"; }
function echo-ok { printf "\r\033[2K\033[0;32m[ OK ]\033[0m %s\n" "$*"; }
function echo-fail { printf "\r\033[2K\033[0;31m[FAIL]\033[0m %s\n" "$*"; }
function _exec { ${DRYRUN:+echo-debug} $@; return ${DRYRUN:+1}; }
function _topic-do {
if [[ -e "$1/_init" ]]; then
if [[ ! -x "$1/_init" ]]; then
echo-fail "$1's init script isn't executable"
return 1
fi
export TOPIC=$1
pushd -q $1
_exec ./_init $2
popd -q
return $?
fi
}
function _topics {
local topics=( "$DOTFILES_DATA"/*.topic(N) )
echo ${${${topics[@]#$DOTFILES_DATA/}%.topic}/$SEP//}
}
# For _init scripts
function topic-enabled-p { [[ -L "$(topic-path $1)" ]] }
function topic-path { echo "$DOTFILES_DATA/${1/\//$SEP}.topic" }
function mklink {
if [[ $1 == '-s' ]]; then
local dosudo=1
shift
fi
local flags="-sv${OVERWRITE:+f}"
local srcs=( ${@:1:-1} )
local dest=${@[-1]}
if [[ $dest == */ && ! -d $dest ]]; then
mkdir -p $dest
elif [[ ! -d ${dest%/*} ]]; then
mkdir -p ${dest%/*}
fi
for lk in ${srcs[@]}; do
local src
case $lk in
/*) src=$lk ;;
.) src="$(topic-path $TOPIC)" ;;
*) src="$(topic-path $TOPIC)/$lk" ;;
esac
if [[ -d $src ]]; then
if [[ $dest != */ && -d $dest && -L $dest ]]; then
${dosudo:+sudo} rm -fv $dest
fi
fi
_exec ${dosudo:+sudo} ln $flags $src $dest
done
}
function init {
declare -f $1 >/dev/null || return 1
echo-info "$TOPIC.init.$1: start"
$1
local retval=$?
echo-ok "$TOPIC.init.$1: done"
return $retval
}
# deploy functions
function topic-init {
for topic in $@; do
if [[ ! -d $topic ]]; then
echo-fail "$topic doesn't exist!"
continue
fi
echo-ok "$topic"
local tpath="$DOTFILES/$topic"
local tsympath="$(topic-path $topic)"
if [[ -d "$topic/bin" ]]; then
export path=( $tpath/bin $path )
echo-ok "$topic: added $topic/bin to PATH, temporarily"
fi
if [[ $LINK ]] || ! topic-enabled-p $topic; then
local op=install
OVERWRITE=1 mklink $tpath $tsympath
_topic-do $topic link
fi
if [[ -z $INHIBIT_INIT ]]; then
_topic-do $topic ${FORCE_OP:-${op:-update}}
if [[ $op == install && $? != 0 ]]; then
topic-remove $topic
fi
fi
done
}
function topic-remove {
for topic in $@; do
if [[ ! -d $topic ]]; then
echo-fail "$topic doesn't exist"
continue
elif ! topic-enabled-p $topic; then
echo-fail "$topic isn't enabled"
continue
fi
[[ $INHIBIT_INIT ]] || _topic-do $topic clean
_exec rm -f "$(topic-path $topic)" && \
echo-ok "Removed $topic" || \
echo-fail "Couldn't remove $topic"
done
}
function clean {
local paths=( $XDG_CACHE_HOME $XDG_CONFIG_HOME $XDG_DATA_HOME $XDG_BIN_HOME )
local links=( ~/.*(-@DN) ${^paths}/**(-@DN))
if [[ ${#links[@]} > 1 ]]; then
echo-info "Removing dead dotfile symlinks..."
for link in "${links[@]}"; do
[[ -e $link ]] || _exec rm -fv "$link"
done
else
echo-ok "No dead symlinks in HOME"
fi
# Remove empty dotfile folders
local dirs=( ${^paths}/**(N/^F) ~/.*(N/^F) )
if [[ ${#dirs[@]} > 1 ]]; then
echo-info "Removing empty dotfile directories..."
for dir in "${dirs[@]}"; do
_exec rmdir "$dir" && echo-ok "Deleted ${dir/$HOME/~}"
done
else
echo-ok "No empty directories in HOME"
fi
}
## Bootstrap
if [[ $ZSH_EVAL_CONTEXT != *:file ]]; then
while getopts acdehlLit opt; do
case $opt in
a) TARGETS="$(_topics)" ;;
c) CLEAN=1 ;;
d) REMOVE=1 ;;
L) LIST=1 ;;
l) export LINK=1 ;&
i) export INHIBIT_INIT=1 ;;
t) export DRYRUN=1 ;;
h) cat <<EOL
Usage: ${0:A:t} [-acdlLit] [TOPIC...]
-a Target all enabled topics (ignores TOPIC args)
-c Afterwards, remove dead symlinks & empty dot-directories in $HOME.
Can be used alone.
-d Disable & unlink topic(s)
-l Only enable & relink topic(s) (implies -i)
-L List enabled topics
-i Do not run install/update/clean init scripts
-t Do a test run; do not actually do anything
EOL
exit ;;
*) >&2 echo-fail "Aborted."
exit 1 ;;
esac
done
shift $((OPTIND-1))
if [[ $LIST ]]; then
_topics | tr ' ' $'\n'
else
pushd -qL "$DOTFILES"
if [[ $REMOVE ]]; then
topic-remove ${TARGETS:-$@}
else
topic-init ${TARGETS:-$@}
fi
[[ $CLEAN ]] && clean
popd -q
fi
fi
# vim:set ft=sh:

25
dev/go/_init Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env zsh
source ${0:A:h}/../../deploy
source env.zsh
install() {
case $(_os) in
macos) brew install go ;;
arch) pacaur --needed --noconfirm -S go ;;
esac
update
}
update() {
go get -u github.com/nsf/gocode
go get -u github.com/motemen/gore
go get -u golang.org/x/tools/cmd/guru
go get -u golang.org/x/tools/cmd/gorename
}
# link() {}
# clean() {}
init "$@"

4
dev/go/env.zsh Normal file
View file

@ -0,0 +1,4 @@
export GOPATH="$XDG_DATA_HOME/go:$HOME/work/go"
# Adds $GOPATH/bin's to PATH
path=( `printf '%s/bin\n' ${(@s/:/)GOPATH}` $path )

22
dev/haskell/_init Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env zsh
source ${0:A:h}/../../deploy
source env.zsh
install() {
case $(_os) in
macos) brew install stack ghc ;;
arch) pacaur --needed --noedit --noconfirm -S ghc stack-static ;;
esac
stack config set system-ghc --global true
stack setup && stack install ShellCheck ghc-mod
}
update() {
stack update
}
# link() {}
# clean() {}
init "$@"

2
dev/haskell/env.zsh Normal file
View file

@ -0,0 +1,2 @@
export STACK_ROOT=$XDG_DATA_HOME/stack
path=( ~/.cabal/bin $path )

19
dev/java/_init Executable file
View file

@ -0,0 +1,19 @@
#!/usr/bin/env zsh
source ${0:A:h}/../../deploy
source env.zsh
install() {
# TODO Install android SDK
case $(_os) in
macos) brew cask install java gradle ;;
arch) pacaur --needed --noedit --noconfirm -S jdk8-openjdk gradle ;;
esac
}
# update() {}
# link() {}
# clean() {}
init "$@"

Some files were not shown because too many files have changed in this diff Show more