From 6e8179fbb909033d6ea2cc4eaf763b0dc89d3be9 Mon Sep 17 00:00:00 2001 From: Xerus <27jf@web.de> Date: Sun, 8 Mar 2020 20:18:49 +0100 Subject: [PATCH] add shell functions & zsh completions --- .local/share/shell/functions | 441 ++++++++++++++++++ .local/share/shell/git | 243 ++++++++++ .local/share/shell/projects | 83 ++++ .local/share/shell/zsh_completion/_duel | 12 + .local/share/shell/zsh_completion/_editshell | 2 + .local/share/shell/zsh_completion/_gitclone | 18 + .../share/shell/zsh_completion/_gitrmbranch | 2 + .local/share/shell/zsh_completion/_gitsquash | 15 + .local/share/shell/zsh_theme | 6 + 9 files changed, 822 insertions(+) create mode 100644 .local/share/shell/functions create mode 100644 .local/share/shell/git create mode 100644 .local/share/shell/projects create mode 100644 .local/share/shell/zsh_completion/_duel create mode 100644 .local/share/shell/zsh_completion/_editshell create mode 100644 .local/share/shell/zsh_completion/_gitclone create mode 100644 .local/share/shell/zsh_completion/_gitrmbranch create mode 100644 .local/share/shell/zsh_completion/_gitsquash create mode 100644 .local/share/shell/zsh_theme diff --git a/.local/share/shell/functions b/.local/share/shell/functions new file mode 100644 index 0000000..9780d53 --- /dev/null +++ b/.local/share/shell/functions @@ -0,0 +1,441 @@ +# Shell configuration for Zsh, works almost completely for Bash as well +export LESS=-R +export LC_MESSAGES=C + +export DIST=$(lsb_release --id | cut -d' ' -f2) + +alias println='printf "\n"' + +alias editgrub='sudo nvim /etc/default/grub && sudo update-grub' + +alias startMinecraftServer='curl https://ipinfo.io/ip | xclip -sel clip && cd ~/daten/games/sharedgames/minecraft/server && java -jar forge-1.12.2-14.23.5.2768-universal.jar -mx 8G' + +# Fast shortcuts +alias t='tree -C | less' +alias c='clear' +alias q='exit' +alias v='nvim' +b() { bat "$@" 2>/dev/null || ls -lah "$@" } + +_FUNCTIONS=${BASH_SOURCE[0]:-${(%):-%x}} +alias r="reset && source $_FUNCTIONS" + +dropbox_path=$(cat ~/.dropbox/info.json | grep -Po '"'"path"'"\s*:\s*"\K([^"]*)') + +# Add an "alert" alias for long running commands. Use like so: sleep 10; alert +#if [ command -v notify-send >/dev/null 2>&1 ]; then +alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(echo "$history[$HISTCMD]" | sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' +#fi + +# Fix broken mime messages +alias fixmime='sudo rm /usr/share/mime/packages/kde.xml && sudo update-mime-database /usr/share/mime' + +# Find zmv in man because I need to look it up all the time ^^ +man() { + (test "$1" = "zmv" && LESS="$LESS+/^ *zmv *\\[" /usr/bin/man zshcontrib) || /usr/bin/man "$@" +} + +updateDeps() { + name="$1" + pattern="$2" + depth="4" + case $name in + gradle-wrapper.properties) depth=6;; + esac + shift 2 + oldversion="[0-9.]\+" + while test $# -gt 1; do + case "$1" in + --pattern) oldversion="$2";; + --version) version="$2";; + esac + shift 2 + done + echo name $name depth $depth pattern $oldversion version $version + find -maxdepth $depth -type f -name $name | while read f + do echo $f + sed -i "s/\($pattern\)$oldversion/\1$version/gw /dev/stdout" $f + done +} +alias updateKotlin='updateDeps build.gradle.kts '\''kotlin(\"jvm\") version \"'\'' --version' +alias updateGradle='updateDeps gradle-wrapper.properties "services.gradle.org\/distributions\/gradle-" --version' +alias updateUtils='updateDeps build.gradle.kts '\''\"com.github.Xerus2000.util\", \".*\", \"'\'' --pattern '\''[^\"]\+'\'' --version' + +alias killbg='kill ${${(v)jobstates##*:*:}%=*}' + +killJava() { + pgrep -f 'java' | while read id + do if [[ $(ps --no-headers -o cmd $id) != *"idea"* ]]; then + [[ "$@" == "-q" ]] || echo "killing $(ps -p $id -o pid,cmd --width 350 --no-headers)" + if [[ "$@" == "-9" ]] + then kill -9 $id + else kill $id + fi + fi; done +} + +clearNpmCache() { + rm -rf $TMPDIR/react-* + rm -rf node_modules/ + npm cache verify + npm install +} + +# NAVIGATION & DISK + +up() { + if [[ $# < 1 ]] ; then + cd .. + else + CDSTR="" + for i in {1..$1} ; do + CDSTR="../$CDSTR" + done + cd $CDSTR + fi +} + +# Switch directory & ls +cl() { + cd $1 + ls -A +} + +# shows size usage for disk or folder +s() { + if test "-d" = "$1" + then df -h + else sudo du --max-depth ${1:-1} -xh | sort -h | grep -v "^0" + fi +} + +alias f='find -not -path "*.sync*" -and -not \( -name daten -prune \)' +alias f1='find -mindepth 1 -maxdepth 1' + +# FILES + +alias lowercase='rename "y/A-Z/a-z/"' + +mkcd() { + mkdir -p $1 && cd $1 +} + +# Creates directory $2 and moves $1 into it +mvk() { + mkdir -p $(dirname "$2") + mv "$1" "$2" +} + +# moves from $1 to $2 and creates a symlink instead +mvln() { + file=$(test -f "$1" && echo 1 || echo 0) + if test -d $1; then + mkdir -p "$2" + mv -T $1 $2 + else + mv -v $1 $2 + fi + [ $file -gt 0 -a -d $2 ] && 2="$2/$(basename $1)" + ln -vsr $2 $1 +} + +# OTHER + +editshell() { + nvim $(test $# -lt 1 && echo "$_FUNCTIONS" || (results=$(find "$dropbox_path/tools/setup" -maxdepth 1 -name "$1.sh") && test "$results" && echo "$results") || echo "$(dirname $_FUNCTIONS)/$1") && r +} + +pathadd() { + local IFS=":" + local result="$@" + unset IFS + cat /etc/environment | head -1 | cut -d'"' -f2 | tr ":" "\n" | while read v; do + [[ " $@ " =~ " $v " ]] || result+=":$v" + done + echo PATH=\"${result}\"\\n$(cat /etc/environment | tail -n +2) | sudo tee /etc/environment +} + +writecompletion() { + echo "#compdef $1" > "_$1" + nvim "_$1" +} + +resetdocker() { + #aptremove docker-ce + kill $(ps -e | grep docker | cut -d' ' -f2) + sudo rm -rf /var/run/docker /var/lib/docker + sudo rm /var/run/docker.* + #aptinstall docker-ce +} + +# MUSIC + +music_folder="/home/janek/daten/musik" +audio_folder="/home/janek/daten/audio" +music_original_folder="$audio_folder/songs/_raw" + +makePl() { echo ${2:-empty} >$1.m3u8 } +makePls() { + i=1; while test $i -le ${1:-9}; do makePl "${2:-Ω}$i" "empty$i"; ((i++)); done +} + +findsongs() { + find -regextype posix-extended -maxdepth 1 -type f -regex "${1:-.*\.(mp3|flac|wav|m4a)}" -printf "%P\n" +} + +addmix() { + mv -v "$1.cue" "$audio_folder/recordings/cues" + addsong "$1.flac" Mixes +} + +addsong() { + test "$1" = "-q" && shift && quick="true" + + local raw="${1%.*}" + local isflac=$(case "$1" in *.flac) echo "true";; esac) + test "$isflac" || (echo "Converting to flac..." && flac "$1" --totally-silent) + + test "$quick" || (echo "Press ENTER when the metadata of the flac file is correct..." && read) + + echo "Converting to mp3..." + lame -V0 "$1" --silent + + mkdir -p "$music_folder/$2" + mkdir -p "$music_original_folder/$2" + + local destination="$music_folder/$2/$raw.mp3" + echo "Moving mp3 with metadata to $destination" + ffmpeg -i "$raw.mp3" -i "$raw.flac" -c copy -map_metadata 1 "$destination" -v warning "${@:3}" && rm "$raw.mp3" + test ! "$PWD" -ef "$music_original_folder/$2" && mv -v "$raw.flac" "$music_original_folder/$2" && (test "$isflac" || rm -v "$1") +} + +addalbum() { + mkdir -p "$music_folder/$1" + mkdir -p "$music_original_folder/$1" + f1 -regextype posix-extended -type f -regex "\./(cover|folder)\.(png|jpg|jpeg)" | while read cover; do + foundcover="true" + cp -v "$cover" "$music_folder/$1" && + mv -v "$cover" "$music_original_folder/$1" + done + test "$foundcover" || f1 -regextype posix-extended -type f -regex ".*\.(png|jpg|jpeg)" | while read cover; do + cp -v "$cover" "$music_folder/$1" && + mv -v "$cover" "$music_original_folder/$1" + done + + IFS=$'\n' + for s in $(findsongs ".*\.(flac|wav)"); do + highlight "$s" + addsong -q "$s" "$1" "${@:2}" + done + unset IFS +} + +formatsongs() { + _pwd="$PWD" + find "$PWD" "$@" -type d | while read d; do cd $d; findsongs | while read song; do + new="$(formatsong "$song")" + test "$new" != "$song" && mv -v "$song" "$new" + done; done + cd "$_pwd" + IFS=$'\n' + for f in $(find "$@" -name "*.wav"); do + echo "Converting $f to ${f%.*}.flac" + ffmpeg -i "$f" "${f%.*}.flac" -v warning && rm -v $f + done + unset IFS +} + +formatsong() { + echo "$1" | sed -e 's/\([ ([]\)\(ft\|Ft\|Feat\)\([ .]\)/\1feat\3/;s/\([ ([]\)feat /\1feat. /;s/ \((Original Mix)\|(Original)\|(Full Stream)\|.NCS Release.\)//i;s/ \(\..\{2,4\}\)$/\1/;s/---/ - /;s/^[0-9]\{6\}_//;s/ / /g;s/\(\w\)+\(\w\)/\1 \2/g' - +} + +# INSTALL + +snapinstall() { + sudo snap install "$@" + refreshSetup +} + +alias aptupdate='sudo apt-get update' +alias aptremove='sudo apt-get remove' +alias aptpurge='sudo apt-get purge' +alias aptclean='sh -c "sudo apt-get clean && sudo apt-get autoremove"' +upgrade() { + if test $DIST = "neon" + then sudo pkcon update + else sudo apt update && sudo apt upgrade + fi + sudo snap refresh + flatpak update -y + sudo npm update -g + # npm -g outdated --parseable=true | cut -d : -f 4 | xargs -n 1 npm -g install +} + +uma() { + if test "$1" + then printf 'y\nj\na' | umake "$1" "$2" "/opt/${3:-$2}" + else + uma ide idea-ultimate idea + uma android android-studio android/android-studio && yes | /opt/android/sdk/tools/bin/sdkmanager --licenses && pathadd /opt/android/sdk/tools/bin /opt/android/sdk/platform-tools && sudo apt install qemu-kvm && sudo adduser janek kvm + test -d "/opt/vscode" && uma ide visual-studio-code vscode + fi +} + +alias aptrepo='sudo add-apt-repository' +_aptrepo_n="$(test "$OSTYPE" != "cygwin" && add-apt-repository --help | grep -- "-n")" +aptrepon() { + test $_aptrepo_n && aptrepo -y -n "$@" || aptrepo -y "$@" +} +aptrepos() { + for repo in "$@" + do aptrepon $repo + done + aptupdate +} +alias aptinstall='sudo apt-get install' +aptrepoinstall() { + aptrepo -yu $1 + if (( $# > 1 )) + then aptinstall "${@:2}" + else aptinstall "${1##*/}" + fi +} + +# Gets the download url for the latest release of a package provided via GitHub Releases +# Usage: ghrelease USER REPO [PATTERN] +ghrelease() { + curl -s "https://api.github.com/repos/$1/$2/releases/latest" | grep -o "http.*${3:-deb}" +} + +# Installs a local or remote(http/https) deb package and removes it after installation +installdeb() { + set -e + loc="/tmp/install.deb" + case $1 in + http*) sudo wget -O "$loc" $1;; + *) loc="$1" + esac + sudo dpkg -i "$loc" + sudo apt -f install + sudo rm -f "$loc" +} + +installgh() { + installdeb $(ghrelease "$@") +} + +# Downloads all dependencies of a package into the current directory +download-debs() { + apt-get download $1 && apt-cache depends -i $1 | awk '/Depends:/ {print $2}' | xargs apt-get download +} + +# RANDOM + +typeset -A _clean_map +if test "$BASH_VERSION" +then _clean_map=([m]=~/.mozilla [c]=~/.cache) +else _clean_map=(m ~/.mozilla c ~/.cache) +fi +_clean_folders=(~/.oracle_jre_usage ~/.gradle-kotlin-dsl ~/.thumbnails ~/.zcompdump*) +clean() { + + for f in $_clean_folders + do test -d $f && rm -rv $f + done + + highlight "g to clean gradle" + if [[ $1 =~ "g" ]]; then + find ~/.gradle/* -maxdepth 0 -not -name "gradle.properties" -exec rm -r {} \; -print + find ~/daten/projects/ -name .gradle -print -exec rm -r {} \; + fi + + if test "$BASH_VERSION"; then + for k in "${!_clean_map[@]}"; do + highlight "$k to delete $_clean_map[$k] + echo "key : $k" + echo "value: ${_clean_map[$k]}" + done + else + for k in "${(@k)_clean_map}"; do + highlight "$k to delete $_clean_map[$k] + [[ $1 =~ "$k" ]] && rm -rfv "$_clean_map[$k]" + done + fi + + aptclean && echo "Cleaned apt" + + highlight "e to delete empty folders" + [[ $1 =~ "e" ]] && find -empty -type d -delete -print +} + +function zipdiff() { + diff -W200 -y <(unzip -vql $1 | sort -k8) <(unzip -vql $2 | sort -k8) #--suppress-common-lines +} + +# PROJECTS + +source "$(dirname $_FUNCTIONS)/git" +source "$(dirname $_FUNCTIONS)/projects" + +genssh() { + mkdir -p ~/.ssh + test -f ~/.ssh/id_rsa.pub || ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -q -N "" -C ${1:-$(hostname)} + if test "$OSTYPE" = "cygwin" + then cat ~/.ssh/id_rsa.pub>/dev/clipboard + else xclip -sel clip < ~/.ssh/id_rsa.pub + fi && echo "SSH Public key copied to clipboard" +} + +pdiff() { + diff -r $1 $2 -x .git -x .idea -x .gradle +} + +createproject() { + mkcd $1 + + echo 'plugins { + kotlin("jvm") version "1.3.41" + application + id("com.github.johnrengelman.shadow") version "5.1.0" + id("com.github.ben-manes.versions") version "0.21.0" +} + +sourceSets { + main { + java.srcDir("src/main") + resources.srcDir("src/resources") + } + test { + java.srcDir("src/test") + } +}' > build.gradle.kts + +} + +# SWAP + +mem_stat() { + mem_total="$(free | head -2 | tail -1 | awk '{print $2}')" + mem_free="$(free | head -2 | tail -1 | awk '{print $4}')" + mem_percentage=$((mem_free * 100 / $mem_total)) + swap_total="$(free | tail -1 | awk '{print $2}')" + swap_used="$(free | tail -1 | awk '{print $3}')" + swap_percentage=$(($swap_used * 100 / $swap_total)) + + echo -e "Free memory:\t$((mem_free / 1024))/$((mem_total / 1024)) MB\t($mem_percentage%)" + echo -e "Used swap:\t$((swap_used / 1024))/$((swap_total / 1024)) MB\t($swap_percentage%)" +} + +stopswap() { + mem_stat + if (( $swap_used == 0 )) + then echo "No swap is in use." + elif (( $swap_used + 100000 < mem_free )) + then echo "Freeing swap..." + sudo swapoff -a + sudo swapon -a + mem_stat + else + echo "Not enough free memory!" + fi +} diff --git a/.local/share/shell/git b/.local/share/shell/git new file mode 100644 index 0000000..5cbe1f4 --- /dev/null +++ b/.local/share/shell/git @@ -0,0 +1,243 @@ + +alias bfg='java -jar ~/daten/dropbox/tools/bfg-1.13.0.jar' +alias gti=git + +# Repo info + +alias gr='git remote -v' +alias gb='git branch -vv' +alias grev='git rev-parse --short' +alias ghead='git rev-parse --short HEAD' +alias gref='git reflog' +gln() { + git --no-pager log --graph --pretty=format:"%C(auto)%h -%d %s %Cgreen(%cr) %Cblue<%an>%Creset" -5 "$@" + println +} + +glno() { + local log= + local loc="$(git log --pretty=format:"%C(auto)%h %s %Cgreen(%cr)" -5 "$@" --color=always "$@")" + local origin="$(git log --pretty=format:"%C(auto)%h %s %Cgreen(%cr)" -5 "origin/$(git curbranch)" --color=always "$@")" + local a=$(echo $loc | wc -l) + local b=$(echo $origin | wc -l) + for i in `seq 1 $([ $a -le $b ] && echo "$a" || echo "$b")`; do + printf '%-120s %s\n' "$(echo $loc | head -n $i | tail -1)" "$(echo $origin | head -n $i | tail -1)" + done +} + +# Shortcuts + +alias gfs='git fetch && git status -s -b' +alias gcap!='git commit -a --amend --no-edit && git push -f' +alias grh!='git reset --hard' +alias grhr='git reset --hard $(git rev-parse --abbrev-ref --symbolic-full-name @{u})' +alias gitgc='git gc && git repack -a -d' +gitchild() { git log --reverse --ancestry-path --pretty=%H $1..${2:-HEAD} | head -1; } +gitrecache() { + git rm --cached --quiet -r ${1:-.} + git add ${1:-.} + git status -s +} + +gitrestore() { + git reset -- "$@" + git checkout -- "$@" +} + +alias gitstandup='git --no-pager log --since yesterday --author Xerus --all' +alias gitready='git rebase -i @{u}' +alias gitwhen="git for-each-ref --sort=committerdate --format='%(refname:short) * %(authorname) * %(committerdate:relative)' refs/remotes/" +gitrebranch() { + branch=${1:-$(git curbranch)} + test "$(git curbranch)" = "$branch" && git checkout ${2:-master} + git branch -D $branch + git checkout -b $branch +} +gitrmbranch() { + branch=${1:-$(git curbranch)} + git push -d origin $branch + test $1 || git checkout master + git branch -D $branch +} +alias gitrmgonebranches='git fetch -p && for branch in `git branch -vv | grep ": gone]" | cut -d" " -f3`; do git branch -D "$branch"; done' + +# Testing + +gittestcommit() { touch file$((++i)) && git add . && git commit -m "Create file$i"; } +gitsnap() { + echo -n "Snapped " + echo $(git rev-parse HEAD) | tee "$(git dir)/${1:-snap}" +} +gitsnaprestore() { + git reset --hard $(cat "$(git dir)/${1:-snap}") +} +gitrmtag() { + declare -a refs + local index=1 + for tag in $@; do refs[index++]=":refs/tags/$tag"; done + git push origin "${refs[@]}" && git tag -d "$@" +} +gitretag() { + git push origin refs/tags/${1}:refs/tags/${2} :refs/tags/$1 && git tag -d $1 +} + +# Repo management + +gitinit() { + git init + git add . + git commit -m "First strike" + gitorigin "$@" + git push +} + +gitbackup() { + p=$(basename $PWD) + cd .. + git clone --mirror $p + cd $p +} + +gitremote() { + case "$1" in + http*) echo "git@$(echo "$1" | cut -d'/' -f3):$(echo "$1" | cut -d'/' -f4)/$(echo "$1" | cut -d'/' -f5)" ;; + *) test "$2" = "-" && 2="" + test "$3" = "cau" && 3="CAU-Kiel-Tech-Inf" + test "$3" = "btl" && 3="betweenthelinesev" + echo "git@git${1:-hub}.com:${3:-Xerus2000}/${2:-$(basename $PWD)}.git" ;; + esac +} + +# Setting up repos + +project() { + cd $projects_dir + if [ -d $2 ] + then cd "$2" && gitorigin "$@" + else gitclone "$@" + fi +} + +gitclone() { + remote=$(gitremote "$@") + echo $remote + git clone $remote "${@:4}" + cd "$2" +} + +gitfork() { + cd "$projects_dir/_forks" + gitclone hub "$1" + test "$2" && git remote add upstream "$(gitremote hub "$1" "$2")" +} + +# sets this repo as origin and sets all branches upstream to their respective remote branch, if available +gitorigin() { + git remote remove origin 2>/dev/null + git remote add origin $(gitremote "$@") + git remote -v && git fetch || ( last=$? && echo "git fetch failed, aborting\!" && return $last ) + + git branch | sed 's/ //g' | sed 's/*//' | while read branch + do test $(git branch -a | grep origin/$branch | wc -l) -gt 0 && git branch -u origin/$branch $branch + done +} + +# sets this repo as upstream +gitupstream() { + local name="${2:-upstream}" + git remote remove $name 2>/dev/null + git remote add $name "$(git remote -v | grep origin | head -1 | cut -f2 | cut -d':' -f1):$1/$(git remote -v | grep origin | head -1 | cut -f2 | cut -d'/' -f2 | cut -d' ' -f1)" + git remote -v && git fetch $name || ( last=$? && echo "git fetch failed, aborting!" && return $last ) +} + +# Rewriting history + +# gets the AuthorDate of a given committish +git-authordate() { + local date=$(git log --pretty=fuller --date=raw -1 $1 | grep AuthorDate) + echo ${date##*: } +} +# executes a git command (usually commit) with the date of a given committish +git-withdate() { + date=$(git-authordate $1) + GIT_AUTHOR_DATE="$date" GIT_COMMITTER_DATE="$date" git "${@:2}" +} + +# takes all changes in the current working tree and amends them to the given commit +gitedit() { + git stash + gitcommits -q $1 + git reset --hard $1 + git stash pop -q + git-withdate $1 commit --all --amend "${@:2}" + gitcommits +} + +# takes two committishs and squashes them with all commits between them into a single commit +# this will rewrite the full history from then on, but should not create any conflicts +gitsquash() { + local -a options + while [ $# -gt 0 ]; do + case $1 in + -i) ignore=true; shift 1;; + -f|--force) force=true; shift 1;; + -*) options+=($1); exit 1;; + *) break;; + esac + done + + ((#!=2)) && echo "Usage: [options] " && return 1 + [[ -n $(git status -s) ]] && [ ! $force ] && echo -e "Tree is dirty, commit or stash your changes first!\nIf you want to execute the command regardless, run again with --force" && return 1 + + 1=$(git rev-parse $1) + 2=$(git rev-parse $2) + [ $(git rev-list $1 --count) -lt $(git rev-list $2 --count) ] && t=$1 && 1=$2 && 2=$t + + gitcommits -q $1 + git reset --hard $1 + if [ $(git rev-list $2 --count) = 1 ]; then + git update-ref -d HEAD + git add . + git-withdate $1 commit -c $1 + else + git reset -q $2 + git add . + git commit --amend + fi + gitcommits +} + +# given a committish, this command saves a list of commits between the HEAD and the given committish into the .git directory +# when ran without parameters it applies the saved list of commits onto the current HEAD +gitcommits() { + verbosity=1 + while [[ $# -gt 0 ]]; do + case $1 in + -v) verbosity=2; shift 1;; + -q|--quiet) verbosity=0; shift 1;; + --theirs) params=(-X theirs); shift 1;; + *) break;; + esac + done + + stashed="$(git rev-parse --show-toplevel)/.git/stashed-commits" + if [ $1 ]; then + if [ $verbosity -eq 0 ] + then git rev-list --reverse HEAD...$1 >$stashed + else git rev-list --reverse HEAD...$1 | tee $stashed + fi + else + local aborted + for commit in $(cat $stashed); do + [ $aborted ] && rest+=($commit) && continue + [ $verbosity -gt 0 ] && git --no-pager log --oneline -1 $commit + git-withdate $commit cherry-pick $commit ${params:0} >/dev/null + last=$? + [ $last -gt 0 ] && aborted=true && typeset -a rest && continue + [ $verbosity -gt 0 ] && echo -e "\e[1A$(git log --color=always --pretty=format:"%C(yellow)$(git rev-parse --short HEAD^^)%C(bold) -> %Creset%C(yellow)%h%Creset %s" -1)" + [ $verbosity -gt 1 ] && git status -s + done + echo $rest >$stashed + [ $aborted ] && echo "A problem was encountered. Fix it and run 'gitcommits' again to apply the remaining ${#rest} commits." + fi +} diff --git a/.local/share/shell/projects b/.local/share/shell/projects new file mode 100644 index 0000000..3d6362e --- /dev/null +++ b/.local/share/shell/projects @@ -0,0 +1,83 @@ +# A tool for managing multiple git projects quickly. Simply source this in your bashrc or zshrc. +# This assumes a common directory that contains all projects. Subfolders are detected as well. +# You can set $projects_dir before or after sourcing this script, or adjust it below. +# The standard command I execute daily is "p status", it updates all projects and shows their status. + +# Common root for all projects +projects_dir=${projects_dir:-~/daten/projects} + +# The max depth to search for when listing projects. The actual depth is this value minus one, since it searches for ".git" folders at that depth. +projects_subfolder_level=4 + + +# Lists all projects under $projects_dir or the current directory if that is a subfolder of $projects_dir and not a git repository. +# This is done by searching for corresponding ".git" folders and then listing their parent directories via "dirname" +listprojects() { + if test "$1" = "--all" + then find $projects_dir -mindepth 2 -maxdepth $projects_subfolder_level -type d -name ".git" | xargs dirname + else + if test "$(echo $PWD | grep $projects_dir/)" -a ! -d ".git" && ! git rev-parse --git-dir > /dev/null 2>&1 + then find $PWD -mindepth 2 -maxdepth $projects_subfolder_level -type d -name ".git" | xargs dirname + else find $projects_dir -mindepth 2 -maxdepth $projects_subfolder_level -type d -not -path "*_*" -name ".git" | xargs dirname + fi + fi +} + +# Underlines the project names +highlight() { echo "$1" } + +# Lists all projects and evaluates the given command. +alias p=projects +projects() { + test "$1" = "--all" && all="$1" && shift + case $1 in + "build") + # Builds all found gradle projects in parallel and then prints the results in batches - WARNING: This is likely to considerably slow down your computer! + listprojects $all | while read d; do + if test "$(find $d -maxdepth 1 -name "*gradle*")"; then + cd $d + buildlog="/tmp/build-$(basename $d)" + (nohup gradle build --no-daemon --console=rich &>$buildlog; highlight $(basename $d | awk '{print toupper($0)}') && cat $buildlog) & + fi + done + wait + ;; + "diffs") + # Puts the diffs of all projects into a single diffs.txt in the current directory + listprojects $all | while read d; do + echo $(basename $d)>>diffs.txt + git -C $d diff -G.>>diffs.txt + printf "\n">>diffs.txt + done + ;; + "status") + # Sets the current branch upstream to a remote branch of the same name, updates it and shows "git status -s -b" + listprojects $all | while read d; do + cd $d + highlight $(basename $d) + git branch --set-upstream-to=origin/$(git curbranch)>/dev/null + git pull --all | grep -v "Already up to date." + git status -s -b + done + ;; + *) + # Just provide a one-line summary of the status of each project and execute the command entered on every project + com="$@" + listprojects $all | while read d; do + cd $d + if [[ $com != gradle* ]] || (( $(f1 -name "*gradle*" | wc -l) > 0 )); then + local st=() + local ahead=$(command git rev-list "${branch_name}"@{upstream}..HEAD 2>/dev/null | wc -l) + test $ahead -gt 0 && st+=("ahead $ahead") + local behind=$(command git rev-list HEAD.."${branch_name}"@{upstream} 2>/dev/null | wc -l) + test $behind -gt 0 && st+=("behind $behind") + local stashes=$(git stash list | wc -l) + test $stashes -gt 0 && st+=("stashed $stashes") + test "$st" && name+=" [$(IFS=, eval 'JOINED="${st[*]}"' && echo $JOINED)]" + highlight $(basename $d) + eval "$com" + fi + done + esac + cd $projects_dir +} diff --git a/.local/share/shell/zsh_completion/_duel b/.local/share/shell/zsh_completion/_duel new file mode 100644 index 0000000..9ce0171 --- /dev/null +++ b/.local/share/shell/zsh_completion/_duel @@ -0,0 +1,12 @@ +#compdef duel battle +cur=$words[$CURRENT-1] +unset 'words[-1]' +case $cur in + -p) compadd {13060..13069};; + *) + case $PREFIX in + -*) compadd -- -p -g -min -v -vv -nodocker;; + *) compadd $(find $projects_dir/softwarechallenge2018/clients -name "*.jar" | sed "s|.*Jumper-||" | sed "s|.jar||" | while read in; do for word in $words; do [ "$in" = "$word" ] && continue 2; done; echo $in; done) + compadd -- -p -g -min -v -vv -nodocker;; + esac +esac diff --git a/.local/share/shell/zsh_completion/_editshell b/.local/share/shell/zsh_completion/_editshell new file mode 100644 index 0000000..42ee1ff --- /dev/null +++ b/.local/share/shell/zsh_completion/_editshell @@ -0,0 +1,2 @@ +#compdef editshell +compadd $(ls -pA ~/shells | grep -v / ) diff --git a/.local/share/shell/zsh_completion/_gitclone b/.local/share/shell/zsh_completion/_gitclone new file mode 100644 index 0000000..d524685 --- /dev/null +++ b/.local/share/shell/zsh_completion/_gitclone @@ -0,0 +1,18 @@ +#compdef gitclone +_arguments '-hub[GitHub]:hub:->hub' '-lab[Gitlab]:GitLab:->lab' +case "$state" in + hub) compadd $(curl -s https://api.github.com/users/xerus2000/repos?per_page=100 | grep '"name"' | grep -v ' ' | cut -d'"' -f4);; + lab) _values -s , 'flags' a b c d e;; +esac + +cur=$words[$CURRENT-1] +unset 'words[-1]' +case $cur in + -p) compadd {13060..13069};; + *) + case $PREFIX in + -*) compadd -- -p -g -min -v -vv -nodocker;; + *) compadd $(find $projects_dir/softwarechallenge2018/clients -name "*.jar" | sed "s|.*Jumper-||" | sed "s|.jar||" | while read in; do for word in $words; do [ "$in" = "$word" ] && continue 2; done; echo $in; done) + compadd -- -p -g -min -v -vv -nodocker;; + esac +esac diff --git a/.local/share/shell/zsh_completion/_gitrmbranch b/.local/share/shell/zsh_completion/_gitrmbranch new file mode 100644 index 0000000..2815cbe --- /dev/null +++ b/.local/share/shell/zsh_completion/_gitrmbranch @@ -0,0 +1,2 @@ +#compdef gitrmbranch gitrebranch +compadd $(git branch | cut -c 3- | grep -v master) diff --git a/.local/share/shell/zsh_completion/_gitsquash b/.local/share/shell/zsh_completion/_gitsquash new file mode 100644 index 0000000..ad3f639 --- /dev/null +++ b/.local/share/shell/zsh_completion/_gitsquash @@ -0,0 +1,15 @@ +#compdef gitsquash +local -a h + +maxargs=4; +for el in "${words[@]}"; do + [[ $el != -* ]] && break + ((++maxargs)) +done +echo $maxargs + +if [ $CURRENT -lt $maxargs ]; then + commits=$( ([ $PREFIX ] && git log --pretty=%h | grep "^$PREFIX" - | head -10) || git log --pretty=%h -10 ) + while read commit; do h+=("$commit:$(git log -1 --pretty=%s $commit)"); done <<< "$commits" +fi +_describe -V "hashes" h diff --git a/.local/share/shell/zsh_theme b/.local/share/shell/zsh_theme new file mode 100644 index 0000000..2331949 --- /dev/null +++ b/.local/share/shell/zsh_theme @@ -0,0 +1,6 @@ + +ZSH_THEME="powerlevel9k/powerlevel9k" +export TERM="xterm-256color" + +POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(root_indicator context dir rbenv vcs) +POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status background_jobs time)