Skip to content

Instantly share code, notes, and snippets.

@redguardtoo
Last active May 8, 2021 00:50
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save redguardtoo/cd5ea2251e0a12fa31a28567b13f741e to your computer and use it in GitHub Desktop.
Save redguardtoo/cd5ea2251e0a12fa31a28567b13f741e to your computer and use it in GitHub Desktop.
My bash configuration
##
# Bash 4+ required
# FROM,
# 1. http://tldp.org/LDP/abs/html/sample-bashrc.html
# 2. git://github.com/chenkaie/DotFiles.git
##
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# Quit if bash version is less than 4
# by default, OSX use Bash 3
# @see https://github.com/mooz/percol/issues/14#issuecomment-150964987
# but you can upgrade bash
# @see http://clubmate.fi/upgrade-to-bash-4-in-mac-os-x/
if [ "${BASH_VERSION%%[^0-9]*}" -lt "4" ]; then
return;
fi
# Source global definitions (if any)
if [ -f /etc/bashrc ]; then
. /etc/bashrc # --> Read /etc/bashrc, if present.
fi
# Gentoo Linux
if [ -f /etc/bash/bashrc ]; then
. /etc/bash/bashrc
fi
# for what distribution?
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
function xpop() {
xprop | grep --color=none "WM_CLASS\|^WM_NAME" | xmessage -file -
}
function p() {
ps axu | grep "$@"
}
# {{ Shell in Emacs sets $TERM to "dumb"
if [ "${TERM}" != "dumb" ]; then
# enable bash completion
# @see http://www.simplicidade.org/notes/archives/2008/02/bash_completion.html
if [ -f /etc/bash_completion ]; then
# ArchLinux
. /etc/bash_completion
elif [ -f /etc/profile.d/bash-completion.sh ]; then
# Gentoo Linux
. /etc/profile.d/bash-completion.sh
elif [ ! -z $BASH_COMPLETION ]; then
. $BASH_COMPLETION
fi
fi
# }}
if [ -d $HOME/bash_completion.d ]; then
. $HOME/bash_completion.d/gibo-completion.bash
. $HOME/bash_completion.d/git-completion.bash
fi
if [ "$OSTYPE" = "cygwin" ]; then
OS_NAME='CYGWIN'
elif [ "`uname -s`" = "Darwin" ]; then
OS_NAME="Darwin"
elif grep -q Microsoft /proc/version; then
OS_NAME="WSL"
else
OS_NAME=`uname -r`
fi
# [ $(uname -s | grep -c CYGWIN) -eq 1 ] && OS_NAME="CYGWIN" || [ $(cat /proc/version | grep -c Microsoft) -eq 1 ] && OS_NAME="WSL" || OS_NAME=`uname -s`
#tomcat root dir on archlinux
# Please note `$HOME/bin` already defined in ~/.profile
export PATH=$HOME/bin:$PATH:/usr/lib/ccache/bin:$HOME/Games
export DTK_PROGRAM=espeak
export MOZ_DISABLE_PANGO=1 #disable pango of firefox
# See what we have to work with ...
HAVE_VIM=$(command -v vim)
HAVE_GVIM=$(command -v gvim)
# EDITOR
test -n "$HAVE_VIM" && EDITOR=vim || EDITOR=vi
export EDITOR
#bug in this .bashrc?
HOST=0
# Easy extact
extract () {
if [ -f $1 ] ; then
case $1 in
*.tar.xz) tar xvJf $1 ;;
*.tar.bz2) tar xvjf $1 ;;
*.tar.gz) tar xvzf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar e $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xvf $1 ;;
*.tbz2) tar xvjf $1 ;;
*.tgz) tar xvzf $1 ;;
*.apk) unzip $1 ;;
*.epub) unzip $1 ;;
*.xpi) unzip $1 ;;
*.zip) unzip $1 ;;
*.odt) unzip $1 ;;
*.war) unzip $1 ;;
*.jar) unzip $1 ;;
*.Z) uncompress $1 ;;
*.7z) 7z x $1 ;;
*) echo "don't know how to extract '$1'..." ;;
esac
else
echo "'$1' is not a valid file!"
fi
}
# easy compress - archive wrapper
compress () {
if [ -n "$1" ] ; then
FILE=$1
case $FILE in
*.tar) shift && tar cf $FILE $* ;;
*.tar.bz2) shift && tar cjf $FILE $* ;;
*.tar.gz) shift && tar czf $FILE $* ;;
*.tgz) shift && tar czf $FILE $* ;;
*.zip) shift && zip $FILE $* ;;
*.rar) shift && rar $FILE $* ;;
esac
else
echo "usage: compress <foo.tar.gz> ./foo ./bar"
fi
}
function relativepath() {
# both $1 and $2 are absolute paths beginning with /
# returns relative path to $2/$target from $1/$source
local source=$1
local target=$2
common_part=$source # for now
result="" # for now
while [[ "${target#$common_part}" == "${target}" ]]; do
# no match, means that candidate common part is not correct
# go up one level (reduce common part)
common_part="$(dirname $common_part)"
# and record that we went back, with correct / handling
if [[ -z $result ]]; then
result=".."
else
result="../$result"
fi
done
if [ "$common_part" = "/" ]; then
# special case for root (no common path)
result="$result/"
fi
# since we now have identified the common part,
# compute the non-common part
forward_part="${target#$common_part}"
# and now stick all parts together
if [[ -n $result ]] && [[ -n $forward_part ]]; then
result="$result$forward_part"
elif [[ -n $forward_part ]]; then
# extra slash removal
result="${forward_part:1}"
fi
echo $result
}
function relativepwd() {
relativepath $PWD $1
}
function ssa2srt() {
# ssa should be utf-8 format
for i in *.ssa ; do ffmpeg -i "$i" "$i.srt" ; done
}
# xclip has some problem with my emacs, so I use xsel for everything
function gclip() {
if [ "$OS_NAME" = "CYGWIN" ]; then
cat /dev/clipboard
elif [ "$OS_NAME" = "Darwin" ]; then
pbpaste $@;
elif hash powershell.exe 2>/dev/null; then
powershell.exe -command Get-Clipboard
elif [ -x /usr/bin/xsel ]; then
xsel -ob $@;
elif [ -x /usr/bin/xclip ]; then
xclip -o $@;
else
echo "Neither xsel or xclip is installed!"
fi
}
function pclip() {
if [ "$OS_NAME" = "CYGWIN" ]; then
# https://stackoverflow.com/questions/29501860/how-can-bash-read-from-piped-input-or-else-from-the-command-line-argument
echo -n $(cat) >> /dev/clipboard
elif [ "$OS_NAME" = "Darwin" ]; then
pbcopy $@;
elif hash clip.exe 2>/dev/null; then
# Linux sub-system on Windows 10
clip.exe $@
elif [ -x /usr/bin/xsel ]; then
xsel -ib $@;
elif [ -x /usr/bin/xclip ]; then
xclip -selection c $@;
else
echo "Neither xsel or xclip is installed!"
fi
}
function fzfnormal {
if [ -x $HOME/bin/fzf ]; then
# `-e` to turn off fuzzy match
$HOME/bin/fzf -e --reverse --cycle -1 -0 -m "$@"
else
python $HOME/bin/percol.py "$@"
fi
}
function h () {
# reverse history, pick up one line, remove new line characters and put it into clipboard
if [ -z "$1" ]; then
echo "Usage: h keyword [-v]"
echo " '-v' will filter OUT matched you typing interactively"
else
history | grep "$1" | sed '1!G;h;$!d' | fzfnormal $2 | sed -n 's/^ *[0-9][0-9]* *\(.*\)$/\1/p'| tr -d '\n' | pclip
fi
}
# @see https://www.techrepublic.com/article/find-and-bind-key-sequences-in-bash/
# run `read' in shell and press "M-n", got "^[n", "^]" is equivalent to [ESC] key
bind -x '"\en": READLINE_LINE=$(history | grep "${READLINE_LINE}" | sed "1!G;h;\$!d" | fzfnormal | sed "s/^ *[0-9]* *//g") READLINE_POINT='
##
# Automatic setting of $DISPLAY (if not set already)
# This works for linux - your mileage may vary....
# The problem is that different types of terminals give
# different answers to 'who am i'......
# I have not found a 'universal' method yet
##
function get_xserver ()
{
case $TERM in
xterm )
XSERVER=$(who am i | awk '{print $NF}' | tr -d ')''(' )
# Ane-Pieter Wieringa suggests the following alternative:
# I_AM=$(who am i)
# SERVER=${I_AM#*(}
# SERVER=${SERVER%*)}
XSERVER=${XSERVER%%:*}
;;
aterm | rxvt)
# find some code that works here.....
;;
esac
}
if [ -z ${DISPLAY:=""} ]; then
get_xserver
if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) ||
${XSERVER} == "unix" ]]; then
DISPLAY=":0.0" # Display on local host
else
DISPLAY=${XSERVER}:0.0 # Display on remote host
fi
fi
export DISPLAY
##
# Some settings
##
set -o notify
#set -o noclobber
set -o ignoreeof
set -o nounset
#set -o xtrace # Useful for debuging
if [ "`echo $BASH_VERSION | cut -b 1`" -eq "4" ]; then
# BASH version 4
shopt -s dirspell
# * `autocd`, e.g. `**/qux` will enter `./foo/bar/baz/qux`
shopt -s autocd
# * Recursive globbing, e.g. `echo **/*.txt`
shopt -s globstar
# Autocorrect typos in path names when using `cd`
shopt -s cdspell
export PROMPT_DIRTRIM=3
fi
export PROMPT_COMMAND="history -a"
# Case-insensitive globbing (used in pathname expansion)
shopt -s nocaseglob
# Treat every non-directory argument to the `cd` as variable containing a directory to cd into. `cd WXWIN` for example
shopt -s cdable_vars
# Checks a command found in the hash table exists before trying to execute it. If a hashed command no longer exists, a normal path search is performed
shopt -s checkhash
# check window size after each command and, if necessary, updates variables LINES and COLUMNS
shopt -s checkwinsize
# the source builtin command uses $PATH to find directory containing the file supplied as an argument. This option is enabled by default.
shopt -s sourcepath
# not attempt to search the PATH for possible completions when completion is attempted on an empty line
shopt -s no_empty_cmd_completion # bash>=2.04 only
#save all lines of a multiple-line command in the same history entry. This allows easy re-editing of multi-line commands.
shopt -s cmdhist
# Append to the Bash history file, rather than overwriting it
shopt -s histappend histreedit histverify
shopt -s extglob # Necessary for programmable completion
# Disable options:
shopt -u mailwarn
unset MAILCHECK # I don not want my shell to warn me of incoming mail
export TIMEFORMAT=$'\nreal %3R\tuser %3U\tsys %3S\tpcpu %P\n'
# @see http://www.talug.org/events/20030709/cmdline_history.html
# If you include the expression "[ \t]*" in the HISTIGNORE string,
# you cansuppress history recording at will for any given command
# just by starting with a space!
export HISTCONTROL=ignoreboth:erasedups
# Larger bash history (allow 32³ entries; default is 500)
export HISTSIZE=32768
export HISTFILESIZE=$HISTSIZE
# @see http:/linux.about.com/od/lts_guide/a/gdelts66t00.htm about wildcards
export HISTIGNORE="*.aspell.en.pws:*.custom.el:*.gnus.el:*~/.gitconfig:* --version:fg *:which *:h *:?:??:???:????:?????:fcitx*:* --help:* -h:whoami: *:ll *:mkcd *:j:kill *:pkill *:du *:glp *:gnb *:git rc *:git co *:gmt:gr?:g:p4?:p4?? *:z *:man *:extract *:ffcd *"
# The FIGNORE environment variable is nice when you want TAB completion to ignore files or folders with certain suffixes, e.g.:
export FIGNORE=~:.o:.svn:.git:.swp:.elc:.swa:.pyc:.a:.class:.la:.mo:.obj:.pyo
export HOSTFILE=$HOME/.hosts # Put a list of remote hosts in ~/.hosts
# {{ Define some colors first:
# infocmp xterm-256color >/dev/null 2>&1 && export TERM=xterm-256color
export MAGENTA="\033[1;31m"
export ORANGE="\033[1;33m"
export GREEN="\033[1;32m"
export PURPLE="\033[1;35m"
export WHITE="\033[1;37m"
export BOLD=""
export RESET="\033[m"
# }}
# Colored manual pages
# Gentoo has some issue, @see http://unix.stackexchangm.com/questions/6010/colored-man-pages-not-working-on-gentoo
export LESS_TERMCAP_mb=$'\E[01;31m' # begin blinking
export LESS_TERMCAP_md=$'\E[01;38;5;74m' # begin bold
export LESS_TERMCAP_me=$'\E[0m' # end mode
export LESS_TERMCAP_se=$'\E[0m' # end standout-mode
export LESS_TERMCAP_so=$'\E[01;44;33m' # begin standout-mode - info box (search result highlight)
export LESS_TERMCAP_ue=$'\E[0m' # end underline
export LESS_TERMCAP_us=$'\E[04;38;5;146m' # begin underline
export GROFF_NO_SGR=1
# Don’t clear the screen after quitting a manual page
export MANPAGER="less -X"
# see http://tf.nist.gov/tf-cgi/servers.cgi
function adjustclock()
{
sudo rdate -s time-c.nist.gov
}
# Speed up SSH X11 Forwarding
function sshx()
{
# -X enables X11 forwarding, -C enables compression of all data
ssh -X -C $@
}
# build ssh tunnel
function ssht()
{
ssh -qTnNfD 7070 $@
}
encrypt () { gpg -ac --no-options "$1"; }
decrypt () { gpg --no-options "$1"; }
##
# Shell Prompt
##
if [[ "${DISPLAY#$HOST}" != ":0.0" && "${DISPLAY}" != ":0" ]]; then
HILIT=${MAGENTA} # remote machine: prompt will be partly red
else
HILIT=${GREEN} # local machine: prompt will be partly green
fi
##
# Personnal Aliases
##
function weather {
curl wttr.in/$@
}
alias starwar="telnet towel.blinkenlights.nl"
alias killemacs="pkill -SIGUSR2 emacs"
alias cal="LC_ALL=C cal"
alias cc="cd -"
alias dir="ls"
# {{ git
# Git alias
function gitshortlogcmd () {
git log --date=short --decorate --graph "$@"
}
function gitlogcmd () {
git log --date=short --decorate --graph --pretty=format:'%C(yellow)%h%Creset%C(green)%d%Creset %ad %s %Cred(%an)%Creset' "$@"
}
alias gg="git status --short -b"
alias gb="git branch"
alias gn="git status --untracked-files=no --short -b"
alias gfl="git diff-tree --no-commit-id --name-only -r"
alias ga="git add"
alias gr="git rebase -i `git remote`/`git symbolic-ref --short HEAD`"
alias gap='git add --patch'
alias gai='git add -i'
alias gau="git add -u"
alias gc="git commit -m"
alias gca="git commit --amend"
alias gja="git --no-pager commit --amend --reuse-message=HEAD" # git just amend
alias gtt="git stash"
alias gta="git stash apply"
alias gmt="git mergetool"
alias gme="git mergetool -t ediff" # use emacs to merge conflicts
alias gl="gitlogcmd"
alias glp="git log -p" # I want to see all details
alias gls="gitlogcmd --stat"
alias gnb="git checkout -b"
alias gss="git show --stat"
alias gsl="git log --pretty=format:'%h %s (%an)' --date=short -n1 | pclip"
alias gd="git diff"
alias gds="git diff --stat"
alias gdc="git diff --cached"
alias gdcs="git diff --cached --stat"
alias gps="git push"
alias gpf="git push --force"
alias gpl="git pull"
alias gpr="git pull -r"
alias cg='cd $(git rev-parse --show-toplevel)' #goto root dir
# find unmerged "*.html" and "*.min.js", checkout theirs version, and add them
alias ghe='git diff --name-only --diff-filter=U|grep "\.html\|\.min\.js"|xargs -I{} sh -c "git checkout --theirs {} && git add {}"'
# show diff from the branch to current HEAD
alias gdp='git diff $(git branch | sed "s/[\* ]\+//g" | fzfnormal)..HEAD'
alias grh='git reset --hard HEAD'
alias gr1='git reset --hard HEAD^'
alias gr2='git reset --hard HEAD^^'
alias gs="git show"
# @see https://stackoverflow.com/questions/15292391/is-it-possible-to-perform-a-grep-search-in-all-the-branches-of-a-git-project
alias grpa="git branch -a | tr -d \* | sed '/->/d' | xargs git grep" # grep all branches
function gsh {
git log --date=short --pretty=format:'%h%d %ad %s (%an)' | fzfnormal | awk '{print $1}' | xargs -I{} git show {}
}
function grpwd {
# reset current directory to certain version
if [ -z $1 ]; then
local ver=`gcid`
else
local ver=$1
fi
if [ -z $ver ]; then
echo "Don't know which version to reset"
else
git checkout $ver .
echo "Files are restored to $ver. Run 'git diff --cached' to see them."
fi
}
function gcn()
{
# commit with timestamp
local d=`date +%m%d-%H%M%S`
git commit -m ${d}
}
# find full path of file who under git controll
# the optional parameter is the keyword
function gf()
{
if [ -z "$1" ]; then
local cli=`git ls-tree -r HEAD --name-status | fzfnormal`
else
local cli=`git ls-tree -r HEAD --name-status | grep "$1" | fzfnormal`
fi
local rlt=$(cd $(dirname $cli); pwd)/$(basename $cli)
echo ${rlt}
echo -n ${rlt} | pclip
}
function glwho () {
local guy=`git shortlog -sn | fzfnormal | sed 's/^\s*[0-9]\+\s*//g'`
# space is a problem, so we can't use gitshortlogcmd here
gitshortlogcmd --pretty=format:'%C(yellow)%h%Creset%C(green)%d%Creset %ad %s %Cred(%an)%Creset' --author="$guy" "$@"
}
function gfp () {
if [ -z "$1" ]; then
echo "Usage: gfp since [file]"
echo " Just alias of 'git format-patch -n --stdout since -- [file]'"
echo " 'gfp since | git am' to apply the patch"
fi
git format-patch -n --stdout $1 -- $2
}
function gcnb () {
local remoteb=$(git branch --all | sed '/no branch/d' | fzfnormal)
local localb=$(echo $remoteb | sed 's/^ *remotes\/[a-z]*\///g')
git checkout -b $localb $remoteb
}
function grb () {
# switch to recent git branch or just another branch
local crtb=`git branch | grep \*`
local ptn="no branch"
# compatible way to detect sub-strin in bash
# @see http://stackoverflow.com/questions/229551/string-contains-in-bash
if [ -z "${crtb##*$ptn*}" ]; then
# detached HEAD
git checkout $(git branch | sed '/no branch/d' | fzfnormal)
else
local myrbs=`git for-each-ref --sort=-committerdate refs/heads/ | sed -e s%.*refs\/heads\/%%g`
local crb=`git symbolic-ref --short HEAD`
git checkout `echo "$myrbs" | sed '/$crb/d' | fzfnormal`
fi
}
# rebase on LOCAL branches
function gri () {
local b=`git branch | sed 's/[\* ]\+//g' | fzfnormal`
git rebase -i ${b}
}
# rebase on ALL braches
function gra () {
local b=`git branch --all | sed 's/[\* ]\+//g' | sed 's/remotes\///g' | fzfnormal`
git rebase -i ${b}
}
# select a local git branch
function gsb () {
local b=`git branch | sed "s/[\* ]\+//g" | fzfnormal`
echo -n ${b} | pclip;
echo ${b}
}
# print current branch name
function gcb () {
local crb=`git symbolic-ref --short HEAD`
echo -n ${crb} | pclip;
echo ${crb}
}
# new local branch based on remote branch
function gnr () {
local myrb=`git for-each-ref --sort=-committerdate refs/remotes/ | sed -e s%.*refs\/remotes\/%%g | fzfnormal`
local mylb=`echo -n $myrb | sed 's/.*\/\([^\/]\+\)$/\1/'`
git checkout -b $mylb $myrb
}
function gchk () {
if [ -z "$1" ]; then
echo "Usage: gchk commit_id"
echo "reset hard certain version of current working directory"
else
rm -rf $PWD/*
git checkout $1 -- $PWD
fi
}
function git2fullpath {
local fullpath=$(git rev-parse --show-toplevel)/$1
echo -n $fullpath | pclip
echo $fullpath
}
function glf () {
local str=`git --no-pager log --oneline --name-only $* | fzfnormal`
git2fullpath $str
}
function gsf () {
local str=`git --no-pager show --pretty=format:'%h %s (%an)' --name-only $* | fzfnormal`
git2fullpath $str
}
function gdf () {
local str=`git --no-pager diff --oneline --name-only $*| fzfnormal`
git2fullpath $str
}
function gdcf () {
local str=`git --no-pager diff --oneline --cached --name-only $* | fzfnormal`
git2fullpath $str
}
function ggr () {
if [ -z "$1" ]; then
echo "Grep files under git controll"
echo "Usage: ggr [filename-pattern] text-pattern"
elif [ $# -eq "1" ]; then
git ls-tree -r HEAD --name-only | xargs grep -sn "$1"
elif [ $# -eq "2" ]; then
git ls-tree -r HEAD --name-only | grep "$1" | xargs grep -sn --color -E "$2"
fi
}
function grpc() {
if [ -z "$1" ]; then
echo "Replace the content of file in latest git commit"
echo "Usage: grpc [commit-hash] old_string new_string (string could be perl regex)"
elif [ $# -eq "2" ]; then
git diff-tree --no-commit-id --name-only -r HEAD | xargs perl -pi -e "s/$1/$2/g"
elif [ $# -eq "3" ]; then
git diff-tree --no-commit-id --name-only -r $1 | xargs perl -pi -e "s/$2/$3/g"
fi
}
function grpf() {
if [ -z "$1" ]; then
echo "Replace the content of file under git"
echo "Usage: grpf old_string new_string (string could be perl regex)"
elif [ $# -eq "2" ]; then
git grep -l "$1" | xargs perl -pi -e "s/$1/$2/g"
fi
}
function gp() {
if [ $# = 0 ]; then
local from=`gitshortlogcmd --pretty=format:'%h %ad %s (%an)' $* | fzfnormal|sed -e"s/^[ *|]*\([a-z0-9]*\) .*$/\1/"`;
local fn=from-$from-`date +%Y%m%d-%H%M`.patch
git format-patch -n --stdout $from > $fn && ls $fn
else
local fn=from-$1-`date +%Y%m%d-%H%M`.patch
git format-patch -n --stdout $1 > $fn && ls $fn
fi;
}
# }}
# {{ subversion
# svn v1.7+
alias svr="svn revert"
alias svrh="svn revert -R ." # git reset hard
alias sv="svn status"
alias svu="svn update"
alias svc="svn commit -m"
alias svds="svn diff --diff-cmd=diff | lsdiff"
function cs ()
{
# @see http://stackoverflow.com/questions/1242364/how-can-i-find-the-root-folder-of-a-given-subversion-working-copy
# go to subversion root, subversion 1.7+
# could be easily extended to other vcs.
# but for now let's focus on svn only
local parent=""
local grandparent="."
while [ ! -d "$grandparent/.svn" ]; do
parent=$grandparent
grandparent="$parent/.."
done
if [ ! -z "$grandparent" ]; then
cd $grandparent
fi
}
function svds()
{
# patchutils required
svn diff "$*" | lsdiff
}
function svd()
{
svn diff "$*" | less -r
}
function svl(){
if [ -f $HOME/bin/svn_short_log ]; then
svn log "$*" | $HOME/bin/svn_short_log | less -r
else
svn log "$*" | less -r
fi
}
function svlp(){
svn log "$*" --diff | less -r
}
function svc(){
svn commit -m "$*"
}
function svs(){
svn diff -c $* | less -r
}
function svss(){
svn diff --summarize -c $*
}
function svdf () {
# svn diff and select a file
local str=`svn diff --diff-cmd=diff $* | lsdiff | fzfnormal`
if [[ $str =~ ^[[:space:]]*([a-z0-9A-Z_.\/-]*).*$ ]]; then
echo -n ${BASH_REMATCH[1]} |pclip;
echo ${BASH_REMATCH[1]}
fi
}
# }}
function frp(){
if [ -z "$1" ]; then
echo "Usage: frp old_string new_string (string could be perl regex)"
echo "replace the content of regular file in $PWD"
else
find . -type f -print0 | xargs -0 perl -i -pe's/$1/$2/g'
fi
}
function grepcmd () {
if hash rg 2>/dev/null; then
# @see http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script
rg -s -n -g="!archive-contents" -g='!.git/*' -g='!.bzr/*' -g='!.svn/*' -g='!bower_components/*' -g='!node_modules/*' -g='!.sass-cache/*' -g='!.cache/*' -g='!test/*' -g='!tests/*' -g='!.metadata/*' -g='!logs/*' -g='!*.log' -g='!*.properties' -g='!*.session' -g='!*.swp' -g='!TAGS' -g='!tags' -g='!GTAGS' -g='!GPATH' -g='!.bookmarks.el' -g='!*.svg' -g='!history' -g='!#*#' -g='!*.min.js' -g='!*bundle*.js' -g='!*vendor*.js' -g='!*.min.css' -g='!*~' "$@"
else
grep -rsnI --exclude='archive-contents' --exclude='*.log' --exclude='*.properties' --exclude='TAGS' --exclude=tags --exclude=GTAGS --exclude-dir=.svn --exclude-dir=bower_components --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=.sass-cache --exclude-dir=.cache --exclude-dir=.cvs --exclude-dir=.git --exclude-dir=test --exclude-dir=tests --exclude-dir=.hg --exclude-dir=.metadata --exclude-dir=logs --exclude='#*#' --exclude='*.swp' --exclude='*.min.js' --exclude='*.min.css' --exclude='*~' --color=auto "$@"
fi
}
# remove beginning ??, UU, space, CC, +, - and trailing + =
function pl () {
fzfnormal | sed -e "s/^[\?\|MUA ]\{1,2\}[ \t][ \t ]*//g" | sed -e "s/[ \t][0-9\+\| \t-]*$//g" | tr -d "\n" | pclip
}
function fef () {
if [ -z "$1" ]; then
echo "Usage: fef file-extension PATTERN"
echo "Find file containing PATTERN wiht file-extension"
echo "Example: fef scss sup"
else
find . -type f \( -path .fseventsd -path .svn -o -path .git -o -path .hg -o -path .sass-cache -o -path node_modules -o -path .cache \) -prune -o -name "$1" -exec grep -l "$2" {} \; | fzfnormal | sed -e "s%^ *\([a-z0-9A-Z_.\/-]*\).*%\1%"|tr -d "\n" | pclip
fi
}
function fge () {
if [ -z "$1" ]; then
echo "Usage: fge file-extension PATTERN"
echo "Find file containing PATTERN wiht file-extension"
echo "Example: fge scss sup"
else
find . -type f \( -path .svn -o -path .git -o -path .hg -o -path .sass-cache -o -path node_modules -o -path .cache \) -prune -o -name "$1" -exec grep -sn "$2" {} \;
fi
}
function a () {
grepcmd "$@"
}
function af () {
local filename=`grepcmd "$@" | fzfnormal | sed -e "s%^ *\([a-z0-9A-Z_.\/+-]*\).*%\1%"|tr -d "\n"`
if [ ! -z "$filename" ];then
echo -n "$PWD/$filename" | pclip
echo `gclip`
fi
}
# change relative path to full path
function fp () {
local str=$PWD/$*
echo -n ${str} |pclip;
echo ${str}
}
# {{ git tools to handle commit id
function gurl () {
if [ -z "$1" ]; then
echo "Usage: gurl commit-id"
echo "get the full http url of commit"
else
local msg=`git remote -v|grep "origin *.* *(fetch)"|sed -e "s/origin *\(.*\) *(fetch)/\1/"`
local url=""
# github
if [ "${msg:0:14}" = "git@github.com" ]; then
echo https://github.com/`echo ${msg}|sed -e "s/^git\@github\.com\:\(.*\)\.git$/\1/"`/commit/$1
fi
fi
}
# pick commit id from `git log`
function gcid () {
local commit_id=`gitshortlogcmd --pretty=format:'%h %ad %s (%an)' $* | fzfnormal|sed -e"s/^[ *|]*\([a-z0-9]*\) .*$/\1/"`
echo ${commit_id}
}
function ggp () {
git format-patch -n --stdout `gcid`
}
#pick commit from `git log` and output its url
function gqurl () {
local commit_id=`gitshortlogcmd --pretty=format:'%h %ad %s (%an)' $* | fzfnormal|sed -e"s/^\([a-z0-9]*\) .*$/\1/"`
gurl ${commit_id}
}
# find files between commit and HEAD and grep
alias glfge='git diff-tree --no-commit-id --name-only -r `gcid` -r HEAD|xargs grepcmd'
# git push origin to selected commit
function gpss () {
local pushopt="`gcid`:`gcb`"
if [ ${#pushopt} -ge 8 ]; then
git push origin $pushopt
else
echo "Nothing pushed"
fi
}
# rebase on origin
function grm () {
git rebase -i origin `gcb`
}
# analyze text from stdin and open file and line number with vi
function grepo () {
if [ -z "$1" ]; then
echo "Usage: grepo regex file(s)"
echo "grep the file(s) and open the user choosen file with specific line number"
echo "the full path of the file will be put into clipboard"
else
local rlt=`grepcmd "$1" ${PWD}/*| fzfnormal`
local vim_options=`echo $rlt|sed -e"s/^\([^:]*\):\([0-9]*\):.*/+\2 \1/g"`
# also put the full file path into clipboard
echo $rlt|sed -e"s/^\([^:]*\):\([0-9]*\):.*/\1/g"|pclip
#echo "vim_options=$vim_options"
vim ${vim_options}
fi
}
function prepend(){
if [ -z "$1" ]; then
echo "Usage: prepend line file"
echo "prepend a line into the file. The line could contain CR"
else
sed -i -e "1i $1" $2
fi
}
function bye () {
if [ "$OS_NAME" = "CYGWIN" ]; then
shutdown -t 3 -f -s
else
sudo shutdown -h now
fi
}
function slp () {
if [ "$OS_NAME" = "CYGWIN" ]; then
# hibernate
rundll32.exe PowrProf.dll,SetSuspendState
elif [ "$OS_NAME" = "Darwin" ]; then
pmset sleepnow
else
# sleep
sudo pm-suspend
fi
}
function rbt() {
if [ "$OS_NAME" = "CYGWIN" ]; then
shutdown -t 3 -f -r
elif [ "$OS_NAME" = "Darwin" ]; then
sudo reboot
else
sudo reboot
fi
}
function memfs() {
mkdir -p ~/tmp;sudo mount -t tmpfs tmpfs ~/tmp -o size=$@
}
# turn on/off the screen
alias von='sudo vbetool dpms on'
alias voff='sudo vbetool dpms off'
# sort and count lines,
#@see http://felipec.wordpress.com/2011/06/02/command-history-meme/
#alias cntl=awk '{a[$1]++} END{for(i in a){printf "%5d\t%s\n",a[i],i}}'|sort -rn
alias my='mystartx' #start my favourit WM
# example, convertdoc pdf *.odt
alias convertdoc="soffice --headless --invisible --convert-to"
#Example: rsync -avz --delete /home/username/ /media/disk/backup
alias bkrsync="rsync -avz --delete"
#grep and its alternatives
#@see http://stackoverflow.com/questions/221921/grep-exclude-include- \
#syntax-do-not-grep-through-certain-files
alias vncsvr1440='vncserver -geometry 1440x900 -depth 16 :1'
alias gfw='python ~/bin/goagent/proxy.py >/dev/null 2>&1'
alias rd='rdesktop -fP'
alias cp='cp '
alias mv='mv '
# -> Prevents accidentally clobbering files.
#I need clip between firefox
alias j='jobs -l'
alias which='type -all'
alias path='echo -e ${PATH//:/\\n}'
alias print='/usr/bin/lp -o nobanner -d $LPDEST'
# Assumes LPDEST is defined
alias pjet='enscript -h -G -fCourier9 -d $LPDEST'
# Pretty-print using enscript
alias background='xv -root -quit -max -rmode 5'
# Put a picture in the background
alias du='du -kh'
alias dush='du -sh'
alias wget='wget -c'
# {{ emacs stuff
# install source code
if [ "$OS_NAME" = "Darwin" ] ; then
# set up PATH so .gitconfig can pick up right version of Emacs
if [ -x /Applications/Emacs.app/Contents/MacOS/Emacs ]; then
# `brew install --with-cocoa --srgb emacs` on OS X
ln -sf /Applications/Emacs.app/Contents/MacOS/Emacs $HOME/bin/emacs
elif [ -x $HOME/Applications/Emacs.app/Contents/MacOS/Emacs ]; then
ln -sf $HOME/Applications/Emacs.app/Contents/MacOS/Emacs $HOME/bin/emacs
fi
fi
function e()
{
if [ "$TERM" = "linux" ]; then
# minimum linux console
emacs -nw "$@"
elif [ -x $HOME/myemacs/26.1/bin/emacs ]; then
if [ "$TERM" = "rxvt" ]; then
# rxvt support 256 colors
TERM=xterm-256color $HOME/myemacs/26.1/bin/emacs -nw "$@"
else
TERM=xterm-24bits $HOME/myemacs/26.1/bin/emacs -nw "$@"
fi
elif [ "$OS_NAME" = "Darwin" ]; then
if [ -x $HOME/Applications/Emacs.app/Contents/MacOS/Emacs ]; then
TERM=xterm-24bits $HOME/Applications/Emacs.app/Contents/MacOS/Emacs -nw "$@"
else
TERM=xterm-24bits emacs -nw "$@"
fi
else
TERM=xterm-256color emacs -nw "$@"
fi
}
function ee()
{
if [ "$TERM" = "linux" ]; then
# minimum linux console
emacs -nw "$@"
else
TERM=xterm-256color emacs -nw "$@"
fi
}
function te()
{
if [ "$TERM" = "linux" ]; then
tsocks emacs -nw "$@"
else
TERM=xterm-256color tsocks emacs "$@"
fi
}
# }}
function odt2doc() {
if [ "$OS_NAME" = "Darwin" ]; then
/Applications/LibreOffice.app/Contents/MacOS/soffice --headless --convert-to doc "$@"
else
soffice --headless --convert-to doc "$@"
fi
}
function odt2pdf() {
if [ "$OS_NAME" = "Darwin" ]; then
/Applications/LibreOffice.app/Contents/MacOS/soffice --headless --convert-to doc "$@"
else
soffice --headless --convert-to pdf "$@"
fi
}
if [ "$OS_NAME" = "Darwin" ]; then
alias df='df -kh'
alias ll='ls -l'
else
alias df='df -kTh'
# The 'ls' family (this assumes you use the GNU ls)
alias ls='ls --show-control-chars --color=auto -hF'
alias lx='ls -lXB' # sort by extension
function ll()
{ ls -l "$@"| egrep "^d" ; ls -lXB "$@" 2>&-| egrep -v "^d|total "; }
fi
alias l1='ls -1'
alias lr='ls -lR' # recursive ls
alias tree='tree -Csu' # nice alternative to 'ls'
alias update-mpd-list="cd ~/Music;find . -name '*.mp3' -o -name '*.flac'|sed -e 's%^./%%g' > all.m3u;mpd ~/.mpd/config;mpc clear;mpc load all.m3u;mpc update"
#@see http://stackoverflow.com/questions/3746/whats-in-your-bashrc
alias cd..="cd .."
alias ..="cd .."
alias ...="cd ../.."
alias ....="cd ../../.."
function m () {
$* --help | less
}
# smarter locate
function baseoo() {
local s=$@
local keyword=${s// /.*}
if [ "$OS_NAME" = "Darwin" ]; then
local file=`locate -i "${keyword}" | fzfnormal`
else
local file=`locate -i --regex "${keyword}" | fzfnormal`
fi
echo -n $file
}
function of() {
local f=`baseoo $*`
echo ${f}
echo -n ${f} | pclip
}
function oo() {
local f=`baseoo $*`
if [ "$OS_NAME" = "Darwin" ]; then
echo $f | xargs open &
else
echo $f | xargs xdg-open &
fi
}
#gcc
alias objdump='objdump -d -S -hrt'
# spelling typos - highly personnal :-)
alias nospan="sed 's%</*span[^>]*>%%g'"
function mk() {
if [ "$OS_NAME" = "Darwin" ]; then
make -j`sysctl -n hw.ncpu`
else
make -j`nproc`
fi
}
function nj() {
if [ "$OS_NAME" = "Darwin" ]; then
ninja -j`sysctl -n hw.ncpu`
else
ninja -j`nproc`
fi
}
## File & strings related functions:
# search the file and pop up dialog, then put the full path in clipboard
# usage: baseff (file|dir) keyword
# is used as API instead of user command
function baseff()
{
local fullpath=$2
local filename=${fullpath##*./} # remove ".../" from the beginning
# - only the filename without path is needed
# - filename should be reasonable
if [ "$1" = "file" ] || [ "$1" = "relfile" ];then
if hash fd 2>/dev/null;then
local rlt=`fd --full-path -H --type f -E'.git/*' -E'vendor/*' -E'.svn/*' -E'.npm/*' -E'.backups/*' -E'.hg/*' -E'node_modules/*' -I ".*${filename}.*" | fzfnormal`
else
local rlt=`find . \( -iwholename '*#' -o -iwholename '*/.backups/*' -o -iwholename '*/deployment/*' -o -iwholename '*/_doc/*' -o -iwholename '*/test/*' -o -iwholename '*/coverage/*' -o -iwholename '*/.gradle/*' -o -iwholename '*~' -o -iwholename '*.swp' -o -iwholename '*/dist/*' -o -iwholename '*.class' -o -iwholename '*.js.html' -o -iwholename '*.elc' -o -iwholename '*.pyc' -o -iwholename '*/bin/*' -o -iwholename '*/.config/*' -o -iwholename '*/vendor/*' -o -iwholename '*/bower_components/*' -o -iwholename '*/node_modules/*' -o -iwholename '*/.svn/*' -o -iwholename '*/.git/*' -o -iwholename '*/.gitback/*' -o -iwholename '*/.npm/*' -o -iwholename '*.sass-cache*' -o -iwholename '*/.hg/*' \) -prune -o -type f -iwholename '*'${filename}'*' -print | fzfnormal`
fi
else
if hash fd 2>/dev/null;then
local rlt=`fd --full-path -H --type d -E'.git/*' -E'vendor/*' -E'.svn/*' -E'.npm/*' -E'.backups/*' -E'.hg/*' -E'node_modules/*' -I ".*${filename}.*" | fzfnormal`
else
local rlt=`find . \( -iwholename '*#' -o -iwholename '*/.backups/*' -o -iwholename '*/deployment/*' -o -iwholename '*/_doc/*' -o -iwholename '*/test/*' -o -iwholename '*/coverage/*' -o -iwholename '*/.gradle/*' -o -iwholename '*~' -o -iwholename '*.swp' -o -iwholename '*/dist/*' -o -iwholename '*.class' -o -iwholename '*.js.html' -o -iwholename '*.elc' -o -iwholename '*.pyc' -o -iwholename '*/bin/*' -o -iwholename '*/.config/*' -o -iwholename '*/vendor/*' -o -iwholename '*/bower_components/*' -o -iwholename '*/node_modules/*' -o -iwholename '*/.svn/*' -o -iwholename '*/.git/*' -o -iwholename '*/.gitback/*' -o -iwholename '*/.npm/*' -o -iwholename '*.sass-cache*' -o -iwholename '*/.hg/*' \) -prune -o -type d -iwholename '*'${filename}'*' -print | fzfnormal`
fi
fi
if [ -z "${rlt}" ];then
echo ""
else
if [ "$1" = "relfile" ]; then
# use relative path
echo $rlt
else
# convert relative path to full path
echo $(cd $(dirname $rlt); pwd)/$(basename $rlt)
fi
fi
}
# find a file and copy its *nix full path into clipboard
function ff {
local cli=`baseff file $*`
echo ${cli}
echo -n ${cli} | pclip
}
function ii {
local cli=`baseff file $* | xargs echo -n`
if [[ "${cli}" =~ ".png" ]]; then
echo -n ${cli} | xargs -I{} xclip -selection clipboard -t image/png -i {}
echo "${cli} => clipboard"
fi
}
# any file on this computer
function aa {
if [ -z "$1" ]; then
local cli=`locate / | fzfnormal`
else
local cli=`locate "$1" | fzfnormal`
fi
echo ${cli}
echo -n ${cli} | pclip
}
function ffr {
local cli=`baseff relfile $*`
echo ${cli}
echo -n ${cli} | pclip
}
# find a file and copy its *nix direcotry (without filename) into clipboard
# cd into that directory at the same time
function ffcd()
{
local cli=`baseff file $*`
if [ -z "${cli}" ]; then
echo "Nothing found!"
else
local dir=$(dirname "${cli}")
cd ${dir} && echo ${dir}
echo -n ${cli} | pclip
fi
}
# find&cd a directory. Copy its full path into clipboard
function zz()
{
local cli=`baseff dir $*`
if [ -z "${cli}" ];then
echo "Nothing found!"
else
echo ${cli}
cd ${cli}
echo -n ${cli} | pclip
fi
}
function zzz() {
cd $HOME && zz
}
# same as ff but we get windows path
function cf()
{
local cli=`baseff file $*`
local p=`cygpath -w $cli`
echo ${p}
echo -n ${p} | pclip;
}
# same as ffcd but we get windows path
function cfcd()
{
local cli=`baseff file $*`
local dir=$(dirname "${cli}")
local p=`cygpath -w $dir`
cd ${dir} && echo ${p}
echo -n ${p} | pclip;
}
# read path from pipe and convert to cygwin path
function cyp() {
read cp;
local p=`cygpath -w $cp`
echo ${p}
echo -n ${p} | pclip;
}
# usage `find -name '*.txt' | sedi matched replaced`
function sedi() {
read cp;
echo $cp | xargs sed -i 's%'$1'%'$2'%g'
echo 'replace $1 with $2 done!'
}
function cuttail() # Cut last n lines in file, 10 by default.
{
nlines=${2:-10}
sed -n -e :a -e "1,${nlines}!{P;N;D;};N;ba" $1
}
function lowercase() # move filenames to lowercase
{
for file ; do
filename=${file##*/}
case "$filename" in
*/*) dirname==${file%/*} ;;
*) dirname=.;;
esac
nf=$(echo $filename | tr A-Z a-z)
newname="${dirname}/${nf}"
if [ "$nf" != "$filename" ]; then
mv "$file" "$newname"
echo "lowercase: $file --> $newname"
else
echo "lowercase: $file not changed."
fi
done
}
function swap() # swap 2 filenames around
{
local TMPFILE=tmp.$$
mv "$1" $TMPFILE
mv "$2" "$1"
mv $TMPFILE "$2"
}
# finds directory sizes and lists them for the current directory
dirsize ()
{
du -shx * .[a-zA-Z0-9_]* 2> /dev/null | \
egrep '^ *[0-9.]*[MG]' | sort -n > /tmp/list
egrep '^ *[0-9.]*M' /tmp/list
egrep '^ *[0-9.]*G' /tmp/list
rm -rf /tmp/list
}
##
# Process/system related functions:
##
function my_ps()
{ ps $@ -u $USER -o pid,%cpu,%mem,bsdtime,command ; }
function pp()
{ my_ps f | awk '!/awk/ && $0~var' var=${1:-".*"} ; }
# This function is roughly the same as 'killall' on linux
# but has no equivalent (that I know of) on Solaris
function killps() # kill by process name
{
local pid pname sig="-TERM" # default signal
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
echo "Usage: killps [-SIGNAL] pattern"
return;
fi
if [ $# = 2 ]; then sig=$1 ; fi
for pid in $(my_ps| awk '!/awk/ && $0~pat { print $1 }' pat=${!#} ) ; do
pname=$(my_ps | awk '$1~var { print $5 }' var=$pid )
if ask "Kill process $pid <$pname> with signal $sig?"
then kill $sig $pid
fi
done
}
function myinfo() # get current host related info
{
echo -e "\nYou are logged on ${MAGENTA}$HOST"
echo -e "\nAdditionnal information:$RESET " ; uname -a
echo -e "\n${MAGENTA}Users logged on:$RESET " ; w -h
echo -e "\n${MAGENTA}Current date :$RESET " ; date
echo -e "\n${MAGENTA}Machine stats :$RESET " ; uptime
echo -e "\n${MAGENTA}Memory stats :$RESET " ; free
echo -e "\n${MAGENTA}Local IP Address :$RESET" ; myip
echo
}
# Misc utilities:
function repeat() # repeat n times command
{
local i max
max=$1; shift;
for ((i=1; i <= max ; i++)); do # --> C-like syntax
eval "$@";
done
}
function ask()
{
echo -n "$@" '[y/n] ' ; read ans
case "$ans" in
y*|Y*) return 0 ;;
*) return 1 ;;
esac
}
#=======================================================================
#
# PROGRAMMABLE COMPLETION - ONLY SINCE BASH-2.04
# Most are taken from the bash 2.05 documentation and from Ian McDonalds
# 'Bash completion' package
# (http://www.caliban.org/bash/index.shtml#completion)
# You will in fact need bash-2.05a for some features
#
#=======================================================================
if [ "${BASH_VERSION%.*}" \< "2.05" ]; then
echo "You will need to upgrade to version 2.05 for programmable completion"
return
fi
set +o nounset # otherwise some completions will fail
complete -A hostname rsh rcp telnet rlogin r ftp ping disk
complete -A export printenv
complete -A variable export local readonly unset
complete -A enabled builtin
complete -A alias alias unalias
complete -A function function
complete -A user su mail finger
complete -A helptopic help # currently same as builtins
complete -A shopt shopt
complete -A stopped -P '%' bg
complete -A job -P '%' fg jobs disown
complete -A directory mkdir rmdir
complete -A directory -o default cd
# Compression
complete -f -o default -X '*.+(zip|ZIP)' zip
complete -f -o default -X '!*.+(zip|ZIP)' unzip
complete -f -o default -X '*.+(z|Z)' compress
complete -f -o default -X '!*.+(z|Z)' uncompress
complete -f -o default -X '*.+(gz|GZ)' gzip
complete -f -o default -X '!*.+(gz|GZ)' gunzip
complete -f -o default -X '*.+(bz2|BZ2)' bzip2
complete -f -o default -X '!*.+(bz2|BZ2)' bunzip2
# Postscript,pdf,dvi.....
complete -f -o default -X '!*.ps' gs ghostview ps2pdf ps2ascii
complete -f -o default -X '!*.dvi' dvips dvipdf xdvi dviselect dvitype
complete -f -o default -X '!*.pdf' acroread pdf2ps zathura
complete -f -o default -X '!*.+(pdf|ps)' gv
complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf
complete -f -o default -X '!*.tex' tex latex slitex
complete -f -o default -X '!*.lyx' lyx
complete -f -o default -X '!*.+(htm*|HTM*)' lynx html2ps w3m
# Multimedia
complete -f -o default -X '!*.+(jp*g|gif|xpm|png|bmp)' xv gimp
complete -f -o default -X '!*.+(mp3|MP3)' mpg123 mpg321
complete -f -o default -X '!*.+(ogg|OGG)' ogg123
complete -f -o default -X '!*.pl' perl perl5
# This is a 'universal' completion function - it works when commands have
# a so-called 'long options' mode , ie: 'ls --all' instead of 'ls -a'
_get_longopts ()
{
$1 --help | sed -e '/--/!d' -e 's/.*--\([^[:space:].,]*\).*/--\1/'| \
grep ^"$2" |sort -u ;
}
_longopts_func ()
{
case "${2:-*}" in
-*) ;;
*) return ;;
esac
case "$1" in
\~*) eval cmd="$1" ;;
*) cmd="$1" ;;
esac
COMPREPLY=( $(_get_longopts ${1} ${2} ) )
}
complete -o default -F _longopts_func configure bash
complete -o default -F _longopts_func wget id info a2ps ls recode
_make_targets ()
{
local mdef makef gcmd cur prev i
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
# if prev argument is -f, return possible filename completions.
# we could be a little smarter here and return matches against
# `makefile Makefile *.mk', whatever exists
case "$prev" in
-*f) COMPREPLY=( $(compgen -f $cur ) ); return 0;;
esac
# if we want an option, return the possible posix options
case "$cur" in
-) COMPREPLY=(-e -f -i -k -n -p -q -r -S -s -t); return 0;;
esac
# make reads `makefile' before `Makefile'
if [ -f makefile ]; then
mdef=makefile
elif [ -f Makefile ]; then
mdef=Makefile
else
mdef=*.mk # local convention
fi
# before we scan for targets, see if a makefile name was specified
# with -f
for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do
if [[ ${COMP_WORDS[i]} == -*f ]]; then
eval makef=${COMP_WORDS[i+1]} # eval for tilde expansion
break
fi
done
[ -z "$makef" ] && makef=$mdef
# if we have a partial word to complete, restrict completions to
# matches of that word
if [ -n "$2" ]; then gcmd='grep "^$2"' ; else gcmd=cat ; fi
# if we don't want to use *.mk, we can take out the cat and use
# test -f $makef and input redirection
COMPREPLY=( $(cat $makef 2>/dev/null | \
awk 'BEGIN {FS=":"} /^[^.# ][^=]*:/ {print $1}' \
| tr -s ' ' '\012' | sort -u | eval $gcmd ) )
}
complete -F _make_targets -X '+($*|*.[cho])' make gmake pmake
_killall ()
{
local cur prev
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
# get a list of processes (the first sed evaluation
# takes care of swapped out processes, the second
# takes care of getting the basename of the process)
COMPREPLY=( $( /usr/bin/ps -u $USER -o comm | \
sed -e '1,1d' -e 's#[]\[]##g' -e 's#^.*/##'| \
awk '{if ($0 ~ /^'$cur'/) print $0}' ))
return 0
}
complete -F _killall killall killps
# A meta-command completion function for commands like sudo(8), which
# need to first complete on a command,
# then complete according to that command's own
# completion definition - currently not quite foolproof
# (e.g. mount and umount don't work properly),
# but still quite useful --
# By Ian McDonald, modified by me.
_my_command()
{
local cur func cline cspec
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
if [ $COMP_CWORD = 1 ]; then
COMPREPLY=( $( compgen -c $cur ) )
elif complete -p ${COMP_WORDS[1]} &>/dev/null; then
cspec=$( complete -p ${COMP_WORDS[1]} )
if [ "${cspec%%-F *}" != "${cspec}" ]; then
# complete -F <function>
#
# COMP_CWORD and COMP_WORDS() are not read-only,
# so we can set them before handing off to regular
# completion routine
# set current token number to 1 less than now
COMP_CWORD=$(( $COMP_CWORD - 1 ))
# get function name
func=${cspec#*-F }
func=${func%% *}
# get current command line minus initial command
cline="${COMP_LINE#$1 }"
# split current command line tokens into array
COMP_WORDS=( $cline )
$func $cline
elif [ "${cspec#*-[abcdefgjkvu]}" != "" ]; then
# complete -[abcdefgjkvu]
#func=$( echo $cspec | sed -e 's/^.*\(-[abcdefgjkvu]\).*$/\1/' )
func=$( echo $cspec | sed -e 's/^complete//' -e 's/[^ ]*$//' )
COMPREPLY=( $( eval compgen $func $cur ) )
elif [ "${cspec#*-A}" != "$cspec" ]; then
# complete -A <type>
func=${cspec#*-A }
func=${func%% *}
COMPREPLY=( $( compgen -A $func $cur ) )
fi
else
COMPREPLY=( $( compgen -f $cur ) )
fi
}
#mkdir, cd into it
mkcd () {
mkdir -p "$*"
cd "$*"
}
complete -o default -F _my_command nohup exec eval \
trace truss strace sotruss gdb
complete -o default -F _my_command command type which man nice
function myip() # get IP adresses
{
local myip=`w3m -dump http://checkip.dyndns.org:8245/`
echo "${myip}"
}
function serverip() {
local ip=`dropbox_uploader.sh download myip.txt /tmp/myip.txt > /dev/null && cat /tmp/myip.txt`
echo "${ip}"
echo "${ip}"|pclip
}
#backup linux system
function bksys(){
echo "HINT: backup file could be myarchlinux-'date +%Y%m%d-%H%M'.tgz"
#my home directory is already backed up, so I don't need archive it now
echo "BACKUP: tar zcvpf mylinux.tgz --exclude=/proc/* --exclude=/lost+found --exclude='mylinux.tgz' --exclude=/mnt/* --exclude=/home/cb/* --exclude=/sys/* /"
echo "RESTORE: 'tar zxvpf mylinux.tgz -C /' to restore system"
echo "http://i.linuxtoy.org/docs/guide/ch31s11.html for grub fstab xorg.conf"
}
function nosl(){
if [ -z "$1" ]; then
echo "Usage: echo /hello/world|nosl num"
echo "strip num leading slashes"
else
perl -pe "\$n=$1;while(\$n>0){ \$_=~ s/[^\\\\\\/]*[\\\\\\/]+//;\$n--; }"
fi
}
function bbdbclean(){
sed -i.bak '/\["" ""/d' $HOME/.bbdb
}
#https://github.com/clvv/fasd
if test -n "`type -t fasd`"; then
eval "$(fasd --init auto)"
alias d='fasd_cd -id'
alias f='fasd -if'
function rr {
local cli=`fasd -if`
echo ${cli}
echo -n ${cli} | pclip
}
fi
function csssize() {
if [ -z "$1" ]; then
echo "Usage: csssize test.png"
echo "create css from image file, imagemagic"
else
identify -format "%[w] %[h]" $1 |sed -e "s/\(.*\) \(.*\)/width:\1px;\nheight:\2px;/g"
fi
}
# {{ subversion stuff
# go to root directory of subversion
# support only subversion 1.7+
function cdsr()
{
grandparent="."
cnt=0
while [ ! -d "$grandparent/.svn" ] && [ $cnt -lt 32 ] ; do
grandparent="$grandparent/.."
cnt=$[cnt + 1]
done
if [ ! -z "$grandparent" ]; then
cd $grandparent
if [ ${#PWD} -lt ${#HOME} ]; then
cd -
fi
else
echo "cannot find svn root diectory"
fi
}
# }}
alias crontabe="EDITOR='emacs -nw' crontab -e"
alias fehphotos="find -name '*.jpg' -o -name '*.JPG' -print0 | xargs -0 feh -d -F"
alias fehall="find -name '*.jpg' -o -name '*.JPG' -o -name '*.png' -o -name '*.PNG' -o -name '*.gif' -o -name '*.GIF' -o -name '*.xpm' -print0 | xargs -0 feh -d -F"
#@see https://github.com/dattanchu/pymodoro
alias timer='~/.pymodoro/pymodoro.py|dzen2'
# just bonus, sed -i 's/hello/hi/g;s/bye/c u/g' my.conf, to replace two variables in one sed cli
alias line2clip="perl -ne 'chomp and print'|pclip"
if [ "$OS_NAME" = "Darwin" ]; then
alias zcat='gunzip -c' #zcat is in POSIX mode and will append .Z to the file name
export PATH=/usr/local/bin:/usr/local/sbin:$PATH #brew install packages shoud run first
if [ -d /Applications/LibreOffice.app/Contents/share/extensions/dict-en ]; then
export DICPATH=/Applications/LibreOffice.app/Contents/share/extensions/dict-en
fi
fi
#set up env for different machines
if [ -f "$HOME/.bashrc.local" ]; then
. "$HOME/.bashrc.local" >/dev/null
fi
alias ca='echo $((`date +"%m"`+1)) `date +"%Y"` | xargs cal -3'
alias mywatch="watch -tn 1 date +%T \|figlet -c -t -W"
function big() {
# find files and sort by size, full path is printed
find -name "$*" -type f -printf "`pwd`%P %s\n"|sort -k2,2n
}
function parse_git_branch() {
git rev-parse --abbrev-ref HEAD 2>/dev/null
}
# {{ @see http://unix.stackexchange.com/questions/14303/bash-cd-up-until-in-certain-folder/14311#14311
upto ()
{
if [ -z "$1" ]; then
return
fi
local upto=$1
cd "${PWD/\/$upto\/*//$upto}"
}
# auto-completion in bash
function _upto()
{
local cur=${COMP_WORDS[COMP_CWORD]}
local d=${PWD//\//\ }
COMPREPLY=( $( compgen -W "$d" -- "$cur" ) )
}
complete -F _upto upto
# In addition, I have another function jd which allows me to jump to any directory below the current one:
function jd() {
if [ -z "$1" ]; then
echo "Usage: jd [directory]";
return 1
else
cd **"/$1"
fi
}
# }}
# {{ toggle coporate proxy
# @see http://stackoverflow.com/questions/21705091/bower-behind-a-proxy
function set_proxy() {
export HTTP_PROXY=http://127.0.0.1:3128
export HTTPS_PROXY=http://127.0.0.1:3128
# some tools uses lowercase env variables
export http_proxy=http://127.0.0.1:3128
export https_proxy=http://127.0.0.1:3128
# config git
git config --global http.proxy http://127.0.0.1:3128
git config --global https.proxy http://127.0.0.1:3128
git config --global url."http://".insteadOf git://
}
function unset_proxy() {
unset HTTP_PROXY
unset HTTPS_PROXY
unset http_proxy
unset https_proxy
git config --global --unset http.proxy
git config --global --unset https.proxy
git config --global --unset url."http://".insteadOf
}
function vidrmseg() {
# Usage:
# vidrmseg test.mp4 48 93 # remove video between sec 48 and sec 93
# vidrmseg test.mp4 48 # remove video after 48
local f=${1%.*}
local ext=${1##*.}
if [ -z "$3" ]; then
ffmpeg -y -i $1 -filter_complex "[0:v]trim=duration=${2}[a]" -map [a] ${f}.copy.${ext}
else
ffmpeg -y -i $1 -filter_complex "[0:v]trim=duration=${2}[a];[0:v]trim=start=${3},setpts=PTS-STARTPTS[b];[a][b]concat[c]" -map [c] ${f}.copy.${ext}
fi
}
# @see https://rudd-o.com/linux-and-free-software/tales-from-responsivenessland-why-linux-feels-slow-and-how-to-fix-that
function enough_memory() {
# change /etc/sysctl.conf to make it permanent
sudo sysctl -w vm.swappiness=1
sudo sysctl -w vm.vfs_cache_pressure=10
}
function video2mp3 () {
if [ -z $1 ]; then
echo "Usage: video2mp3 filename [start_second] [total_second]"
echo "For example, video2mp3 1.mp4 5 10"
return;
fi
# set gif width
if [ -z $2 ]; then
local start=0
else
local start=$2
fi
if [ -z $2 ]; then
local total=5
else
local total=$3
fi
ffmpeg -i "$1" -vn -ss $start -t $total -acodec copy "${1%%.*}-$start-$total.mp3"
}
function video2gif () {
if [ -z $1 ]; then
echo "Usage: video2gif filename [width]"
return;
fi
# set gif width
if [ -z $2 ]; then
local width=320
else
local width=$2
fi
local palette="/tmp/palette.png"
local filters="fps=15,scale=$width:-1:flags=lanczos"
if [ -f $1 ]; then
ffmpeg -i $1 -vf "$filters,palettegen" -y $palette
ffmpeg -i $1 -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y ${1%%.*}.gif
echo "${1%%.*}.gif is created."
else
echo "File $1 does NOT exist!"
fi
}
function audio2video {
# Add audio to video using ffmpeg
# @see https://superuser.com/questions/590201/add-audio-to-video-using-ffmpeg
if [ -z $1 ]; then
echo "Usage: audio2video 1.mp4"
return;
fi
ffmpeg -i $1 -i ${1%%.*}.mp3 -c copy -map 0:v:0 -map 1:a:0 new-$1
mv new-$1 $1
}
function video-rotate-resize {
if [ -z $1 ]; then
echo "Usage: video-rotate-resize 1.mp4"
return;
fi
ffmpeg -i $1 -vf "transpose=1" -filter:v scale=640:-1 new-${1%%.*}.mp4
mv new-${1%%.*}.mp4 ${1%%.*}.mp4
}
function video-resize {
if [ -z $1 ]; then
echo "Usage: video-resize 1.mp4"
return;
fi
ffmpeg -i $1 -filter:v scale=640:-1 new-${1%%.*}.mp4
mv new-${1%%.*}.mp4 ${1%%.*}.mp4
}
# https://stackoverflow.com/questions/9679932/how-to-use-package-installed-locally-in-node-modules
alias npmbin='PATH=$(npm bin):$PATH'
export PS1="\[${BOLD}${MAGENTA}\]\u\[$RESET\]@\[$ORANGE\]\h\[$RESET\]:\[$GREEN\]\w\[$RESET\]\$(echo \" on \")\[$PURPLE\]\$(parse_git_branch)\[$RESET\]\n\[$RESET\]\$ "
export PS2="\[$ORANE\]->\[$RESET\]"
# @see https://github.com/mathiasbynens/dotfiles/blob/master/.bash_profile
# Add tab completion for SSH hostnames based on ~/.ssh/config, ignoring wildcards
[ -e "$HOME/.ssh/config" ] && complete -o "default" -o "nospace" -W "$(grep "^Host" ~/.ssh/config | grep -v "[?*]" | cut -d " " -f2 | tr ' ' '\n')" scp sftp ssh
# bash completion
bind "set completion-ignore-case on"
bind "set show-all-if-ambiguous on"
bind "set page-completions off"
bind "set show-all-if-unmodified on"
bind "set completion-query-items -1"
# {{ perl local libs
PATH="$HOME/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="$HOME/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="$HOME/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"$HOME/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=$HOME/perl5"; export PERL_MM_OPT;
# }}
# {{ python
if [ -d $HOME/.virtualenvs ]; then
export WORKON_HOME=$HOME/.virtualenvs
fi
if [ -x /usr/bin/python3 ]; then
# safer than `ln -s /usr/bin/python3 /usr/bin/python'
alias python="/usr/bin/python3"
fi
# }}
# @see https://www.gnupg.org/documentation/manuals/gnupg/Invoking-GPG_002dAGENT.html
export GPG_TTY=$(tty)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment