0

I need to know what was the last command executed while setting my bash prompt in the function corresponding to PROMPT_COMMAND. I have code as follows

function bash_prompt_command () { 
...
    local last_cmd="$(history | tail -n 2 | head -n 1  | tr -s ' ' | cut -d ' ' -f3-)"
    [[ ${last_cmd} =~ .*git\s+checkout.* ]] && ( ... )
...
}

Is there is faster(bash built-in way) to know the what was the command which invoked PROMPT_COMMAND. I tried using BASH_COMMAND, but that too does not return the command which actually invoked PROMPT_COMMAND.

hardeep
  • 186
  • 1
  • 7
  • 1
    As far as I know, there is no other way. What issues do you have with your code? What else would you want it to do? – Nic3500 Oct 19 '21 at 01:49
  • You can certainly create a DEBUG trap that stores the commands it's asked whether to permit execution of, much more efficiently than what you're trying here. – Charles Duffy Oct 19 '21 at 01:53
  • if current(last) command is git checkout, i want to set PS1 in certain way. – hardeep Oct 19 '21 at 01:53
  • 1
    @hardeep, have you considered just creating a function to shadow `git` and modify behavior when running `checkout`? – Charles Duffy Oct 19 '21 at 01:53
  • 1
    BTW, `function funcname() {` merges the ksh syntax `function funcname {` and the POSIX sh syntax `funcname() {` in a way that's incompatible with _both_ ksh and POSIX. Pick one or the other (the POSIX one if you care about portability), don't merge both together -- see also https://wiki.bash-hackers.org/scripting/obsolete – Charles Duffy Oct 19 '21 at 01:54
  • I can try shadow git but since git is used by several other bash completion functions, it will be tricky. – hardeep Oct 19 '21 at 01:57
  • Not tricky at all. I've shown how to do it in other Q&A entries. – Charles Duffy Oct 19 '21 at 01:57
  • ok, i will try..thx – hardeep Oct 19 '21 at 01:58
  • @hardeep : From a practical viewpoint: Why do you want to show a different prompt after a `git checkout`? Wouldn't it make more sense to **always** show the current git branch, if the working directory happens to be within a git repositiory? – user1934428 Oct 19 '21 at 04:51

1 Answers1

5

General case: Collecting all commands

You can use a DEBUG trap to store each command before it's run.

store_command() {
  declare -g last_command current_command
  last_command=$current_command
  current_command=$BASH_COMMAND
  return 0
}
trap store_command DEBUG

...and thereafter you can check "$last_command"


Special case: Only trying to shadow one (sub)command

If you only want to change how one command operates, you can just shadow that one command. For git checkout:

git() {
  # if $1 is not checkout, just run real git and pretend we weren't here
  [[ $1 = checkout ]] || { command git "$@"; return; }
  # if $1 _is_ checkout, run real git and do our own thing
  local rc=0
  command git "$@" || rc=$?
  ran_checkout=1 # ...put the extra code you want to run here...
  return "$rc"
}

...potentially used from something like:

bash_prompt_command() {
  if (( ran_checkout )); then
    ran_checkout=0
    : "do special thing here"
  else
    : "do other thing here"
  fi
}
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441