update
This commit is contained in:
parent
cde17b7dc9
commit
ea76cc9ef2
7 changed files with 208 additions and 173 deletions
23
README.md
23
README.md
|
|
@ -16,6 +16,7 @@ or Nushell.
|
|||
- Load environment setup that is portable at login, such as Cargo's `env` file.
|
||||
- Provide common aliases and small interactive functions that are useful
|
||||
across supported Bourne-family shells.
|
||||
- Isolate Arch Linux commands from otherwise portable shell configuration.
|
||||
|
||||
## Boundaries
|
||||
|
||||
|
|
@ -23,7 +24,7 @@ The `profile` file must remain quiet, idempotent and safe for a POSIX shell to
|
|||
source during login. It must not print an alias catalogue, configure a prompt,
|
||||
perform interactive terminal operations or start background work.
|
||||
|
||||
Interactive shells should source `aliases.sh` from their own RC file. The
|
||||
Interactive shells should source `interactive.sh` from their own RC file. The
|
||||
login profile deliberately does not source it, because login profiles may also
|
||||
run in non-interactive sessions.
|
||||
|
||||
|
|
@ -34,18 +35,26 @@ belong in the separate `systemd` repository.
|
|||
## Files
|
||||
|
||||
- `profile`: portable login environment and PATH construction.
|
||||
- `aliases.sh`: common interactive aliases and helper functions.
|
||||
- `commands.tsv`: curated command descriptions and startup visibility.
|
||||
- `interactive.sh`: POSIX loader and manually curated alias reminder.
|
||||
- `aliases.sh`: common POSIX interactive aliases and helper functions.
|
||||
- `commands.sh`: command-catalogue display and validation functions.
|
||||
- `hosts.sh`: SSH destination listing function.
|
||||
- `platform/arch.sh`: Arch Linux applications, GNU options and Pacman/systemd
|
||||
integration, written with POSIX shell syntax.
|
||||
- `commands.tsv`: curated command descriptions and reminder visibility.
|
||||
- `commands.README.md`: format and maintenance instructions for `commands.tsv`.
|
||||
- `install.sh`: installs the `~/.profile` symlink.
|
||||
|
||||
## Alias portability
|
||||
|
||||
`aliases.sh` is intended to become POSIX-compatible for Bourne-family shells,
|
||||
but it currently contains some Bash-oriented constructs. Before another shell
|
||||
sources it, replace or isolate uses of `source`, `disown`, `local`, `echo -e`,
|
||||
Bash-style `cd --`, and the transitional `debug.log` alias name.
|
||||
The shared interactive files use POSIX shell syntax. Bash-only compatibility
|
||||
aliases—including names that are deliberately being retired—live in the Bash
|
||||
repository's `aliases.bash` instead.
|
||||
|
||||
External commands remain platform-specific by design: aliases for Pacman,
|
||||
systemd, GNU utilities and local applications target this Arch Linux setup.
|
||||
Syntax portability does not imply operating-system portability.
|
||||
|
||||
The Arch `update` function runs the local `archnews_wrap` Pacman workflow and,
|
||||
after a successful upgrade, requests a non-blocking refresh from the systemd
|
||||
user service `package-status-refresh.service`.
|
||||
|
|
|
|||
201
aliases.sh
201
aliases.sh
|
|
@ -1,27 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# shellcheck shell=bash
|
||||
ALIASES_GREEN='\033[0;32m' # Green
|
||||
ALIASES_BLUE='\033[0;34m' # Blue
|
||||
ALIASES_WHITE='\033[1;37m' # White
|
||||
ALIASES_NC='\033[0m' # No Color
|
||||
#!/bin/sh
|
||||
|
||||
echo "Remember aliases:"
|
||||
echo -e "${ALIASES_WHITE} et en ens ee"
|
||||
echo " dusort debuglog mkcd"
|
||||
echo -e "${ALIASES_NC}"
|
||||
echo ""
|
||||
# Common interactive aliases and helpers using POSIX shell syntax.
|
||||
|
||||
alias backup='sudo borgmatic create --verbosity 1 --files'
|
||||
alias disk-usage='printf "%s\n" "disk-usage is deprecated; use dusort instead." >&2'
|
||||
|
||||
alias cs='lxc list -c ns4b,user.comment:comment'
|
||||
alias pc='pcmanfm . & disown'
|
||||
|
||||
# enable aliases for commands inside sudo
|
||||
# TOOD check this is safe
|
||||
alias sudo='sudo '
|
||||
|
||||
alias venv='source ./venv/bin/activate'
|
||||
alias venv='. ./venv/bin/activate'
|
||||
|
||||
alias e='nvim'
|
||||
alias er='nvim README.md'
|
||||
|
|
@ -31,182 +12,68 @@ alias ens='nvim NEXT_STEPS.md'
|
|||
alias ea='nvim .autonote.md'
|
||||
alias ee='nvim .'
|
||||
|
||||
alias speak='/usr/local/src/kokora/speak'
|
||||
|
||||
debuglog() {
|
||||
clear
|
||||
: > debug.log
|
||||
tail -f debug.log
|
||||
}
|
||||
|
||||
alias debug.log='printf "%s\n" "debug.log is deprecated; use debuglog instead." >&2'
|
||||
alias g='git status'
|
||||
|
||||
dusort() {
|
||||
if [ "$#" -gt 1 ]; then
|
||||
printf '%s\n' 'Usage: dusort [path]' >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
_dusort_path=${1:-.}
|
||||
if [ ! -e "$_dusort_path" ]; then
|
||||
printf 'dusort: path does not exist: %s\n' "$_dusort_path" >&2
|
||||
unset _dusort_path
|
||||
return 1
|
||||
fi
|
||||
|
||||
if sudo du -h -d 2 -- "$_dusort_path" | sort -h; then
|
||||
unset _dusort_path
|
||||
gg() {
|
||||
_gg_message=${*:-update}
|
||||
if git add . && git commit -m "$_gg_message" && git push; then
|
||||
unset _gg_message
|
||||
return 0
|
||||
fi
|
||||
|
||||
unset _dusort_path
|
||||
unset _gg_message
|
||||
return 1
|
||||
}
|
||||
|
||||
alias g='git status'
|
||||
alias gg='git add . && git commit -m "update" && git push'
|
||||
wget() {
|
||||
printf 'wget wrapper: using HSTS file %s\n' "$XDG_DATA_HOME/wget-hsts" >&2
|
||||
command wget --hsts-file="$XDG_DATA_HOME/wget-hsts" "$@"
|
||||
}
|
||||
|
||||
alias ls='LC_COLLATE=C ls --color=auto -h --group-directories-first --time-style=+"%d.%m.%Y %H:%M" -F'
|
||||
|
||||
alias cp='cp -irv'
|
||||
alias mkdir='mkdir -vp'
|
||||
alias mv='mv -iv'
|
||||
alias rm='rm -dv'
|
||||
|
||||
alias wget='wget --hsts-file="$XDG_DATA_HOME/wget-hsts"'
|
||||
|
||||
alias grep='grep --colour=auto'
|
||||
alias egrep='egrep --colour=auto'
|
||||
alias fgrep='fgrep --colour=auto'
|
||||
alias bc='bc -q -l'
|
||||
|
||||
alias ytdl='yt-dlp --write-info-json --write-description --no-playlist'
|
||||
alias ytdlb='yt-dlp --write-info-json --write-description --no-playlist -a'
|
||||
alias ytdl-mp3='yt-dlp -f bestaudio --extract-audio --audio-format mp3 --embed-thumbnail --add-metadata'
|
||||
|
||||
# Transitional aliases for destinations now managed by ~/.ssh/config.
|
||||
alias mac='printf "%s\n" "mac is deprecated; use ssh mac instead." >&2'
|
||||
alias pi4='printf "%s\n" "pi4 is deprecated; use ssh pi4 instead." >&2'
|
||||
alias red='printf "%s\n" "red is deprecated; use ssh red instead." >&2'
|
||||
alias alice='printf "%s\n" "alice is deprecated; use ssh alice instead." >&2'
|
||||
alias phthalo='printf "%s\n" "phthalo is deprecated; use ssh phthalo instead." >&2'
|
||||
alias zirconia='printf "%s\n" "zirconia is deprecated; use ssh zirconia instead." >&2'
|
||||
alias zirconiarc='printf "%s\n" "zirconiarc is deprecated; use ssh zirconiarc instead." >&2'
|
||||
alias datapasa='printf "%s\n" "datapasa is deprecated; use ssh datapasa instead." >&2'
|
||||
alias ultra='printf "%s\n" "ultra is deprecated; use ssh ultra instead." >&2'
|
||||
alias singsay='printf "%s\n" "singsay is deprecated; use ssh singsay instead." >&2'
|
||||
alias kermit='printf "%s\n" "kermit is deprecated; use ssh kermit instead." >&2'
|
||||
alias crafty='printf "%s\n" "crafty is deprecated; use ssh crafty instead." >&2'
|
||||
alias lv='printf "%s\n" "lv is deprecated; use ssh lv instead." >&2'
|
||||
|
||||
commands() {
|
||||
awk -F '\t' '
|
||||
NF == 0 { next }
|
||||
NF != 3 || ($1 != "yes" && $1 != "no") || $2 == "" || $3 == "" {
|
||||
printf "Invalid command reminder on line %d.\n", NR > "/dev/stderr"
|
||||
invalid = 1
|
||||
next
|
||||
}
|
||||
seen[$2]++ {
|
||||
printf "Duplicate command reminder for %s on line %d.\n", $2, NR > "/dev/stderr"
|
||||
invalid = 1
|
||||
next
|
||||
}
|
||||
{
|
||||
count++
|
||||
reminder[count] = $1
|
||||
command[count] = $2
|
||||
description[count] = $3
|
||||
if (length($2) > command_width) command_width = length($2)
|
||||
if (length($3) > description_width) description_width = length($3)
|
||||
}
|
||||
END {
|
||||
if (invalid) exit 1
|
||||
if (length("COMMAND") > command_width) command_width = length("COMMAND")
|
||||
if (length("DESCRIPTION") > description_width) description_width = length("DESCRIPTION")
|
||||
printf "%-*s %-*s %s\n", command_width, "COMMAND", description_width, "DESCRIPTION", "REMINDER"
|
||||
for (row = 1; row <= count; row++) {
|
||||
printf "%-*s %-*s %s\n", command_width, command[row], description_width, description[row], reminder[row]
|
||||
}
|
||||
}
|
||||
' "${XDG_CONFIG_HOME:-$HOME/.config}/profile/commands.tsv"
|
||||
}
|
||||
|
||||
_command_reminder() {
|
||||
awk -F '\t' -v width="${COLUMNS:-80}" '
|
||||
NF == 0 { next }
|
||||
NF != 3 || ($1 != "yes" && $1 != "no") || $2 == "" || $3 == "" {
|
||||
printf "Invalid command reminder on line %d.\n", NR > "/dev/stderr"
|
||||
invalid = 1
|
||||
next
|
||||
}
|
||||
seen[$2]++ {
|
||||
printf "Duplicate command reminder for %s on line %d.\n", $2, NR > "/dev/stderr"
|
||||
invalid = 1
|
||||
next
|
||||
}
|
||||
$1 == "yes" { command[++count] = $2 }
|
||||
END {
|
||||
if (invalid) exit 1
|
||||
if (width < 40) width = 80
|
||||
line = " "
|
||||
for (row = 1; row <= count; row++) {
|
||||
separator = (line == " " ? "" : " ")
|
||||
if (length(line) + length(separator) + length(command[row]) > width) {
|
||||
print line
|
||||
line = " " command[row]
|
||||
} else {
|
||||
line = line separator command[row]
|
||||
}
|
||||
}
|
||||
if (line != " ") print line
|
||||
}
|
||||
' "${XDG_CONFIG_HOME:-$HOME/.config}/profile/commands.tsv"
|
||||
}
|
||||
|
||||
# lf gets confused by TERMINFO env var when running in tmux
|
||||
# lf gets confused by TERMINFO when running in tmux.
|
||||
# https://github.com/gokcehan/lf/issues/138#issuecomment-464477665
|
||||
if [ -n "$TERMINFO" ] ; then
|
||||
alias lf="TERMINFO= lf -last-dir-path=~/.cache/lf-last-dir"
|
||||
if [ -n "${TERMINFO:-}" ]; then
|
||||
alias lf='TERMINFO= lf -last-dir-path="$HOME/.cache/lf-last-dir"'
|
||||
else
|
||||
alias lf="lf -last-dir-path=~/.cache/lf-last-dir"
|
||||
alias lf='lf -last-dir-path="$HOME/.cache/lf-last-dir"'
|
||||
fi
|
||||
|
||||
cdlf() {
|
||||
local last_dir
|
||||
[ -r "$HOME/.cache/lf-last-dir" ] || return 1
|
||||
IFS= read -r last_dir < "$HOME/.cache/lf-last-dir"
|
||||
[ -n "$last_dir" ] || return 1
|
||||
cd -- "$last_dir" || return
|
||||
IFS= read -r _cdlf_last_dir < "$HOME/.cache/lf-last-dir"
|
||||
[ -n "$_cdlf_last_dir" ] || return 1
|
||||
|
||||
if cd "$_cdlf_last_dir"; then
|
||||
unset _cdlf_last_dir
|
||||
return 0
|
||||
fi
|
||||
|
||||
unset _cdlf_last_dir
|
||||
return 1
|
||||
}
|
||||
|
||||
lfcd() {
|
||||
lf -last-dir-path="$HOME"/.cache/lf-last-dir && cdlf
|
||||
}
|
||||
|
||||
hosts() {
|
||||
if [ ! -r "$HOME/.ssh/config.d/hosts.conf" ]; then
|
||||
printf '%s\n' 'SSH host configuration is unavailable.' >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
awk '
|
||||
tolower($1) == "host" {
|
||||
for (field = 2; field <= NF; field++) {
|
||||
if ($field !~ /[*?!]/) print $field
|
||||
}
|
||||
}
|
||||
' "$HOME/.ssh/config.d/hosts.conf"
|
||||
}
|
||||
|
||||
update() {
|
||||
echo -e "Executing \"${ALIASES_GREEN}pacman -Syu${ALIASES_NC}\" via \"${ALIASES_BLUE}archnews_wrap${ALIASES_NC}\" wrapper"
|
||||
|
||||
sudo ~/.src/archnews/archnews_wrap -Syu || return
|
||||
systemctl --user start --no-block package-status-refresh.service >/dev/null 2>&1 || true
|
||||
lf -last-dir-path="$HOME/.cache/lf-last-dir" && cdlf
|
||||
}
|
||||
|
||||
mkcd() {
|
||||
mkdir "$1" || return
|
||||
if [ "$#" -ne 1 ]; then
|
||||
printf '%s\n' 'Usage: mkcd <directory>' >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
mkdir -p "$1" || return
|
||||
cd "$1" || return
|
||||
}
|
||||
|
|
|
|||
68
commands.sh
Normal file
68
commands.sh
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Display and validate the curated command catalogue.
|
||||
|
||||
commands() {
|
||||
awk -F '\t' '
|
||||
NF == 0 { next }
|
||||
NF != 3 || ($1 != "yes" && $1 != "no") || $2 == "" || $3 == "" {
|
||||
printf "Invalid command reminder on line %d.\n", NR > "/dev/stderr"
|
||||
invalid = 1
|
||||
next
|
||||
}
|
||||
seen[$2]++ {
|
||||
printf "Duplicate command reminder for %s on line %d.\n", $2, NR > "/dev/stderr"
|
||||
invalid = 1
|
||||
next
|
||||
}
|
||||
{
|
||||
count++
|
||||
reminder[count] = $1
|
||||
command[count] = $2
|
||||
description[count] = $3
|
||||
if (length($2) > command_width) command_width = length($2)
|
||||
if (length($3) > description_width) description_width = length($3)
|
||||
}
|
||||
END {
|
||||
if (invalid) exit 1
|
||||
if (length("COMMAND") > command_width) command_width = length("COMMAND")
|
||||
if (length("DESCRIPTION") > description_width) description_width = length("DESCRIPTION")
|
||||
printf "%-*s %-*s %s\n", command_width, "COMMAND", description_width, "DESCRIPTION", "REMINDER"
|
||||
for (row = 1; row <= count; row++) {
|
||||
printf "%-*s %-*s %s\n", command_width, command[row], description_width, description[row], reminder[row]
|
||||
}
|
||||
}
|
||||
' "${XDG_CONFIG_HOME:-$HOME/.config}/profile/commands.tsv"
|
||||
}
|
||||
|
||||
_command_reminder() {
|
||||
awk -F '\t' -v width="${COLUMNS:-80}" '
|
||||
NF == 0 { next }
|
||||
NF != 3 || ($1 != "yes" && $1 != "no") || $2 == "" || $3 == "" {
|
||||
printf "Invalid command reminder on line %d.\n", NR > "/dev/stderr"
|
||||
invalid = 1
|
||||
next
|
||||
}
|
||||
seen[$2]++ {
|
||||
printf "Duplicate command reminder for %s on line %d.\n", $2, NR > "/dev/stderr"
|
||||
invalid = 1
|
||||
next
|
||||
}
|
||||
$1 == "yes" { command[++count] = $2 }
|
||||
END {
|
||||
if (invalid) exit 1
|
||||
if (width < 40) width = 80
|
||||
line = " "
|
||||
for (row = 1; row <= count; row++) {
|
||||
separator = (line == " " ? "" : " ")
|
||||
if (length(line) + length(separator) + length(command[row]) > width) {
|
||||
print line
|
||||
line = " " command[row]
|
||||
} else {
|
||||
line = line separator command[row]
|
||||
}
|
||||
}
|
||||
if (line != " ") print line
|
||||
}
|
||||
' "${XDG_CONFIG_HOME:-$HOME/.config}/profile/commands.tsv"
|
||||
}
|
||||
|
|
@ -7,7 +7,6 @@ yes qv4l2 Video4Linux control panel
|
|||
no cheat command-line cheatsheets
|
||||
no vimv batch rename files in Vim
|
||||
yes rclone sync files with cloud storage
|
||||
yes mid3v2 edit ID3 audio metadata
|
||||
yes zathura document viewer
|
||||
yes tesseract optical character recognition
|
||||
yes remmina remote desktop client
|
||||
|
|
|
|||
|
16
hosts.sh
Normal file
16
hosts.sh
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/sh
|
||||
|
||||
hosts() {
|
||||
if [ ! -r "$HOME/.ssh/config.d/hosts.conf" ]; then
|
||||
printf '%s\n' 'SSH host configuration is unavailable.' >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
awk '
|
||||
tolower($1) == "host" {
|
||||
for (field = 2; field <= NF; field++) {
|
||||
if ($field !~ /[*?!]/) print $field
|
||||
}
|
||||
}
|
||||
' "$HOME/.ssh/config.d/hosts.conf"
|
||||
}
|
||||
20
interactive.sh
Normal file
20
interactive.sh
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Shared interactive setup for POSIX-compatible shells.
|
||||
|
||||
_profile_interactive_dir=${XDG_CONFIG_HOME:-$HOME/.config}/profile
|
||||
|
||||
. "$_profile_interactive_dir/aliases.sh"
|
||||
. "$_profile_interactive_dir/commands.sh"
|
||||
. "$_profile_interactive_dir/hosts.sh"
|
||||
|
||||
if [ -r /etc/arch-release ]; then
|
||||
. "$_profile_interactive_dir/platform/arch.sh"
|
||||
fi
|
||||
|
||||
printf '%s\n' 'Remember aliases:'
|
||||
printf '\033[1;37m%s\n' ' et en ens ee'
|
||||
printf '%s\n' ' dusort debuglog mkcd'
|
||||
printf '\033[0m\n\n'
|
||||
|
||||
unset _profile_interactive_dir
|
||||
56
platform/arch.sh
Normal file
56
platform/arch.sh
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Interactive commands specific to this Arch Linux workstation.
|
||||
|
||||
_ARCH_GREEN='\033[0;32m'
|
||||
_ARCH_BLUE='\033[0;34m'
|
||||
_ARCH_NC='\033[0m'
|
||||
|
||||
alias backup='sudo borgmatic create --verbosity 1 --files'
|
||||
alias cs='lxc list -c ns4b,user.comment:comment'
|
||||
|
||||
pc() {
|
||||
nohup pcmanfm . >/dev/null 2>&1 &
|
||||
}
|
||||
|
||||
# Expand aliases for commands following sudo.
|
||||
alias sudo='sudo '
|
||||
|
||||
alias speak='/usr/local/src/kokora/speak'
|
||||
|
||||
alias ls='LC_COLLATE=C ls --color=auto -h --group-directories-first --time-style=+"%d.%m.%Y %H:%M" -F'
|
||||
alias cp='cp -irv'
|
||||
alias mkdir='mkdir -vp'
|
||||
alias mv='mv -iv'
|
||||
alias rm='rm -dv'
|
||||
alias grep='grep --colour=auto'
|
||||
|
||||
dusort() {
|
||||
if [ "$#" -gt 1 ]; then
|
||||
printf '%s\n' 'Usage: dusort [path]' >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
_dusort_path=${1:-.}
|
||||
if [ ! -e "$_dusort_path" ]; then
|
||||
printf 'dusort: path does not exist: %s\n' "$_dusort_path" >&2
|
||||
unset _dusort_path
|
||||
return 1
|
||||
fi
|
||||
|
||||
if sudo du -h -d 2 -- "$_dusort_path" | sort -h; then
|
||||
unset _dusort_path
|
||||
return 0
|
||||
fi
|
||||
|
||||
unset _dusort_path
|
||||
return 1
|
||||
}
|
||||
|
||||
update() {
|
||||
printf 'Executing "%bpacman -Syu%b" via "%barchnews_wrap%b" wrapper\n' \
|
||||
"$_ARCH_GREEN" "$_ARCH_NC" "$_ARCH_BLUE" "$_ARCH_NC"
|
||||
|
||||
sudo "$HOME/.src/archnews/archnews_wrap" -Syu || return
|
||||
systemctl --user start --no-block package-status-refresh.service >/dev/null 2>&1 || true
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue