refactoring to more granular flakes and modules
This commit is contained in:
parent
6570da6f33
commit
50825c9b84
52 changed files with 2501 additions and 9 deletions
17
flakes/common/nix_modules/docker.nix
Normal file
17
flakes/common/nix_modules/docker.nix
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
config,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
virtualisation.docker = {
|
||||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
};
|
||||
users.extraGroups.docker.members = builtins.AttrNames config.users.users;
|
||||
environment.shellAliases = {
|
||||
dockerv = "docker volume";
|
||||
dockeri = "docker image";
|
||||
dockerc = "docker container";
|
||||
};
|
||||
}
|
||||
55
flakes/common/nix_modules/essentials/default.nix
Normal file
55
flakes/common/nix_modules/essentials/default.nix
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
# Essentials
|
||||
vim
|
||||
nano
|
||||
wget
|
||||
curl
|
||||
traceroute
|
||||
dig
|
||||
fastfetch
|
||||
jq
|
||||
bat
|
||||
htop
|
||||
unzip
|
||||
fzf
|
||||
ripgrep
|
||||
lsof
|
||||
killall
|
||||
speedtest-cli
|
||||
];
|
||||
|
||||
environment.shellAliases = {
|
||||
n = "nvim";
|
||||
nn = "nvim --headless '+SessionDelete' +qa > /dev/null 2>&1 && nvim";
|
||||
bat = "bat --theme Coldark-Dark";
|
||||
cat = "bat --pager=never -p";
|
||||
|
||||
# TODO this may not be needed now that I am using `nh` clean mode (see /hosts/_common/configuration.nix#programs.nh)
|
||||
nix-boot-clean = "find '/boot/loader/entries' -type f ! -name 'windows.conf' | head -n -4 | xargs -I {} rm {}; nix store gc; nixos-rebuild boot; echo; df";
|
||||
ndr = "nix-direnv-reload";
|
||||
|
||||
# general unix
|
||||
date_compact = "date +'%Y%m%d'";
|
||||
date_short = "date +'%Y-%m-%d'";
|
||||
ls = "ls --color -Gah";
|
||||
ll = "ls --color -Galhtr";
|
||||
lss = "du --max-depth=0 -h {.,}* 2>/dev/null | sort -hr";
|
||||
psg = "ps aux | head -n 1 && ps aux | grep -v 'grep' | grep";
|
||||
|
||||
# ripgrep
|
||||
rg = "rg --no-ignore";
|
||||
rgf = "rg --files --glob '!/nix/store/**' 2>/dev/null | rg";
|
||||
};
|
||||
|
||||
environment.shellInit = lib.concatStringsSep "\n\n" [
|
||||
(builtins.readFile ./unix_utils.func.sh)
|
||||
(builtins.readFile ./nixpkg.func.sh)
|
||||
];
|
||||
}
|
||||
13
flakes/common/nix_modules/essentials/nixpkg.func.sh
Normal file
13
flakes/common/nix_modules/essentials/nixpkg.func.sh
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# nix
|
||||
alias nixpkgs=nixpkg
|
||||
nixpkg () {
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Error: No arguments provided. Please specify at least one package."
|
||||
return 1
|
||||
fi
|
||||
cmd="nix shell"
|
||||
for pkg in "$@"; do
|
||||
cmd="$cmd \"nixpkgs#$pkg\""
|
||||
done
|
||||
eval $cmd
|
||||
}
|
||||
65
flakes/common/nix_modules/essentials/unix_utils.func.sh
Normal file
65
flakes/common/nix_modules/essentials/unix_utils.func.sh
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# Check if ~/.config/environment exists and source all files within it
|
||||
if [ -d "$HOME/.config/environment" ]; then
|
||||
for file in "$HOME/.config/environment/"*; do
|
||||
if [ -r "$file" ]; then
|
||||
if ! . "$file"; then
|
||||
echo "Failed to source $file"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
htop_psg () {
|
||||
htop -p $(psg $1 | awk '{r=r s $2;s=","} END{print r}')
|
||||
}
|
||||
|
||||
htop_pid () {
|
||||
htop -p $(ps -ef | awk -v proc=$1 '$3 == proc { cnt++;if (cnt == 1) { printf "%s",$2 } else { printf ",%s",$2 } }')
|
||||
}
|
||||
|
||||
psg_kill() {
|
||||
ps aux | grep -v "grep" | grep "${1}" | awk '{print $2}' | while read -r pid; do
|
||||
if [ -n "${pid}" ]; then
|
||||
echo "killing ${pid}"
|
||||
kill -9 "${pid}" &> /dev/null
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
psg_terminate() {
|
||||
ps aux | grep -v "grep" | grep "${1}" | awk '{print $2}' | while read -r pid; do
|
||||
if [ -n "${pid}" ]; then
|
||||
echo "Terminating ${pid}"
|
||||
kill -15 "${pid}" &> /dev/null
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
psg_skill() {
|
||||
ps aux | grep -v "grep" | grep "${1}" | awk '{print $2}' | while read -r pid; do
|
||||
if [ -n "${pid}" ]; then
|
||||
echo "Killing ${pid}"
|
||||
sudo kill -9 "${pid}" &> /dev/null
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
mail_clear() {
|
||||
: > /var/mail/$USER
|
||||
}
|
||||
|
||||
speedtest_fs () {
|
||||
dir=$(pwd)
|
||||
drive=$(df -h ${dir} | awk 'NR==2 {print $1}')
|
||||
echo Testing read speeds on drive ${drive}
|
||||
sudo hdparm -Tt ${drive}
|
||||
test_file=$(date +%u%m%d)
|
||||
test_file="${dir}/speedtest_fs_${test_file}"
|
||||
echo
|
||||
echo Testing write speeds into test file: ${test_file}
|
||||
dd if=/dev/zero of=${test_file} bs=8k count=10k; rm -f ${test_file}
|
||||
}
|
||||
|
||||
speedtest_internet () {
|
||||
speedtest-cli
|
||||
}
|
||||
213
flakes/common/nix_modules/git/branch.func.sh
Normal file
213
flakes/common/nix_modules/git/branch.func.sh
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
branch() {
|
||||
local branch_name=${1:-}
|
||||
|
||||
# helper: set tmux window name. If tmux is in auto mode, always rename.
|
||||
# If tmux is manual but the current window name matches the previous branch,
|
||||
# allow renaming from previous branch name to the new one.
|
||||
_branch__maybe_set_tmux_name() {
|
||||
if ! command -v tmux_window >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
local new_name prev_branch tmux_status tmux_cur
|
||||
new_name=${1:-}
|
||||
prev_branch=${2:-}
|
||||
tmux_status=$(tmux_window status 2>/dev/null || true)
|
||||
if [ "$tmux_status" = "auto" ]; then
|
||||
tmux_window rename "$new_name" 2>/dev/null || true
|
||||
return 0
|
||||
fi
|
||||
# tmux is manual. If the current tmux name matches the previous branch,
|
||||
# we consider it safe to update it to the new branch name.
|
||||
if [ -n "$prev_branch" ]; then
|
||||
tmux_cur=$(tmux_window get 2>/dev/null || true)
|
||||
if [ "$tmux_cur" = "$prev_branch" ]; then
|
||||
tmux_window rename "$new_name" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# helper: revert tmux to automatic rename only if current tmux name matches previous branch
|
||||
_branch__revert_tmux_auto() {
|
||||
if ! command -v tmux_window >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
local prev_branch=${1:-}
|
||||
if [ -z "$prev_branch" ]; then
|
||||
tmux_window rename 2>/dev/null || true
|
||||
return 0
|
||||
fi
|
||||
local tmux_cur
|
||||
tmux_cur=$(tmux_window get 2>/dev/null || true)
|
||||
if [ "$tmux_cur" = "$prev_branch" ]; then
|
||||
tmux_window rename 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
# Determine repo root early so we can run branches inside it
|
||||
local common_dir
|
||||
if ! common_dir=$(git rev-parse --git-common-dir 2>/dev/null); then
|
||||
echo "Not inside a git repository." >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "${common_dir#/}" = "$common_dir" ]; then
|
||||
common_dir="$(pwd)/$common_dir"
|
||||
fi
|
||||
local repo_dir="${common_dir%%/.git*}"
|
||||
if [ -z "$repo_dir" ]; then
|
||||
echo "Unable to determine repository root." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# If no branch was provided, present an interactive selector combining local and remote branches
|
||||
if [ -z "$branch_name" ]; then
|
||||
if ! command -v fzf >/dev/null 2>&1; then
|
||||
echo "Usage: branch <name>" >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
local branches_list_raw branches_list selection
|
||||
# Gather local and remote branches with fallbacks to ensure locals appear
|
||||
branches_list_raw=""
|
||||
if declare -f local_branches >/dev/null 2>&1; then
|
||||
branches_list_raw=$(cd "$repo_dir" && local_branches 2>/dev/null || true; cd "$repo_dir" && remote_branches 2>/dev/null || true)
|
||||
fi
|
||||
branches_list=$(printf "%s
|
||||
" "$branches_list_raw" | awk '!seen[$0]++')
|
||||
if [ -z "$branches_list" ]; then
|
||||
echo "No branches found." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
fzf_out=$(printf "%s\n" "$branches_list" | fzf --height=40% --prompt="Select branch: " --print-query)
|
||||
if [ -z "$fzf_out" ]; then
|
||||
echo "No branch selected." >&2
|
||||
return 1
|
||||
fi
|
||||
branch_query=$(printf "%s\n" "$fzf_out" | sed -n '1p')
|
||||
branch_selection=$(printf "%s\n" "$fzf_out" | sed -n '2p')
|
||||
if [ -n "$branch_selection" ]; then
|
||||
branch_name="$branch_selection"
|
||||
else
|
||||
# user typed something in fzf but didn't select: use that as new branch name
|
||||
branch_name=$(printf "%s" "$branch_query" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||
fi
|
||||
fi
|
||||
|
||||
local repo_base repo_hash default_branch
|
||||
repo_base=$(basename "$repo_dir")
|
||||
repo_hash=$(printf "%s" "$repo_dir" | sha1sum | awk '{print $1}')
|
||||
|
||||
default_branch=$(getdefault)
|
||||
|
||||
# capture current branch name as seen by tmux so we can decide safe renames later
|
||||
local prev_branch
|
||||
prev_branch=$(git -C "$PWD" rev-parse --abbrev-ref HEAD 2>/dev/null || true)
|
||||
|
||||
# Special-case: jump to the main working tree on the default branch
|
||||
if [ "$branch_name" = "default" ] || [ "$branch_name" = "master" ] || [ "$branch_name" = "$default_branch" ]; then
|
||||
if [ "$repo_dir" = "$PWD" ]; then
|
||||
echo "Already in the main working tree on branch '$default_branch'."
|
||||
return 0
|
||||
fi
|
||||
echo "Switching to main working tree on branch '$default_branch'."
|
||||
# capture current branch name as seen by tmux so we only revert if it matches
|
||||
prev_branch=$(git -C "$PWD" rev-parse --abbrev-ref HEAD 2>/dev/null || true)
|
||||
cd "$repo_dir" || return 1
|
||||
_branch__revert_tmux_auto "$prev_branch" || true
|
||||
return 0
|
||||
fi
|
||||
|
||||
# If a worktree for this branch is already registered elsewhere, open a shell there
|
||||
local existing
|
||||
existing=$(git -C "$repo_dir" worktree list --porcelain 2>/dev/null | awk -v b="$branch_name" 'BEGIN{RS="";FS="\n"} $0 ~ "refs/heads/"b{for(i=1;i<=NF;i++) if ($i ~ /^worktree /){ sub(/^worktree /,"",$i); print $i }}')
|
||||
if [ -n "$existing" ]; then
|
||||
echo "Opening existing worktree for branch '$branch_name' at '$existing'."
|
||||
cd "$existing" || return 1
|
||||
_branch__maybe_set_tmux_name "$branch_name" "$prev_branch" || true
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Ensure we have up-to-date remote info
|
||||
git -C "$repo_dir" fetch --all --prune || true
|
||||
|
||||
local wt_root wt_path
|
||||
if [ -z "$xdg" ]; then
|
||||
xdg="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
fi
|
||||
wt_root="$xdg/git_worktrees/${repo_base}_${repo_hash}"
|
||||
wt_path="$wt_root/$branch_name"
|
||||
|
||||
# ensure worktree root exists
|
||||
if [ ! -d "$wt_root" ]; then
|
||||
mkdir -p "$wt_root" || { echo "Failed to create worktree root: $wt_root" >&2; return 1; }
|
||||
fi
|
||||
|
||||
# If worktree already exists at our expected path, open a shell there
|
||||
if [ -d "$wt_path" ]; then
|
||||
echo "Opening existing worktree at '$wt_path'."
|
||||
cd "$wt_path" || return 1
|
||||
_branch__maybe_set_tmux_name "$branch_name" "$prev_branch" || true
|
||||
return 0
|
||||
fi
|
||||
|
||||
local branch_exists branch_from local_exists
|
||||
branch_exists=$(git -C "$repo_dir" ls-remote --heads origin "$branch_name" | wc -l)
|
||||
# check if a local branch exists
|
||||
if git -C "$repo_dir" show-ref --verify --quiet "refs/heads/$branch_name"; then
|
||||
local_exists=1
|
||||
else
|
||||
local_exists=0
|
||||
fi
|
||||
|
||||
branch_from="$default_branch"
|
||||
if [ "$branch_exists" -eq 0 ]; then
|
||||
if [ "$local_exists" -eq 1 ]; then
|
||||
branch_from="$branch_name"
|
||||
echo "Branch '$branch_name' exists locally; creating worktree from local branch."
|
||||
else
|
||||
echo "Branch '$branch_name' does not exist on remote; creating from '$branch_from'."
|
||||
fi
|
||||
else
|
||||
branch_from="origin/$branch_name"
|
||||
echo "Branch '$branch_name' exists on remote; creating worktree tracking it."
|
||||
fi
|
||||
|
||||
echo "Creating new worktree for branch '$branch_name' at '$wt_path'."
|
||||
|
||||
# Try to add or update worktree from the resolved ref. Use a fallback path if needed.
|
||||
if [ "$local_exists" -eq 1 ]; then
|
||||
if git -C "$repo_dir" worktree add "$wt_path" "$branch_name" 2>/dev/null; then
|
||||
cd "$wt_path" || return 1
|
||||
_branch__maybe_set_tmux_name "$branch_name" "$prev_branch" || true
|
||||
return 0
|
||||
fi
|
||||
|
||||
else
|
||||
if git -C "$repo_dir" worktree add -b "$branch_name" "$wt_path" "$branch_from" 2>/dev/null; then
|
||||
cd "$wt_path" || return 1
|
||||
_branch__maybe_set_tmux_name "$branch_name" "$prev_branch" || true
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fallback: try to resolve a concrete SHA and create the branch ref locally, then add worktree
|
||||
local start_sha
|
||||
if start_sha=$(git -C "$repo_dir" rev-parse --verify "$branch_from" 2>/dev/null); then
|
||||
if git -C "$repo_dir" branch "$branch_name" "$start_sha" 2>/dev/null; then
|
||||
if git -C "$repo_dir" worktree add "$wt_path" "$branch_name" 2>/dev/null; then
|
||||
cd "$wt_path" || return 1
|
||||
_branch__maybe_set_tmux_name "$branch_name" "$prev_branch" || true
|
||||
return 0
|
||||
else
|
||||
git -C "$repo_dir" branch -D "$branch_name" 2>/dev/null || true
|
||||
rmdir "$wt_path" 2>/dev/null || true
|
||||
echo "Failed to add worktree after creating branch ref." >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Failed to add worktree for branch '$branch_name'." >&2
|
||||
rmdir "$wt_path" 2>/dev/null || true
|
||||
return 1
|
||||
}
|
||||
131
flakes/common/nix_modules/git/branchd.func.sh
Normal file
131
flakes/common/nix_modules/git/branchd.func.sh
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
branchdel() {
|
||||
# branchdel — remove a branch worktree (optional branch arg)
|
||||
local branch_arg
|
||||
branch_arg="$1"
|
||||
local wt_path
|
||||
wt_path=$(pwd)
|
||||
local common_dir repo_dir
|
||||
if ! common_dir=$(git rev-parse --git-common-dir 2>/dev/null); then
|
||||
echo "Not inside a git repository." >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "${common_dir#/}" = "$common_dir" ]; then
|
||||
common_dir="$(pwd)/$common_dir"
|
||||
fi
|
||||
repo_dir="${common_dir%%/.git*}"
|
||||
if [ -z "$repo_dir" ]; then
|
||||
echo "Unable to determine repository root." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# determine current branch in this worktree
|
||||
local current default_branch branch target_wt
|
||||
current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || { echo "Not inside a git repository." >&2; return 1; }
|
||||
|
||||
default_branch=$(getdefault)
|
||||
|
||||
# choose branch: provided arg or current
|
||||
if [ -z "$branch_arg" ]; then
|
||||
branch="$current"
|
||||
else
|
||||
branch="$branch_arg"
|
||||
fi
|
||||
# normalize branch name if refs/heads/ was provided
|
||||
branch="${branch#refs/heads/}"
|
||||
|
||||
# don't remove default
|
||||
if [ "$branch" = "$default_branch" ] || [ "$branch" = "default" ]; then
|
||||
echo "Refusing to remove default branch worktree ($default_branch)." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# find the worktree path for the requested branch
|
||||
target_wt=$(git -C "$repo_dir" worktree list --porcelain 2>/dev/null | awk -v b="refs/heads/$branch" '
|
||||
$1=="worktree" { w=$2 }
|
||||
$1=="branch" && $2==b { print w; exit }
|
||||
')
|
||||
|
||||
# if not found in worktree list, check main worktree branch
|
||||
if [ -z "$target_wt" ]; then
|
||||
local main_branch
|
||||
main_branch=$(git -C "$repo_dir" rev-parse --abbrev-ref HEAD 2>/dev/null || true)
|
||||
if [ "$main_branch" = "$branch" ]; then
|
||||
target_wt="$repo_dir"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$target_wt" ]; then
|
||||
echo "No worktree found for branch '$branch'." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$target_wt" = "$repo_dir" ]; then
|
||||
echo "Branch '$branch' is the main worktree at '$repo_dir'. Will not delete main worktree." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# if we're currently in that branch/worktree, switch to default and cd to repo root first
|
||||
if [ "$current" = "$branch" ]; then
|
||||
echo "Currently on branch '$branch' in '$wt_path'. Switching to default branch '$default_branch' in main worktree..."
|
||||
if declare -f branch >/dev/null 2>&1; then
|
||||
branch default || { echo "Failed to switch to default branch" >&2; return 1; }
|
||||
else
|
||||
git -C "$repo_dir" checkout "$default_branch" || { echo "Failed to checkout default branch" >&2; return 1; }
|
||||
fi
|
||||
cd "$repo_dir" || { echo "Failed to change directory to repo root: $repo_dir" >&2; return 1; }
|
||||
fi
|
||||
|
||||
echo "Removing worktree at: $target_wt"
|
||||
# helper: attempt a guarded, forceful removal of a directory
|
||||
remove_dir_forcefully() {
|
||||
local dir="$1"
|
||||
if [ -z "$dir" ]; then
|
||||
return 1
|
||||
fi
|
||||
# resolve absolute paths
|
||||
local abs_dir abs_repo
|
||||
abs_dir=$(readlink -f -- "$dir" 2>/dev/null) || abs_dir="$dir"
|
||||
abs_repo=$(readlink -f -- "$repo_dir" 2>/dev/null) || abs_repo="$repo_dir"
|
||||
|
||||
# safety checks: do not remove repository root or /
|
||||
if [ "$abs_dir" = "/" ] || [ "$abs_dir" = "$abs_repo" ]; then
|
||||
echo "Refusing to remove unsafe path: $abs_dir" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# try plain rm -rf
|
||||
rm -rf -- "$abs_dir" 2>/dev/null && return 0
|
||||
|
||||
# fix permissions then try again
|
||||
chmod -R u+rwx "$abs_dir" 2>/dev/null || true
|
||||
rm -rf -- "$abs_dir" 2>/dev/null && return 0
|
||||
|
||||
# try removing contents first, then remove directory
|
||||
if find "$abs_dir" -mindepth 1 -exec rm -rf -- {} + 2>/dev/null; then
|
||||
rmdir "$abs_dir" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# final existence check
|
||||
[ ! -e "$abs_dir" ]
|
||||
}
|
||||
|
||||
# try unregistering the worktree, prefer normal then fallback to --force
|
||||
if git -C "$repo_dir" worktree remove "$target_wt" 2>/dev/null || git -C "$repo_dir" worktree remove --force "$target_wt" 2>/dev/null; then
|
||||
if remove_dir_forcefully "$target_wt"; then
|
||||
echo "Removed worktree: $target_wt"
|
||||
else
|
||||
echo "Worktree removed from git, but failed to fully delete directory: $target_wt" >&2
|
||||
echo "Attempted to force-delete; you may need to remove it manually with sudo." >&2
|
||||
fi
|
||||
|
||||
# delete local branch if it exists
|
||||
if git -C "$repo_dir" show-ref --verify --quiet "refs/heads/$branch"; then
|
||||
git -C "$repo_dir" branch -D "$branch" 2>/dev/null || true
|
||||
echo "Deleted local branch: $branch"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Failed to remove worktree: $target_wt" >&2
|
||||
return 1
|
||||
}
|
||||
32
flakes/common/nix_modules/git/default.nix
Normal file
32
flakes/common/nix_modules/git/default.nix
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
];
|
||||
|
||||
environment.shellAliases = {
|
||||
# git
|
||||
status = "git status";
|
||||
diff = "git diff";
|
||||
branches = "git branch -a";
|
||||
gcam = "git commit -a -m";
|
||||
gcm = "git commit -m";
|
||||
stashes = "git stash list";
|
||||
bd = "branch default";
|
||||
li = "link_ignored";
|
||||
bx = "branchdel";
|
||||
b = "branch";
|
||||
};
|
||||
|
||||
environment.shellInit = lib.concatStringsSep "\n\n" [
|
||||
(builtins.readFile ./utils.func.sh)
|
||||
(builtins.readFile ./branch.func.sh)
|
||||
(builtins.readFile ./branchd.func.sh)
|
||||
(builtins.readFile ./link_ignored.func.sh)
|
||||
];
|
||||
}
|
||||
159
flakes/common/nix_modules/git/link_ignored.func.sh
Normal file
159
flakes/common/nix_modules/git/link_ignored.func.sh
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
link_ignored() {
|
||||
local DRY_RUN=0
|
||||
local USE_FZF=1
|
||||
local -a PATTERNS=()
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--dry-run) DRY_RUN=1; shift ;;
|
||||
--no-fzf) USE_FZF=0; shift ;;
|
||||
-h|--help) link_ignored_usage; return 0 ;;
|
||||
--) shift; break ;;
|
||||
*) PATTERNS+=("$1"); shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
link_ignored_usage() {
|
||||
cat <<EOF
|
||||
Usage: link_ignored [--dry-run] [--no-fzf] [pattern ...]
|
||||
|
||||
Interactively or non-interactively create symlinks in the current worktree
|
||||
for files/dirs that exist in the main repository root but are git-ignored /
|
||||
untracked.
|
||||
EOF
|
||||
}
|
||||
|
||||
# Determine the main repo root using git-common-dir (handles worktrees)
|
||||
local common_dir repo_root
|
||||
if ! common_dir=$(git rev-parse --git-common-dir 2>/dev/null); then
|
||||
echo "Error: not in a git repository." >&2
|
||||
return 2
|
||||
fi
|
||||
if [ "${common_dir#/}" = "$common_dir" ]; then
|
||||
common_dir="$(pwd)/$common_dir"
|
||||
fi
|
||||
repo_root="${common_dir%%/.git*}"
|
||||
if [ -z "$repo_root" ]; then
|
||||
echo "Error: unable to determine repository root." >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
local -a candidates=()
|
||||
while IFS= read -r -d '' file; do
|
||||
candidates+=("$file")
|
||||
done < <(git -C "$repo_root" ls-files --others --ignored --exclude-standard -z || true)
|
||||
|
||||
if [ ${#candidates[@]} -eq 0 ]; then
|
||||
echo "No untracked/ignored files found in $repo_root"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local -a tops=()
|
||||
for c in "${candidates[@]}"; do
|
||||
c="${c%/}"
|
||||
local top="${c%%/*}"
|
||||
[ -z "$top" ] && continue
|
||||
local found=0
|
||||
for existing in "${tops[@]}"; do
|
||||
[ "$existing" = "$top" ] && found=1 && break
|
||||
done
|
||||
[ "$found" -eq 0 ] && tops+=("$top")
|
||||
done
|
||||
|
||||
if [ ${#tops[@]} -eq 0 ]; then
|
||||
echo "No top-level ignored/untracked entries found in $repo_root"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local -a filtered
|
||||
if [ ${#PATTERNS[@]} -gt 0 ]; then
|
||||
for t in "${tops[@]}"; do
|
||||
for p in "${PATTERNS[@]}"; do
|
||||
if [[ "$t" == *"$p"* ]]; then
|
||||
filtered+=("$t")
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
else
|
||||
filtered=("${tops[@]}")
|
||||
fi
|
||||
|
||||
if [ ${#filtered[@]} -eq 0 ]; then
|
||||
echo "No candidates match the provided patterns." >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
local -a chosen
|
||||
if command -v fzf >/dev/null 2>&1 && [ "$USE_FZF" -eq 1 ]; then
|
||||
local selected
|
||||
selected=$(printf "%s\n" "${filtered[@]}" | fzf --multi --height=40% --border --prompt="Select files to link: " --preview "if [ -f '$repo_root'/{} ]; then bat --color always --paging=never --style=plain '$repo_root'/{}; else ls -la '$repo_root'/{}; fi")
|
||||
if [ -z "$selected" ]; then
|
||||
echo "No files selected." && return 0
|
||||
fi
|
||||
chosen=()
|
||||
while IFS= read -r line; do
|
||||
chosen+=("$line")
|
||||
done <<EOF
|
||||
$selected
|
||||
EOF
|
||||
else
|
||||
chosen=("${filtered[@]}")
|
||||
fi
|
||||
|
||||
local worktree_root
|
||||
worktree_root=$(pwd)
|
||||
|
||||
echo "Repository root: $repo_root"
|
||||
echo "Worktree root : $worktree_root"
|
||||
|
||||
local -a created=()
|
||||
local -a skipped=()
|
||||
local -a errors=()
|
||||
|
||||
for rel in "${chosen[@]}"; do
|
||||
rel=${rel%%$'\n'}
|
||||
local src="${repo_root}/${rel}"
|
||||
local dst="${worktree_root}/${rel}"
|
||||
|
||||
if [ ! -e "$src" ]; then
|
||||
errors+=("$rel (source missing)")
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -L "$dst" ]; then
|
||||
echo "Skipping $rel (already symlink)"
|
||||
skipped+=("$rel")
|
||||
continue
|
||||
fi
|
||||
if [ -e "$dst" ]; then
|
||||
echo "Skipping $rel (destination exists)"
|
||||
skipped+=("$rel")
|
||||
continue
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$dst")"
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
echo "DRY RUN: ln -s '$src' '$dst'"
|
||||
else
|
||||
if ln -s "$src" "$dst"; then
|
||||
echo "Linked: $rel"
|
||||
created+=("$rel")
|
||||
else
|
||||
echo "Failed to link: $rel" >&2
|
||||
errors+=("$rel (link failed)")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "Summary:"
|
||||
echo " Linked: ${#created[@]}"
|
||||
[ ${#created[@]} -gt 0 ] && printf ' %s\n' "${created[@]}"
|
||||
echo " Skipped: ${#skipped[@]}"
|
||||
[ ${#skipped[@]} -gt 0 ] && printf ' %s\n' "${skipped[@]}"
|
||||
echo " Errors: ${#errors[@]}"
|
||||
[ ${#errors[@]} -gt 0 ] && printf ' %s\n' "${errors[@]}"
|
||||
|
||||
return 0
|
||||
}
|
||||
133
flakes/common/nix_modules/git/utils.func.sh
Normal file
133
flakes/common/nix_modules/git/utils.func.sh
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# git
|
||||
getdefault () {
|
||||
git remote show origin | grep "HEAD branch" | sed 's/.*: //'
|
||||
}
|
||||
|
||||
master () {
|
||||
branch $(getdefault)
|
||||
git checkout $(getdefault)
|
||||
pull
|
||||
}
|
||||
|
||||
mp () {
|
||||
master
|
||||
prunel
|
||||
}
|
||||
|
||||
pullmaster () {
|
||||
git pull origin $(getdefault)
|
||||
}
|
||||
|
||||
push () {
|
||||
B=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
|
||||
git pull origin $B
|
||||
git push origin $B --no-verify
|
||||
}
|
||||
|
||||
pull () {
|
||||
git fetch
|
||||
B=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
|
||||
git pull origin $B
|
||||
}
|
||||
|
||||
forcepush () {
|
||||
B=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
|
||||
git push origin $B --force
|
||||
}
|
||||
|
||||
remote_branches () {
|
||||
git for-each-ref --format='%(refname:short)' refs/remotes 2>/dev/null | sed 's#^[^/]*/##' | grep -v '^HEAD$' || true
|
||||
}
|
||||
|
||||
local_branches () {
|
||||
git for-each-ref --format='%(refname:short)' refs/heads 2>/dev/null || true
|
||||
}
|
||||
|
||||
prunel () {
|
||||
git fetch
|
||||
git remote prune origin
|
||||
|
||||
for local in $(local_branches); do
|
||||
in=false
|
||||
for remote in $(remote_branches); do
|
||||
if [[ ${local} = ${remote} ]]; then
|
||||
in=true
|
||||
fi
|
||||
done;
|
||||
if [[ $in = 'false' ]]; then
|
||||
git branch -D ${local}
|
||||
else
|
||||
echo 'Skipping branch '${local}
|
||||
fi
|
||||
done;
|
||||
}
|
||||
|
||||
from_master () {
|
||||
git checkout $(getdefault) $@
|
||||
}
|
||||
|
||||
stash() {
|
||||
local branch
|
||||
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
||||
local datetime
|
||||
datetime=$(date +"%Y-%m-%d_%H-%M")
|
||||
local default_label="${datetime}_${branch}"
|
||||
if [ -n "$ZSH_VERSION" ]; then
|
||||
read "label?Stash label [default: $default_label]: "
|
||||
else
|
||||
read -e -p "Stash label [default: $default_label]: " label
|
||||
fi
|
||||
label=${label:-$default_label}
|
||||
git stash push -u -k -m "$label"
|
||||
}
|
||||
|
||||
pop() {
|
||||
local selection
|
||||
selection=$(git stash list | \
|
||||
fzf --prompt="Select stash to pop: " \
|
||||
--preview="git stash show -p \$(echo {} | awk -F: '{print \$1}') | bat --color always --paging=never --style=plain -l diff")
|
||||
[ -z "$selection" ] && echo "No stash selected." && return 1
|
||||
local stash_ref
|
||||
stash_ref=$(echo "$selection" | awk -F: '{print $1}')
|
||||
echo "Popping $stash_ref..."
|
||||
git stash pop "$stash_ref"
|
||||
}
|
||||
|
||||
delstash() {
|
||||
local selection
|
||||
selection=$(git stash list | \
|
||||
fzf --prompt="Select stash to pop: " \
|
||||
--preview="git stash show -p \$(echo {} | awk -F: '{print \$1}') | bat --color always --paging=never --style=plain -l diff")
|
||||
[ -z "$selection" ] && echo "No stash selected." && return 1
|
||||
local stash_ref
|
||||
stash_ref=$(echo "$selection" | awk -F: '{print $1}')
|
||||
echo "About to delete $stash_ref."
|
||||
git stash drop "$stash_ref"
|
||||
}
|
||||
|
||||
# Marks some files as in "git" but they won't actually get pushed up to the git repo
|
||||
# Usefull for `gintent .envrc flake.lock flake.nix` to add nix items required by flakes in a git repo that won't want flakes added
|
||||
gintent() {
|
||||
for file in "$@"; do
|
||||
if [ -f "$file" ]; then
|
||||
git add --intent-to-add "$file"
|
||||
git update-index --assume-unchanged "$file"
|
||||
echo "Intent added for $file"
|
||||
else
|
||||
echo "File not found: $file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
alias gintentnix="gintent .envrc flake.lock flake.nix"
|
||||
|
||||
gintent_undo() {
|
||||
for file in "$@"; do
|
||||
if [ -f "$file" ]; then
|
||||
git update-index --no-assume-unchanged "$file"
|
||||
echo "Intent removed for $file"
|
||||
else
|
||||
echo "File not found: $file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
alias gintentnix_undo="gintent_undo .envrc flake.lock flake.nix"
|
||||
87
flakes/common/nix_modules/hardening.nix
Normal file
87
flakes/common/nix_modules/hardening.nix
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
openssh
|
||||
autossh
|
||||
];
|
||||
|
||||
# name this computer
|
||||
networking = {
|
||||
# hostName = top_cfg.systemName;
|
||||
nftables.enable = true;
|
||||
# Clears firewall rules on reboot, only ones set in config will be remade
|
||||
nftables.flushRuleset = true;
|
||||
firewall.enable = true;
|
||||
};
|
||||
|
||||
# TODO invesitgate onensnitch usage and rules I may want. It is cumbersome with flushRuleset above...
|
||||
# services.opensnitch = {
|
||||
# enable = true;
|
||||
# settings = {
|
||||
# Firewall = if config.networking.nftables.enable then "nftables" else "iptables";
|
||||
# InterceptUknown = true;
|
||||
# ProcMonitorMethod = "ebpf";
|
||||
# DefaultAction = "deny";
|
||||
# };
|
||||
# rules = {
|
||||
#
|
||||
# };
|
||||
# };
|
||||
|
||||
# Use fail2ban
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
# Ignore my tailnet
|
||||
ignoreIP = [
|
||||
"100.64.0.0/10"
|
||||
];
|
||||
};
|
||||
|
||||
# Open ports in the firewall if enabled.
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
22 # sshd
|
||||
];
|
||||
|
||||
# Enable the OpenSSH daemon.
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
LogLevel = "VERBOSE";
|
||||
PermitRootLogin = "yes";
|
||||
PasswordAuthentication = false;
|
||||
};
|
||||
};
|
||||
|
||||
# Ensure SSH key pair generation for non-root users
|
||||
systemd.services = lib.mapAttrs' (name: _: {
|
||||
name = "generate_ssh_key_${name}";
|
||||
value = {
|
||||
description = "Generate SSH key pair for ${name}";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
User = name;
|
||||
Type = "oneshot";
|
||||
};
|
||||
script = ''
|
||||
#!/run/current-system/sw/bin/bash
|
||||
if [ ! -f /home/${name}/.ssh/id_ed25519 ]; then
|
||||
if [ -v DRY_RUN ]; then
|
||||
echo "DRY_RUN is set. Would generate SSH key for ${name}.";
|
||||
else
|
||||
echo "Generating SSH key for ${name}.";
|
||||
mkdir -p /home/${name}/.ssh;
|
||||
chmod 700 /home/${name}/.ssh;
|
||||
/run/current-system/sw/bin/ssh-keygen -t ed25519 -f /home/${name}/.ssh/id_ed25519 -N "";
|
||||
fi
|
||||
else
|
||||
echo "SSH key already exists for ${name}.";
|
||||
fi
|
||||
'';
|
||||
};
|
||||
}) config.users.users;
|
||||
}
|
||||
33
flakes/common/nix_modules/jetbrains_font.nix
Normal file
33
flakes/common/nix_modules/jetbrains_font.nix
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
hasNewJetbrainsMono =
|
||||
if builtins.hasAttr "nerd-fonts" pkgs then
|
||||
builtins.hasAttr "jetbrains-mono" pkgs."nerd-fonts"
|
||||
else
|
||||
false;
|
||||
|
||||
jetbrainsMonoFont =
|
||||
if hasNewJetbrainsMono then
|
||||
pkgs.nerd-fonts.jetbrains-mono
|
||||
else
|
||||
(pkgs.nerdfonts.override { fonts = [ "JetBrainsMono" ]; });
|
||||
in
|
||||
{
|
||||
config = {
|
||||
fonts.fontconfig.enable = true;
|
||||
|
||||
fonts.packages = [
|
||||
jetbrainsMonoFont
|
||||
]
|
||||
# TODO verify if these are needed/working
|
||||
# ++ (with pkgs; [
|
||||
# ipafont
|
||||
# kochi-substitute
|
||||
# noto-fonts-cjk-sans # Or another CJK font
|
||||
# ])
|
||||
;
|
||||
};
|
||||
}
|
||||
62
flakes/common/nix_modules/nix_options.nix
Normal file
62
flakes/common/nix_modules/nix_options.nix
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
# Enable flakes
|
||||
nix.settings.experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
|
||||
# Allow unfree if set in config
|
||||
nixpkgs.config.allowUnfreePredicate = lib.mkIf config.nixpkgs.config.allowUnfree (pkg: true);
|
||||
environment.variables = lib.mkIf config.nixpkgs.config.allowUnfree {
|
||||
NIXPKGS_ALLOW_UNFREE = "1";
|
||||
};
|
||||
|
||||
nix.settings = {
|
||||
max-jobs = "auto";
|
||||
# Fallback quickly if substituters are not available.
|
||||
connect-timeout = 5;
|
||||
download-attempts = 3;
|
||||
download-buffer-size = 524288000; # default is 67108864, this increases to ~500MB
|
||||
# The default at 10 is rarely enough.
|
||||
log-lines = 50;
|
||||
# Avoid disk full issues
|
||||
max-free = (3000 * 1024 * 1024);
|
||||
min-free = (1000 * 1024 * 1024);
|
||||
# Avoid copying unnecessary stuff over SSH
|
||||
builders-use-substitutes = true;
|
||||
auto-optimise-store = true;
|
||||
trusted-users = [
|
||||
"root"
|
||||
"@wheel"
|
||||
];
|
||||
substituters = [
|
||||
"https://cache.nixos.org/"
|
||||
"https://nix-community.cachix.org"
|
||||
];
|
||||
trusted-substituters = config.nix.settings.substituters;
|
||||
trusted-public-keys = [
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
];
|
||||
};
|
||||
nix.extraOptions = ''
|
||||
keep-outputs = true
|
||||
keep-derivations = true
|
||||
${lib.optionalString (
|
||||
# TODO revisit this should it move?
|
||||
config ? age && config.age ? secrets && config.age.secrets ? github_read_token
|
||||
) "!include ${config.age.secrets.github_read_token.path}"}
|
||||
'';
|
||||
|
||||
# nix helper
|
||||
programs.nh = {
|
||||
enable = true;
|
||||
# clean.enable = true; # TODO revist does this solve my re-building issues?
|
||||
clean.extraArgs = "--keep 10";
|
||||
};
|
||||
}
|
||||
11
flakes/common/nix_modules/no_sleep.nix
Normal file
11
flakes/common/nix_modules/no_sleep.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ ... }:
|
||||
{
|
||||
# Turn off sleep
|
||||
systemd.sleep.extraConfig = ''
|
||||
[Sleep]
|
||||
AllowSuspend=no
|
||||
AllowHibernation=no
|
||||
AllowSuspendThenHibernate=no
|
||||
AllowHybridSleep=no
|
||||
'';
|
||||
}
|
||||
11
flakes/common/nix_modules/podman.nix
Normal file
11
flakes/common/nix_modules/podman.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
virtualisation.podman = {
|
||||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
};
|
||||
users.extraGroups.docker.members = builtins.AttrNames config.users.users;
|
||||
}
|
||||
14
flakes/common/nix_modules/q_flipper.nix
Normal file
14
flakes/common/nix_modules/q_flipper.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
hardware.flipperzero.enable = true;
|
||||
environment.systemPackages = with pkgs; [ qFlipper ];
|
||||
services.udev.extraRules = ''
|
||||
#Flipper Zero serial port
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", ATTRS{manufacturer}=="Flipper Devices Inc.", GROUP="users", TAG+="uaccess"
|
||||
#Flipper Zero DFU
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", ATTRS{manufacturer}=="STMicroelectronics", GROUP="users", TAG+="uaccess"
|
||||
'';
|
||||
}
|
||||
35
flakes/common/nix_modules/remote_lio_builds.nix
Normal file
35
flakes/common/nix_modules/remote_lio_builds.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
# Remote build off home lio computer
|
||||
programs.ssh.extraConfig = ''
|
||||
Host lio_
|
||||
PubkeyAcceptedKeyTypes ssh-ed25519
|
||||
ServerAliveInterval 60
|
||||
IPQoS throughput
|
||||
IdentityFile ${config.age.secrets.nix2lio.path}
|
||||
'';
|
||||
nix = {
|
||||
distributedBuilds = true;
|
||||
buildMachines = [
|
||||
{
|
||||
# TODO require hostname in ssh config?
|
||||
hostName = "lio_";
|
||||
system = "x86_64-linux";
|
||||
protocol = "ssh-ng";
|
||||
maxJobs = 32;
|
||||
speedFactor = 2;
|
||||
supportedFeatures = [
|
||||
"nixos-test"
|
||||
"benchmark"
|
||||
"big-parallel"
|
||||
"kvm"
|
||||
"uid-range" # Often helpful
|
||||
];
|
||||
mandatoryFeatures = [ ];
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
22
flakes/common/nix_modules/tailnet.nix
Normal file
22
flakes/common/nix_modules/tailnet.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [ tailscale ];
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
useRoutingFeatures = "client";
|
||||
authKeyFile = config.age.secrets.headscale_auth.path;
|
||||
extraUpFlags = [
|
||||
"--login-server=https://headscale.joshuabell.xyz"
|
||||
];
|
||||
extraDaemonFlags = [
|
||||
"--no-logs-no-support"
|
||||
];
|
||||
};
|
||||
networking.firewall.trustedInterfaces = [ config.services.tailscale.interfaceName ];
|
||||
networking.firewall.checkReversePath = "loose";
|
||||
}
|
||||
7
flakes/common/nix_modules/timezone_auto.nix
Normal file
7
flakes/common/nix_modules/timezone_auto.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
...
|
||||
}:
|
||||
{
|
||||
time.timeZone = null;
|
||||
services.automatic-timezoned.enable = true;
|
||||
}
|
||||
19
flakes/common/nix_modules/tmux/default.nix
Normal file
19
flakes/common/nix_modules/tmux/default.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = [
|
||||
pkgs.tmux
|
||||
];
|
||||
|
||||
environment.shellAliases = {
|
||||
tat = "tmux attach-session";
|
||||
t = "tmux";
|
||||
};
|
||||
|
||||
environment.shellInit = lib.concatStringsSep "\n\n" [
|
||||
(builtins.readFile ./tmux_helpers.sh)
|
||||
];
|
||||
}
|
||||
34
flakes/common/nix_modules/tmux/tmux_helpers.sh
Normal file
34
flakes/common/nix_modules/tmux/tmux_helpers.sh
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
tmux_window () {
|
||||
cmd=${1:-}
|
||||
case "${cmd}" in
|
||||
rename)
|
||||
if [ -z "${2:-}" ]; then
|
||||
tmux setw automatic-rename
|
||||
else
|
||||
tmux rename-window "$2"
|
||||
fi
|
||||
;;
|
||||
get)
|
||||
printf '%s' "$(tmux display-message -p '#W')"
|
||||
;;
|
||||
status)
|
||||
out="$(tmux show-window-options automatic-rename 2>/dev/null || true)"
|
||||
if printf '%s' "$out" | grep -q 'automatic-rename on'; then
|
||||
printf 'auto'
|
||||
elif printf '%s' "$out" | grep -q 'automatic-rename off'; then
|
||||
printf 'manual'
|
||||
else
|
||||
# If tmux returns nothing (option not set), default to auto
|
||||
if [ -z "$out" ]; then
|
||||
printf 'auto'
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
printf 'Usage: tmux_window {rename [NAME]|get|status}\n' >&2
|
||||
return 2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
13
flakes/common/nix_modules/tty_caps_esc.nix
Normal file
13
flakes/common/nix_modules/tty_caps_esc.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
services.xserver.xkb.options = "caps:escape";
|
||||
console = {
|
||||
earlySetup = true;
|
||||
packages = with pkgs; [ terminus_font ];
|
||||
# use xkb.options in tty. (caps -> escape)
|
||||
useXkbConfig = true;
|
||||
};
|
||||
}
|
||||
11
flakes/common/nix_modules/uhk_agent.nix
Normal file
11
flakes/common/nix_modules/uhk_agent.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
uhk-agent
|
||||
uhk-udev-rules
|
||||
];
|
||||
services.udev.packages = [ pkgs.uhk-udev-rules ];
|
||||
}
|
||||
9
flakes/common/nix_modules/zsh.nix
Normal file
9
flakes/common/nix_modules/zsh.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
programs.zsh.enable = true;
|
||||
environment.pathsToLink = [ "/share/zsh" ];
|
||||
users.defaultUserShell = pkgs.zsh;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue