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: 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

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 --'
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
# * [ ] <dir> - 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] [<directory>]'
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:
<directory> 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 <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
# 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`.