Press Ctrl-B to fuzzy find all configuration CMake variables for the current build directory. Once a variable is selected, rewrite the command-line to set the selected CMake variable.
230 lines
6.8 KiB
Bash
230 lines
6.8 KiB
Bash
# 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
|
|
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
|
|
nvim "+packadd termdebug" "+TermdebugCommand $args"
|
|
}
|
|
if command -v nvim &> /dev/null; then
|
|
alias debug=vimdebug
|
|
elif command -v gdb &> /dev/null; then
|
|
alias debug='gdb --args'
|
|
fi
|
|
elif [ `uname` = Darwin ]; then
|
|
command -v 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] [<directory>]'
|
|
local -a help show do_build
|
|
zparseopts -D h=help -help=help s=show -show=show -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
|
|
-s, --show show the current build directory
|
|
--build invoke a build after selection
|
|
EOF
|
|
return
|
|
fi
|
|
error() { echo "\e[31merror:\e[0m $1" }
|
|
warning() { echo "\e[33mwarning:\e[0m $1" }
|
|
if [[ -n $show ]]; then
|
|
if [[ ! -n $build_dir ]]; then
|
|
error "build directory not set"
|
|
return 1
|
|
else
|
|
echo "$build_dir"
|
|
return
|
|
fi
|
|
fi
|
|
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 <directory> 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} -eq 1 ]]; then
|
|
local_build_dir=${local_build_dirs[1]}
|
|
elif [[ ${#local_build_dirs} -gt 1 ]]; then
|
|
if command -v fzf &> /dev/null; then
|
|
# Use fzf to select a build directory
|
|
local max=$(( $( tput lines ) / 2 ))
|
|
local best=$(( ${#local_build_dirs} + 4 ))
|
|
local_build_dir=$(
|
|
printf '%s\n' "${local_build_dirs[@]}" |
|
|
fzf --layout=reverse --tac --info=hidden --border=rounded \
|
|
--cycle --height=$(( $best < $max ? $best : $max ))
|
|
)
|
|
if [[ $? -ne 0 ]]; then
|
|
return 1
|
|
fi
|
|
else
|
|
# Fallback to zcurses selector when fzf is not available
|
|
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
|
|
}
|
|
|
|
# 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]}
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# 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
|
|
}
|
|
|
|
# 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 "$@"
|
|
}
|
|
|
|
# Fuzzy find CMake variables, select one to set the variable via a command.
|
|
.build-var() {
|
|
if [[ ! -n $build_dir ]]; then
|
|
build-dir
|
|
fi
|
|
local var=$(
|
|
cat $build_dir/CMakeCache.txt |
|
|
grep --color=never -Ex '^\w+:\w+=.*$' |
|
|
fzf --layout=reverse --info=hidden --border=rounded \
|
|
--cycle --height=50%
|
|
)
|
|
if [[ -n "$var" ]]; then
|
|
BUFFER="cmake -B\$build_dir -D$var"
|
|
zle end-of-line
|
|
fi
|
|
zle reset-prompt
|
|
}
|
|
zle -N .build-var
|
|
bindkey '^B' .build-var
|