M README.md => README.md +1 -1
@@ 52,7 52,7 @@ Livecoding terminal UI: The above, plus ncurses (or compatible curses library),
## Build
-The build script, called simply `tool`, is written in `bash`. It should work with `gcc` (including the `musl-gcc` wrapper), `tcc`, and `clang`, and will automatically detect your compiler. You can manually specify a compiler with the `-c` option.
+The build script, called simply `tool`, is written in POSIX `sh`. It should work with `gcc` (including the `musl-gcc` wrapper), `tcc`, and `clang`, and will automatically detect your compiler. You can manually specify a compiler with the `-c` option.
Currently known to build on macOS (`gcc`, `clang`, `tcc`) and Linux (`gcc`, `musl-gcc`, `tcc`, and `clang`, optionally with `LLD`), and Windows via cygwin or WSL (`gcc` or `clang`, `tcc` untested).
M term_util.c => term_util.c +55 -36
@@ 70,55 70,66 @@ void qnav_deinit() {
while (qnav_stack.top)
qnav_stack_pop();
}
+// Set new y and x coordinates for the top and left of a Qblock based on the
+// position of the Qblock "below" it in the stack. (Below meaning its order in
+// the stack, not vertical position on a Y axis.) The target Qblock should
+// already be inserted into the stack somewhere, so don't call this before
+// you've finished doing the rest of the setup on the Qblock. The y and x
+// fields can be junk, though, since this function writes to them without
+// reading them.
+static ORCA_NOINLINE void qnav_reposition_block(Qblock *qb) {
+ int top = 0, left = 0;
+ Qblock *prev = qb->down;
+ if (!prev)
+ goto done;
+ int total_h, total_w;
+ getmaxyx(qb->outer_window, total_h, total_w);
+ WINDOW *w = prev->outer_window;
+ int prev_y = prev->y, prev_x = prev->x, prev_h, prev_w;
+ getmaxyx(w, prev_h, prev_w);
+ // Start by trying to position the item to the right of the previous item.
+ left = prev_x + prev_w + 0;
+ int term_h, term_w;
+ getmaxyx(stdscr, term_h, term_w);
+ // Check if we'll run out of room if we position the new item to the right
+ // of the existing item (with the same Y position.)
+ if (left + total_w > term_w) {
+ // If we have enough room if we position just below the previous item in
+ // the stack, do that instead of positioning to the right of it.
+ if (prev_x + total_w <= term_w && total_h < term_h - (prev_y + prev_h)) {
+ top = prev_y + prev_h;
+ left = prev_x;
+ }
+ // If the item doesn't fit there, but it's less wide than the terminal,
+ // right-align it to the edge of the terminal.
+ else if (total_w < term_w) {
+ left = term_w - total_w;
+ }
+ // Otherwise, just start the layout over at Y=0,X=0
+ else {
+ left = 0;
+ }
+ }
+done:
+ qb->y = top;
+ qb->x = left;
+}
static ORCA_NOINLINE void qnav_stack_push(Qblock *qb, int height, int width) {
#ifndef NDEBUG
for (Qblock *i = qnav_stack.top; i; i = i->down) {
assert(i != qb);
}
#endif
- int top = 0, left = 0;
int total_h = height + 2, total_w = width + 2;
- if (qnav_stack.top) {
- WINDOW *w = qnav_stack.top->outer_window;
- int prev_y, prev_x, prev_h, prev_w;
- getbegyx(w, prev_y, prev_x);
- getmaxyx(w, prev_h, prev_w);
- // Start by trying to position the item to the right of the previous item.
- left = prev_x + prev_w + 0;
- int term_h, term_w;
- getmaxyx(stdscr, term_h, term_w);
- // Check if we'll run out of room if we position the new item to the right
- // of the existing item (with the same Y position.)
- if (left + total_w > term_w) {
- // If we have enough room if we position just below the previous item in
- // the stack, do that instead of positioning to the right of it.
- if (prev_x + total_w <= term_w && total_h < term_h - (prev_y + prev_h)) {
- top = prev_y + prev_h;
- left = prev_x;
- }
- // If the item doesn't fit there, but it's less wide than the terminal,
- // right-align it to the edge of the terminal.
- else if (total_w < term_w) {
- left = term_w - total_w;
- }
- // Otherwise, just start the layout over at Y=0,X=0
- else {
- left = 0;
- }
- }
+ if (qnav_stack.top)
qnav_stack.top->up = qb;
- } else {
+ else
qnav_stack.bottom = qb;
- }
qb->down = qnav_stack.top;
qnav_stack.top = qb;
qb->outer_window = newpad(total_h, total_w);
- // This used to be derwin when when used newwin instead of newpad -- not sure
- // if we should use derwin or subpad now. subpad is probably more compatible.
- // ncurses docs state that it handles it correctly, unlike some others?
qb->content_window = subpad(qb->outer_window, height, width, 1, 1);
- qb->y = top;
- qb->x = left;
+ qnav_reposition_block(qb);
qnav_stack.occlusion_dirty = true;
}
@@ 216,6 227,14 @@ done:
return drew_any;
}
+void qnav_adjust_term_size(void) {
+ if (!qnav_stack.bottom)
+ return;
+ for (Qblock *qb = qnav_stack.bottom; qb; qb = qb->up)
+ qnav_reposition_block(qb);
+ qnav_stack.occlusion_dirty = true;
+}
+
void qblock_print_border(Qblock *qb, unsigned int attr) {
wborder(qb->outer_window, ACS_VLINE | attr, ACS_VLINE | attr,
ACS_HLINE | attr, ACS_HLINE | attr, ACS_ULCORNER | attr,
M term_util.h => term_util.h +1 -0
@@ 120,6 120,7 @@ void qnav_deinit(void);
Qblock *qnav_top_block(void);
void qnav_stack_pop(void);
bool qnav_draw(void); // also clear qnav_stack.occlusion_dirty
+void qnav_adjust_term_size(void);
void qblock_print_frame(Qblock *qb, bool active);
void qblock_set_title(Qblock *qb, char const *title);
M tool => tool +208 -212
@@ 1,5 1,5 @@
-#!/usr/bin/env bash
-set -eu -o pipefail
+#!/bin/sh
+set -euf
print_usage() {
cat <<EOF
@@ 40,8 40,12 @@ Optional Features:
EOF
}
-if [[ -z "${1:-}" ]]; then
- echo "Error: Command required" >&2
+warn() { printf 'Warning: %s\n' "$*" >&2; }
+fatal() { printf 'Error: %s\n' "$*" >&2; exit 1; }
+script_error() { printf 'Script error: %s\n' "$*" >&2; exit 1; }
+
+if [ -z "${1:-}" ]; then
+ printf 'Error: Command required\n' >&2
print_usage >&2
exit 1
fi
@@ 49,18 53,17 @@ fi
cmd=$1
shift
-os=
case $(uname -s | awk '{print tolower($0)}') in
linux*) os=linux;;
darwin*) os=mac;;
cygwin*) os=cygwin;;
*bsd*) os=bsd;;
- *) os=unknown;;
+ *) os=unknown; warn "Build script not tested on this platform";;
esac
cc_exe="${CC:-cc}"
-if [[ $os = cygwin ]]; then
+if [ $os = cygwin ]; then
# Under cygwin, specifically ignore the mingw compilers if they're set as the
# CC environment variable. This may be the default from the cygwin installer.
# But we want to use 'gcc' from the cygwin gcc-core package (probably aliased
@@ 74,8 77,7 @@ if [[ $os = cygwin ]]; then
# happens. So we'll just explicitly set it to gcc. This might mess up people
# who have clang installed but not gcc, I guess? Is that even possible?
case $cc_exe in
- i686-w64-mingw32-gcc.exe|\
- x86_64-w64-mingw32-gcc.exe)
+ i686-w64-mingw32-gcc.exe|x86_64-w64-mingw32-gcc.exe)
cc_exe=gcc;;
esac
fi
@@ 90,151 92,138 @@ mouse_disabled=0
config_mode=release
while getopts c:dhsv-: opt_val; do
- case "$opt_val" in
- -)
- case "$OPTARG" in
- harden) protections_enabled=1;;
- help) print_usage; exit 0;;
- static) static_enabled=1;;
- pie) pie_enabled=1;;
- portmidi) portmidi_enabled=1;;
- no-portmidi|noportmidi) portmidi_enabled=0;;
- mouse) mouse_disabled=0;;
- no-mouse|nomouse) mouse_disabled=1;;
- *)
- echo "Unknown long option --$OPTARG" >&2
- print_usage >&2
- exit 1
- ;;
- esac
- ;;
- c) cc_exe="$OPTARG";;
+ case $opt_val in
+ -) case $OPTARG in
+ harden) protections_enabled=1;;
+ help) print_usage; exit 0;;
+ static) static_enabled=1;;
+ pie) pie_enabled=1;;
+ portmidi) portmidi_enabled=1;;
+ no-portmidi|noportmidi) portmidi_enabled=0;;
+ mouse) mouse_disabled=0;;
+ no-mouse|nomouse) mouse_disabled=1;;
+ *) printf 'Unknown option --%s\n' "$OPTARG" >&2; exit 1;;
+ esac;;
+ c) cc_exe=$OPTARG;;
d) config_mode=debug;;
h) print_usage; exit 0;;
s) stats_enabled=1;;
v) verbose=1;;
\?) print_usage >&2; exit 1;;
- *) break;;
esac
done
-arch=
case $(uname -m) in
x86_64) arch=x86_64;;
*) arch=unknown;;
esac
-warn() {
- echo "Warning: $*" >&2
-}
-fatal() {
- echo "Error: $*" >&2
- exit 1
-}
-script_error() {
- echo "Script error: $*" >&2
- exit 1
-}
-
verbose_echo() {
- if [[ $verbose = 1 ]]; then
- echo "$@"
+ # Don't print 'timed_stats' if it's the first part of the command
+ if [ $verbose = 1 ] && [ $# -gt 1 ]; then
+ printf '%s ' "$@" | sed -E -e 's/^timed_stats[[:space:]]+//' -e 's/ $//' \
+ | tr -d '\n'
+ printf '\n'
fi
"$@"
}
-TIMEFORMAT='%3R'
-
-last_time=
-
file_size() {
wc -c < "$1" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
}
+timed_stats_result=
timed_stats() {
- if [[ $stats_enabled = 1 ]]; then
- { last_time=$( { time "$@" 1>&3- 2>&4-; } 2>&1 ); } 3>&1 4>&2
+ if [ $stats_enabled = 1 ] && command -v time >/dev/null 2>&1; then
+ TIMEFORMAT='%3R'
+ { timed_stats_result=$( { time "$@" 1>&3- 2>&4-; } 2>&1 ); } 3>&1 4>&2
else
"$@"
fi
}
-version_string_normalized() {
- echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }';
+normalized_version() {
+ printf '%s\n' "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }';
}
-if [[ ($os == unknown) ]]; then
- warn "Build script not tested on this platform"
-fi
-
-# This is not perfect by any means
cc_id=
cc_vers=
lld_detected=0
-if cc_vers=$(echo -e '#ifndef __clang__\n#error Not found\n#endif\n__clang_major__.__clang_minor__.__clang_patchlevel__' | "$cc_exe" -E -xc - 2>/dev/null | tail -n 1 | tr -d '\040'); then
- cc_id=clang
- # Mac clang/llvm doesn't say the real version of clang. Just assume it's 3.9.0
- if [[ $os == mac ]]; then
- cc_vers=3.9.0
- else
- if command -v "lld" >/dev/null 2>&1; then
- lld_detected=1
- fi
- fi
-elif cc_vers=$(echo -e '#ifndef __GNUC__\n#error Not found\n#endif\n__GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__' | "$cc_exe" -E -xc - 2>/dev/null | tail -n 1 | tr -d '\040'); then
- cc_id=gcc
-elif cc_vers=$(echo -e '#ifndef __TINYC__\n#error Not found\n#endif\n__TINYC__' | "$cc_exe" -E -xc - 2>/dev/null | tail -n 1 | tr -d '\040'); then
- cc_id=tcc
+lld_name=lld
+if preproc_result=$( \
+ ("$cc_exe" -E -xc - 2>/dev/null | tail -n 2 | tr -d '\040') <<EOF
+#if defined(__clang__)
+clang
+__clang_major__.__clang_minor__.__clang_patchlevel__
+#elif defined(__GNUC__)
+gcc
+__GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__
+#elif defined(__TINYC__)
+tcc
+__TINYC__
+#else
+#error Unknown compiler
+#endif
+EOF
+); then
+ cc_id=$(printf %s "$preproc_result" | head -n 1)
+ cc_vers=$(printf %s "$preproc_result" | tail -n 1)
fi
-if [[ -z $cc_id ]]; then
- warn "Failed to detect compiler type"
-fi
-if [[ -z $cc_vers ]]; then
- warn "Failed to detect compiler version"
+if [ "$cc_id" = clang ]; then
+ case $os in
+ # Mac clang/llvm doesn't say the real version of clang. Assume it's 3.9.0.
+ mac) cc_vers=3.9.0;;
+ *)
+ # Debian names versions clang like "clang-9" and also LLD like "lld-9".
+ # To tell clang to use LLD, we have to pass an argument like
+ # '-fuse-ld=lld'. You would expect that the Debian versions of clang,
+ # like clang-9, would want '-fuse-ld=lld-9', but it seems to work both as
+ # '-fuse-ld=lld-' and also as '-fuse-ld=lld'. I'm not sure if this holds
+ # true if multiple versions of clang are installed.
+ if output=$(printf %s "$cc_exe" | awk -F- '
+ /^clang\+?\+?-/ && $NF ~ /^[0-9]+$/ { a=$NF }
+ END { if (a == "") exit -1; printf("lld-%s", a) }'); then
+ lld_name=$output
+ fi
+ if command -v "$lld_name" >/dev/null 2>&1; then lld_detected=1; fi
+ ;;
+ esac
fi
+test -z "$cc_id" && warn "Failed to detect compiler type"
+test -z "$cc_vers" && warn "Failed to detect compiler version"
+
+cc_vers_normalized=$(normalized_version "$cc_vers")
+
cc_vers_is_gte() {
- if [[ $(version_string_normalized "$cc_vers") -ge $(version_string_normalized "$1") ]]; then
- return 0
- else
- return 1
- fi
+ test "$cc_vers_normalized" -ge "$(normalized_version "$1")"
}
cc_id_and_vers_gte() {
- if [[ $cc_id == "$1" ]] && cc_vers_is_gte "$2"; then
- return 0
- else
- return 1
- fi
+ test "$cc_id" = "$1" && cc_vers_is_gte "$2"
}
+# Append arguments to a string, separated by newlines. Like a bad array.
add() {
- if [[ -z "${1:-}" ]]; then
- script_error "At least one argument required for array add"
+ if [ -z "${1:-}" ]; then
+ script_error "At least one argument required for add"
fi
- local array_name
- array_name=${1}
+ _add_name=${1}
shift
- eval "$array_name+=($(printf "'%s' " "$@"))"
-}
-
-concat() {
- if [[ -z "${1:-}" || -z "${2:-}" ]]; then
- script_error "Two arguments required for array concat"
- fi
- local lhs_name
- local rhs_name
- lhs_name=${1}
- rhs_name=${2}
- eval "$lhs_name+=(\"\${${rhs_name}[@]}\")"
+ while [ -n "${1+x}" ]; do
+ # shellcheck disable=SC2034
+ _add_hidden=$1
+ eval "$_add_name"'=$(printf '"'"'%s\n%s.'"' "'"$'"$_add_name"'" "$_add_hidden")'
+ eval "$_add_name"'=${'"$_add_name"'%.}'
+ shift
+ done
}
try_make_dir() {
- if ! [[ -e "$1" ]]; then
+ if ! [ -e "$1" ]; then
verbose_echo mkdir "$1"
- elif ! [[ -d "$1" ]]; then
+ elif ! [ -d "$1" ]; then
fatal "File $1 already exists but is not a directory"
fi
}
@@ 242,10 231,10 @@ try_make_dir() {
build_dir=build
build_target() {
- local cc_flags=()
- local libraries=()
- local source_files=()
- local out_exe
+ cc_flags=
+ libraries=
+ source_files=
+ out_exe=
add cc_flags -std=c99 -pipe -finput-charset=UTF-8 -Wall -Wpedantic -Wextra \
-Wwrite-strings
if cc_id_and_vers_gte gcc 6.0.0 || cc_id_and_vers_gte clang 3.9.0; then
@@ 253,10 242,10 @@ build_target() {
-Werror=implicit-function-declaration -Werror=implicit-int \
-Werror=incompatible-pointer-types -Werror=int-conversion
fi
- if [[ $cc_id = tcc ]]; then
+ if [ "$cc_id" = tcc ]; then
add cc_flags -Wunsupported
fi
- if [[ $os = mac && $cc_id = clang ]]; then
+ if [ $os = mac ] && [ "$cc_id" = clang ]; then
# The clang that's shipped with Mac 10.12 has bad behavior for issuing
# warnings for structs initialed with {0} in C99. We have to disable this
# warning, or it will issue a bunch of useless warnings. It might be fixed
@@ 264,26 253,26 @@ build_target() {
# indecipherable, so we'll just always turn it off.
add cc_flags -Wno-missing-field-initializers
fi
- if [[ $lld_detected = 1 ]]; then
- add cc_flags -fuse-ld=lld
+ if [ $lld_detected = 1 ]; then
+ add cc_flags "-fuse-ld=$lld_name"
fi
- if [[ $protections_enabled = 1 ]]; then
+ if [ $protections_enabled = 1 ]; then
add cc_flags -D_FORTIFY_SOURCE=2 -fstack-protector-strong
fi
- if [[ $pie_enabled = 1 ]]; then
+ if [ $pie_enabled = 1 ]; then
add cc_flags -pie -fpie -Wl,-pie
# Only explicitly specify no-pie if cc version is new enough
elif cc_id_and_vers_gte gcc 6.0.0 || cc_id_and_vers_gte clang 6.0.0; then
add cc_flags -no-pie -fno-pie
fi
- if [[ $static_enabled = 1 ]]; then
+ if [ $static_enabled = 1 ]; then
add cc_flags -static
fi
case $config_mode in
debug)
add cc_flags -DDEBUG -ggdb
- # cygwin gcc doesn't seem to have this stuff, just elide for now
- if [[ $os != cygwin ]]; then
+ # cygwin gcc doesn't seem to have this stuff, so just elide for now
+ if [ $os != cygwin ]; then
if cc_id_and_vers_gte gcc 6.0.0 || cc_id_and_vers_gte clang 3.9.0; then
add cc_flags -fsanitize=address -fsanitize=undefined \
-fsanitize=float-divide-by-zero
@@ 293,63 282,50 @@ build_target() {
-fsanitize=unsigned-integer-overflow
fi
fi
- if [[ $os = mac ]]; then
- # Our mac clang does not have -Og
- add cc_flags -O1
- else
- add cc_flags -Og
- # needed if address is already specified? doesn't work on mac clang, at
- # least
- # add cc_flags -fsanitize=leak
- fi
+ case $os in
+ mac) add cc_flags -O1;; # Our Mac clang does not have -Og
+ *) add cc_flags -Og;;
+ esac
case $cc_id in
tcc) add cc_flags -g -bt10;;
esac
- ;;
+ ;;
release)
add cc_flags -DNDEBUG -O2 -g0
- if [[ $protections_enabled != 1 ]]; then
+ if [ $protections_enabled != 1 ]; then
add cc_flags -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
case $cc_id in
- gcc|clang) add cc_flags -fno-stack-protector;;
+ gcc|clang) add cc_flags -fno-stack-protector
esac
fi
- if [[ $os = mac ]]; then
- # todo some stripping option
- true
- else
- # -flto is good on both clang and gcc on Linux
- case $cc_id in
- gcc|clang)
- if [[ $os != bsd ]]; then
- add cc_flags -flto
- fi
- esac
- add cc_flags -s
- fi
- ;;
+ # -flto is good on both clang and gcc on Linux and Cygwin. Not supported
+ # on BSD, and no improvement on Mac. -s gives an obsolescence warning on
+ # Mac. For tcc, -flto gives and unsupported warning, and -s is ignored.
+ case $cc_id in gcc|clang) case $os in
+ linux|cygwin) add cc_flags -flto -s;;
+ bsd) add cc_flags -s;;
+ esac esac
+ ;;
*) fatal "Unknown build config \"$config_mode\"";;
esac
case $arch in
x86_64)
- # 'nehalem' tuning actually produces faster code for orca than later
- # archs, for both gcc and clang, even if it's running on a later arch
- # CPU. This is likely due to smaller emitted code size. gcc earlier than
- # 4.9 does not recognize the arch flag for it it, though, and I haven't
- # tested a compiler that old, so I don't know what optimization behavior
- # we get with it is. Just leave it at default, in that case.
case $cc_id in
+ # 'nehalem' tuning actually produces faster code for orca than later
+ # archs, for both gcc and clang, even if it's running on a later arch
+ # CPU. This is likely due to smaller emitted code size. gcc earlier
+ # than 4.9 does not recognize the arch flag for it it, though, and I
+ # haven't tested a compiler that old, so I don't know what optimization
+ # behavior we get with it is. Just leave it at default, in that case.
gcc)
if cc_vers_is_gte 4.9; then
add cc_flags -march=nehalem
fi
- ;;
- clang)
- add cc_flags -march=nehalem
- ;;
+ ;;
+ clang) add cc_flags -march=nehalem;;
esac
- ;;
+ ;;
esac
add source_files gbuffer.c field.c vmio.c sim.c
@@ 357,7 333,7 @@ build_target() {
cli)
add source_files cli_main.c
out_exe=cli
- ;;
+ ;;
orca|tui)
add source_files osc_out.c term_util.c sysmisc.c thirdparty/oso.c tui_main.c
add cc_flags -D_XOPEN_SOURCE_EXTENDED=1
@@ 369,14 345,14 @@ build_target() {
out_exe=orca
case $os in
mac)
- local brew_prefix=
if ! brew_prefix=$(printenv HOMEBREW_PREFIX); then
- brew_prefix=/usr/local/
+ brew_prefix=/usr/local
fi
- local ncurses_dir="$brew_prefix/opt/ncurses"
- if ! [[ -d "$ncurses_dir" ]]; then
- echo "Error: ncurses directory not found at $ncurses_dir" >&2
- echo "Install with: brew install ncurses" >&2
+ ncurses_dir="$brew_prefix/opt/ncurses"
+ if ! [ -d "$ncurses_dir" ]; then
+ printf 'Error: ncurses directory not found at %s\n' \
+ "$ncurses_dir" >&2
+ printf 'Install with: brew install ncurses\n' >&2
exit 1
fi
# prefer homebrew version of ncurses if installed. Will give us
@@ 384,11 360,12 @@ build_target() {
add libraries "-L$ncurses_dir/lib"
add cc_flags "-I$ncurses_dir/include"
# todo mach time stuff for mac?
- if [[ $portmidi_enabled = 1 ]]; then
- local portmidi_dir="$brew_prefix/opt/portmidi"
- if ! [[ -d "$portmidi_dir" ]]; then
- echo "Error: PortMidi directory not found at $portmidi_dir" >&2
- echo "Install with: brew install portmidi" >&2
+ if [ $portmidi_enabled = 1 ]; then
+ portmidi_dir="$brew_prefix/opt/portmidi"
+ if ! [ -d "$portmidi_dir" ]; then
+ printf 'Error: PortMidi directory not found at %s\n' \
+ "$portmidi_dir" >&2
+ printf 'Install with: brew install portmidi\n' >&2
exit 1
fi
add libraries "-L$portmidi_dir/lib"
@@ 398,7 375,7 @@ build_target() {
add cc_flags -DORCA_OS_MAC
;;
bsd)
- if [[ $portmidi_enabled = 1 ]]; then
+ if [ $portmidi_enabled = 1 ]; then
add libraries "-L/usr/local/lib"
add cc_flags "-I/usr/local/include"
fi
@@ 413,11 390,12 @@ build_target() {
# as a separate library that explicitly needs to be linked, or it might
# not. And if it does, it might need to be either -ltinfo or -ltinfow.
# Yikes. If this is Linux, let's try asking pkg-config what it thinks.
- local curses_flags=0
- if [[ $os == linux ]]; then
+ curses_flags=0
+ if [ $os = linux ]; then
if curses_flags=$(pkg-config --libs ncursesw formw 2>/dev/null); then
- # split by spaces into separate args, then append to array
- IFS=" " read -r -a libraries <<< "$curses_flags"
+ # Split by spaces intentionall
+ # shellcheck disable=SC2086
+ IFS=' ' add libraries $curses_flags
curses_flags=1
else
curses_flags=0
@@ 425,44 403,60 @@ build_target() {
fi
# If we didn't get the flags by pkg-config, just guess. (This will work
# most of the time, including on Mac with Homebrew, and cygwin.)
- if [[ $curses_flags = 0 ]]; then
+ if [ $curses_flags = 0 ]; then
add libraries -lncursesw -lformw
fi
- if [[ $portmidi_enabled = 1 ]]; then
+ if [ $portmidi_enabled = 1 ]; then
add libraries -lportmidi
add cc_flags -DFEAT_PORTMIDI
- if [[ $config_mode = debug ]]; then
- echo -e "Warning: The PortMidi library contains code that may trigger address sanitizer in debug builds.\\nThese are not bugs in orca." >&2
+ if [ $config_mode = debug ]; then
+ cat >&2 <<EOF
+Warning: The PortMidi library contains code that may trigger address sanitizer
+in debug builds. These are probably not bugs in orca.
+EOF
fi
fi
- if [[ $mouse_disabled = 1 ]]; then
+ if [ $mouse_disabled = 1 ]; then
add cc_flags -DFEAT_NOMOUSE
fi
- ;;
+ ;;
*)
- echo -e "Unknown build target '$1'\\nValid targets: orca, cli" >&2
+ printf 'Unknown build target %s\nValid build targets: %s\n' \
+ "$1" 'orca, cli' >&2
exit 1
- ;;
+ ;;
esac
try_make_dir "$build_dir"
- if [[ $config_mode = debug ]]; then
+ if [ $config_mode = debug ]; then
build_dir=$build_dir/debug
try_make_dir "$build_dir"
fi
- local out_path=$build_dir/$out_exe
- # bash versions quirk: empty arrays might give error on expansion, use +
- # trick to avoid expanding second operand
- verbose_echo timed_stats "$cc_exe" "${cc_flags[@]}" -o "$out_path" "${source_files[@]}" ${libraries[@]+"${libraries[@]}"}
- if [[ $stats_enabled = 1 ]]; then
- echo "time: $last_time"
- echo "size: $(file_size "$out_path")"
+ out_path=$build_dir/$out_exe
+ IFS='
+'
+ # shellcheck disable=SC2086
+ verbose_echo timed_stats "$cc_exe" $cc_flags -o "$out_path" $source_files $libraries
+ compile_ok=$?
+ if [ $stats_enabled = 1 ]; then
+ if [ -n "$timed_stats_result" ]; then
+ printf '%s\n' "time: $timed_stats_result"
+ else
+ printf '%s\n' "time: unavailable (missing 'time' command)"
+ fi
+ if [ $compile_ok = 0 ]; then
+ printf '%s\n' "size: $(file_size "$out_path")"
+ fi
fi
}
print_info() {
- local linker_name
- if [[ $lld_detected = 1 ]]; then
+ if [ $lld_detected = 1 ]; then
linker_name=LLD
+ # Not sure if we should always print the specific LLD name or not. Or never
+ # print it.
+ if [ "$lld_name" != lld ]; then
+ linker_name="$linker_name ($lld_name)"
+ fi
else
linker_name=default
fi
@@ 480,36 474,38 @@ shift $((OPTIND - 1))
case $cmd in
info)
- if [[ "$#" -gt 1 ]]; then
- fatal "Too many arguments for 'info'"
- fi
- print_info; exit 0;;
+ test "$#" -gt 1 && fatal "Too many arguments for 'info'"
+ print_info; exit 0
+ ;;
build)
- if [[ "$#" -lt 1 ]]; then
- fatal "Too few arguments for 'build'"
- fi
- if [[ "$#" -gt 1 ]]; then
- echo "Too many arguments for 'build'" >&2
- echo "The syntax has changed. Updated usage examples:" >&2
- echo "./tool build --portmidi orca (release)" >&2
- echo "./tool build -d orca (debug)" >&2
+ test "$#" -lt 1 && fatal "Too few arguments for 'build'"
+ if [ "$#" -gt 1 ]; then
+ cat >&2 <<EOF
+Too many arguments for 'build'
+The syntax has changed. Updated usage examples:
+./tool build --portmidi orca (release)
+./tool build -d orca (debug)
+EOF
exit 1
fi
build_target "$1"
- ;;
+ ;;
clean)
- if [[ -d "$build_dir" ]]; then
- verbose_echo rm -rf "$build_dir"
+ if [ -d "$build_dir" ]; then
+ verbose_echo rm -rf "$build_dir";
fi
- ;;
- help) print_usage; exit 0;;
- -*)
- echo "The syntax has changed for the 'tool' build script." >&2
- echo "The options now need to come after the command name." >&2
- echo "Do it like this instead:" >&2
- echo "./tool build --portmidi orca" >&2
+ ;;
+ help)
+ print_usage; exit 0
+ ;;
+ -*) cat >&2 <<EOF
+The syntax has changed for the 'tool' build script.
+The options now need to come after the command name.
+Do it like this instead:
+./tool build --portmidi orca
+EOF
exit 1
- ;;
+ ;;
*) fatal "Unrecognized command $cmd";;
esac
M tui_main.c => tui_main.c +1 -0
@@ 3523,6 3523,7 @@ event_loop:;
}
case KEY_RESIZE:
tui_adjust_term_size(&t, &cont_window);
+ qnav_adjust_term_size();
goto event_loop;
#ifndef FEAT_NOMOUSE
case KEY_MOUSE: {