# A collection of commands to make it easier to build projects. # Default `build` alias to select a `build-dir` then invoke a build, using an # alias means the configured build command's completion works out of the box. alias build="build-dir --build" # Detect installed debugger and set the `debug` alias to debug a program with # command line arguments. if [ `uname` = Linux ]; then if [[ "`vim --version`" =~ "^VIM - Vi IMproved 8\.1.*$" ]]; then autoload -U regexp-replace function vimdebug() { # For each item in $* replace * and \* and then replace \ with \\ local args=() for arg in "$@"; do regexp-replace arg '\*' '\\*' args+=($arg) done vim "+packadd termdebug" "+TermdebugCommand $args" } alias debug='vimdebug' elif which cgdb &> /dev/null; then alias debug='cgdb --args' elif which gdb &> /dev/null; then alias debug='gdb --args' fi elif [ `uname` = Darwin ]; then which lldb &> /dev/null && \ alias debug='lldb --' fi # Interactively choose a `~build` directory for `build` to build. 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 error() { echo "\e[31merror:\e[0m $1" } warning() { echo "\e[33mwarning:\e[0m $1" } local local_build_dir if [[ ${#*} -gt 1 ]]; then echo $usage error "unexpected position arguments: ${*[2,${#*}]}"; return 1 elif [[ ${#*} -eq 1 ]]; then if [[ ! -d ${*[1]} ]]; then warning "directory not found: ${*[1]}" else local_build_dir=${*[1]} fi fi # If was not set begin selection if [[ -z $local_build_dir ]]; then # Find build directories local -a local_build_dirs for entry in `ls -A`; do [ -d $entry ] && [[ $entry =~ build* ]] && \ local_build_dirs+=${entry/\//} done # Interactively select a build directory if more than 1 found integer index=0 if [[ ${#local_build_dirs} -eq 0 ]]; then error "no build directories found"; return 1 elif [[ ${#local_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 < ${#local_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 ${local_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 ${#local_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 $local_build_dir ]] && \ local_build_dir=${local_build_dirs[$index+1]} # If `build.ninja` exists in alias `ninja`, return. local build [ -f $local_build_dir/build.ninja ] && \ build="ninja -C $local_build_dir" # If `Makefile` exists in alias `make`, return. if [ -f $local_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 $local_build_dir" fi # If the build variable is not defined the command could not be determined if [ -z $build ]; then warning "build command detection failed: $local_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=$local_build_dir export build_dir=$local_build_dir # If `--build` is specified then evaluate the command. if [[ -n $do_build ]]; then eval build fi fi } # Build then run a target residing in `~build/bin`. build-run() { local target=$1; shift 1 eval build $target && ~build/bin/$target "$@" } # Build then debug a target residing in `~build/bin`. build-debug() { local target=$1; shift 1 eval build $target && debug ~build/bin/$target "$@" }