refactor: nixify / clean remaining dots scripts
This commit is contained in:
1 parent
9030f33842
commit
9110789527
53 files changed
+265
-655
No files matched your search
@@ -42,7 +42,6 @@ inputs.colmena.lib.makeHive (
|
||||
specialArgs = {
|
||||
inherit inputs lib';
|
||||
outputs = self;
|
||||
dotsPath = ../dots;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
# Scripts
|
||||
|
||||
Mostly tiny helper scripts \& experiments, some more useful than others.
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure the scripts are in your `$PATH` and executable.
|
||||
|
||||
To add the complete directory of scripts to your `$PATH`:
|
||||
|
||||
```bash
|
||||
export PATH=~/.bin:$PATH
|
||||
```
|
||||
|
||||
To make a any script `<script>` executable:
|
||||
```bash
|
||||
chmod +x <script>
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
Statusbar scripts are prefixed with `sb` under the assumption you're using
|
||||
`polybar` (scripts my need changes to be used with different statusbars).
|
||||
|
||||
Some scripts have dependencies (e.g. `fzf`, `jq`, `xclip`, ...), make sure you
|
||||
have them installed.
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Tiny AUR clone helper
|
||||
# aurpac <package-name>
|
||||
|
||||
git clone "https://aur.archlinux.org/$1.git"
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
ipython -i /home/h/.bin/calc.py
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Open webcam window
|
||||
|
||||
ffplay -f v4l2 -x 640 -y 480 -i /dev/video0 >/dev/null 2>&1 & disown
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs')
|
||||
|
||||
const objLength = obj => Object.keys(obj).length
|
||||
|
||||
fs.readFile(process.argv[2], (err, data) => (err ? console.error(err) : console.log(objLength(JSON.parse(data)))))
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
xdg-open https://devdocs.io/offline
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
options="Mouse\nHeadphones"
|
||||
|
||||
selected="$(echo -e "$options" | fzf)"
|
||||
|
||||
case "$selected" in
|
||||
"Mouse") toggle-bt-device E4:19:21:56:C8:70;;
|
||||
"Headphones") toggle-bt-device 38:18:4C:D4:74:42;;
|
||||
esac
|
||||
@@ -1,2 +0,0 @@
|
||||
pactl load-module module-jack-source connect=0
|
||||
pactl load-module module-loopback source=jack_in
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import yaml, json, sys
|
||||
|
||||
print(yaml.dump(json.load(open(sys.argv[1])), allow_unicode=True), end='')
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sudo pacman -Qtdq | sudo pacman -Rns -
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
session="r5rs"
|
||||
|
||||
tmux attach-session -t "$session" || tmux new-session -s "$session" \; \
|
||||
split-window -h -t $session \; \
|
||||
send-keys -t 1 "nvim -c \"set ft=scheme\"" C-m \; \
|
||||
send-keys -t 2 "plt-r5rs --no-prim" C-m \; \
|
||||
select-pane -t 1
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sed -i -r 's/\[*\]\(\.\/([A-z-]*.md)/\]\(\1/g' *.md
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function start() {
|
||||
adb start-server
|
||||
nohup gnirehtet autorun &> /dev/null &
|
||||
printf "Started reverse tethering \n"
|
||||
}
|
||||
|
||||
function stop() {
|
||||
adb kill-server
|
||||
gnirehtet stop
|
||||
pkill gnirehtet
|
||||
printf "Stopped reverse tethering \n"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start) start ;;
|
||||
stop) stop ;;
|
||||
restart) stop; start ;;
|
||||
*) printf "start | stop | restart \n" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Anki review percentage for statusbar
|
||||
|
||||
num_to_review=200
|
||||
|
||||
# Get current card count from Anki
|
||||
count=$(curl -s 127.0.0.1:8765 -X POST -d '{"action": "getNumCardsReviewedToday", "version": 6}' | jq '.result')
|
||||
|
||||
if [ -z "$count" ]
|
||||
then
|
||||
if [ -s /tmp/anki-reviews ]; then
|
||||
true
|
||||
else
|
||||
echo "-1" > /tmp/anki-reviews
|
||||
fi
|
||||
else
|
||||
echo "$count" > /tmp/anki-reviews
|
||||
fi
|
||||
|
||||
num_reviews=$(cat /tmp/anki-reviews)
|
||||
echo -n -e " Reviews: $(python3 -c "print('{:.2%}'.format($num_reviews/$num_to_review))") "
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cap="$(cat /sys/class/power_supply/BAT0/capacity)"
|
||||
|
||||
if [ "$cap" -ge 33 ];then
|
||||
color="\x01"
|
||||
elif [ "$cap" -ge 10 ]; then
|
||||
color="\x03"
|
||||
else
|
||||
color="\x04"
|
||||
fi
|
||||
|
||||
echo -n -e "$color $cap% \x01"
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo -n -e "Week $(date '+%V') $(date '+%a %d %b %H:%M') "
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if grep -xq 'up' /sys/class/net/w*/operstate 2>/dev/null ; then
|
||||
wifiicon="$(awk '/^\s*w/ { print "WiFi", int($3 * 100 / 70) "% " }' /proc/net/wireless)"
|
||||
fi
|
||||
|
||||
printf " %s%s%s" "$wifiicon" "$(sed "s/down//;s/up/Ethernet/" /sys/class/net/e*/operstate 2>/dev/null)"
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
[ -f "/home/h/.local/share/pomo" ] && cat /home/h/.local/share/pomo || echo ""
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Render contents of $HOME/.project if present
|
||||
[ -f "$HOME/.project" ] && cat "$HOME/.project" || echo ""
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
num_done="$(task end.after:today status:completed count)"
|
||||
num_pending="$(($(task count status:pending) + $num_done))"
|
||||
num_waiting="$(($(task count status:waiting)))"
|
||||
|
||||
echo -e "Tasks: $num_done/$num_pending+$num_waiting"
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Reference: https://github.com/mil-ad/polybar-wireguard
|
||||
|
||||
connected_interfaces=$(networkctl | grep -P "\d+ .* wireguard routable" -o | cut -d" " -f2)
|
||||
|
||||
if [ -n "$connected_interfaces" ];
|
||||
then
|
||||
for interface in $connected_interfaces; do echo "$interface"; done
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Script to create script
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: script <scriptname>"
|
||||
exit
|
||||
fi
|
||||
|
||||
path="$HOME/.bin/$1"
|
||||
|
||||
# Prevent overwriting existing script
|
||||
set -o noclobber
|
||||
|
||||
# Create script
|
||||
cat > "$path" << EOF
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
EOF
|
||||
|
||||
chmod +x "$path"
|
||||
|
||||
# Open script in editor on line 3
|
||||
"$EDITOR" +3 "$path"
|
||||
-208
@@ -1,208 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
pac_list=(
|
||||
at
|
||||
automake
|
||||
autopep8
|
||||
base
|
||||
base-devel
|
||||
bash-completion
|
||||
bash-language-server
|
||||
bc
|
||||
brightnessctl
|
||||
chromium
|
||||
dmidecode
|
||||
entr
|
||||
eslint_d
|
||||
feh
|
||||
firefox-developer-edition
|
||||
firefox-tridactyl
|
||||
firefox-tridactyl-native
|
||||
firefox-tridactyl-native-debug
|
||||
fzf
|
||||
gcc
|
||||
git
|
||||
haskell-language-server
|
||||
haskell-ormolu
|
||||
hsetroot
|
||||
htop
|
||||
httpie
|
||||
jq
|
||||
keepassxc
|
||||
kitty
|
||||
lua-language-server
|
||||
make
|
||||
man-db
|
||||
man-pages
|
||||
neovim
|
||||
nmap
|
||||
nodejs-lts-jod
|
||||
pacman-contrib
|
||||
pandoc-cli
|
||||
pandoc-crossref
|
||||
parallel
|
||||
pass
|
||||
pkgbuild-language-server
|
||||
pnpm
|
||||
ripgrep
|
||||
sshfs
|
||||
stylelint
|
||||
svelte-language-server
|
||||
tailwindcss-language-server
|
||||
task
|
||||
tldr
|
||||
tmux
|
||||
tmuxp
|
||||
tree
|
||||
tree-sitter-cli
|
||||
ts-node
|
||||
typescript-language-server
|
||||
unzip
|
||||
vim-language-server
|
||||
wget
|
||||
xclip
|
||||
yaml-language-server
|
||||
)
|
||||
|
||||
aurpac_list=(
|
||||
hadolint-bin
|
||||
nvm
|
||||
nvimpager
|
||||
paru
|
||||
tmux-bash-completion-git
|
||||
ttf-iosevka-term-ss08
|
||||
vim-plug
|
||||
vtsls
|
||||
xbanish
|
||||
)
|
||||
|
||||
install() {
|
||||
local package="$1"
|
||||
if pacman -Qi "$package" &> /dev/null; then
|
||||
echo "$package is already installed"
|
||||
else
|
||||
echo "Installing " "$package"
|
||||
sudo pacman -S --noconfirm --needed "$package"
|
||||
fi
|
||||
}
|
||||
|
||||
aurpac() {
|
||||
git clone "https://aur.archlinux.org/$1.git" "$HOME/.build/$1"
|
||||
}
|
||||
|
||||
install_packages() {
|
||||
announce "Installing packages"
|
||||
local count
|
||||
for pac in "${pac_list[@]}" ; do
|
||||
count=$((count+1))
|
||||
install "$pac";
|
||||
done
|
||||
echo "$count packages installed"
|
||||
}
|
||||
|
||||
install_dotfiles() {
|
||||
announce "Installing dotfiles"
|
||||
origin="https://git.hektormisplon.xyz/hektor/dots"
|
||||
git clone "$origin" "$HOME/dots"
|
||||
cp -r "$HOME/dots/.git" "$HOME/.git"
|
||||
git --git-dir="$HOME/.git" config --local status.showUntrackedFiles no
|
||||
git --git-dir="$HOME/.git" stash -m "[dots]"
|
||||
git --git-dir="$HOME/.git" stash apply
|
||||
git --git-dir="$HOME/.git" restore "$HOME"
|
||||
}
|
||||
|
||||
install_aur_packages() {
|
||||
announce "Installing AUR packages"
|
||||
local count
|
||||
for package in "${aurpac_list[@]}" ; do
|
||||
if pacman -Qi "$1" &> /dev/null; then
|
||||
echo "$1 is already installed"
|
||||
else
|
||||
count=$((count+1))
|
||||
aurpac "$package" && makepkg -si -D "$HOME/.build/$package"
|
||||
fi
|
||||
done
|
||||
echo "$count AUR packages installed"
|
||||
}
|
||||
|
||||
setup_neovim() {
|
||||
announce "Setting up NeoVim"
|
||||
git clone --depth=1 https://github.com/savq/paq-nvim.git \
|
||||
"${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/pack/paqs/start/paq-nvim
|
||||
}
|
||||
|
||||
setup_keyboard() {
|
||||
announce "Setting up keyboard"
|
||||
install "interception-tools"
|
||||
install "interception-caps2esc"
|
||||
udevmon_config_contents="\
|
||||
- JOB: intercept -g \$DEVNODE | caps2esc -m 1 | uinput -d \$DEVNODE
|
||||
DEVICE:
|
||||
EVENTS:
|
||||
EV_KEY: [KEY_CAPSLOCK]"
|
||||
if [ -f /etc/interception/udevmon.yaml ] && diff -q <(echo "$udevmon_config_contents") /etc/interception/udevmon.yaml; then
|
||||
echo "udevmon config already exists"
|
||||
echo "$udevmon_config_contents"
|
||||
elif [ -f /etc/interception/udevmon.yaml ]; then
|
||||
echo "interception udevmon.yaml already exists"
|
||||
cat /etc/interception/udevmon.yaml
|
||||
echo "verify if this config matches the one below"
|
||||
echo "$udevmon_config_contents"
|
||||
else
|
||||
echo "interception udevmon.yaml does not exist, creating one"
|
||||
sudo bash -c "echo '$udevmon_config_contents' > /etc/interception/udevmon.yaml"
|
||||
fi
|
||||
|
||||
sudo systemctl enable --now udevmon.service
|
||||
|
||||
if pgrep -x caps2esc > /dev/null; then
|
||||
echo "caps2esc is already running"
|
||||
else
|
||||
caps2esc -m 1
|
||||
fi
|
||||
}
|
||||
|
||||
configure_gnome() {
|
||||
announce "Configuring Gnome"; setup-gnome
|
||||
}
|
||||
|
||||
setup_firewall() {
|
||||
announce "Configuring firewalld"
|
||||
install firewalld
|
||||
sudo systemctl enable --now firewalld
|
||||
}
|
||||
|
||||
setup_docker() {
|
||||
announce "Setting up Docker"
|
||||
install docker
|
||||
install docker-compose
|
||||
sudo systemctl enable --now docker.socket
|
||||
sudo usermod -aG docker "$USER"
|
||||
echo "User added to docker group, please restart your session"
|
||||
}
|
||||
|
||||
announce() {
|
||||
local message="$1"
|
||||
echo " "
|
||||
echo "[dots] $message"
|
||||
echo " "
|
||||
}
|
||||
|
||||
confirm() {
|
||||
local question="$1"
|
||||
read -r -p "[dots] $question? [y/N]" -n 1
|
||||
case "$REPLY" in y|Y ) "$2";; * ) echo "Skipping"; esac
|
||||
}
|
||||
|
||||
printf '%s\n' "${pac_list[@]}"
|
||||
confirm "Install these packages? " install_packages
|
||||
printf '%s\n' "${aurpac_list[@]}"
|
||||
confirm "Install these AUR packages? " install_aur_packages
|
||||
confirm "Setup NeoVim? " setup_neovim
|
||||
confirm "Install dotfiles? " install_dotfiles
|
||||
confirm "Setup keyboard? " setup_keyboard
|
||||
if pacman -Qi "gdm" &> /dev/null; then
|
||||
confirm "Configure Gnome? " configure_gnome
|
||||
fi
|
||||
confirm "Setup firewall? " setup_firewall
|
||||
confirm "Setup Docker? " setup_docker
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
ssh_hosts="$(grep -E 'Host [a-z0-9\-]*$' ~/.ssh/config | awk '{print $2}')"
|
||||
|
||||
echo "$ssh_hosts"
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euf -o pipefail
|
||||
|
||||
VIM=${VIM:-"vim"}
|
||||
TMUX=${TMUX:-"tmux"}
|
||||
|
||||
FILE=${FILE:-"$(date +%F).tidal"}
|
||||
SESSION=${SESSION:-"tidal"}
|
||||
|
||||
TIDAL_BOOT_PATH=${TIDAL_BOOT_PATH:-""}
|
||||
GHCI=${GHCI:-""}
|
||||
|
||||
args=${*:-$FILE}
|
||||
|
||||
# attach if session else create
|
||||
$TMUX attach-session -t "$SESSION" || $TMUX new-session -s "$SESSION" \; \
|
||||
split-window -h -t "$SESSION" \; \
|
||||
send-keys -t 0 "$VIM $args" C-m \; \
|
||||
send-keys -t 1 "TIDAL_BOOT_PATH=$TIDAL_BOOT_PATH GHCI=$GHCI tidal" C-m \; \
|
||||
new-window -t "$SESSION":2 -n SuperDirt \; \
|
||||
send-keys -t 0 "jack_control start && sclang ~/dev/live/scripts/start.scd" C-m \; \
|
||||
select-window -t 1 \; \
|
||||
resize-pane -t 1 -x 100 \; \
|
||||
resize-pane -t 0 -x 125 \; \
|
||||
select-pane -t 0
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
session="main"
|
||||
|
||||
tmux attach-session -t $session || tmux new-session -s $session \; \
|
||||
rename-window task \; \
|
||||
send-keys -t 1 "task" C-m \; \
|
||||
new-window -n zk \; \
|
||||
send-keys -t 2 "nvim $ZK_PATH/index.md" C-m \; \
|
||||
new-window -n term \; \
|
||||
new-window -n music \; \
|
||||
send-keys -t 4 "echo 'TODO: open music player'" C-m \; \
|
||||
select-window -t 1 \;
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
status="$(bluetoothctl info "$1" | grep Connected | cut -f 2 -d ':' | cut -f 2 -d ' ')"
|
||||
|
||||
if [ "$status" == "yes" ]
|
||||
then
|
||||
bluetoothctl disconnect "$1"
|
||||
else
|
||||
trust "$1"
|
||||
bluetoothctl connect "$1"
|
||||
fi
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sudo pacman -Syu
|
||||
@@ -1,13 +0,0 @@
|
||||
# My dotfiles
|
||||
|
||||
To get started, run the following:
|
||||
|
||||
```
|
||||
bash <(curl -s https://git.hektormisplon.xyz/hektor/dots/raw/branch/master/.bin/setup)
|
||||
```
|
||||
|
||||
Note: will not set up *everything* (e.g. `/etc` configs, dependencies...), but
|
||||
should get you up and running.
|
||||
|
||||
2025-10-04: I am migrating from Arch Linux to NixOS. For this transition, these
|
||||
dotfiles are currently included as a subtree in my [NixOS repository](https://git.hektormisplon.xyz/hektor/nix).
|
||||
@@ -24,6 +24,7 @@
|
||||
};
|
||||
anki.enable = true;
|
||||
audio.enable = true;
|
||||
bin.enable = true;
|
||||
browser.primary = "librewolf";
|
||||
cloud.hetzner.enable = true;
|
||||
comms.signal.enable = true;
|
||||
@@ -57,7 +58,6 @@
|
||||
shell = {
|
||||
enable = true;
|
||||
bash.aliases.lang-js = true;
|
||||
bash.addBinToPath = true;
|
||||
};
|
||||
ssh.enable = true;
|
||||
taskwarrior.enable = true;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
anki.enable = true;
|
||||
archiving.enable = true;
|
||||
audio.enable = true;
|
||||
bin.enable = true;
|
||||
browser.enable = true;
|
||||
browser.primary = "librewolf";
|
||||
cloud.hetzner.enable = true;
|
||||
@@ -50,7 +51,6 @@
|
||||
shell = {
|
||||
enable = true;
|
||||
bash.aliases.lang-js = true;
|
||||
bash.addBinToPath = true;
|
||||
};
|
||||
ssh.enable = true;
|
||||
deploy.enable = true;
|
||||
|
||||
@@ -11,6 +11,10 @@ let
|
||||
in
|
||||
{
|
||||
options.anki.enable = lib.mkEnableOption "Anki";
|
||||
options.anki.reviewsCache = lib.mkOption {
|
||||
default = "/tmp/anki-reviews";
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
secrets.files.anki = [
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
script =
|
||||
name: args:
|
||||
pkgs.writeShellApplication (
|
||||
{
|
||||
inherit name;
|
||||
text = builtins.readFile ./scripts/${name};
|
||||
}
|
||||
// args
|
||||
);
|
||||
pythonScript =
|
||||
name: runtimeInputs:
|
||||
pkgs.writeShellApplication {
|
||||
inherit name runtimeInputs;
|
||||
text = ''exec ${lib.getExe pkgs.python3} ${pkgs.writeTextDir name (builtins.readFile ./scripts/${name})}/${name} "$@"'';
|
||||
};
|
||||
ssh-hosts = script "ssh-hosts" {
|
||||
runtimeInputs = with pkgs; [
|
||||
gnugrep
|
||||
gawk
|
||||
];
|
||||
};
|
||||
scripts = with pkgs; {
|
||||
bak.runtimeInputs = [ coreutils ];
|
||||
notify.runtimeInputs = [ libnotify ];
|
||||
pdftitle.runtimeInputs = [
|
||||
poppler-utils
|
||||
gawk
|
||||
coreutils
|
||||
];
|
||||
fzf-book.runtimeInputs = [
|
||||
findutils
|
||||
fzf
|
||||
coreutils
|
||||
];
|
||||
fzf-ssh.runtimeInputs = [
|
||||
ssh-hosts
|
||||
fzf
|
||||
];
|
||||
save-ssh-host = {
|
||||
runtimeInputs = [
|
||||
ssh-hosts
|
||||
fzf
|
||||
];
|
||||
excludeShellChecks = [ "SC2029" ];
|
||||
};
|
||||
fzf-fontnames.runtimeInputs = [
|
||||
fontconfig
|
||||
fzf
|
||||
gawk
|
||||
coreutils
|
||||
];
|
||||
get-anki-decks.runtimeInputs = [
|
||||
curl
|
||||
jq
|
||||
];
|
||||
get-anki-reviews-status = {
|
||||
runtimeInputs = [ coreutils ];
|
||||
runtimeEnv.ANKI_REVIEWS = config.anki.reviewsCache;
|
||||
};
|
||||
};
|
||||
pythonScripts = with pkgs; {
|
||||
pomo = [ libnotify ];
|
||||
taskdeps = [ ];
|
||||
};
|
||||
in
|
||||
{
|
||||
options.bin.enable = lib.mkOption {
|
||||
default = false;
|
||||
type = lib.types.bool;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.bin.enable {
|
||||
home.packages = [
|
||||
ssh-hosts
|
||||
]
|
||||
++ lib.mapAttrsToList script scripts
|
||||
++ lib.mapAttrsToList pythonScript pythonScripts;
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# back up a file by copying it to a new file with a .bak extension
|
||||
# reference: https://askubuntu.com/questions/962489/is-there-any-way-to-create-backup-copy-of-a-file-without-type-its-name-twice
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Generate menu of book filenames and save paths
|
||||
# Preview window contains metadata
|
||||
|
||||
function get_book_paths {
|
||||
find /home/h/doc/books/ -regex '.*\.\(pdf\|epub\|djvu\)' -type f | sort
|
||||
find "$HOME/doc/books/" -regex '.*\.\(pdf\|epub\|djvu\)' -type f | sort
|
||||
}
|
||||
|
||||
function select_file {
|
||||
@@ -21,10 +19,8 @@ function open {
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
case "${1:-}" in
|
||||
--open) open "$(select_file)" ;;
|
||||
--help) printf "open \n" >&2 ;;
|
||||
*) open "$(select_file)" ;;
|
||||
esac
|
||||
|
||||
[[ -n "$selected" ]] && xdg-open "$selected" &> /dev/null & disown
|
||||
@@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
fn="/tmp/fontnames.txt"
|
||||
|
||||
contains_dash() {
|
||||
@@ -7,16 +5,16 @@ contains_dash() {
|
||||
}
|
||||
|
||||
update() {
|
||||
echo "" > "$fn"
|
||||
: > "$fn"
|
||||
|
||||
font_list=$(fc-list -f "%{fullname}\n")
|
||||
|
||||
echo "$font_list" | while read line ; do
|
||||
echo "$font_list" | while read -r line ; do
|
||||
|
||||
first="$(echo "$line" | cut -d',' -f1)"
|
||||
last="$(echo "$line" | cut -d',' -f2)"
|
||||
|
||||
if $(contains_dash "$first"); then
|
||||
if contains_dash "$first"; then
|
||||
echo "$last" >> "$fn"
|
||||
else
|
||||
echo "$first" >> "$fn"
|
||||
@@ -24,7 +22,7 @@ update() {
|
||||
done
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
case "${1:-}" in
|
||||
--update) update;;
|
||||
*) cat "$fn" | sort | uniq | awk 'NF' | fzf;;
|
||||
*) sort -u "$fn" | awk 'NF' | fzf;;
|
||||
esac
|
||||
@@ -1,3 +1 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
ssh "$(ssh-hosts | fzf)"
|
||||
@@ -1,3 +1 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
curl 127.0.0.1:8765 -X POST -d '{"action": "deckNames", "version": 6}' | jq '.result[]' -r
|
||||
+1
-3
@@ -1,8 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Get Anki review status from exit code
|
||||
|
||||
num_reviews="$(cat /tmp/anki-reviews)"
|
||||
num_reviews="$(cat "$ANKI_REVIEWS")"
|
||||
|
||||
if [ "$num_reviews" -ge "400" ]
|
||||
then
|
||||
@@ -1,8 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Pipe into notify-send
|
||||
#
|
||||
# e.g. `echo "Hello world" | notify`
|
||||
|
||||
read -r msg
|
||||
read -r msg || true
|
||||
notify-send "$msg" "$@"
|
||||
@@ -1,3 +1 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
pdfinfo "$1" | head -n 1 | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'
|
||||
@@ -10,11 +10,11 @@ Pomodoro timer
|
||||
|
||||
import atexit
|
||||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
from argparse import ArgumentParser
|
||||
from time import sleep
|
||||
|
||||
from plyer import notification
|
||||
|
||||
POMO_PATH = os.path.join(
|
||||
os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share")), "pomo"
|
||||
)
|
||||
@@ -30,17 +30,14 @@ def format_mins_secs(mins, secs):
|
||||
return f"{mins:02d}:{secs:02d}"
|
||||
|
||||
|
||||
def make_countdown():
|
||||
def countdown(duration):
|
||||
while duration != 0:
|
||||
mins = duration // 60
|
||||
secs = duration % 60
|
||||
time_str = format_mins_secs(mins, secs)
|
||||
os.system(f'echo -n "{time_str}" > {POMO_PATH}')
|
||||
sleep(1)
|
||||
duration -= 1
|
||||
|
||||
return countdown
|
||||
def countdown(duration):
|
||||
while duration != 0:
|
||||
mins = duration // 60
|
||||
secs = duration % 60
|
||||
with open(POMO_PATH, "w") as f:
|
||||
f.write(format_mins_secs(mins, secs))
|
||||
sleep(1)
|
||||
duration -= 1
|
||||
|
||||
|
||||
def main(args):
|
||||
@@ -48,16 +45,13 @@ def main(args):
|
||||
break_duration = args.break_duration * 60
|
||||
repeats = args.repeats
|
||||
|
||||
work_countdown = make_countdown()
|
||||
break_countdown = make_countdown()
|
||||
|
||||
while repeats != 0:
|
||||
notification.notify(title="Get started")
|
||||
work_countdown(work_duration)
|
||||
subprocess.run(["notify-send", "Get started"])
|
||||
countdown(work_duration)
|
||||
if break_duration != 0:
|
||||
notification.notify(title="Time for a break")
|
||||
break_countdown(break_duration)
|
||||
notification.notify(title="Break is over, back to work")
|
||||
subprocess.run(["notify-send", "Time for a break"])
|
||||
countdown(break_duration)
|
||||
subprocess.run(["notify-send", "Break is over, back to work"])
|
||||
repeats -= 1
|
||||
|
||||
|
||||
@@ -84,4 +78,10 @@ if __name__ == "__main__":
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
main(args)
|
||||
signal.signal(signal.SIGINT, handle_signal)
|
||||
signal.signal(signal.SIGTERM, handle_signal)
|
||||
|
||||
if args.clear:
|
||||
clear()
|
||||
else:
|
||||
main(args)
|
||||
@@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
selected_hosts="$(ssh-hosts | fzf -m)"
|
||||
|
||||
for host in $selected_hosts; do
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
grep -E 'Host [a-z0-9\-]*$' ~/.ssh/config | awk '{print $2}'
|
||||
@@ -7,12 +7,8 @@ from collections import defaultdict
|
||||
|
||||
|
||||
def get_task_data():
|
||||
command = (
|
||||
"task +PENDING or +WAITING -COMPLETED -DELETED export | "
|
||||
"jq '[.[] | {uuid: .uuid, id, depends: .depends, description: .description, status: .status }]'"
|
||||
)
|
||||
output = subprocess.check_output(command, shell=True)
|
||||
return json.loads(output)
|
||||
command = ["task", "+PENDING", "or", "+WAITING", "-COMPLETED", "-DELETED", "export"]
|
||||
return json.loads(subprocess.check_output(command))
|
||||
|
||||
|
||||
def parse_task_data(data):
|
||||
@@ -27,61 +23,14 @@ def parse_task_data(data):
|
||||
"description": task.get("description", "No description"),
|
||||
"status": task.get("status", "Unknown status"),
|
||||
}
|
||||
if task["depends"]:
|
||||
for dependency in task["depends"]:
|
||||
dependency_graph[dependency].append(task_id)
|
||||
dependent_tasks.add(task_id)
|
||||
for dependency in task.get("depends", []):
|
||||
dependency_graph[dependency].append(task_id)
|
||||
dependent_tasks.add(task_id)
|
||||
|
||||
root_tasks = set(task_details.keys()) - dependent_tasks
|
||||
return task_details, dependency_graph, root_tasks
|
||||
|
||||
|
||||
def get_all_parents(task_id, dependency_graph):
|
||||
return [
|
||||
parent for parent, children in dependency_graph.items() if task_id in children
|
||||
]
|
||||
|
||||
|
||||
def build_ascii_dag(
|
||||
task_id,
|
||||
task_details,
|
||||
dependency_graph,
|
||||
prefix="",
|
||||
is_last=True,
|
||||
show_id=True,
|
||||
visited=None,
|
||||
):
|
||||
if visited is None:
|
||||
visited = set()
|
||||
|
||||
if task_id in visited:
|
||||
return [f"{prefix}{'└── ' if is_last else '├── '}... (cycle detected)"]
|
||||
|
||||
visited.add(task_id)
|
||||
|
||||
task_info = task_details[task_id]
|
||||
task_line = f"{prefix}{'└── ' if is_last else '├── '}{task_info['id'] + ': ' if show_id else ''}{task_info['description']} ({task_info['status']})"
|
||||
lines = [task_line]
|
||||
|
||||
children = dependency_graph.get(task_id, [])
|
||||
for idx, child in enumerate(children):
|
||||
child_is_last = idx == len(children) - 1
|
||||
child_prefix = prefix + (" " if is_last else "│ ")
|
||||
lines.extend(
|
||||
build_ascii_dag(
|
||||
child,
|
||||
task_details,
|
||||
dependency_graph,
|
||||
child_prefix,
|
||||
child_is_last,
|
||||
show_id,
|
||||
visited.copy(),
|
||||
)
|
||||
)
|
||||
|
||||
return lines
|
||||
|
||||
|
||||
def render_dependency_dag(task_details, dependency_graph, root_tasks, show_id):
|
||||
dag_lines = []
|
||||
global_visited = set()
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
lib',
|
||||
...
|
||||
}:
|
||||
|
||||
@@ -22,11 +21,6 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
addBinToPath = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
extraInit = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
@@ -65,7 +59,5 @@ in
|
||||
${cfg.extraInit}
|
||||
'';
|
||||
};
|
||||
|
||||
home.sessionPath = lib.optional cfg.addBinToPath "${lib'.dotsPath}/.bin";
|
||||
};
|
||||
}
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
# Anki review percentage for statusbar
|
||||
|
||||
num_to_review=200
|
||||
|
||||
# Get current card count from Anki
|
||||
count=$(curl -s 127.0.0.1:8765 -X POST -d '{"action": "getNumCardsReviewedToday", "version": 6}' | jq '.result') || count=
|
||||
|
||||
if [ -n "$count" ]; then
|
||||
echo "$count" > "$ANKI_REVIEWS"
|
||||
elif [ ! -s "$ANKI_REVIEWS" ]; then
|
||||
echo "-1" > "$ANKI_REVIEWS"
|
||||
fi
|
||||
|
||||
num_reviews=$(cat "$ANKI_REVIEWS")
|
||||
echo -n " Reviews: $(awk -v n="$num_reviews" -v t="$num_to_review" 'BEGIN { printf "%.2f%%", 100 * n / t }') "
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
pomo="${XDG_DATA_HOME:-$HOME/.local/share}/pomo"
|
||||
if [ -f "$pomo" ]; then cat "$pomo"; fi
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
# Render contents of $HOME/.project if present
|
||||
if [ -f "$HOME/.project" ]; then cat "$HOME/.project"; fi
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
num_done="$(task end.after:today status:completed count)"
|
||||
num_pending="$(($(task count status:pending) + num_done))"
|
||||
num_waiting="$(task count status:waiting)"
|
||||
|
||||
echo "Tasks: $num_done/$num_pending+$num_waiting"
|
||||
@@ -1,59 +1,115 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
status =
|
||||
name: args:
|
||||
lib.getExe (
|
||||
pkgs.writeShellApplication (
|
||||
{
|
||||
inherit name;
|
||||
text = builtins.readFile ./scripts/${name};
|
||||
}
|
||||
// args
|
||||
)
|
||||
);
|
||||
in
|
||||
{
|
||||
programs.waybar.settings = [
|
||||
{
|
||||
height = 16;
|
||||
spacing = 4;
|
||||
modules-left = [ "niri/workspaces" ];
|
||||
modules-right = [
|
||||
"pulseaudio"
|
||||
"memory"
|
||||
"cpu"
|
||||
"network"
|
||||
"clock"
|
||||
"battery"
|
||||
];
|
||||
clock = {
|
||||
format = "W{:%V %d %b %H:%M}";
|
||||
tooltip-format = "{calendar}";
|
||||
format-alt = "{:%Y-%m-%d %H:%M:%S}";
|
||||
};
|
||||
battery = {
|
||||
bat = "BAT0";
|
||||
adapter = "ADP1";
|
||||
interval = 5;
|
||||
full-at = 99;
|
||||
states = {
|
||||
good = 80;
|
||||
warning = 20;
|
||||
critical = 10;
|
||||
(
|
||||
{
|
||||
height = 16;
|
||||
spacing = 4;
|
||||
modules-left = [ "niri/workspaces" ];
|
||||
modules-right = [
|
||||
"custom/project"
|
||||
"custom/pomo"
|
||||
]
|
||||
++ lib.optional config.taskwarrior.enable "custom/tasks"
|
||||
++ lib.optional config.anki.enable "custom/anki"
|
||||
++ [
|
||||
"pulseaudio"
|
||||
"memory"
|
||||
"cpu"
|
||||
"network"
|
||||
"clock"
|
||||
"battery"
|
||||
];
|
||||
clock = {
|
||||
format = "W{:%V %d %b %H:%M}";
|
||||
tooltip-format = "{calendar}";
|
||||
format-alt = "{:%Y-%m-%d %H:%M:%S}";
|
||||
};
|
||||
format = "{capacity}%--";
|
||||
format-charging = "{capacity}%++";
|
||||
format-plugged = "{capacity}%";
|
||||
format-alt = "{time} {power}W";
|
||||
};
|
||||
pulseaudio = {
|
||||
format = "VOL {volume}%";
|
||||
format-muted = "muted";
|
||||
on-click = "pavucontrol";
|
||||
};
|
||||
memory = {
|
||||
interval = 2;
|
||||
format = "RAM {percentage}%";
|
||||
format-alt = "RAM {used:0.1f}G/{total:0.1f}G";
|
||||
};
|
||||
cpu = {
|
||||
interval = 2;
|
||||
format = "CPU {usage}%";
|
||||
format-alt = "CPU {avg_frequency}GHz";
|
||||
};
|
||||
network = {
|
||||
interval = 5;
|
||||
format-wifi = "{ifname} {ipaddr} {essid}";
|
||||
format-ethernet = "{ifname} {ipaddr}";
|
||||
format-disconnected = "{ifname} disconnected";
|
||||
tooltip-format = "{ifname}: {ipaddr}/{cidr}";
|
||||
};
|
||||
}
|
||||
battery = {
|
||||
bat = "BAT0";
|
||||
adapter = "ADP1";
|
||||
interval = 5;
|
||||
full-at = 99;
|
||||
states = {
|
||||
good = 80;
|
||||
warning = 20;
|
||||
critical = 10;
|
||||
};
|
||||
format = "{capacity}%--";
|
||||
format-charging = "{capacity}%++";
|
||||
format-plugged = "{capacity}%";
|
||||
format-alt = "{time} {power}W";
|
||||
};
|
||||
pulseaudio = {
|
||||
format = "VOL {volume}%";
|
||||
format-muted = "muted";
|
||||
on-click = "pavucontrol";
|
||||
};
|
||||
memory = {
|
||||
interval = 2;
|
||||
format = "RAM {percentage}%";
|
||||
format-alt = "RAM {used:0.1f}G/{total:0.1f}G";
|
||||
};
|
||||
cpu = {
|
||||
interval = 2;
|
||||
format = "CPU {usage}%";
|
||||
format-alt = "CPU {avg_frequency}GHz";
|
||||
};
|
||||
network = {
|
||||
interval = 5;
|
||||
format-wifi = "{ifname} {ipaddr} {essid}";
|
||||
format-ethernet = "{ifname} {ipaddr}";
|
||||
format-disconnected = "{ifname} disconnected";
|
||||
tooltip-format = "{ifname}: {ipaddr}/{cidr}";
|
||||
};
|
||||
"custom/project" = {
|
||||
exec = status "sb-project" { runtimeInputs = [ pkgs.coreutils ]; };
|
||||
interval = 30;
|
||||
};
|
||||
"custom/pomo" = {
|
||||
exec = status "sb-pomo" { runtimeInputs = [ pkgs.coreutils ]; };
|
||||
interval = 1;
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs config.taskwarrior.enable {
|
||||
"custom/tasks" = {
|
||||
exec = status "sb-tasks" { runtimeInputs = [ config.programs.taskwarrior.package ]; };
|
||||
interval = 60;
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs config.anki.enable {
|
||||
"custom/anki" = {
|
||||
exec = status "sb-anki" {
|
||||
runtimeInputs = with pkgs; [
|
||||
coreutils
|
||||
curl
|
||||
gawk
|
||||
jq
|
||||
];
|
||||
runtimeEnv.ANKI_REVIEWS = config.anki.reviewsCache;
|
||||
};
|
||||
interval = 300;
|
||||
};
|
||||
}
|
||||
)
|
||||
];
|
||||
}
|
||||
+1
-3
@@ -4,7 +4,5 @@ let
|
||||
fs = import ./fs.nix { inherit lib; };
|
||||
hosts = import ./hosts.nix { inherit lib; };
|
||||
secrets = import ./secrets.nix { inherit lib; };
|
||||
|
||||
dotsPath = ../dots;
|
||||
in
|
||||
fs // hosts // secrets // { inherit dotsPath; }
|
||||
fs // hosts // secrets
|
||||
Reference in new issue
Block a user