diff --git a/README.md b/README.md index d2d02c71..c8412c92 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Bash it -'Bash it' is a mash up of my own bash commands and scripts, other bash stuff I have found and a shameless ripoff of oh-my-zsh. :) +'Bash it' is a mash up of my own bash commands and scripts, other bash stuff I have found and a shameless ripoff of [oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh). :) Includes some autocompletion tools, theming support, aliases, custom functions, a few stolen pieces from Steve Losh, and more. @@ -47,4 +47,4 @@ So, if you have contributions to bash-it, please send me a pull request and I'll * [List of contributors][contribute] -[contribute]: https://github.com/revans/bash-it/contributors \ No newline at end of file +[contribute]: https://github.com/revans/bash-it/contributors diff --git a/aliases/general.aliases.bash b/aliases/general.aliases.bash index 1cb470f1..0e05eb02 100644 --- a/aliases/general.aliases.bash +++ b/aliases/general.aliases.bash @@ -23,6 +23,8 @@ alias q="exit" alias irc="$IRC_CLIENT" +alias rb="ruby" + # Pianobar can be found here: http://github.com/PromyLOPh/pianobar/ alias piano="pianobar" diff --git a/aliases/git.aliases.bash b/aliases/git.aliases.bash index 40d87802..45d7d05f 100644 --- a/aliases/git.aliases.bash +++ b/aliases/git.aliases.bash @@ -16,6 +16,7 @@ alias gpo='git push origin' alias gdv='git diff -w "$@" | vim -R -' alias gc='git commit -v' alias gca='git commit -v -a' +alias gci='git commit --interactive' alias gb='git branch' alias gba='git branch -a' alias gcount='git shortlog -sn' @@ -23,6 +24,8 @@ alias gcp='git cherry-pick' alias gco='git checkout' alias gexport='git archive --format zip --output' alias gdel='git branch -D' +alias gmu='git fetch origin -v; git fetch upstream -v; git merge upstream/master' +alias gll='git log --graph --pretty=oneline --abbrev-commit' case $OSTYPE in linux*) @@ -55,13 +58,16 @@ function git-help() { echo " gdv = git diff -w \"$@\" | vim -R -" echo " gc = git commit -v" echo " gca = git commit -v -a" + echo " gci = git commit --interactive" echo " gb = git branch" echo " gba = git branch -a" echo " gcount = git shortlog -sn" echo " gcp = git cherry-pick" echo " gco = git checkout" echo " gexport = git git archive --format zip --output" - echo " gdel = git branch -D" - echo " gpo = git push origin" + echo " gdel = git branch -D" + echo " gpo = git push origin" + echo " gmu = git fetch origin -v; git fetch upstream -v; git merge upstream/master" + echo " gll = git log --graph --pretty=oneline --abbrev-commit" echo } diff --git a/bash_it.sh b/bash_it.sh index f0c850c2..60bef802 100644 --- a/bash_it.sh +++ b/bash_it.sh @@ -47,8 +47,9 @@ done unset config_file -export PS1=$PROMPT - +if [[ $PROMPT ]]; then + export PS1=$PROMPT +fi # Adding Support for other OSes PREVIEW="less" diff --git a/completion/ssh.completion.bash b/completion/ssh.completion.bash new file mode 100644 index 00000000..30fd65d6 --- /dev/null +++ b/completion/ssh.completion.bash @@ -0,0 +1,23 @@ +#!/bin/bash +# Bash completion support for ssh. + +export COMP_WORDBREAKS=${COMP_WORDBREAKS/\:/} + +_sshcomplete() { + + # parse all defined hosts from .ssh/config + if [ -r $HOME/.ssh/config ]; then + COMPREPLY=($(compgen -W "$(grep ^Host $HOME/.ssh/config | awk '{print $2}' )" -- ${COMP_WORDS[COMP_CWORD]})) + fi + + # parse all hosts found in .ssh/known_hosts + if [ -r $HOME/.ssh/known_hosts ]; then + if grep -v -q -e '^ ssh-rsa' $HOME/.ssh/known_hosts ; then + COMPREPLY=( $COMPREPLY $(compgen -W "$( awk '{print $1}' $HOME/.ssh/known_hosts | cut -d, -f 1 | sed -e 's/\[//g' | sed -e 's/\]//g' | cut -d: -f1 | grep -v ssh-rsa)" -- ${COMP_WORDS[COMP_CWORD]} )) + fi + fi + + return 0 +} + +complete -o default -o nospace -F _sshcomplete ssh diff --git a/lib/appearance.bash b/lib/appearance.bash index 4b1f568e..f7235118 100644 --- a/lib/appearance.bash +++ b/lib/appearance.bash @@ -8,4 +8,6 @@ export GREP_COLOR='1;33' export LSCOLORS='Gxfxcxdxdxegedabagacad' # Load the theme -source "$BASH/themes/$BASH_THEME/$BASH_THEME.theme.bash" \ No newline at end of file +if [[ $BASH_THEME ]]; then + source "$BASH/themes/$BASH_THEME/$BASH_THEME.theme.bash" +fi \ No newline at end of file diff --git a/plugins/base.plugin.bash b/plugins/base.plugin.bash index 9eceaf94..02c0104b 100644 --- a/plugins/base.plugin.bash +++ b/plugins/base.plugin.bash @@ -30,6 +30,10 @@ pri() { ri -T "${1}" | open -f -a $PREVIEW } +quiet() { + $* &> /dev/null & +} + banish-cookies() { rm -r ~/.macromedia ~/.adobe ln -s /dev/null ~/.adobe @@ -83,4 +87,10 @@ function plugins-help() { | grep -v "COMPREPLY=()" | sed -e "s/()//" } - +# back up file with timestamp +# useful for administrators and configs +buf () { + filename=$1 + filetime=$(date +%Y%m%d_%H%M%S) + cp ${filename} ${filename}_${filetime} +} diff --git a/plugins/git.plugins.bash b/plugins/git.plugins.bash index ad21591d..5f4cc51e 100644 --- a/plugins/git.plugins.bash +++ b/plugins/git.plugins.bash @@ -17,4 +17,40 @@ function git_remove_missing_files() { # Adds files to git's exclude file (same as .gitignore) function local-ignore() { echo "$1" >> .git/info/exclude -} \ No newline at end of file +} + +# get a quick overview for your git repo +function git_info() { + if [ -n "$(git symbolic-ref HEAD 2> /dev/null)" ]; then + # print informations + echo "git repo overview" + echo "-----------------" + echo + + # print all remotes and thier details + for remote in $(git remote show); do + echo $remote: + git remote show $remote + echo + done + + # print status of working repo + echo "status:" + if [ -n "$(git status -s 2> /dev/null)" ]; then + git status -s + else + echo "working directory is clean" + fi + + # print at least 5 last log entries + echo + echo "log:" + git log -5 --oneline + echo + + else + echo "you're currently not in a git repository" + + fi +} + diff --git a/plugins/hcht.plugin.bash b/plugins/hcht.plugin.bash new file mode 100644 index 00000000..cdab44fb --- /dev/null +++ b/plugins/hcht.plugin.bash @@ -0,0 +1,116 @@ +#!/bin/bash +# hcht.plugin.bash: the handmade commandline history tool +# Copyright: (C) 2010 Florian Baumann +# License: GPL-3 +# Date: Dienstag 2010-11-30 + +### readme +# basiclly the handmade commandline history tool was made for storing +# informations. yeah, you're right. sounds a bit boring. many other +# applications can do this much better. but storing things from commandline? +# +# hcht was fitted to work at your terminal. +# your daily stuff like notices, todos, commands or output from a command. +# all these things will be stored without complex syntax. +# +# once you defined your storing-directory you will be able to easily +# save all the stuff listed above. +# + +### create a file +# the basic feature. open a file, do stuff and save. +# +# $ hcht evilcommand.hch +# +# this will create a new file or edit a existing one. +# paste your command or notice in your favorite editor + +### show all stored informations +# to get an overview of your storedir: +# +# $ hcht + +### todo with a whole sentence +# you can give hcht a bunch of parameters +# +# $ hcht this is a long reminder about a anything + +### save last executed command +# lets say you did a great hack at your system and you +# want to save it without complicated use of coping: +# +# $ hcht !! +# +# the "!!" will repeat the _last_ command you executed at +# your terminal. after asking you about a name the hch file +# will be saved. + +### read from stdin +# hcht is also able to read anything from stdin. +# +# $ cat any_important_logfile | hcht anylog +# +# "anylog" will be the name of the saved file. + +hcht() { + # configured? + if [ -z $hchtstoredir ]; then + echo "ERROR: handmade commandline history tool isn't configured." + return 1 + else + hchtstoredir=$(echo $hchtstoredir | sed -e 's/\/$//') + fi + + # dir available? + if [ ! -d $hchtstoredir ]; then + echo "ERROR: No such directory: $hchtstoredir" + return 1 + fi + + # get favorite editor + if [ -z $EDITOR ]; then + EDITOR=$(which vim || which nano) + fi + + # check if stdin-data is present and save content + if [ "$(tty)" = "not a tty" ]; then + hchname=$(echo $1 | sed -e 's/\ //g') + if [ -z $hchname ]; then + cat < /dev/stdin >> $hchtstoredir/$(date +%Y%m%d%H%M%S).hch + else + cat < /dev/stdin >> $hchtstoredir/$hchname.hch + fi + return 0 + fi + + # list all hch files if no parameter is given + if [ $# -eq 0 ]; then + for file in $(ls $hchtstoredir); do + echo $file + done + return 0 + fi + + # if a *.hch file is given start editing or creating it + if [ "$#" -eq "1" ]; then + if echo "$1" | grep -q -e ".*.hch$" ; then + $EDITOR ${hchtstoredir}/${1} + return 0 + else + $EDITOR ${hchtstoredir}/${1}.hch + return 0 + fi + fi + + # autocreate a new hch + if [ "$#" -gt "1" ]; then + echo -n "define a name: " ; read hchname + hchname=$(echo $hchname | sed -e 's/\ /_/g') + if [ -z "$hchname" ]; then + echo "$*" > $hchtstoredir/${1}-$(date +%Y%m%d%H%M%S).hch + else + echo "$*" > ${hchtstoredir}/${hchname}.hch + fi + return 0 + fi +} diff --git a/plugins/jekyll.plugins.bash b/plugins/jekyll.plugins.bash index 9b0d5c1e..e87b82db 100644 --- a/plugins/jekyll.plugins.bash +++ b/plugins/jekyll.plugins.bash @@ -1,5 +1,31 @@ #!/bin/bash +editpost() { + builtin cd "$JEKYLL_LOCAL_ROOT/_posts" + + COUNTER=1 + NUMBER="$RANDOM" + TMPFILE="/tmp/editpost-$NUMBER" + + for POST in * + do + DATE=`echo $POST | grep -oE "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}"` + TITLE=`cat $POST | grep -oE "title: (.+)"` + TITLE=`echo $TITLE | sed 's/title: //'` + echo "$COUNTER) $DATE $TITLE" >> "$TMPFILE" + POSTS[$COUNTER]=$POST + COUNTER=`expr $COUNTER + 1` + done + less $TMPFILE + read -p "Number of post to edit: " POST_TO_EDIT + if [ -z "$EDITOR" ] + then + nano "${POSTS[$POST_TO_EDIT]}" + else + "$EDITOR" "${POSTS[$POST_TO_EDIT]}" + fi +} + newpost() { # 'builtin cd' into the local jekyll root @@ -12,7 +38,7 @@ newpost() { # If the user is using markdown formatting, let them choose what type of post they want. Sort of like Tumblr. - OPTIONS="Text Quote Image Audio Video" + OPTIONS="Text Quote Image Audio Video Link" if [ $JEKYLL_FORMATTING = "markdown" -o $JEKYLL_FORMATTING = "textile" ] then @@ -47,6 +73,12 @@ newpost() { POST_TYPE="Video" break fi + + if [[ $OPTION = "Link" ]] + then + POST_TYPE="Link" + break + fi done fi @@ -122,6 +154,15 @@ newpost() { then echo "" >> $FNAME fi + + if [[ $POST_TYPE = "Link" ]] + then + echo "[link][1]" >> $FNAME + echo >> $FNAME + echo "> Quote" >> $FNAME + echo >> $FNAME + echo "[1]: url" >> $FNAME + fi fi if [[ $JEKYLL_FORMATTING = "textile" ]] @@ -152,6 +193,13 @@ newpost() { then echo "" >> $FNAME fi + + if [[ $POST_TYPE = "Link" ]] + then + echo "\"Site\":url" >> $FNAME + echo >> $FNAME + echo "bq. Quote" >> $FNAME + fi fi # Open the file in your favorite editor diff --git a/plugins/python.plugin.bash b/plugins/python.plugin.bash new file mode 100644 index 00000000..92f50e02 --- /dev/null +++ b/plugins/python.plugin.bash @@ -0,0 +1,4 @@ +#!/bin/bash + +alias http='python -m SimpleHTTPServer' + diff --git a/plugins/z.bash b/plugins/z.bash new file mode 100644 index 00000000..d8c3cd6b --- /dev/null +++ b/plugins/z.bash @@ -0,0 +1,148 @@ +#!/bin/bash + +# maintains a jump-list of the directories you actually use +# +# INSTALL: +# * put something like this in your .bashrc: +# . /path/to/z.sh +# * cd around for a while to build up the db +# * PROFIT!! +# +# USE: +# * z foo # goes to most frecent dir matching foo +# * z foo bar # goes to most frecent dir matching foo and bar +# * z -r foo # goes to highest ranked dir matching foo +# * z -t foo # goes to most recently accessed dir matching foo +# * z -l foo # list all dirs matching foo (by frecency) + +z() { + local datafile="$HOME/.z" + if [ "$1" = "--add" ]; then + # add + shift + # $HOME isn't worth matching + [ "$*" = "$HOME" ] && return + awk -v p="$*" -v t="$(date +%s)" -F"|" ' + BEGIN { rank[p] = 1; time[p] = t } + $2 >= 1 { + if( $1 == p ) { + rank[$1] = $2 + 1 + time[$1] = t + } else { + rank[$1] = $2 + time[$1] = $3 + } + count += $2 + } + END { + if( count > 1000 ) { + for( i in rank ) print i "|" 0.9*rank[i] "|" time[i] # aging + } else for( i in rank ) print i "|" rank[i] "|" time[i] + } + ' "$datafile" 2>/dev/null > "$datafile.tmp" + mv -f "$datafile.tmp" "$datafile" + elif [ "$1" = "--complete" ]; then + # tab completion + awk -v q="$2" -F"|" ' + BEGIN { + if( q == tolower(q) ) nocase = 1 + split(substr(q,3),fnd," ") + } + { + if( system("test -d \"" $1 "\"") ) next + if( nocase ) { + for( i in fnd ) tolower($1) !~ tolower(fnd[i]) && $1 = "" + if( $1 ) print $1 + } else { + for( i in fnd ) $1 !~ fnd[i] && $1 = "" + if( $1 ) print $1 + } + } + ' "$datafile" 2>/dev/null + else + # list/go + while [ "$1" ]; do case "$1" in + -h) echo "z [-h][-l][-r][-t] args" >&2; return;; + -l) local list=1;; + -r) local typ="rank";; + -t) local typ="recent";; + --) while [ "$1" ]; do shift; local fnd="$fnd $1";done;; + *) local fnd="$fnd $1";; + esac; local last=$1; shift; done + [ "$fnd" ] || local list=1 + # if we hit enter on a completion just go there + [ -d "$last" ] && cd "$last" && return + [ -f "$datafile" ] || return + local cd="$(awk -v t="$(date +%s)" -v list="$list" -v typ="$typ" -v q="$fnd" -v tmpfl="$datafile.tmp" -F"|" ' + function frecent(rank, time) { + dx = t-time + if( dx < 3600 ) return rank*4 + if( dx < 86400 ) return rank*2 + if( dx < 604800 ) return rank/2 + return rank/4 + } + function output(files, toopen, override) { + if( list ) { + if( typ == "recent" ) { + cmd = "sort -nr >&2" + } else cmd = "sort -n >&2" + for( i in files ) if( files[i] ) printf "%-10s %s\n", files[i], i | cmd + if( override ) printf "%-10s %s\n", "common:", override > "/dev/stderr" + } else { + if( override ) toopen = override + print toopen + } + } + function common(matches, fnd, nc) { + for( i in matches ) { + if( matches[i] && (!short || length(i) < length(short)) ) short = i + } + if( short == "/" ) return + for( i in matches ) if( matches[i] && i !~ short ) x = 1 + if( x ) return + if( nc ) { + for( i in fnd ) if( tolower(short) !~ tolower(fnd[i]) ) x = 1 + } else for( i in fnd ) if( short !~ fnd[i] ) x = 1 + if( !x ) return short + } + BEGIN { split(q, a, " ") } + { + if( system("test -d \"" $1 "\"") ) next + print $0 >> tmpfl + if( typ == "rank" ) { + f = $2 + } else if( typ == "recent" ) { + f = t-$3 + } else f = frecent($2, $3) + wcase[$1] = nocase[$1] = f + for( i in a ) { + if( $1 !~ a[i] ) delete wcase[$1] + if( tolower($1) !~ tolower(a[i]) ) delete nocase[$1] + } + if( wcase[$1] > oldf ) { + cx = $1 + oldf = wcase[$1] + } else if( nocase[$1] > noldf ) { + ncx = $1 + noldf = nocase[$1] + } + } + END { + if( cx ) { + output(wcase, cx, common(wcase, a, 0)) + } else if( ncx ) output(nocase, ncx, common(nocase, a, 1)) + } + ' "$datafile")" + if [ $? -gt 0 ]; then + rm -f "$datafile.tmp" + else + mv -f "$datafile.tmp" "$datafile" + [ "$cd" ] && cd "$cd" + fi + fi +} +# tab completion +complete -C 'z --complete "$COMP_LINE"' z +# populate directory list. avoid clobbering other PROMPT_COMMANDs. +echo $PROMPT_COMMAND | grep -q "z --add" +[ $? -gt 0 ] && PROMPT_COMMAND='z --add "$(pwd -P)";'"$PROMPT_COMMAND" diff --git a/template/bash_profile.template.bash b/template/bash_profile.template.bash index a98e65c8..17853b1a 100644 --- a/template/bash_profile.template.bash +++ b/template/bash_profile.template.bash @@ -47,5 +47,8 @@ export IRC_CLIENT='irssi' export TODO="t" +# Set store directory for handmade commandline history tool +export hchtstoredir="$HOME/.hcht" + # Load Bash It source $BASH/bash_it.sh diff --git a/themes/base.theme.bash b/themes/base.theme.bash index 9ae5d0e8..e77d1d23 100644 --- a/themes/base.theme.bash +++ b/themes/base.theme.bash @@ -50,7 +50,7 @@ function prompt_char { } function git_prompt_info { - if [[ -n $(git status -s 2> /dev/null) ]]; then + if [[ -n $(git status -s 2> /dev/null |grep -v ^# |grep -v "working directory clean") ]]; then state=${GIT_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} else state=${GIT_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} @@ -81,4 +81,4 @@ function rvm_version_prompt { rvm=$(rvm tools identifier) || return echo -e "$RVM_THEME_PROMPT_PREFIX$rvm$RVM_THEME_PROMPT_SUFFIX" fi -} \ No newline at end of file +} diff --git a/themes/minimal/minimal.theme.bash b/themes/minimal/minimal.theme.bash index 2f9b926e..a94c4536 100644 --- a/themes/minimal/minimal.theme.bash +++ b/themes/minimal/minimal.theme.bash @@ -1,8 +1,18 @@ prompt_setter() { if [[ $? -eq 0 ]]; then - PS1="\W " + if [ ! $VIMRUNTIME = "" ] + then + PS1="{vim} \W " + else + PS1="\W " + fi else - PS1="${bold_red}\W ${normal}" + if [ ! $VIMRUNTIME = "" ] + then + PS1="{vim} ${bold_red}\W ${normal}" + else + PS1="${bold_red}\W ${normal}" + fi fi } diff --git a/themes/modern/modern.theme.bash b/themes/modern/modern.theme.bash new file mode 100644 index 00000000..8688f366 --- /dev/null +++ b/themes/modern/modern.theme.bash @@ -0,0 +1,47 @@ +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" + +SCM_THEME_PROMPT_DIRTY=' ${bold_red}✗${normal}' +SCM_THEME_PROMPT_CLEAN=' ${bold_green}✓${normal}' +SCM_GIT_CHAR='${bold_green}±${normal}' +SCM_SVN_CHAR='${bold_cyan}⑆${normal}' +SCM_HG_CHAR='${bold_red}☿${normal}' + +PS3=">> " + +is_vim_shell() { + if [ ! -z "$VIMRUNTIME" ] + then + echo "[${cyan}vim shell${normal}]" + fi +} + +modern_scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ] + then + return + else + echo "[$(scm_char)][$(scm_prompt_info)]" + fi +} + +prompt() { + if [ $? -ne 0 ] + then + # Yes, the indenting on these is weird, but it has to be like + # this otherwise it won't display properly. + + PS1="${bold_red}┌─${reset_color}$(modern_scm_prompt)[${cyan}\W${normal}]$(is_vim_shell) +${bold_red}└─▪${normal} " + else + PS1="┌─$(modern_scm_prompt)[${cyan}\W${normal}]$(is_vim_shell) +└─▪ " + fi +} + +PS2="└─▪ " + + + +PROMPT_COMMAND=prompt diff --git a/themes/n0qorg/n0qorg.theme.bash b/themes/n0qorg/n0qorg.theme.bash new file mode 100644 index 00000000..fcaca43f --- /dev/null +++ b/themes/n0qorg/n0qorg.theme.bash @@ -0,0 +1,22 @@ +#!/bin/bash +# n0qorg theme by Florian Baumann + +## look-a-like +# host directory (branch*)» +# for example: +# ananas ~/Code/bash-it/themes (master*)» +PROMPT="${bold_blue}\[\$(hostname)\]${normal} \w${normal} ${bold_white}\[\$(git_prompt_info)\]${normal}» " + +## git-theme +# feel free to change git chars. +GIT_THEME_PROMPT_DIRTY="${bold_blue}*${bold_white}" +GIT_THEME_PROMPT_CLEAN="" +GIT_THEME_PROMPT_PREFIX="${bold_blue}(${bold_white}" +GIT_THEME_PROMPT_SUFFIX="${bold_blue})" + +## alternate chars +# +SCM_THEME_PROMPT_DIRTY="*" +SCM_THEME_PROMPT_CLEAN="" +SCM_THEME_PROMPT_PREFIX="(" +SCM_THEME_PROMPT_SUFFIX=")"