From 99f76ced50567338922292eb0617089940997b08 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Wed, 10 Jan 2024 22:23:51 +0900 Subject: [PATCH] feat(bash): support high-resolution timing even without ble.sh (#1534) * feat(bash): support high-resolution timing without blesh For the integration using bash-preexec, this measures the execution time of the command using EPOCHREALTIME without the support by ble.sh. This is not as accurate as the measurement by ble.sh as it contains also the processing time of the preexec and precmd hooks, but it is still free from the fork cost. * fix(shell): work around custom IFS for duration When a custom IFS is set by the user, the word splitting of ${duration:+--duration "$duration"} does not work as expected. We instead use the form "--duration=$duration" with the word splitting being disabled. --- atuin/src/shell/atuin.bash | 33 ++++++++++++++++++++++++++------- atuin/src/shell/atuin.zsh | 2 +- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/atuin/src/shell/atuin.bash b/atuin/src/shell/atuin.bash index c6967942..3814193e 100644 --- a/atuin/src/shell/atuin.bash +++ b/atuin/src/shell/atuin.bash @@ -15,23 +15,42 @@ __atuin_preexec() { local id id=$(atuin history start -- "$1") export ATUIN_HISTORY_ID=$id + __atuin_preexec_time=${EPOCHREALTIME-} } __atuin_precmd() { - local EXIT=$? + local EXIT=$? __atuin_precmd_time=${EPOCHREALTIME-} [[ ! $ATUIN_HISTORY_ID ]] && return local duration="" - # shellcheck disable=SC2154,SC2309 - if [[ ${BLE_ATTACHED-} && _ble_bash -ge 50000 && ${_ble_exec_time_ata-} ]]; then + if ((BASH_VERSINFO[0] >= 5)); then # We use the high-resolution duration based on EPOCHREALTIME (bash >= - # 5.0) that is recorded by ble.sh. The shell variable - # `_ble_exec_time_ata` contains the execution time in microseconds. - duration=${_ble_exec_time_ata}000 + # 5.0) if available. + # shellcheck disable=SC2154,SC2309 + if [[ ${BLE_ATTACHED-} && ${_ble_exec_time_ata-} ]]; then + # With ble.sh, we utilize the shell variable `_ble_exec_time_ata` + # recorded by ble.sh. + duration=${_ble_exec_time_ata}000 + else + # With bash-preexec, we calculate the time duration here, though it + # might not be as accurate as `_ble_exec_time_ata` because it also + # includes the time for precmd/preexec handling. Bash does not + # allow floating-point arithmetic, so we remove the non-digit + # characters and perform the integral arithmetic. The fraction + # part of EPOCHREALTIME is fixed to have 6 digits in Bash. We + # remove all the non-digit characters because the decimal point is + # not necessarily a period depending on the locale. + duration=$((${__atuin_precmd_time//[!0-9]} - ${__atuin_preexec_time//[!0-9]})) + if ((duration >= 0)); then + duration=${duration}000 + else + duration="" # clear the result on overflow + fi + fi fi - (ATUIN_LOG=error atuin history end --exit "$EXIT" ${duration:+--duration "$duration"} -- "$ATUIN_HISTORY_ID" &) >/dev/null 2>&1 + (ATUIN_LOG=error atuin history end --exit "$EXIT" ${duration:+"--duration=$duration"} -- "$ATUIN_HISTORY_ID" &) >/dev/null 2>&1 export ATUIN_HISTORY_ID="" } diff --git a/atuin/src/shell/atuin.zsh b/atuin/src/shell/atuin.zsh index 26294ae9..85aba182 100644 --- a/atuin/src/shell/atuin.zsh +++ b/atuin/src/shell/atuin.zsh @@ -44,7 +44,7 @@ _atuin_precmd() { printf -v duration %.0f $(((__atuin_precmd_time - __atuin_preexec_time) * 1000000000)) fi - (ATUIN_LOG=error atuin history end --exit $EXIT ${=duration:+--duration $duration} -- $ATUIN_HISTORY_ID &) >/dev/null 2>&1 + (ATUIN_LOG=error atuin history end --exit $EXIT ${duration:+--duration=$duration} -- $ATUIN_HISTORY_ID &) >/dev/null 2>&1 export ATUIN_HISTORY_ID="" }