Skip to content

Commit e033875

Browse files
committed
core: Preserve true line endings in @go.printf
Closes #146. Works by adding the ASCII Unit Separator character after every newline character and using it as the delimiter for `read`. This way output that shouldn't end with a newline won't. Seems to add about 0.003-0.005s to the time on average as measured by: time COLUMNS=<N> ./go help builtins regardless of the value of `<N>` used to set `COLUMNS`. Also measurably faster than the alternate methods of: - counting the total number of characters printed and only emitting a newline if the number of `result` characters hasn't been reached - counting the number of lines and only emitting a newline if the current line number is less than or equal to the length of `${result//[^$'\n']}` Also includes an update to `libexec/get.d/file` to fix a test broken by this new behavior, as it previously depended upon the old behavior to add a newline by default.
1 parent 5ff82ac commit e033875

File tree

3 files changed

+15
-8
lines changed

3 files changed

+15
-8
lines changed

go-core.bash

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,18 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH"
154154
local result
155155
local line
156156
local prefix
157-
local IFS=
158157

159158
if [[ "$#" -eq 0 ]]; then
160159
format="${format//\%/%%}"
161160
fi
162161
printf -v result -- "$format" "$@"
163162
result="${result//$'\r\n'/$'\n'}"
164163

165-
# If `result` ends with a newline, chomp it, since the loop will add one.
166-
while read -r line; do
164+
# Use the ASCII Unit Separator as a delimiter to preserve true line endings.
165+
while IFS= read -r -d $'\x1f' line; do
167166
while [[ "${#line}" -gt "$COLUMNS" ]]; do
168167
prefix="${line:0:$COLUMNS}"
169-
prefix="${prefix% *}"
168+
prefix="${prefix%[[:space:]]*}"
170169
line="${line#$prefix}"
171170

172171
if [[ "$prefix" =~ [[:space:]]+$ ]]; then
@@ -177,8 +176,8 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH"
177176
fi
178177
printf '%s\n' "$prefix"
179178
done
180-
printf '%s\n' "$line"
181-
done <<<"${result%$'\n'}"
179+
printf '%s' "$line"
180+
done <<<"${result//$'\n'/$'\n\x1f'}"$'\x1f'
182181
}
183182

184183
# Prints the stack trace at the point of the call.

libexec/get.d/file

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ _@go.get_file_download_command() {
9696
if [[ -n "$dl_cmd" ]]; then
9797
@go.printf 'Download program not supported: %s\n' "$dl_cmd" >&2
9898
fi
99-
@go.printf 'Please install curl or wget before running "%s".' \
99+
@go.printf 'Please install curl or wget before running "%s".\n' \
100100
"${_GO_CMD_NAME[*]}" >&2
101101
return 1
102102
;;
@@ -144,7 +144,7 @@ _@go.get_file_impl() {
144144
if ! "${__go_get_file_download_cmd[@]}" "$url" 2>"$errfile"; then
145145
errmsg="$(< "$errfile")"
146146
printf '%s\n' "$errmsg" >&2
147-
@go.printf 'Failed to download using %s: %s' \
147+
@go.printf 'Failed to download using %s: %s\n' \
148148
"${__go_get_file_download_cmd[0]}" "$url" >&2
149149

150150
if [[ "${__go_get_file_download_cmd[0]}" != 'curl' ]]; then

tests/core/printf.bats

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,11 @@ teardown() {
4949
COLUMNS=15 run "$TEST_GO_SCRIPT"
5050
assert_success $'123456789012345\n67890\n1234567890'
5151
}
52+
53+
@test "$SUITE: don't add newline if format doesn't include one" {
54+
@go.create_test_go_script "@go.printf '%s' 'foo'" \
55+
"@go.printf '%s' 'bar'" \
56+
"@go.printf '%s' 'baz'"
57+
run "$TEST_GO_SCRIPT"
58+
assert_success 'foobarbaz'
59+
}

0 commit comments

Comments
 (0)