diff --git a/.conduit.yaml b/.conduit.yaml index acb7792..491664f 100644 --- a/.conduit.yaml +++ b/.conduit.yaml @@ -16,6 +16,8 @@ - {src: zshrc, dst: ~/.zshrc} - src: prompt_fresh_setup dst: ~/.local/share/zsh/site-functions/prompt_fresh_setup + - src: build/_build-dir + dst: ~/.local/share/zsh/site-functions/_build-dir - src: sandbox/_sandbox dst: ~/.local/share/zsh/site-functions/_sandbox - src: layout/_layout @@ -26,6 +28,4 @@ - https://github.com/zsh-users/zsh-autosuggestions.git - https://github.com/zsh-users/zsh-history-substring-search.git - https://github.com/zdharma/fast-syntax-highlighting.git -- pip: - - pick - message: zsh will be the default prompt after next login diff --git a/build/_build-dir b/build/_build-dir new file mode 100644 index 0000000..fb7aaf9 --- /dev/null +++ b/build/_build-dir @@ -0,0 +1,6 @@ +#compdef build-dir + +_arguments \ + '(-h --help)'{-h,--help}'[]' \ + '--build[invoke a build after selection]' \ + '1:directory:_files' diff --git a/build/build.plugin.zsh b/build/build.plugin.zsh index 5a1510b..6a35643 100644 --- a/build/build.plugin.zsh +++ b/build/build.plugin.zsh @@ -17,46 +17,140 @@ elif [ `uname` = Darwin ]; then alias debug='lldb --' fi -# Store the path to `build-dir.py`, using `${0:a:h}` does not work in a -# function because it will result in `pwd` not this scripts directory. -_build_dir_py=${0:a:h}/build-dir.py - # Interactively choose a `~build` directory for `build` to build. -# TODO: Support arguments: -# * [ ] [-h,--help] - show this help message and exit -# * [x] [--build] - execute the build commend -# * [ ] - start in another directory, not `pwd` build-dir() { - # Get a unique filename to store the chosen build directory in. - [ `uname` = Darwin ] && local file=`mktemp` || local file=`tempfile` - # Prompt user to choose a build directory. - python $_build_dir_py $file; - local error=$? - # If the file exists, read the build directory from it, then delete it. - [ -f $file ] && local build_dir=$PWD/`cat $file`; rm $file - # If choosing a build directory failed, return that error. - [[ "$error" = "0" ]] || return $error - # If `build.ninja` exists in alias `ninja`, return. - [ -f $build_dir/build.ninja ] && \ - local build="ninja -C $build_dir" - # If `Makefile` exists in alias `make`, return. - if [ -f $build_dir/Makefile ]; then - [ `uname` = Darwin ] && \ - local cpu_count=`sysctl -n hw.ncpu` || - local cpu_count=`grep -c '^processor' /proc/cpuinfo` - local build="make -j $cpu_count -C $build_dir" + local usage='usage: build-dir [-h] [--build] []' + local -a help do_build + zparseopts -D h=help -help=help -build=do_build + if [[ -n $help ]]; then + cat << EOF +$usage + +Find and select the current build directory interactively. + +positional arguments: + the build directory to select + +optional arguments: + -h, --help show this help message and exit + --build invoke a build after selection +EOF + return fi - # If the build variable is not defined the command could not be determined. - if [ -z $build ]; then - # TODO: Prompt user to choose a build command? - echo "could not determine build command" - return 1 + error() { echo "\e[31merror:\e[0m $1"; return 1 } + local build_dir + if [[ ${#*} -gt 1 ]]; then + echo $usage + error "unexpected position arguments: ${*[2,${#*}]}" + elif [[ ${#*} -eq 1 ]]; then + build_dir=${*[1]} + [[ ! -d $build_dir ]] && \ + error "directory not found: $build_dir" + fi + + # If was not set begin selection + if [[ -z $build_dir ]]; then + # Find build directories + local -a build_dirs + for entry in `ls -A`; do + [ -d $entry ] && [[ $entry =~ build* ]] && \ + build_dirs+=${entry/\//} + done + + # Interactively select a build directory if more than 1 found + integer index=0 + if [[ ${#build_dirs} -eq 0 ]]; then + error "no build directories found" + elif [[ ${#build_dirs} -gt 1 ]]; then + zmodload zsh/curses && { + # Get the size of the terminal + local size=`stty size` + integer height=${size% *} + integer width=${size#* } + + # Create the window and hide the cursor + zcurses init + zcurses addwin build-dir $height $width 0 0 + + # Hide the cursor for zcurses, trap SIGINT to ensure cleanup in + # always-list occurs below + tput civis; trap 'return 130' INT + + # Enter display loop + local key keypad + while (( 1 )); do + zcurses clear build-dir + + # Add the prompt text + zcurses move build-dir 1 1 + zcurses string build-dir 'Select a build directory:' + + # Add the selections text + for (( i = 0; i < ${#build_dirs}; i++ )); do + integer line=$i+3 + zcurses move build-dir $line 1 + [[ $index -eq $i ]] && + zcurses string build-dir "* " || + zcurses string build-dir " " + zcurses string build-dir ${build_dirs[$i+1]} + done + + # Display the text the and wait for input + zcurses refresh build-dir + zcurses input build-dir key keypad + + # Handle user input + case $key in + (UP|k|$'\C-P') + [[ $index -gt 0 ]] && index=$index-1 ;; + (DOWN|j|$'\C-N') + [[ $index -lt ${#build_dirs}-1 ]] && index=$index+1 ;; + (ENTER|$'\n') + break ;; + esac + done + } always { + # Restore the cursor and cleanup zcurses + tput cvvis; tput cnorm + zcurses delwin build-dir + zcurses end + } + fi + fi + + # On success setup the build directory for use + if [[ $? -eq 0 ]]; then + # Set the build directory from selection if empty + [[ -z $build_dir ]] && \ + build_dir=${build_dirs[$index+1]} + + # If `build.ninja` exists in alias `ninja`, return. + local build + [ -f $build_dir/build.ninja ] && \ + build="ninja -C $build_dir" + + # If `Makefile` exists in alias `make`, return. + if [ -f $build_dir/Makefile ]; then + [ `uname` = Darwin ] && \ + local cpu_count=`sysctl -n hw.ncpu` || + local cpu_count=`grep -c '^processor' /proc/cpuinfo` + build="make -j $cpu_count -C $build_dir" + fi + + # If the build variable is not defined the command could not be determined + if [ -z $build ]; then + echo "\e[33mwarning:\e[0m build command detection failed: $build_dir" + # Prompt user to enter a build command + vared -p 'enter comand: ' build + fi + + # Redefine the `build` alias and update the `~build` hash directory + alias build="$build" + hash -d build=$build_dir + + # If `--build` is specified then evaluate the command. + [[ -n $do_build ]] && eval build fi - # Redefine the `build` alias and update the `~build` hash directory. - alias build="$build" - hash -d build=$build_dir - # If `--build` is specified then evaluate the command. - [[ "$1" = "--build" ]] && eval $build || true } # Build then run a target residing in `~build/bin`.