# integration/bash --- Bash integration

# Copyright (C) 2022 Akib Azmain Turja.

# This file is not part of GNU Emacs.

# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# For a full copy of the GNU General Public License
# see <https://www.gnu.org/licenses/>.

__eat_prompt_command () {
  # Send exit status.
  if test -n "$__eat_current_command"
  then
    printf '\e]51;e;H;%i\e\\' "$__eat_exit_status"
  fi
  __eat_current_command=""
  # Inform that a new prompt is going to be printed.
  printf '\e]51;e;J\e\\'
  # Send the current working directory, for directory tracking.
  printf '\e]51;e;A;%s;%s\e\\' "$(printf "%s" "$HOSTNAME" | base64)" \
         "$(printf "%s" "$PWD" | base64)"
  # Update title.
  # "${PWD/$HOME/'~'}" converts "/home/akib/org/" to "~/org/".
  # The next one is substituted with '$', or '#' if we're "root".
  printf '\e]2;%s@%s:%s%s\e\\' "$USER" "$HOSTNAME" \
         "${PWD/$HOME/'~'}" \
         "$(test $UID -eq 0 && echo '#' || echo '$')"
}

__eat_preexec () {
  # Get the real command typed by the user from the history.
  __eat_current_command="$(history 1 | sed 's/ *[0-9]* *//')"
  # Send current command.
  printf '\e]51;e;F;%s\e\\' \
         "$(printf "%s" "$__eat_current_command" | base64)"
  # Send pre-exec sequence.
  printf '\e]51;e;G\e\\'
  # Update title to include the command running.
  # "${PWD/$HOME/'~'}" converts "/home/akib/foo/" to "~/foo/".
  # The next one is substituted with '$', or '#' if we're "root".
  printf '\e]2;%s@%s:%s%s %s\e\\' "$USER" "$HOSTNAME" \
         "${PWD/$HOME/'~'}" \
         "$(test $UID -eq 0 && echo '#' || echo '$')" \
         "$__eat_current_command"
}

__eat_before_prompt_command ()
{
  __eat_exit_status="$?"
  __eat_inhibit_preexec=yes
}

__eat_after_prompt_command ()
{
  __eat_inhibit_preexec=no
}

__eat_before_exec () {
  if test $__eat_inhibit_preexec = no \
      && test "$BASH_COMMAND" != __eat_before_prompt_command
  then
    __eat_inhibit_preexec=yes
    __eat_preexec
  fi
}

__eat_enable_integration ()
{
  __eat_integration_enabled=yes
  __eat_current_command=""
  __eat_exit_status=0
  __eat_inhibit_preexec=yes
  local __eat_prompt_start='\e]51;e;B\e\\'
  local __eat_prompt_end='\e]51;e;C\e\\'
  local __eat_continuation_start='\e]51;e;D\e\\'
  local __eat_continuation_end='\e]51;e;E\e\\'
  PS1="\[$__eat_prompt_start\]$PS1\[$__eat_prompt_end\]"
  PS2="\[$__eat_continuation_start\]$PS2\[$__eat_continuation_end\]"
  PROMPT_COMMAND+=(__eat_prompt_command)
  trap '__eat_before_exec' DEBUG
  # Wrap 'PROMPT_COMMAND' to avoid it getting trapped in 'DEBUG' trap.
  # Fun fact: Microsoft doesn't still about know this simple trick.
  # They ended up using something as silly and pityful as
  # 'VAR=$PROMPT_COMMAND' to copy a Bash array in VSCode Bash
  # integration script, which simply won't work ever, and then
  # complain about Bash in the comments!  xD
  PROMPT_COMMAND+=(__eat_after_prompt_command)
  PROMPT_COMMAND=(__eat_before_prompt_command "${PROMPT_COMMAND[@]}")
  # Send the history, for native shell prompt.
  printf '\e]51;e;I;0;bash;%s;%s\e\\' \
         "$(printf "%s" "$HOSTNAME" | base64)" \
         "$(printf "%s" "$HISTFILE" | base64)"
  local REPLY
  IFS=$';\e' read -r -s -t 10 -d "\\" -a REPLY
  if test "${REPLY[4]}" != 0
  then
    printf '\e]51;e;I;1;bash;%s\e\\' \
           "$(tail -n "${REPLY[4]}" "$HISTFILE" | base64)"
  fi
}

_eat_msg () {
  local msg=$'\e]51;e;M'
  for _ in $(eval "echo {1..$#}")
  do
    msg="$msg;$(printf "%s" "$1" | base64)"
    shift
  done
  printf "%s\e\\" "$msg"
}

# Enable.
if test -z "$__eat_integration_enabled" && \
    test "${TERM:0:4}" = "eat-"
then
  __eat_enable_integration
else
  true
fi

# Local Variables:
# mode: sh
# sh-shell: bash
# End: