# Text formatting utilities bold=$(tput bold) underline=$(tput sgr 0 1) reset=$(tput sgr0) purple=$(tput setaf 171) red=$(tput setaf 1) green=$(tput setaf 76) tan=$(tput setaf 3) blue=$(tput setaf 38) header() { printf "\n${bold}${purple}========== %s ==========${reset}\n" "$@" } arrow() { printf " ➜ $@\n" } success() { printf "${green} ✔ %s${reset}\n" "$@" } error() { printf "${red} ✖ %s${reset}\n" "$@" } warning() { printf "${tan} ➜ %s${reset}\n" "$@" } underline() { printf "${underline}${bold}%s${reset}\n" "$@" } bold() { printf "${bold}%s${reset}\n" "$@" } note() { printf "${underline}${bold}${blue}Note:${reset} ${blue}%s${reset}\n" "$@" } # Browser interaction utilities function google() { open -na "Google Chrome" --args "https://www.google.com/search?q=$*" } function stackoverflow() { open -na "Google Chrome" --args "https://www.google.com/search?q=site:stackoverflow.com $*" } function github() { open -na "Google Chrome" --args "https://github.com/search?q=$*" } function hacker() { open -na "Google Chrome" --args "https://hn.algolia.com/?sort=byDate&query=$*" } function gmail() { open -na "Google Chrome" --args "https://mail.google.com/mail/u/0" } function gmail2() { open -na "Google Chrome" --args "https://mail.google.com/mail/u/1" } function cicdboard() { open -na "Google Chrome" --args "$JIRA_URL/secure/RapidBoard.jspa?rapidView=457&view=planning.nodetail" } function cicddashboard() { open -na "Google Chrome" --args "$JIRA_URL/secure/Dashboard.jspa?selectPageId=13131" } function issues() { jira issue jql "status = Open AND text ~ \"$*\" ORDER BY Created DESC" } function calendar() { open -na "Google Chrome" --args "https://calendar.google.com/calendar/r?tab=mc" } function asana() { open -na "Google Chrome" --args "https://app.asana.com" } function bookmarks() { open -na "Google Chrome" --args "https://github.com/MorganGeek/bookmarks/blob/master/README.md" } function spotify() { open -na "Google Chrome" --args "https://open.spotify.com/search/$*" } function lob() { open -na "Google Chrome" --args "https://lobste.rs" } function logtalk() { path_swilgt=$(find /usr/local/Cellar/logtalk -name "*swilgt.sh" 2>/dev/null) sh "$path_swilgt" } function archive() { open -na "Google Chrome" --args "https://web.archive.org/web/*/$*" } function git_listobjectsbysize() { tempFile=$(mktemp) IFS=$'\n' for commitSHA1 in $(git rev-list --all); do git ls-tree -r --long "$commitSHA1" >>"$tempFile" done # sort files by SHA1, de-dupe list and finally re-sort by filesize sort --key 3 "$tempFile" | \ uniq | \ sort --key 4 --numeric-sort --reverse # remove temp file rm -f "$tempFile" } function top_commands() { local filter="$1" history | \cat | awk '{CMD[$2]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a; }' | grep -v "./" | column -c3 -s " " -t | grep "$filter" | sort -nr | nl | head -n50 } function top_commands_full() { local filter="$1" history | \cat | awk '{$1=$1};1' | sed 's/^[0-9 TAB]*//g' | awk '{CMD[$0]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "%\t" a; }' | grep "$filter" | sort -nr | nl | head -n50 } function istherenewissues() { LASTISSUE=$(newissues | sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g' | awk 'FNR==2{print $2}') if [[ -f "$HOME/.newjiraissue" ]] then previous_jira_issue=$(\cat "$HOME/.newjiraissue" | sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g') # the sed part is for removing output colors if [ "$LASTISSUE" != "$previous_jira_issue" ]; then newissues else success "no new issue" fi fi echo "$LASTISSUE" > "$HOME/.newjiraissue" } function aboutpage() { year=$(echo "$*" | egrep -Eo '\b[[:digit:]]{4}\b' | head -n1) if [ -z "$year" ] then year=$(curl -sSL "$*" | tr '<' '\r' | \egrep -i "date|datetime" -A 1 | \grep -Eo '\b[[:digit:]]{4}\b' | head -n1) fi author=$(curl -sSL "$*" | tr '<' '\r' | \egrep -i "author" -A 1 | \grep -Eo '([A-Z][A-Za-z]+\s([A-Za-z ]+)*)' | head -n1) title=$(curl -sSL "$*" | tr '<' '<\n' | \grep title -A 1 | head -n1 | sed -E 's/.*(.*)<\/title>.*/\1/' | sed "s/ [^[:alnum:]]*$author//") yearint=$(($year + 0)) currentyear=$(echo `date +"%Y"`) if [ ! -z "$author" ] then echo "by $author" fi if [ ! -z "$title" ] then echo "-> $title" fi if [[ $yearint -ge 1970 && $yearint -le $currentyear ]] then echo "$yearint" fi if [ ! -z "$title" ] && [ ! -z "$author" ] && [[ $yearint -ge 1970 && $yearint -le $currentyear ]]; then echo "[$author]($*) - ($yearint) $title" fi } # Extract a column from a tabular output # via https://blog.developer.atlassian.com/ten-tips-for-wonderful-bash-productivity/ function col() { awk -v col=$1 '{print $col}' } # Skip first x words in line # via https://blog.developer.atlassian.com/ten-tips-for-wonderful-bash-productivity/ function skip { n=$(($1 + 1)) cut -d' ' -f$n- } cmd_loc="find . -type f \( \ -name '*.py' \ -o -name '*.rb' \ -o -name '*.go' \ -o -name '*.java' \ -o -name '*.kt' \ -o -name '*.c' -o -name '*.h' \ -o -name '*.js' \ -o -name '*.tsx' \ -o -name '*.sh' \ -o -name '*.md' \ -o -name '*.xml' \ -o -name '*.yaml' -o -name '*.yml' \ -o -name '*.groovy' \ -o -name '*.gradle' \ -o -name '*.properties' \ \) -exec \cat \{\} \; | LANG=C LC_CTYPE=C sed -e 's/^[ \t]*//;s/[ \t]*$//'" # Unique lines of code # Via https://text.causal.agency/004-uloc.txt function uloc { eval "$cmd_loc | LANG=C LC_CTYPE=C sort -u | wc -l" } # Top lines of code function toploc { eval "$cmd_loc | LANG=C LC_CTYPE=C cut -c 1-100 | LANG=C LC_CTYPE=C sort | uniq -c | LANG=C LC_CTYPE=C sort -nr | head -50" } # Find files bigger than X size and sort them by size function biggerthan() { find . -size "+$*" -type f -print0 | xargs -0 ls -Ssh | sort -z } # To automatically ls when changing directory function cd() { builtin cd "$@" && ls -latr } function mouse() { case "$(uname -s)" in Darwin) sh ~/.scripts/mouse_bluetooth.sh ;; esac } function meteo() { curl "fr.wttr.in/$*" } function how_in() { where="$1"; shift IFS=+ curl "cht.sh/${where}/$*" } function rate() { curl "http://rate.sx/$*" } function transfer() { # check arguments if [ $# -eq 0 ]; then warning "No arguments specified. Usage:\necho transfer /tmp/test.md\ncat /tmp/test.md | transfer test.md" return 1 fi # get temporarily filename, output is written to this file show progress can be showed tmpfile=$( mktemp -t transferXXX ) # upload stdin or file file=$1 if tty -s; then basefile=$(basename "$file" | sed -e 's/[^a-zA-Z0-9._-]/-/g') if [ ! -e $file ]; then error "File $file doesn't exists." return 1 fi if [ -d $file ]; then # zip directory and transfer zipfile=$( mktemp -t transferXXX.zip ) cd $(dirname $file) && zip -r -q - $(basename $file) >> $zipfile curl --progress-bar --upload-file "$zipfile" "https://transfer.sh/$basefile.zip" >> $tmpfile rm -f $zipfile else # transfer file curl --progress-bar --upload-file "$file" "https://transfer.sh/$basefile" >> $tmpfile fi else # transfer pipe curl --progress-bar --upload-file "-" "https://transfer.sh/$file" >> $tmpfile fi # cat output link cat $tmpfile # cleanup rm -f $tmpfile } # Where is a function defined? function whichfunc() { whence -v $1 type -a $1 } # git shortcuts function gcrb { branch=$1 git checkout -b $branch origin/$branch } function terraform-compliance { docker run --rm -v "$(pwd):/target" -i -t eerkunt/terraform-compliance "$@"; } function checkov { docker run -i --rm -v "$(pwd):/tf" bridgecrew/checkov -d /tf "$@" ; } function vimat { vim +/$1 $2 } function installhooks { pre-commit install --install-hooks --overwrite --allow-missing-config } function copyhooks { cp -f ~/.git-template/.pre-commit-config.yaml ./ installhooks; runhooks; } function httperr { curl -s "https://http.cat/$1" | imgcat } function terragrunt_color { BOLD=$(tput bold) BLACK=$(tput setaf 0) RED=$(tput setaf 1) GREEN=$(tput setaf 2) YELLOW=$(tput setaf 3) BLUE=$(tput setaf 4) CYAN=$(tput setaf 6) RESET=$(tput sgr0) REDBOLD=${RED}${BOLD} REDRESET=${RESET}${RED} BLUEBOLD=${BLUE}${BOLD} BLUERESET=${RESET}${BLUE} terragrunt ${*} 2>&1 | sed \ -e "s/\(\\[terragrunt\\] \\[.*\\]\)\( [0-9\\/]* [0-9:]*\) /${BLUEBOLD}\1${BLUERESET}\2${RESET} /" \ -e "s/\(\\[terragrunt\\]\)\( [0-9\\/]* [0-9:]*\) /${BLUEBOLD}\1${BLUERESET}\2${RESET} /" \ -e "s/\(Error: \)\(.*\)/${REDBOLD}\1${REDRESET}\2${RESET}/" \ -e "s/\(Hit multiple errors:\)/${REDBOLD}\1${RESET}/" \ -e "s/\(exit status 1\)/${RED}\1${RESET}/" \ -e "s/\( WARNING: \)\(.*\)/${YELLOW}${BOLD}\1${RESET}${YELLOW}\2${RESET}/" \ -e "s/\( Running command: \)\(.*\)/\1${CYAN}\2${RESET}/" \ -e "s/\( *.*: *\)\(\".*\"\)\( => \)\(\".*\"\)/${YELLOW}\1${RED}\2${BLACK}\3${GREEN}\4${RESET}/" \ -e "s/\( *.*: *\".*\"\)/${GREEN}\1${RESET}/" } function git-project { if [ -d "$REPO_PATH" ]; then REPO_PATH="$(pwd)" fi local preview='lsd --color always --icon always --group-dirs first {}' local dir=$(find $REPO_PATH -maxdepth 3 -type d -name ".git" | sed 's#.git$##' | fzf --select-1 --query="$*" --preview "$preview") if [[ -n "$dir" ]]; then cd "$dir" || exit fi } function jenkins-cli { local script_location=$(find $HOME/code/jenkins-cloudbees-core -name "jenkins-cli.sh") eval "$script_location $*" } function passwords { bw list items --search "$1" | jq -c '.[] | .name + " " + .login.username + ":" + .login.password + " " + .login.uris[0].uri' } function password { bw get password "$1" } function vaultgetsecret { local secret=$(grep -A 500 "ANSIBLE_VAULT" "$1" | awk '{$1=$1;print}' | \grep -Eo "^[0-9a-z^ ]+$") local secret_string=$(echo "\$ANSIBLE_VAULT;1.1;AES256\n$secret") echo "$secret_string" | awk '{$1=$1;print}' | ansible-vault decrypt --vault-password-file=$VAULT_PASSWORD_FILE } function setorigin { gra origin "$1" 2>/dev/null grset origin "$1" if [[ $string =~ "collibra" ]]; then copyhooks fi } function gitpushcurrentremote { gitpushallremote "$(git_current_branch)" } function gitpushallremote { local param_branch="$1" grv grv | grep push | awk '{print $1}' | while read -r remote do if [ -z "$param_branch" ]; then arrow "pushing all branches to $remote" git push --all "$remote" else arrow "pushing $param_branch to $remote" git push "$remote" "$param_branch" fi done } function clone { local folder=$(basename $1 | sed 's/\.git.*//g') arrow "git project identified as $folder" if gcls "$1"; then if [[ -n "$folder" ]]; then cd "$folder" || exit if [[ $string =~ "collibra" ]]; then copyhooks fi else error "unable to change current directory to : $folder" fi else error "unable to clone repository url : $1" fi } function colorpic { local picture_url="$1" arrow "Colorizing $picture_url" local result_url=$(\curl -F "image=@$picture_url" -H "api-key:$COLORPIC_APIKEY" https://api.deepai.org/api/colorizer -s | jq '.output_url' | strings) success "Generated $result_url" arrow "Display in progress..." eval "\curl -s $result_url | imgcat" } function brewadd { brew install "$1" ansible 127.0.0.1 -m lineinfile -a "path=~/Brewfile line='brew \"$1\"'" } function pipadd { pip install "$1" pip freeze > "$HOME/requirements.txt" } function goadd { ansible 127.0.0.1 -m lineinfile -a "path=~/.scripts/godeps.sh line='go get -u -v $1'" go get -u -v "$1" } function rssadd { ansible 127.0.0.1 -m lineinfile -a "path=~/.newsboat/urls line='"$1"'" newsboat } function bookmarkadd { ansible 127.0.0.1 -m lineinfile -a "path=~/Code/bookmarks/README.md insertafter='"$1"' line='* "$2"'" } function backupgithub { curl -sL "https://api.github.com/users/$1/repos" | jq -r '.[] | .ssh_url' | xargs -n1 git clone --mirror --no-hardlinks } # Make a directory and cd to it function take { mkdir -p $@ && cd ${@:$#} } function endofday { local planned_end=$(moro status 2>&1 | \grep -Eo "Working until ([0-9:]+) will make.*" | uniq | \grep -Eo "([0-9]+:[0-9]+)") local max_hour="$planned_end" local min_hour=`current_time` if [ -z "$planned_end" ]; then local clockout=$(moro report 2>&1 | \grep -Eo "Clock out.*([0-9:]+)" | \grep -Eo "([0-9]+:[0-9]+)") max_hour="$clockout" fi if is_earlier "$min_hour" "$max_hour"; then arrow "you should keep working, it's only $min_hour while you should work until $max_hour" moro status else warning "you should stop working now because it's later than $max_hour" moro report fi } function convtimetodate { date -j -f '%H:%M' "$1" +'%Y/%m/%d %H:%M' } function convtimetotimestamp { date -j -f '%H:%M' "$1" +'%s' } function is_earlier { local first=$(convtimetotimestamp "$1") local second=$(convtimetotimestamp "$2") if [ "$second" -gt "$first" ]; then true else false fi } function gitydiff { local path_to_file="$1" git show "HEAD:$path_to_file" | colordiff -y - "$path_to_file" } function dl_stopwords { curl -Lks https://raw.githubusercontent.com/MorganGeek/bookmarks/master/stopwords.txt -o "$HOME/stopwords.txt" } function file_getwords { dl_stopwords; \cat "$1" | tr '[:upper:]' '[:lower:]' | \grep -o -E '\w{3,}' | \grep --invert-match --word-regexp --fixed-strings --file="$HOME/stopwords.txt" | \sed 's/s$//g' | \sed 's/ing$//g' | sort | uniq -c | sort --numeric-sort --reverse } function file_getpairs { dl_stopwords; \cat "$1" | tr '[:upper:]' '[:lower:]' | \grep -o -E '\w{3,} \w{3,}' | \grep --invert-match --word-regexp --fixed-strings --file="$HOME/stopwords.txt" | \sed 's/s$//g' | \sed 's/ing$//g' | sort | uniq -c | sort --numeric-sort --reverse } function file_dups { \cat "$1" | sort | uniq -c | sort -nr } function foreach_run { find . -name "$1" -exec "$2" {} \; }