From 98d83fbd3c9cc25d44757ef1a844a7e6ccd4be5b Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Sun, 26 Nov 2023 18:24:11 -0800 Subject: [PATCH 4/9] Support preexec notifications from an interactive shell Add sequences OSC 777 ; preexec BEL OSC 777 ; preexec ST that can be used from an interactive shell's preexec hook to notify the terminal emulator that a new command is about to be executed. Examples of such hooks are Bash's PS0 and Zsh's preexec. The OSC 777 escape sequence is taken from Enlightenment's Terminology: https://phab.enlightenment.org/T1765 https://bugzilla.gnome.org/show_bug.cgi?id=711059 https://bugzilla.gnome.org/show_bug.cgi?id=711060 --- src/vte.cc | 6 ++++++ src/vte.sh.in | 3 ++- src/vte/vteterminal.h | 3 ++- src/vtegtk.cc | 18 ++++++++++++++++++ src/vtegtk.hh | 1 + src/vteinternal.hh | 1 + src/vteseq.cc | 4 ++++ 7 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/vte.cc b/src/vte.cc index c7981e1b..49a3d8f3 100644 --- a/src/vte.cc +++ b/src/vte.cc @@ -10774,6 +10774,12 @@ Terminal::emit_pending_signals() m_notification_summary.c_str(), m_notification_body.c_str()); } + + if (m_pending_changes & vte::to_integral(PendingChanges::SHELL_PREEXEC)) { + _vte_debug_print (VTE_DEBUG_SIGNALS, + "Emitting `shell-preexec'.\n"); + g_signal_emit(freezer.get(), signals[SIGNAL_SHELL_PREEXEC], 0); + } #endif if (m_pending_changes & vte::to_integral(PendingChanges::TITLE)) { diff --git a/src/vte.sh.in b/src/vte.sh.in index 50242223..fbbb1a03 100644 --- a/src/vte.sh.in +++ b/src/vte.sh.in @@ -51,9 +51,10 @@ if [[ -n "${BASH_VERSION:-}" ]]; then # use the __vte_prompt_command function which also sets the title. if [[ "$(declare -p PROMPT_COMMAND 2>&1)" =~ "declare -a" ]]; then - PROMPT_COMMAND+=(__vte_osc7) + PROMPT_COMMAND+=(__vte_osc7) && PS0=$(printf "\033]777;preexec\033\\") else PROMPT_COMMAND="__vte_prompt_command" + PROMPT_COMMAND="__vte_prompt_command" && PS0=$(printf "\033]777;preexec\033\\") fi elif [[ -n "${ZSH_VERSION:-}" ]]; then diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h index 77d96a31..29529020 100644 --- a/src/vte/vteterminal.h +++ b/src/vte/vteterminal.h @@ -115,10 +115,11 @@ struct _VteTerminalClass { #if _VTE_GTK == 3 void (*notification_received)(VteTerminal* terminal, const gchar *summary, const gchar *body); + void (*shell_preexec)(VteTerminal* terminal); /* Compatibility padding due to fedora patches intruding on our ABI */ /*< private >*/ - gpointer _extra_padding[2]; + gpointer _extra_padding[1]; #endif /* _VTE_GTK == 3 */ void (*setup_context_menu)(VteTerminal* terminal, diff --git a/src/vtegtk.cc b/src/vtegtk.cc index c924df55..c4cf5537 100644 --- a/src/vtegtk.cc +++ b/src/vtegtk.cc @@ -1347,6 +1347,7 @@ vte_terminal_class_init(VteTerminalClass *klass) klass->char_size_changed = NULL; #if _VTE_GTK == 3 klass->notification_received = NULL; + klass->shell_preexec = NULL; #endif klass->window_title_changed = NULL; klass->icon_title_changed = NULL; @@ -1451,6 +1452,23 @@ vte_terminal_class_init(VteTerminalClass *klass) _vte_marshal_VOID__STRING_STRING, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); + + /** + * VteTerminal::shell-preexec: + * @vteterminal: the object which received the signal + * + * Emitted when the interactive shell has read in a complete + * command and is about to execute it. + */ + signals[SIGNAL_SHELL_PREEXEC] = + g_signal_new(I_("shell-preexec"), + G_OBJECT_CLASS_TYPE(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(VteTerminalClass, shell_preexec), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); #endif /** diff --git a/src/vtegtk.hh b/src/vtegtk.hh index e811bd1c..4e400cd3 100644 --- a/src/vtegtk.hh +++ b/src/vtegtk.hh @@ -54,6 +54,7 @@ enum { SIGNAL_SELECTION_CHANGED, SIGNAL_SETUP_CONTEXT_MENU, #if _VTE_GTK == 3 + SIGNAL_SHELL_PREEXEC, SIGNAL_NOTIFICATION_RECEIVED, #endif SIGNAL_WINDOW_TITLE_CHANGED, diff --git a/src/vteinternal.hh b/src/vteinternal.hh index cb4f00bb..0479ae0e 100644 --- a/src/vteinternal.hh +++ b/src/vteinternal.hh @@ -757,6 +757,7 @@ public: CWF = 1u << 2, #if _VTE_GTK == 3 NOTIFICATION = 1u << 3, + SHELL_PREEXEC = 1u << 4, #endif }; unsigned m_pending_changes{0}; diff --git a/src/vteseq.cc b/src/vteseq.cc index 97e2c5f8..92d1f857 100644 --- a/src/vteseq.cc +++ b/src/vteseq.cc @@ -1325,6 +1325,10 @@ Terminal::handle_urxvt_extension(vte::parser::Sequence const& seq, m_notification_body = *token; return; } + + if (*token == "preexec") { + m_pending_changes |= vte::to_integral(PendingChanges::SHELL_PREEXEC); + } } #endif -- 2.43.0