Add server CLI tools installer for Ubuntu/Debian servers
Introduce a self-contained repo with an interactive install.sh that provisions zsh, oh-my-zsh, aliases, bat/yazi configs, docker shortcuts, and git-delta pager setup. Configs are adapted from dotfiles for SSH-only servers — no desktop or neovim dependencies. Installer supports --all, --update (git pull + re-run), and --uninstall with backup restore. Core packages include vim (default editor), yazi via apt, and idempotent apt installs with warnings for eza and git-delta when repos lack them.
This commit is contained in:
52
configs/aliases/.aliases
Normal file
52
configs/aliases/.aliases
Normal file
@@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=.functions.sh
|
||||
. ~/.config/aliases/.functions.sh
|
||||
|
||||
### General aliases
|
||||
# ll pimped with eza
|
||||
alias ll="eza -lag --icons=always --group-directories-first --smart-group --time-style='+%d %b %y %H:%M'"
|
||||
# du all items in folder, human readable
|
||||
alias dh='du -chs *'
|
||||
# yazi file manager
|
||||
alias y='yazi'
|
||||
# preview/find file using fzf and bat
|
||||
alias pf='fzf --preview "bat --color=always {}"'
|
||||
# cd to dir using fuzzy finder (fzf)
|
||||
alias cdf='cd "$(find . -type d | fzf)"'
|
||||
# (executed from / or /home might be slow)
|
||||
next_line
|
||||
# cd to file's directory
|
||||
alias cdtf=cd_to_file
|
||||
# mkdir & cd to it
|
||||
alias mkcd=mkdir_and_cd
|
||||
# grep shorthand
|
||||
alias g='grep'
|
||||
# python interpreter/REPL
|
||||
alias py='python3'
|
||||
# source ~/.config/aliases/.aliases
|
||||
alias sa='source ~/.config/aliases/.aliases'
|
||||
# edit aliases files ('ea h' for help)
|
||||
alias ea=edit_aliases
|
||||
# pack 'cwd' to tar.gz in parent with 'cwd' name
|
||||
alias twd='tar -czf "../$(basename "$PWD").tar.gz" .'
|
||||
# print alias description
|
||||
alias h='display_alias_descriptions'
|
||||
|
||||
# LOCAL/CUSTOM bash aliases
|
||||
# You can create custom local aliases in .local_aliases
|
||||
# or .custom_aliases file for some temporary aliases
|
||||
if [ -f ~/.config/aliases/.local_aliases ]; then
|
||||
. ~/.config/aliases/.local_aliases
|
||||
fi
|
||||
if [ -f ~/.config/aliases/.custom_aliases ]; then
|
||||
. ~/.config/aliases/.custom_aliases
|
||||
fi
|
||||
# source git aliases
|
||||
if [ -f ~/.config/aliases/.git_aliases ]; then
|
||||
. ~/.config/aliases/.git_aliases
|
||||
fi
|
||||
# source docker aliases
|
||||
if [ -f ~/.config/aliases/.docker_aliases ]; then
|
||||
. ~/.config/aliases/.docker_aliases
|
||||
fi
|
||||
69
configs/aliases/.docker_aliases
Normal file
69
configs/aliases/.docker_aliases
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker_start_stop() {
|
||||
local cname="$1"
|
||||
if [ -z "$cname" ]; then
|
||||
e_info "Usage: docker_toggle <container_name_or_id>"
|
||||
return 1
|
||||
fi
|
||||
state=$(docker inspect -f '{{.State.Status}}' "$cname" 2>/dev/null)
|
||||
case $state in
|
||||
"running")
|
||||
docker stop "$cname"
|
||||
e_info "Container '$cname' stopped."
|
||||
;;
|
||||
"exited")
|
||||
docker start "$cname"
|
||||
e_info "Container '$cname' started."
|
||||
;;
|
||||
*)
|
||||
e_err "Container '$cname' not found or not in a valid state."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
docker_stop_all() {
|
||||
for cont in $(docker ps -a --format {{.Names}}); do
|
||||
docker stop $cont >/dev/null
|
||||
e_info "Container $cont stopped."
|
||||
done
|
||||
}
|
||||
|
||||
docker_remove() {
|
||||
container=$(docker rm $1)
|
||||
e_info "Container $container removed."
|
||||
}
|
||||
|
||||
docker_remove_all() {
|
||||
for cont in $(docker ps -a --format {{.Names}}); do
|
||||
docker rm $cont >/dev/null
|
||||
e_info "Container $cont removed."
|
||||
done
|
||||
}
|
||||
|
||||
docker_remove_all_images() {
|
||||
for img in $(docker image ls --format '{{.Repository}}:{{.Tag}}'); do
|
||||
docker image rm $img >/dev/null
|
||||
e_info "Image $img removed."
|
||||
done
|
||||
}
|
||||
|
||||
### Docker aliases
|
||||
# show docker containers
|
||||
alias da='docker ps -a'
|
||||
# start or stop docker <container>
|
||||
alias ds=docker_start_stop
|
||||
# stop all docker containers
|
||||
alias dsa=docker_stop_all
|
||||
# remove docker <container>
|
||||
alias dr=docker_remove
|
||||
# remove all docker containers
|
||||
alias dra=docker_remove_all
|
||||
# list docker images in 'repo:tag'
|
||||
alias dia='docker image ls --format {{.Repository}}:{{.Tag}}'
|
||||
# remove docker <image>
|
||||
alias dri='docker image rm'
|
||||
# remove all docker images
|
||||
alias dria=docker_remove_all_images
|
||||
|
||||
136
configs/aliases/.functions.sh
Normal file
136
configs/aliases/.functions.sh
Normal file
@@ -0,0 +1,136 @@
|
||||
#!/bin/bash
|
||||
|
||||
e_err() {
|
||||
echo -e "\e[1;31m$1\e[0m"
|
||||
}
|
||||
|
||||
e_info() {
|
||||
echo -e "\e[1;34m$1\e[0m"
|
||||
}
|
||||
|
||||
e_succ() {
|
||||
echo -e "\e[1;32m$1\e[0m"
|
||||
}
|
||||
|
||||
e_warn() {
|
||||
echo -e "\e[1;38;5;208m$1\e[0m"
|
||||
}
|
||||
|
||||
function fake_alias() {
|
||||
:
|
||||
}
|
||||
|
||||
function next_line() {
|
||||
:
|
||||
}
|
||||
|
||||
# FILL LINE FUNCTIONS
|
||||
fill_line_with_string() {
|
||||
local string="$1"
|
||||
local length="$2"
|
||||
local fill="${3:- }"
|
||||
if [[ ${#fill} -eq 1 ]]; then
|
||||
beg_char=$fill
|
||||
end_char=$fill
|
||||
fi
|
||||
if [[ ${#fill} -eq 2 ]]; then
|
||||
beg_char="${fill:0:1}"
|
||||
end_char="${fill:1:1}"
|
||||
fi
|
||||
if [[ ${#fill} -gt 2 ]]; then
|
||||
beg_char="${fill:0:1}"
|
||||
end_char="${fill:0:1}"
|
||||
fi
|
||||
local padding=$(((length - ${#string} - 2) / 2))
|
||||
local beg
|
||||
beg=$(printf "%${padding}s" | tr ' ' "$beg_char")
|
||||
local end
|
||||
end=$(printf "%${padding}s" | tr ' ' "$end_char")
|
||||
printf "%s%s%s" "$beg" " $string " "$end"
|
||||
echo ""
|
||||
}
|
||||
|
||||
fill_line() {
|
||||
local length="$1"
|
||||
local fill="$2"
|
||||
printf "%*s\n" "$length" "" | tr ' ' "$fill"
|
||||
}
|
||||
|
||||
# ALIAS DESCRIPTIONS
|
||||
line_length=59
|
||||
|
||||
get_alias_descriptions() {
|
||||
local file_path="$1"
|
||||
if [ -f "$file_path" ]; then
|
||||
echo ""
|
||||
echo "@ $file_path"
|
||||
local description=""
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" =~ ^### ]]; then
|
||||
fill_line_with_string "${line#'### '}" "$line_length" "-"
|
||||
elif [[ "$line" =~ ^# ]]; then
|
||||
description="${line#"# "}"
|
||||
elif [[ "$line" =~ ^(alias|fake_alias) ]]; then
|
||||
alias_name=$(printf "%10s" "$(echo "$line" | cut -d'=' -f1 | awk '{print $2}')")
|
||||
echo "$alias_name :: $description"
|
||||
elif [[ $line == "next_line" ]]; then
|
||||
printf "%*s%s\n" "14" "" "$description"
|
||||
else
|
||||
description=""
|
||||
fi
|
||||
done <"$file_path"
|
||||
fi
|
||||
}
|
||||
|
||||
display_alias_descriptions() {
|
||||
echo ""
|
||||
fill_line_with_string "ALIASES DESCRIPTIONS" "$line_length" " "
|
||||
get_alias_descriptions "$ALIASES"/.aliases
|
||||
get_alias_descriptions "$ALIASES"/.git_aliases
|
||||
get_alias_descriptions "$ALIASES"/.docker_aliases
|
||||
get_alias_descriptions "$ALIASES"/.local_aliases
|
||||
get_alias_descriptions "$ALIASES"/.custom_aliases
|
||||
fill_line "$line_length" "-"
|
||||
}
|
||||
|
||||
ea_help() {
|
||||
e_info "Usage: ea [c|l|h]"
|
||||
echo "Edit ~/.config/aliases/.aliases file when used without arguments"
|
||||
echo "Args: c :: edit ~/.config/aliases/.custom_aliases"
|
||||
echo " l :: edit ~/.config/aliases/.local_aliases"
|
||||
echo " f edit ~/.config/aliases/.functions.sh"
|
||||
echo " h :: print help"
|
||||
}
|
||||
|
||||
edit_aliases() {
|
||||
if [ $# -eq 0 ]; then
|
||||
${EDITOR:-nano} "$ALIASES"/.aliases
|
||||
elif [ $# -gt 1 ]; then
|
||||
e_err "Too many arguments!"
|
||||
ea_help
|
||||
else
|
||||
case "$1" in
|
||||
l) ${EDITOR:-nano} "$ALIASES"/.local_aliases ;;
|
||||
c) ${EDITOR:-nano} "$ALIASES"/.custom_aliases ;;
|
||||
f) ${EDITOR:-nano} "$ALIASES"/.functions.sh ;;
|
||||
h) ea_help ;;
|
||||
*) e_err "Invalid option!"; ea_help ;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
cd_to_file() {
|
||||
cwd=$(pwd)
|
||||
cd "${1:-.}" || return
|
||||
file=$(fzf --preview 'bat --color=always {}')
|
||||
if [ -z "$file" ]; then
|
||||
cd "$cwd" || return
|
||||
else
|
||||
cd "$(dirname "$file")" || return
|
||||
fi
|
||||
}
|
||||
|
||||
mkdir_and_cd() {
|
||||
mkdir -p "$1" || e_err "Failed to create directory: $1"
|
||||
cd "$1" || e_err "Failed to navigate to directory: $1"
|
||||
}
|
||||
179
configs/aliases/.git_aliases
Normal file
179
configs/aliases/.git_aliases
Normal file
@@ -0,0 +1,179 @@
|
||||
#!/bin/bash
|
||||
|
||||
# GIT FUNCTIONS
|
||||
|
||||
# git checkout with tab completion
|
||||
# bash override for zsh gco alias
|
||||
if [ -n "$BASH_VERSION" ] && [ -f ~/.config/aliases/.git_bash_autocomplete ]; then
|
||||
. ~/.config/aliases/.git_bash_autocomplete
|
||||
fi
|
||||
|
||||
# git create stast with message
|
||||
git_stash_msg() {
|
||||
if [ -z "$1" ]; then
|
||||
e_warn "Stash changes with message! Don't be lazy..."
|
||||
else
|
||||
local msg="$*"
|
||||
git stash -m "$msg"
|
||||
e_succ "Succesfully stashed changes as '$msg' on branch '$(git branch --show-current)'."
|
||||
fi
|
||||
}
|
||||
|
||||
# git apply stash by number
|
||||
git_apply_stash() {
|
||||
if [ $# -eq 0 ]; then
|
||||
e_warn "Please specify stash number!"
|
||||
return 1
|
||||
elif [ $# -gt 1 ]; then
|
||||
e_warn "Please specify only one stash number!"
|
||||
return 1
|
||||
else
|
||||
git stash apply stash@"{$1}"
|
||||
fi
|
||||
}
|
||||
|
||||
# git echo stasth diff by number
|
||||
# useful combined with '| xc'
|
||||
git_stash_patch() {
|
||||
if [ $# -eq 0 ]; then
|
||||
e_warn "Please specify a stash number!"
|
||||
return 1
|
||||
elif [ $# -gt 1 ]; then
|
||||
e_warn "Please specify only one stash number!"
|
||||
return 1
|
||||
else
|
||||
git stash show -p stash@"{$1}"
|
||||
fi
|
||||
}
|
||||
|
||||
# drop stash by number with confirmation
|
||||
# I accidentally dropped stashes, because I mix up gsp and gsd
|
||||
git_stash_drop() {
|
||||
if [ $# -eq 0 ]; then
|
||||
e_warn "Please specify a stash number!"
|
||||
return 1
|
||||
elif [ $# -gt 1 ]; then
|
||||
e_warn "Please specify only one stash number!"
|
||||
return 1
|
||||
else
|
||||
printf "Are you sure you want to drop stash #$1? (Y/N): "
|
||||
read -r confirm
|
||||
if [[ "$confirm" =~ ^[yY]$ ]]; then
|
||||
git stash drop stash@"{$1}"
|
||||
e_info "Stash #$1 dropped."
|
||||
else
|
||||
e_warn "Aborted. Stash #$1 not dropped."
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# git diff with optional filename from git diff --names-only | nl
|
||||
git_diff_numbered() {
|
||||
local files file
|
||||
files=()
|
||||
while IFS= read -r line; do
|
||||
files+=("$line")
|
||||
done < <(git diff --name-only)
|
||||
if [ $# -eq 0 ]; then
|
||||
printf "%s\n" "${files[@]}" | nl
|
||||
elif [ $# -eq 1 ] && [[ $1 =~ ^[0-9]+$ ]]; then
|
||||
if [ -n "$BASH_VERSION" ]; then
|
||||
file="${files[$1 - 1]}"
|
||||
else
|
||||
file="${files[$1]}"
|
||||
fi
|
||||
[ -n "$file" ] && git diff "$file"
|
||||
else
|
||||
e_err "Invalid argument! Provide number from the output of 'gdn'."
|
||||
fi
|
||||
}
|
||||
|
||||
# git restore file based on the number from git diff --names-only | nl
|
||||
git_restore_by_number() {
|
||||
local files file
|
||||
files=()
|
||||
while IFS= read -r line; do
|
||||
files+=("$line")
|
||||
done < <(git diff --name-only)
|
||||
if [ $# -eq 0 ]; then
|
||||
e_err "Missing argument! Provide number from the output of 'gdn'."
|
||||
elif [ $# -eq 1 ] && [[ $1 =~ ^[0-9]+$ ]]; then
|
||||
if [ -n "$BASH_VERSION" ]; then
|
||||
file="${files[$1 - 1]}"
|
||||
else
|
||||
file="${files[$1]}"
|
||||
fi
|
||||
[ -n "$file" ] && git restore "$file"
|
||||
else
|
||||
e_err "Invalid argument! Provide number from the output of 'gdn'."
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# git add untracked files, commit and push
|
||||
git_commit_push() {
|
||||
if [ -z "$1" ]; then
|
||||
e_err "No commit message provided!"
|
||||
return 1
|
||||
else
|
||||
local message="$*"
|
||||
git add -u
|
||||
git commit -m "$message"
|
||||
git push
|
||||
e_succ -e "\nCommit '$message' succesfully pushed to branch: '$(git branch --show-current)'."
|
||||
fi
|
||||
}
|
||||
|
||||
# git list stashes
|
||||
git_stash_list() {
|
||||
printf "%s\n" "$(git stash list)"
|
||||
}
|
||||
|
||||
### Git aliases
|
||||
# git status
|
||||
fake_alias gst
|
||||
if [ -n "$BASH_VERSION" ]; then
|
||||
alias gst='git status'
|
||||
fi
|
||||
# git fetch all
|
||||
fake_alias gfa
|
||||
if [ -n "$BASH_VERSION" ]; then
|
||||
alias gfa='git fetch --all --prune'
|
||||
fi
|
||||
# git diff
|
||||
fake_alias gd
|
||||
if [ -n "$BASH_VERSION" ]; then
|
||||
alias gd='git diff'
|
||||
fi
|
||||
# git diff classic with less pager
|
||||
alias gdc="git -c core.pager='less' diff"
|
||||
# git diff numbered
|
||||
alias gdn=git_diff_numbered
|
||||
# (with filenum works only in repo root)
|
||||
next_line
|
||||
# git commit and push with message
|
||||
alias gcpm=git_commit_push
|
||||
# git checkout with tab completion
|
||||
fake_alias gco
|
||||
# git submodule update
|
||||
fake_alias gsu
|
||||
if [ -n "$BASH_VERSION" ]; then
|
||||
alias gsu='git submodule update'
|
||||
fi
|
||||
# git stash with message
|
||||
alias gstm=git_stash_msg
|
||||
# git stash list
|
||||
alias gstl=git_stash_list
|
||||
# git stash patch <#>
|
||||
alias gstp=git_stash_patch
|
||||
# git stash apply <#>
|
||||
alias gsta=git_apply_stash
|
||||
# gti stash drop <#>
|
||||
alias gstd=git_stash_drop
|
||||
# git restore
|
||||
alias grs='git restore'
|
||||
# git restore by number from gdn
|
||||
alias grsn=git_restore_by_number
|
||||
# run pre-commit on changed files only
|
||||
alias pc='pre-commit run --files $(git diff --name-only)'
|
||||
11
configs/aliases/.git_bash_autocomplete
Normal file
11
configs/aliases/.git_bash_autocomplete
Normal file
@@ -0,0 +1,11 @@
|
||||
gco() {
|
||||
git checkout "$@"
|
||||
}
|
||||
# Enable git completion if available
|
||||
if [ -f /usr/share/bash-completion/completions/git ]; then
|
||||
. /usr/share/bash-completion/completions/git
|
||||
fi
|
||||
# Enable git branch completion for gc
|
||||
if type __git_complete &>/dev/null; then
|
||||
__git_complete gco _git_checkout
|
||||
fi
|
||||
Reference in New Issue
Block a user