To help me figure this out, I use a few shell functions. Firstly, I need to know what configuration file that was used.

function shell_init_file () { # Returns what would be your initfile if [[ $- == *i* ]] ; then echo ~/.bashrc elif [[ -f ~/.bash_profile ]] ; then echo ~/.bash_profile elif [[ -f ~/.bash_login ]] ; then echo ~/.bash_login elif [[ -f ~/.profile ]] ; then echo ~/.profile else echo "Could not find any config files.." return 1 fi }

This function checks if we’re in an interactive shell or not, and returns bashrc if we are. If not it checks for the various login files.

Thats all great, but now we need to figure out what files have been sourced from that first file.

function _sourced_files (){ # Helper for sourced_files sed -En 's/^[.|source]+ (.*)/\1/p' " $1 " | while IFS = read -r f; do expanded = $( echo ${ f/# \~ /$HOME } | envsubst | tr -d '"' ) echo " $expanded " _sourced_files " $expanded " done } function sourced_files () { # Lists files which (s/w)hould have been sourced to this shell init_file = $( shell_init_file ) echo " $init_file " _sourced_files " $init_file " }

The function sourced_files is just a wrapper that checks the initial config file, and then calls _sourced_files to check what files are then being sourced etc..

Now we have some kind of idea about what is being configured in our shell. You might have noticed that I add # some description after my function definitions? This is so I can get these two nifty helpers:

alias halp = 'echo -e "Sourced files:

$(sourced_files | sed "s#$HOME/#~/#")

#

Functions:

$(list_functions)

#

Aliases:



$(list_aliases)" | column -t -s "#"' # Show all custom aliases and functions

This is simply an alias that will list my sourced files, and show all functions, aliases and their description.

function _wat () { # Completion for wat local cur words _get_comp_words_by_ref cur words = $( list_aliases; list_functions | cut -d ' ' -f 1 ) COMPREPLY =( $( compgen -W " $words " -- " $cur " ) ) } complete -o nospace -F _wat wat function wat () { # show help and location of a custom function or alias local query pp query = " $1 " pp = "cat" if [[ -n " $( type bat 2> /dev/null ) " ]] ; then pp = "bat -l bash -p" fi for file in $( sourced_files ) ; do awk '/^function ' " $query " '\(\)/,/^}/ { i++; if(i==1){print "# " FILENAME ":" FNR RS $0;} else {print $0;}}' " $file " awk '/^function \_' " $query " '\(\)/,/^}/ { i++; if(i==1){print "# " FILENAME ":" FNR RS $0;} else {print $0;}}' " $file " awk '/^alias ' " $query " '=/,/$/ {print "# " FILENAME ":" FNR RS $0 RS;}' " $file " done | $pp complete -p " $query " 2> /dev/null }

So after looking at what helpers I have available using halp I can use wat to show me exactly where it’s defined, what it looks like and how it’s auto completed. wat also has auto completion through the _wat function. A sample output would look like this:

$> wat list_aliases # /Users/brujoand/src/brujoand/dotfiles/bash/function.bash:66 function list_aliases () { # List all sourced aliases for f in $( sourced_files ) ; do sed -n "s/^alias \(.*\)=['|\"].*#\(.*\) $ /\1 #\2/p" " $f " | sed "s/list_aliases=.*#/list_aliases #/" done | sort } $> wat list_functions # /Users/brujoand/src/brujoand/dotfiles/bash/function.bash:60 function list_functions () { # List all sourced functions for f in $( sourced_files ) ; do sed -n "s/^function \(.*\)() { \(.*\) $ /\1 \2/p" < ( cat " $f " ) | grep -v "^_" done | sort }

Oh, and this output is pretty printed using bat , it’s super nice :) Unfortunately I haven’t found a great way of pretty printing code on this blog though :/ (ha, finally figured it out. Pygments powered syntax highlighting)

Now, the final touch. I can figure out what helpers I have, where they are defined, and what they do. Now I’d like to edit the config file containing some helper. Enter esc , which auto completes to my sourced files, and opens it with whatever I’ve set as my $EDITOR .

function esc () { # Edit a shell config file local file file = $( grep "/ $1$ " < ( sourced_files ) ) " ${ EDITOR :- vi } " " $file " } function _esc () { # Fuzzy tabcompletion for esc local cur config_files _get_comp_words_by_ref cur config_files = $(for file in $( sourced_files ) ; do echo " ${ file##*/ } " ; done) if [[ -z " $cur " ]] ; then COMPREPLY =( $( compgen -W " $config_files " ) ) else COMPREPLY =( $( grep -i " $cur " <<< " $config_files " ) ) fi } complete -o nospace -F _esc esc

Discussion: reddit.com/r/bash - post