# 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 . __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: