Skip to content

Commit

Permalink
syntax: optimize large array passing
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed May 4, 2021
1 parent f795c07 commit c89aa23
Show file tree
Hide file tree
Showing 12 changed files with 1,059 additions and 57 deletions.
52 changes: 33 additions & 19 deletions ble.pp
Expand Up @@ -397,6 +397,7 @@ function ble/bin/.default-utility-path {
function ble/bin/.freeze-utility-path {
local cmd path q=\' Q="'\''" fail=
for cmd; do
type -t "ble/bin/$cmd" &>/dev/null && continue
if ble/util/assign path "builtin type -P -- $cmd 2>/dev/null" && [[ $path ]]; then
builtin eval "function ble/bin/$cmd { '${path//$q/$Q}' \"\$@\"; }"
else
Expand Down Expand Up @@ -462,8 +463,39 @@ function ble/.check-environment {
return 1
fi

# src/util で awk を使う
function ble/bin/awk {
local path q=\' Q="'\''"
if [[ $OSTYPE == solaris* ]] && type /usr/xpg4/bin/awk >/dev/null; then
# Solaris の既定の awk は全然駄目なので /usr/xpg4 以下の awk を使う。
function ble/bin/awk { /usr/xpg4/bin/awk -v AWKTYPE=xpg4 "$@"; }
elif ble/util/assign path "builtin type -P -- nawk 2>/dev/null" && [[ $path ]]; then
builtin eval "function ble/bin/awk { '${path//$q/$Q}' -v AWKTYPE=nawk \"\$@\"; }"
elif ble/util/assign path "builtin type -P -- mawk 2>/dev/null" && [[ $path ]]; then
builtin eval "function ble/bin/awk { '${path//$q/$Q}' -v AWKTYPE=mawk \"\$@\"; }"
elif ble/util/assign path "builtin type -P -- gawk 2>/dev/null" && [[ $path ]]; then
builtin eval "function ble/bin/awk { '${path//$q/$Q}' -v AWKTYPE=gawk \"\$@\"; }"
elif ble/util/assign path "builtin type -P -- awk 2>/dev/null" && [[ $path ]]; then
local version type
ble/util/assign version '"$path" --version 2>&1'
if [[ $version == *'GNU Awk'* ]]; then
type=gawk
elif [[ $version == *mawk* ]]; then
type=mawk
elif [[ $version == 'awk version '[12][0-9][0-9][0-9][01][0-9][0-3][0-9] ]]; then
type=nawk
else
type=unknown
fi
builtin eval "function ble/bin/awk { '${path//$q/$Q}' -v AWKTYPE=$type \"\$@\"; }"
else
return 1
fi
ble/bin/awk "$@"
}

_ble_bin_awk_supports_null_RS=
function ble/bin/awk-supports-null-record-separator {
function ble/bin/awk.supports-null-record-separator {
if [[ ! $_ble_bin_awk_supports_null_RS ]]; then
local count=0 awk_script='BEGIN { RS = "\0"; } { count++; } END { print count; }'
ble/util/assign count 'printf "a\0b\0" | ble/bin/awk "$awk_script" '
Expand All @@ -475,20 +507,6 @@ function ble/bin/awk-supports-null-record-separator {
fi
[[ $_ble_bin_awk_supports_null_RS == yes ]]
}
_ble_bin_awk_solaris_xpg4=
function ble/bin/awk.use-solaris-xpg4 {
if [[ ! $_ble_bin_awk_solaris_xpg4 ]]; then
if [[ $OSTYPE == solaris* ]] && type /usr/xpg4/bin/awk >/dev/null; then
_ble_bin_awk_solaris_xpg4=yes
else
_ble_bin_awk_solaris_xpg4=no
fi
fi

# Solaris の既定の awk は絶望的なので /usr/xpg4/bin/awk (nawk) を使う
[[ $_ble_bin_awk_solaris_xpg4 == yes ]] &&
function ble/bin/awk { /usr/xpg4/bin/awk "$@"; }
}

#------------------------------------------------------------------------------

Expand Down Expand Up @@ -819,8 +837,6 @@ function ble-update {
}
#%end

# Solaris: src/util の中でちゃんとした awk が必要
ble/bin/awk.use-solaris-xpg4

#------------------------------------------------------------------------------
_ble_attached=
Expand All @@ -831,8 +847,6 @@ function ble-update {
ble/bin/.freeze-utility-path "${_ble_init_posix_command_list[@]}" # <- this uses ble/util/assign.
ble/bin/.freeze-utility-path man
ble/bin/.freeze-utility-path groff nroff mandoc gzip bzcat lzcat xzcat # used by core-complete.sh
# Solaris: .freeze-utility-path で上書きされた awk を戻す
ble/bin/awk.use-solaris-xpg4

ble/builtin/trap/install-hook EXIT
ble/builtin/trap/install-hook INT
Expand Down
6 changes: 4 additions & 2 deletions lib/core-complete.sh
Expand Up @@ -1753,11 +1753,13 @@ function ble/complete/util/eval-pathname-expansion {
local sync_opts=progressive-weight
[[ :$comp_type: == *:auto:* && $bleopt_complete_timeout_auto ]] &&
sync_opts=$sync_opts:timeout=$((bleopt_complete_timeout_auto))

local def
ble/util/assign def 'ble/util/conditional-sync "$sync_command" "" "" "$sync_opts"' &>/dev/null; local ext=$?
((ext==148)) && return 148
ble/complete/check-cancel && return 148
builtin eval -- "$def"
fi
fi 2>/dev/tty

ble/array#reverse dtor
ble/util/invoke-hook dtor
Expand Down Expand Up @@ -4333,7 +4335,7 @@ function ble/complete/insert-all {
function ble/complete/insert-braces/.compose {
# Note: awk が RS = "\0" に対応していれば \0 で区切る。
# それ以外の場合には \x1E (ASCII RS) で区切る。
if ble/bin/awk-supports-null-record-separator; then
if ble/bin/awk.supports-null-record-separator; then
local printf_format='%s\0' RS='"\0"'
else
local printf_format='%s\x1E' RS='"\x1E"'
Expand Down
27 changes: 24 additions & 3 deletions lib/core-syntax.sh
Expand Up @@ -1325,6 +1325,25 @@ function ble/syntax:bash/simple-word/extract-parameter-names/.process-dquot {

function ble/syntax:bash/simple-word/eval/.set-result { __ble_ret=("$@"); }
function ble/syntax:bash/simple-word/eval/.print-result {
if (($#>=1000)) && [[ $OSTYPE != cygwin ]]; then
# ファイル数が少ない場合は fork コストを避ける為に多少遅くても quote&eval
# でデータを親シェルに転送する。Cygwin では mapfile/read が unbuffered で遅
# いので、ファイル数が遅くても quote&eval を使う。

# # もし mapfile -d "" が buffered になったら以下のコードを使用したい。
# if ((_ble_bash>=50200)); then
# printf '%s\0' "$@" >| "$__ble_simple_word_tmpfile"
# ble/util/print 'ble/util/readarray -d "" __ble_ret < "$__ble_simple_word_tmpfile"'
# return 0
# fi
if ((_ble_bash>=40000)); then
ret=("$@")
ble/util/writearray --nlfix ret >| "$__ble_simple_word_tmpfile"
ble/util/print 'ble/util/readarray --nlfix __ble_ret < "$__ble_simple_word_tmpfile"'
return 0
fi
fi

local ret; ble/string#quote-words "$@"
ble/util/print "__ble_ret=($ret)"
}
Expand Down Expand Up @@ -1395,9 +1414,11 @@ function ble/syntax:bash/simple-word/eval/.impl {
[[ $__ble_sync_timeout ]] &&
__ble_sync_opts=$__ble_sync_opts:timeout=$((__ble_sync_timeout))

local __ble_def
ble/util/assign __ble_def 'ble/util/conditional-sync "$__ble_sync_command" "" "$__ble_sync_weight" "$__ble_sync_opts"' &>/dev/null; local ext=$?
builtin eval -- "$__ble_def"
local __ble_simple_word_tmpfile=$_ble_util_assign_base.$((_ble_util_assign_level++))
local __ble_script
ble/util/assign __ble_script 'ble/util/conditional-sync "$__ble_sync_command" "" "$__ble_sync_weight" "$__ble_sync_opts"' &>/dev/null; local ext=$?
builtin eval -- "$__ble_script"
((_ble_util_assign_level--))
else
builtin eval "ble/syntax:bash/simple-word/eval/.set-result $__ble_word" &>/dev/null; local ext=$?
builtin eval : # Note: bash 3.1/3.2 eval バグ対策 (#D1132)
Expand Down
37 changes: 24 additions & 13 deletions lib/test-canvas.sh
Expand Up @@ -5,7 +5,7 @@ ble-import lib/core-test
_ble_test_canvas_contra=
if [[ -x ext/contra ]]; then
_ble_test_canvas_contra=ext/contra
elif [[ $(printf 'hello world' | contra test 5 2) == $' worl\nd ' ]]; then
elif [[ $(printf 'hello world' | contra test 5 2 2>/dev/null) == $' worl\nd ' ]]; then
_ble_test_canvas_contra=contra
fi

Expand Down Expand Up @@ -74,25 +74,29 @@ ble/test:canvas/trace.contra 10:6 $'hello\e[B\e[4D123' measure-bbox x=3:y=2 << E
$
$
EOF
ble/test '[[ $x1-$x2:$y1-$y2 == 3-8:2-4 ]]'
[[ $_ble_test_canvas_contra ]] &&
ble/test 'echo "$x1-$x2:$y1-$y2"' stdout='3-8:2-4'

ble/test:canvas/trace.contra 10:2 日本語 measure-bbox << EOF
日本語 $
$
EOF
ble/test '[[ $x1-$x2:$y1-$y2 == 0-6:0-1 ]]'
[[ $_ble_test_canvas_contra ]] &&
ble/test 'echo "$x1-$x2:$y1-$y2"' stdout='0-6:0-1'

ble/test:canvas/trace.contra 10:2 $'hello\eDworld' measure-bbox << EOF
hello $
world$
EOF
ble/test '[[ $x1-$x2:$y1-$y2 == 0-10:0-2 ]]'
[[ $_ble_test_canvas_contra ]] &&
ble/test 'echo "$x1-$x2:$y1-$y2"' stdout='0-10:0-2'

ble/test:canvas/trace.contra 10:2 $'hello\eMworld' measure-bbox << EOF
world$
hello $
EOF
ble/test '[[ $x1-$x2:$y1-$y2 == 0-10:-1-1 ]]'
[[ $_ble_test_canvas_contra ]] &&
ble/test 'echo "$x1-$x2:$y1-$y2"' stdout='0-10:-1-1'


#------------------------------------------------------------------------------
Expand Down Expand Up @@ -149,9 +153,10 @@ E $
$
EOF
)
ble/test --depth=1 \
'ble/canvas/flush.draw | ext/contra test 40 15' \
stdout="$expect"
[[ $_ble_test_canvas_contra ]] &&
ble/test --depth=1 \
'ble/canvas/flush.draw | $_ble_test_canvas_contra test 40 15' \
stdout="$expect"
}
ble/test:canvas/check-trace

Expand Down Expand Up @@ -243,20 +248,26 @@ ble/test:canvas/trace.contra 30:3 $'hello\n2021-01-01\nA' right:measure-bbox:mea
2021-01-01$
A$
EOF
ble/test '[[ bbox:$x1,$y1-$x2,$y2 == bbox:0,0-30,3 ]]'
ble/test '[[ gbox:$gx1,$gy1-$gx2,$gy2 == gbox:20,0-30,3 ]]'
if [[ $_ble_test_canvas_contra ]]; then
ble/test 'echo "bbox:$x1,$y1-$x2,$y2"' stdout='bbox:0,0-30,3'
ble/test 'echo "gbox:$gx1,$gy1-$gx2,$gy2"' stdout='gbox:20,0-30,3'
fi

ble/test:canvas/trace.contra 30:3 $'hello\n2021-01-01\nA' center:measure-bbox:measure-gbox << EOF
hello $
2021-01-01 $
A $
EOF
ble/test '[[ bbox:$x1,$y1-$x2,$y2 == bbox:0,0-20,3 ]]'
ble/test '[[ gbox:$gx1,$gy1-$gx2,$gy2 == gbox:10,0-20,3 ]]'
if [[ $_ble_test_canvas_contra ]]; then
ble/test 'echo "bbox:$x1,$y1-$x2,$y2"' stdout='bbox:0,0-20,3'
ble/test 'echo "gbox:$gx1,$gy1-$gx2,$gy2"' stdout='gbox:10,0-20,3'
fi

ble/test:canvas/trace.contra 10:1 $'xyz\e[4Daxyz' relative:measure-bbox x=3 << EOF
axyz $
EOF
ble/test '[[ bbox:$x1,$y1-$x2,$y2 == bbox:2,0-6,1 ]]'
if [[ $_ble_test_canvas_contra ]]; then
ble/test 'echo "bbox:$x1,$y1-$x2,$y2"' stdout='bbox:2,0-6,1'
fi

ble/test/end-section
2 changes: 1 addition & 1 deletion lib/test-main.sh
Expand Up @@ -2,7 +2,7 @@

ble-import lib/core-test

ble/test/start-section 'main' 14
ble/test/start-section 'main' 16

# ble/util/{put,print}
(
Expand Down
8 changes: 7 additions & 1 deletion lib/test-util.sh
Expand Up @@ -2,7 +2,7 @@

ble-import lib/core-test

ble/test/start-section 'util' 1191
ble/test/start-section 'util' 1192

# bleopt

Expand Down Expand Up @@ -1191,6 +1191,12 @@ function is-global() (readonly "$1"; ! local "$1" 2>/dev/null)
ble/test 'ble/util/assign-array a "echo 1; echo; echo 2"; status' stdout='3:(1 2)'
)

# ble/util/writearray
(
x=($'\1' $'\2' $'\32' ' ' $'\a' $'\b' $'\t' $'\n' $'\v' $'\f' $'\r' $'\177' a \" \' \$ \! \` \~)
ble/test "ble/util/writearray -d '' x | sha256sum | awk '{print \$1}'" stdout=$(printf '%s\0' "${x[@]}" | sha256sum | awk '{print $1}')
)

# ble/is-function
(
var=variable
Expand Down
7 changes: 6 additions & 1 deletion memo/ChangeLog.md
Expand Up @@ -26,7 +26,7 @@
- prompt: support multiline `prompt_rps1` `#D1502` 4fa139a
- syntax: support tilde expansions in parameter expansions `#D1513` 0506df2
- decode: support `ble-bind -m KEYMAP --cursor DECSCUSR` (motivated by jmederosalvarado) `#D1514` `#D1515` `#D1516` 79d671d
- edit: support `nsearch` options (motivated by Alyetama, rashil2000, carv-silva) `#D1517` 0000000
- edit: support `nsearch` options (motivated by Alyetama, rashil2000, carv-silva) `#D1517` 9125795

## Changes

Expand All @@ -49,7 +49,10 @@
- README: update informations on stable versions `#D1509` c8e658e
- README: update the description of how to uninstall `#D1510` c8e658e
- util (`bleopt`): validate initial user settings `#D1511` 82c5ece
- util (`bleopt`): fix a bug that old values are double-expanded on init (fixup 82c5ece) `#D1521` f795c07
- complete (`ble/complete/source:file`): remove slow old codes (reported by timjrd) `#D1512` e5be0c1
- main: preserve user-space overridden builtins `#D1519` 0860be0
- syntax (`ble/syntax:bash/simple-word/eval`): optimize large array passing `#D1522` 0000000

## Fixes

Expand Down Expand Up @@ -101,6 +104,8 @@
- util, etc: ensure each function to work with arbitrary `IFS` `#D1490` `#D1491` 5f9adfe
- tui, canvas (`ble/canvas/trace`): support `opts=clip` `#D1493` 61ce90c
- tui, edit: add a new render mode for full-screen applications 817889d
- main: prefer `nawk` over `mawk` and `gawk` `#D1523` `#D1524` 0000000
- test (`test-canvas`): fix dependency on `ext/contra` `#D1525` 0000000

<!---------------------------------------------------------------------------->
# ble-0.4.0-devel2
Expand Down

0 comments on commit c89aa23

Please sign in to comment.