├── .gitignore ├── workspace.vim ├── README.md └── workspace.sh /.gitignore: -------------------------------------------------------------------------------- 1 | test/ 2 | *.swp 3 | -------------------------------------------------------------------------------- /workspace.vim: -------------------------------------------------------------------------------- 1 | function! Bws_import() 2 | silent execute "!bws _call export_workspace_to_vim &" | redraw! 3 | source ~/.bash-workspace/vim 4 | endfunction 5 | 6 | function! Bws_cd(name) 7 | call Bws_import() 8 | let var_name = "_bws_link_" . a:name 9 | if !exists("g:{var_name}") 10 | echo a:name "not found" 11 | return 12 | endif 13 | cd `=g:{var_name}` 14 | pwd 15 | endfunction 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | bash-workspace 3 | ============== 4 | 5 | Overview 6 | -------- 7 | 8 | bash-workspace makes it easy to navigate the filesystem using context sensitive shortcuts. 9 | 10 | This script implements workspaces for the terminal. The idea is to create one workspace per 11 | project (or context), and store a bunch of shortcuts to relevant folders in each workspace so 12 | that you quickly can jump from place to place. 13 | 14 | Workspaces, including all shortcuts are stored in `~/.bash-workspace/log/`. 15 | This let you access your workspaces between sessions (in multiple terminals, etc.). 16 | 17 | Installation 18 | ------------ 19 | 20 | 1. Download workspace.sh and place it in `/some/path/workspace.sh` 21 | 22 | 2. Add the following to `~/.bashrc` 23 | 24 | alias bws='source /some/path/workspace.sh' 25 | bws autocomplete # If you chose another alias, run autocomplete 26 | 27 | Usage 28 | ----- 29 | 30 | If you type `bws ` and click tab twice auto-complete will suggest all available commands. 31 | 32 | ### Change workspace (it will be created if id doesn't already exist) 33 | 34 | Auto-complete will suggest available workspaces, including the 35 | current directory name 36 | 37 | bws cw my_workspace 38 | 39 | ### Add link to current directory 40 | 41 | Auto-complete will suggest the current directory name 42 | 43 | bws ln some_link_name 44 | 45 | ### Move to workspace root 46 | 47 | bws cd 48 | 49 | ### Move to linked folder 50 | 51 | Auto-complete will suggest links added using `bws ln` 52 | 53 | bws cd some_link_name 54 | 55 | ### Remove a shortcut from the active workspace 56 | 57 | Auto-complete will suggest links added using `bws ln` 58 | 59 | bws rm 60 | 61 | ### Clear the current workspace (i.e. delete all shortcuts for this workspace) 62 | 63 | bws empty 64 | 65 | ### Remove the current workspace 66 | 67 | bws rm 68 | 69 | ### Remove all workspaces and shortcuts 70 | 71 | bws reset 72 | 73 | ### List all shortcuts for the active workspace 74 | 75 | bws list 76 | 77 | ### List all stored workspaces 78 | 79 | bws 80 | 81 | ### Get help 82 | 83 | bws help 84 | -------------------------------------------------------------------------------- /workspace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | _BWS_DIR=~/.bash-workspace 4 | _BWS_ALIAS="bws" 5 | _DU_CMD="du" 6 | 7 | _bws_args() { 8 | # Pass variables through: 9 | # `eval _bws_args "$@"` 10 | # @param Index of first argument to pass through 11 | # @param List of parameters 12 | local i=1 13 | local min=$(( $1 + 1 )) 14 | for var in "$@"; do 15 | i=$(( $i + 1 )) 16 | if [ $i -gt $min ]; then echo $var; fi 17 | done; 18 | } 19 | 20 | _bws_init() { 21 | export _bws_active=default 22 | mkdir $_BWS_DIR > /dev/null 2>&1 23 | mkdir $_BWS_DIR/log> /dev/null 2>&1 24 | 25 | _bws_load_workspace 26 | _bws_remove_empty_workspaces 27 | } 28 | 29 | _bws_load_du_cmd() { 30 | which gdu &> /dev/null 31 | 32 | if [ $? -eq 0 ] 33 | then 34 | _DU_CMD="gdu" 35 | else 36 | du -b /dev/null &> /dev/null 37 | if [ $? -ne 0 ] 38 | then 39 | echo "Error: The du installed on your system does not support the -b option." 40 | return 1 41 | fi 42 | fi 43 | } 44 | 45 | _bws_load_workspace() { 46 | source $_BWS_DIR/active 2> /dev/null 47 | unset ${!_bws_link_*} 48 | source $_BWS_DIR/log/$_bws_active 2> /dev/null 49 | if [ $? == 1 ]; then 50 | if [ $_bws_active == 'default' ]; then 51 | _bws_add_link r "`echo ~`" 52 | else 53 | _bws_add_link r "`pwd`" 54 | fi 55 | _bws_save_workspace 56 | fi 57 | } 58 | 59 | _bws_save_workspace() { 60 | export -p | grep _bws_link_ | sed -e 's/.*\?_bws_link_/export _bws_link_/g' > $_BWS_DIR/log/$_bws_active 61 | } 62 | 63 | _bws_export_workspace_to_vim() { 64 | export -p | grep _bws_link_ | sed -e 's/.*\?_bws_link_/let g:_bws_link_/g' > $_BWS_DIR/vim 65 | } 66 | 67 | _bws_remove_empty_workspaces() { 68 | _bws_load_du_cmd 69 | if [ $? -ne 0 ]; then return 1; fi 70 | for ws in `ls $_BWS_DIR/log`; do 71 | local file_size=`$_DU_CMD -b $_BWS_DIR/log/$ws | sed -e s/[^0-9]*//g` 72 | if [ $file_size -le 1 ] && [ "$ws" != "default" ] && [ "$ws" != $_bws_active ]; then 73 | rm "$_BWS_DIR/log/$ws" 74 | fi; 75 | done; 76 | } 77 | 78 | _bws_change_workspace() { 79 | # @param workspace to be activated 80 | _bws_save_workspace 81 | echo "export _bws_active=$1" > $_BWS_DIR/active 82 | _bws_load_workspace 83 | } 84 | 85 | _bws_activate_workspace() { 86 | # @param workspace to be activated 87 | echo "export _bws_active=$1" > $_BWS_DIR/active 88 | _bws_load_workspace 89 | } 90 | 91 | _bws_rebase_workspace() { 92 | local new_root="`pwd`" 93 | for var_name in ${!_bws_link*}; do 94 | local var_value="`echo "${!var_name}" | sed -e "s#^$_bws_link_r#$new_root#g" | sed -e 's#//#/#g'`" 95 | export `echo $var_name`="$var_value" 96 | done; 97 | export _bws_link_r="$new_root" 98 | _bws_save_workspace 99 | } 100 | 101 | _bws_empty_workspace() { 102 | local root="$_bws_link_r" 103 | unset ${!_bws_link_*} 104 | export _bws_link_r="$root" 105 | _bws_save_workspace 106 | } 107 | 108 | _bws_remove_workspace() { 109 | unset ${!_bws_link_*} 110 | rm $_BWS_DIR/log/$_bws_active 111 | _bws_activate_workspace "default" 112 | } 113 | 114 | _bws_remove_all_workspaces() { 115 | unset ${!_bws_link_*} 116 | rm $_BWS_DIR/log/* 117 | _bws_activate_workspace "default" 118 | _bws_save_workspace 119 | } 120 | 121 | _bws_escape() { 122 | # Replace illegal characters with underline 123 | # @param Link name 124 | echo $1 | sed -e s/[^a-z0-9_]/_/gi 125 | } 126 | 127 | _bws_escape_current_basename() { 128 | local tmp="`pwd`" 129 | tmp="`basename "$tmp"`" 130 | _bws_escape "$tmp" 131 | } 132 | 133 | _bws_add_link() { 134 | # @param Link name 135 | # @param Target directory 136 | export _bws_link_$1="$2" 137 | _bws_save_workspace 138 | } 139 | 140 | _bws_remove_links() { 141 | # @param List of link names 142 | for var in $@; do 143 | unset _bws_link_$var 144 | done; 145 | _bws_save_workspace 146 | } 147 | 148 | _bws_lookup() { 149 | # Get directory path that link poins to 150 | # @param Link name 151 | local path=_bws_link_$1; 152 | path=${!path} 153 | if [ -z "$path" ]; then 154 | return 1 155 | fi 156 | echo $path 157 | } 158 | 159 | _bws_list_workspaces() { 160 | local s="[" #local s="\033[40m\033[1;34m" 161 | local e="]" #local e="\033[0m" 162 | for ws in `ls $_BWS_DIR/log`; do 163 | if [ "$ws" == $_bws_active ]; then 164 | echo -n -e "${s}$ws${e} " 165 | else 166 | echo -n -e "$ws " 167 | fi; 168 | done; 169 | echo 170 | } 171 | 172 | _bws_list_link_names() { 173 | # List links in current workspace 174 | export -p | grep _bws_link_ | sed -e 's/.*\?_bws_link_//g' -e 's/=.*//g' | tr "\n" " " 175 | echo 176 | } 177 | 178 | _bws_list_links() { 179 | # List links in current workspace 180 | export -p | grep _bws_link_ | sed -e 's/.*\?_bws_link_//g' 181 | } 182 | 183 | _bws_confirm() { 184 | # Get user confirmation 185 | # @param message 186 | # @return 0 if user answered yes, 1 otherwise 187 | message=$1 188 | echo -n "$message Yes/No " 189 | read action_confirmed 190 | local action_confirmed=`echo $action_confirmed | tr '[:upper:]' '[:lower:]'` 191 | if [ "$action_confirmed" == "yes" ] || [ "$action_confirmed" == "y" ]; then 192 | return 0 193 | else 194 | return 1 195 | fi 196 | } 197 | 198 | _bws_list_commands() { 199 | echo "cd cw empty help ln lookup ls rebase reset rm" 200 | } 201 | 202 | _bws_helptext() { 203 | # @param Name of command 204 | echo "Usage: $1 [COMMAND]" 205 | echo "If COMMAND is not specified, current workspaces are listed." 206 | echo 207 | echo "Available commands:" 208 | echo "cd [NAME] Change directory, if NAME is omitted, go to \"r\" (workspace root)" 209 | echo "cw [NAME] Change workspace, if NAME is omitted, default workspace is activated" 210 | echo "empty Empty active workspace (removing all links)" 211 | echo "help Display this.." 212 | echo "ln NAME [DIRECTORY] Add link to DIRECTORY, or to current working directory if not specified" 213 | echo "lookup NAME Lookup link (returns an absolute filepath)" 214 | echo "ls List all directories in workspace" 215 | echo "rebase Rebase the workspace (i.e. change \"r\" to current directory, and replace workspace prefix for all links)" 216 | echo "reset Remove all workspaces" 217 | echo "rm [NAME]... Remove directories from workspace, or remove entire workspace if no names are specified" 218 | } 219 | 220 | _bws_autocomplete() { 221 | local cur suggestions cmd 222 | COMPREPLY=() 223 | cur="${COMP_WORDS[COMP_CWORD]}" 224 | cmd="${COMP_WORDS[1]}" 225 | 226 | if [ $COMP_CWORD -eq 1 ]; then 227 | suggestions="`_bws_list_commands`" 228 | elif [ $COMP_CWORD -eq 2 ]; then 229 | if [ "$cmd" == "cd" ] || [ "$cmd" == "rm" ] || [ "$cmd" == "lookup" ]; then 230 | suggestions="`_bws_list_link_names`" 231 | elif [ "$cmd" == "cw" ]; then 232 | suggestions="`ls $_BWS_DIR/log` `_bws_escape_current_basename`" 233 | elif [ "$cmd" == "ln" ]; then 234 | suggestions="`_bws_escape_current_basename`" 235 | fi 236 | elif [ $COMP_CWORD -eq 3 ]; then 237 | if [ "$cmd" == "ln" ] ; then 238 | suggestions="`ls`" 239 | fi 240 | fi 241 | COMPREPLY=(`compgen -W "${suggestions}" $cur`) 242 | } 243 | 244 | _bws_run() { 245 | _bws_init 246 | 247 | local command="$1" 248 | 249 | # Add 250 | if [ "$command" == 'ln' ]; then 251 | if [ -n "$2" ]; then 252 | local dir=`pwd` 253 | if [ -n "$3" ]; then dir="$3"; fi 254 | _bws_add_link `_bws_escape "$2"` "$dir" 255 | else 256 | _bws_helptext $_BWS_ALIAS 257 | fi 258 | 259 | # Remove 260 | elif [ "$command" == 'rm' ]; then 261 | if [ -n "$2" ]; then 262 | _bws_remove_links `eval _bws_args 2 "$@"` 263 | else 264 | _bws_confirm "Remove active workspace ($_bws_active)?" && _bws_remove_workspace 265 | fi 266 | 267 | # Lookup 268 | elif [ "$command" == 'lookup' ]; then 269 | echo `_bws_lookup "$2"` 270 | 271 | # Change directory 272 | elif [ "$command" == 'cd' ]; then 273 | if [ -n "$2" ]; then 274 | cd "`_bws_lookup $2`" 275 | else 276 | cd "`_bws_lookup r`" 277 | fi 278 | 279 | # Change workspace 280 | elif [ "$command" == 'cw' ]; then 281 | if [ -n "$2" ]; then 282 | _bws_change_workspace `_bws_escape "$2"` 283 | else 284 | _bws_change_workspace default 285 | fi 286 | 287 | # Rebase 288 | elif [ "$command" == 'rebase' ]; then 289 | _bws_confirm "Rebase workspace?" && _bws_rebase_workspace 290 | 291 | # Reset (remove all workspaces) 292 | elif [ "$command" == 'reset' ]; then 293 | _bws_confirm "Remove all workspaces?" && _bws_remove_all_workspaces && _bws_activate_workspace "default" 294 | 295 | # Empty workspace 296 | elif [ "$command" == 'empty' ]; then 297 | _bws_confirm "Empty workspace ($_bws_active)?" && _bws_empty_workspace 298 | 299 | # List links 300 | elif [ "$command" == 'ls' ]; then 301 | _bws_list_links 302 | 303 | # Help 304 | elif [ "$command" == 'help' ]; then 305 | _bws_helptext $_BWS_ALIAS 306 | 307 | # List workspaces 308 | elif [ -z "$command" ]; then 309 | _bws_list_workspaces 310 | 311 | # Autocomplete 312 | elif [ "$command" == 'autocomplete' ]; then 313 | if [ -n "$2" ]; then 314 | complete -F _bws_autocomplete "$2" 315 | else 316 | complete -F _bws_autocomplete $_BWS_ALIAS 317 | fi; 318 | 319 | # Run workspace function directly 320 | elif [ "$command" == '_call' ]; then 321 | eval "_bws_$2 `eval _bws_args 3 "$@"`" 322 | 323 | # Default 324 | else 325 | _bws_helptext $_BWS_ALIAS 326 | fi 327 | } 328 | 329 | _bws_run "$@" 330 | --------------------------------------------------------------------------------