diff --git a/README.md b/README.md index 81663d0..4e8fc92 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # proj +## TODO + +* Actually spawn the shell + +* Figure out why the pre-spawn hook is using the `project_dir` value + ## Usage Invoke the script and pass the name of the project as its only non-flag argument: @@ -16,7 +22,7 @@ When invoked as specified in usage (with any number of valid flags plus exactly * Check for the existence of `project_dir` - * If `project_dir` is a directory or symbolic link, proceed + * If `project_dir` is a directory or symbolic link to one, proceed * If `project_dir` is any other type of file, panic @@ -26,7 +32,7 @@ When invoked as specified in usage (with any number of valid flags plus exactly * Check for the existence of `$arg1` - * If `$arg1` is a directory or symbolic link, proceed + * If `$arg1` is a directory or symbolic link to one, proceed * If `$arg1` is any other type of file, panic @@ -36,9 +42,7 @@ When invoked as specified in usage (with any number of valid flags plus exactly * Create `$arg1` as a directory - * Initialize an empty git repository if configured to do so - - * Add and commit a `.gitignore` if configured to do so + * Execute the post-create hook if configured to do so * `cd` to `$arg1` @@ -59,9 +63,8 @@ flag|description|args value|description|default ---|---|--- -git\_auto\_init|If not set to `0`, automatically initialize a git repository on project creation|`0` -git\_auto\_init\_gitignore|A colon-separated ($PATH-style) list of items to include in the initial `.gitignore`|`*.swp` hook\_pre\_create|Path to a script invoked (not sourced) before a project is created. Script will be executed relative to `project_dir`|Empty string +hook\_post\_create|Path to a script invoked (not sourced) after a project is created. Script will be executed relative to the project's root directory|Empty string hook\_pre\_spawn|Path to a script invoked (not sourced) before a shell is spawned in the project directory. Script will be executed relative to the project's root directory|Empty string hook\_env|Path to a script to *source in* after entering a project directory but before a shell is spawned. Script will be sourced relative to the project's root directory|`.projenv` project\_dir|Path to where projects should be stored.|`$HOME/Projects` @@ -73,3 +76,5 @@ code|description 0|Success 2|Invalid flag or missing flag argument 50|Non-flag arguments have errors or are nonsensical +61|`project_dir` exists and is not a directory +62|`$arg1` exists and is not a directory diff --git a/proj b/proj index a84042a..21f705a 100755 --- a/proj +++ b/proj @@ -12,9 +12,8 @@ set -e declare -r _name="$(basename -- "$0")" # Options declare -a _config=( - [git_auto_init]="0" - [git_auto_init_gitignore]="*.swp" [hook_pre_create]="" + [hook_post_create]="" [hook_pre_spawn]="" [hook_env]=".projenv" [project_dir]="$HOME/Projects" @@ -94,9 +93,74 @@ Copyright (c) 2021 rehashedsalt@cock.li Licensed under the MIT license EOF } +hook() { + # Execute a hook, if it exists + # If it fails for whatever reason, continue anyway silently + # $1 path to executable + # $2 name of hook + [ -z "$1" ] && return 1 + [ -z "$2" ] && return 2 + log "Attempting to execute hook \"$2\": $1" + if ! [ -e "$1" ]; then + warn "Hook \"$2\" does not exist: $1" + return + fi + if ! [ -x "$1" ]; then + warn "Hook \"$2\" cannot be executed: $1" + return + fi + if [ -d "$1" ]; then + warn "Hook \"$2\" is a directory: $1" + return + fi + "$1" || warn "Hook \"$2\" failed: $?" +} proj() { - # Do the do + # Create/find a project directory and get in there + [ -z "$1" ] && return 1 + # Get to project_dir + local projdir="${_config[project_dir]}" + log "Using project_dir: $projdir" 2 + if ! [ -d "$projdir" ]; then + if [ -e "$projdir" ]; then + error "Project directory exists as another file type: $projdir" 61 + fi + mkdir -p "$projdir" + log "Created project directory: $projdir" 1 + fi + + log "Entering directory: $projdir" 2 + cd "$projdir" + + # Get to THE project directory + local dir="$1" + local dirnew + if ! [ -d "$1" ]; then + if [ -e "$1" ]; then + error "File is in the way of creating a directory: $dir" 62 + fi + # Execute the pre-create hook + [ -n "${_config[hook_pre_create]}" ] && hook "${_config[hook_pre_create]}" "pre-create" + mkdir -p "$dir" + dirnew=1 + fi + + log "Entering directory: $dir" 2 + cd "$dir" + + # Execute a post-create hook if necessary + if [ -n "$dirnew" ]; then + [ -n "${_config[hook_post_create]}" ] && hook "${_config[hook_post_create]}" "post-create" + fi + + # Execute the pre-spawn hook if necesary + [ -n "${_config[hook_pre_spawn]}" ] && hook "${_config[hook_pre_spawn]}" "pre-spawn" + + # Get in there + ( : + ) || : + unset dirnew precreatehook postcreatehook } # Main @@ -135,7 +199,7 @@ main() { [ -n "$_opthelp" ] && printhelp && exit 0 # Parse out a config file if it exists if [ -f "$_optconfigfile" ]; then - log "Loading config file" 2 + log "Loading config file: $_optconfigfile" 2 while read line; do # If the line has an equals sign and isn't a comment if [ "$line" != "${line#*=}" ] && validateline "$line"; then @@ -161,7 +225,7 @@ main() { fi # Do the do - proj + proj "${_args[0]}" exit 0 }