From 3194afc80d67c94f38d4f05e9477275ed49403da Mon Sep 17 00:00:00 2001 From: "Kenneth Benzie (Benie)" Date: Thu, 23 Aug 2018 10:29:11 +0100 Subject: [PATCH] Replace build-dir.py with zcurses build-dir Update the build-dir shell function to usage zcurses instead of the Python pick package to interactively select build directories, this results in a more responsive user experience. Add argument parsing to handle various use cases. Add prompt when the build command for the selected build directory could not be detected, allowing the user to specify the desired build command. ``` usage: build-dir [-h] [--build] [] 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 ``` --- .conduit.yaml | 4 +- build/_build-dir | 6 ++ build/build.plugin.zsh | 166 ++++++++++++++++++++++++++++++++--------- 3 files changed, 138 insertions(+), 38 deletions(-) create mode 100644 build/_build-dir 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`.