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] [<directory>]

Find and select the current build directory interactively.

positional arguments:
  <directory> the build directory to select

optional arguments:
  -h, --help  show this help message and exit
  --build     invoke a build after selection
```
This commit is contained in:
Kenneth Benzie 2018-08-23 10:29:11 +01:00
parent 087a315289
commit 3194afc80d
3 changed files with 138 additions and 38 deletions

View File

@ -16,6 +16,8 @@
- {src: zshrc, dst: ~/.zshrc} - {src: zshrc, dst: ~/.zshrc}
- src: prompt_fresh_setup - src: prompt_fresh_setup
dst: ~/.local/share/zsh/site-functions/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 - src: sandbox/_sandbox
dst: ~/.local/share/zsh/site-functions/_sandbox dst: ~/.local/share/zsh/site-functions/_sandbox
- src: layout/_layout - src: layout/_layout
@ -26,6 +28,4 @@
- https://github.com/zsh-users/zsh-autosuggestions.git - https://github.com/zsh-users/zsh-autosuggestions.git
- https://github.com/zsh-users/zsh-history-substring-search.git - https://github.com/zsh-users/zsh-history-substring-search.git
- https://github.com/zdharma/fast-syntax-highlighting.git - https://github.com/zdharma/fast-syntax-highlighting.git
- pip:
- pick
- message: zsh will be the default prompt after next login - message: zsh will be the default prompt after next login

6
build/_build-dir Normal file
View File

@ -0,0 +1,6 @@
#compdef build-dir
_arguments \
'(-h --help)'{-h,--help}'[]' \
'--build[invoke a build after selection]' \
'1:directory:_files'

View File

@ -17,46 +17,140 @@ elif [ `uname` = Darwin ]; then
alias debug='lldb --' alias debug='lldb --'
fi 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. # 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
# * [ ] <dir> - start in another directory, not `pwd`
build-dir() { build-dir() {
# Get a unique filename to store the chosen build directory in. local usage='usage: build-dir [-h] [--build] [<directory>]'
[ `uname` = Darwin ] && local file=`mktemp` || local file=`tempfile` local -a help do_build
# Prompt user to choose a build directory. zparseopts -D h=help -help=help -build=do_build
python $_build_dir_py $file; if [[ -n $help ]]; then
local error=$? cat << EOF
# If the file exists, read the build directory from it, then delete it. $usage
[ -f $file ] && local build_dir=$PWD/`cat $file`; rm $file
# If choosing a build directory failed, return that error. Find and select the current build directory interactively.
[[ "$error" = "0" ]] || return $error
# If `build.ninja` exists in alias `ninja`, return. positional arguments:
[ -f $build_dir/build.ninja ] && \ <directory> the build directory to select
local build="ninja -C $build_dir"
# If `Makefile` exists in alias `make`, return. optional arguments:
if [ -f $build_dir/Makefile ]; then -h, --help show this help message and exit
[ `uname` = Darwin ] && \ --build invoke a build after selection
local cpu_count=`sysctl -n hw.ncpu` || EOF
local cpu_count=`grep -c '^processor' /proc/cpuinfo` return
local build="make -j $cpu_count -C $build_dir"
fi fi
# If the build variable is not defined the command could not be determined. error() { echo "\e[31merror:\e[0m $1"; return 1 }
if [ -z $build ]; then local build_dir
# TODO: Prompt user to choose a build command? if [[ ${#*} -gt 1 ]]; then
echo "could not determine build command" echo $usage
return 1 error "unexpected position arguments: ${*[2,${#*}]}"
elif [[ ${#*} -eq 1 ]]; then
build_dir=${*[1]}
[[ ! -d $build_dir ]] && \
error "directory not found: $build_dir"
fi
# If <directory> 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 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`. # Build then run a target residing in `~build/bin`.