feat: implement `cmd_duration` for bash (#144)
This commit is contained in:
parent
56f4797a25
commit
22c8c3459f
|
@ -119,11 +119,16 @@ The `cmd_duration` module shows how long the last command took to execute.
|
|||
The module will be shown only if the command took longer than two seconds, or
|
||||
the `min_time` config value, if it exists.
|
||||
|
||||
::: warning NOTE
|
||||
Command duration is currently not supported in `bash`. See
|
||||
[this issue](https://github.com/starship/starship/issues/124) for more details.
|
||||
::: warning Do Not Hook the DEBUG trap in Bash
|
||||
If you are running Starship in `bash`, do not hook the `DEBUG` trap after running
|
||||
`eval $(starship init $0)`, or this module **will** break.
|
||||
:::
|
||||
|
||||
Bash users who need preexec-like functionality can use
|
||||
[rcaloras's bash_preexec framework](https://github.com/rcaloras/bash-preexec).
|
||||
Simply define the arrays `preexec_functions` and `precmd_functions` before
|
||||
running `eval $(starship init $0)`, and then proceed as normal.
|
||||
|
||||
### Options
|
||||
|
||||
| Variable | Default | Description |
|
||||
|
|
76
src/init.rs
76
src/init.rs
|
@ -52,23 +52,74 @@ pub fn init(shell_name: &str) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Bash does not currently support command durations (see issue #124) for details
|
||||
https://github.com/starship/starship/issues/124
|
||||
/*
|
||||
For bash: we need to manually hook functions ourself: PROMPT_COMMAND will exec
|
||||
right before the prompt is drawn, and any function trapped by DEBUG will exec
|
||||
before a command is run.
|
||||
|
||||
We need to quote the output of `$(jobs -p | wc -l)` since MacOS `wc` leaves
|
||||
giant spaces in front of the number (e.g. " 3"), which messes up the
|
||||
word-splitting. Instead, quote the whole thing, then let Rust do the whitespace
|
||||
trimming within the jobs module.
|
||||
There is a preexec/precmd framework for bash out there: if we find the
|
||||
appropriate variables set, assume we are using that framework:
|
||||
https://github.com/rcaloras/bash-preexec
|
||||
|
||||
Bash quirk: DEBUG is triggered whenever a command is executed, even if that
|
||||
command is part of a pipeline. To avoid only timing the last part of a pipeline,
|
||||
we only start the timer if no timer has been started since the last prompt draw,
|
||||
tracked by the variable PREEXEC_READY. Similarly, only draw timing info if
|
||||
STARSHIP_START_TIME is defined, in case preexec was interrupted.
|
||||
|
||||
Finally, to work around existing DEBUG traps in the absence of a preexec-like,
|
||||
we parse out the name of the old DEBUG hook, then make a new function which
|
||||
calls both that function and our starship hooks. We don't do this for
|
||||
PROMPT_COMMAND because that would probably result in two prompts.
|
||||
|
||||
We need to quote the output of `$(jobs -p | wc -l)` since MacOS `wc` leaves
|
||||
giant spaces in front of the number (e.g. " 3"), which messes up the
|
||||
word-splitting. Instead, quote the whole thing, then let Rust do the whitespace
|
||||
trimming within the jobs module
|
||||
*/
|
||||
|
||||
/*
|
||||
Note to programmers: this and the zsh init will be evaluated on a single line.
|
||||
Use semicolons, avoid comments, and generally think like all newlines will be
|
||||
deleted.
|
||||
*/
|
||||
const BASH_INIT: &str = r##"
|
||||
starship_precmd() {
|
||||
PS1="$(starship prompt --status=$? --jobs="$(jobs -p | wc -l)")";
|
||||
starship_preexec() {
|
||||
if [ "$PREEXEC_READY" = "true" ]; then
|
||||
PREEXEC_READY=false;
|
||||
STARSHIP_START_TIME=$(date +%s);
|
||||
fi
|
||||
};
|
||||
PROMPT_COMMAND=starship_precmd;
|
||||
starship_precmd() {
|
||||
STATUS=$?;
|
||||
if [[ $STARSHIP_START_TIME ]]; then
|
||||
STARSHIP_END_TIME=$(date +%s);
|
||||
STARSHIP_DURATION=$((STARSHIP_END_TIME - STARSHIP_START_TIME));
|
||||
PS1="$(starship prompt --status=$STATUS --jobs="$(jobs -p | wc -l)" --cmd-duration=$STARSHIP_DURATION)";
|
||||
unset STARSHIP_START_TIME;
|
||||
else
|
||||
PS1="$(starship prompt --status=$STATUS --jobs="$(jobs -p | wc -l)")";
|
||||
fi;
|
||||
PREEXEC_READY=true;
|
||||
};
|
||||
if [[ $preexec_functions ]]; then
|
||||
preexec_functions+=(starship_preexec);
|
||||
precmd_functions+=(starship_precmd);
|
||||
STARSHIP_START_TIME=$(date +%s);
|
||||
else
|
||||
dbg_trap="$(trap -p DEBUG | cut -d' ' -f3 | tr -d \')";
|
||||
if [[ -z "$dbg_trap" ]]; then
|
||||
trap starship_preexec DEBUG;
|
||||
elif [[ "$dbg_trap" != "starship_preexec" && "$dbg_trap" != "starship_preexec_all" ]]; then
|
||||
function starship_preexec_all(){
|
||||
$dbg_trap; starship_preexec;
|
||||
};
|
||||
trap starship_preexec_all DEBUG;
|
||||
fi;
|
||||
PROMPT_COMMAND=starship_precmd;
|
||||
STARSHIP_START_TIME=$(date +%s);
|
||||
fi;
|
||||
"##;
|
||||
/* TODO: Once warning/error system is implemented in starship, print a warning
|
||||
if starship will not be printing timing due to DEBUG clobber error */
|
||||
|
||||
/* For zsh: preexec_functions and precmd_functions provide preexec/precmd in a
|
||||
way that lets us avoid clobbering them.
|
||||
|
@ -80,6 +131,9 @@ if starship will not be printing timing due to DEBUG clobber error */
|
|||
|
||||
To fix this, only pass the time if STARSHIP_START_TIME is defined, and unset
|
||||
it after passing the time, so that we only measure actual commands.
|
||||
|
||||
We need to quote the output of the jobs command for the same reason as
|
||||
bash.
|
||||
*/
|
||||
|
||||
const ZSH_INIT: &str = r##"
|
||||
|
|
Loading…
Reference in New Issue