From a87eff451ae5ad21ffbd491f6f7959b007b455fa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 11:39:35 +0000 Subject: [PATCH 01/10] Initial plan From baf2479e82b408d15c077d935c7c884b8899b50d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 11:44:56 +0000 Subject: [PATCH 02/10] Add Windows Terminal shell integration installer Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com> --- completions/pengwin-setup | 4 +- pengwin-setup.d/shell-integration.sh | 80 +++++++++++++++++++ pengwin-setup.d/shells.sh | 8 +- pengwin-setup.d/uninstall.sh | 6 ++ .../uninstall/shell-integration.sh | 41 ++++++++++ tests/run_tests.sh | 2 + tests/shell-integration.sh | 48 +++++++++++ 7 files changed, 186 insertions(+), 3 deletions(-) create mode 100755 pengwin-setup.d/shell-integration.sh create mode 100755 pengwin-setup.d/uninstall/shell-integration.sh create mode 100755 tests/shell-integration.sh diff --git a/completions/pengwin-setup b/completions/pengwin-setup index 3cb17a33..8011fcf8 100644 --- a/completions/pengwin-setup +++ b/completions/pengwin-setup @@ -42,7 +42,7 @@ function _pengwin_setup() { # By convention, the function name mapfile -t COMPREPLY < <(compgen -W 'EXPLORER COLORTOOL LANGUAGE SHELLS' -- "${cur}") ;; SHELLS) - mapfile -t COMPREPLY < <(compgen -W 'BASH-RL CSH FISH ZSH' -- "${cur}") + mapfile -t COMPREPLY < <(compgen -W 'BASH-RL CSH FISH SHELLINT ZSH' -- "${cur}") ;; TOOLS) mapfile -t COMPREPLY < <(compgen -W 'ANSIBLE CLOUDCLI DOCKER FZF HOMEBREW POWERSHELL' -- "${cur}") @@ -51,7 +51,7 @@ function _pengwin_setup() { # By convention, the function name mapfile -t COMPREPLY < <(compgen -W 'AWS AZURE DO IBM KUBERNETES OPENSTACK TERRAFORM' -- "${cur}") ;; UNINSTALL) - mapfile -t COMPREPLY < <(compgen -W 'ANSIBLE AWS AZURE BASH-RL C++ CASSANDRA COLORTOOL COPILOT-CLI COPILOT-VIM DIGITALOCEAN DOCKER DOTNET FCITX FISH GO GUILIB HIDPI HOMEBREW IBM IBUS JAVA JETBRAINS KEYCHAIN KUBERNETES LAMP MSEDIT NIM NODEJS OPENSTACK POETRY POWERSHELL PYENV RCLOCAL RUBY RUST STARTMENU SSH SYNAPTIC SYSTEMD TERRAFORM VCXSRV VSCODE WINTHEME WSLTTY X410 XFCE' -- "${cur}") + mapfile -t COMPREPLY < <(compgen -W 'ANSIBLE AWS AZURE BASH-RL C++ CASSANDRA COLORTOOL COPILOT-CLI COPILOT-VIM DIGITALOCEAN DOCKER DOTNET FCITX FISH GO GUILIB HIDPI HOMEBREW IBM IBUS JAVA JETBRAINS KEYCHAIN KUBERNETES LAMP MSEDIT NIM NODEJS OPENSTACK POETRY POWERSHELL PYENV RCLOCAL RUBY RUST SHELLINT STARTMENU SSH SYNAPTIC SYSTEMD TERRAFORM VCXSRV VSCODE WINTHEME WSLTTY X410 XFCE' -- "${cur}") ;; *) mapfile -t COMPREPLY < <(compgen -W "--debug -d --verbose -v -y --yes --assume-yes --noupdate --norebuildicons -q \ diff --git a/pengwin-setup.d/shell-integration.sh b/pengwin-setup.d/shell-integration.sh new file mode 100755 index 00000000..ce96a77b --- /dev/null +++ b/pengwin-setup.d/shell-integration.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# shellcheck source=common.sh +source "$(dirname "$0")/common.sh" "$@" + +#Imported from common.sh +declare HOME + +readonly PENGWIN_SHELL_INTEGRATION_MARKER='### PENGWIN WINDOWS TERMINAL SHELL INTEGRATION' + +####################################### +# Install Windows Terminal shell integration to ~/.bashrc +# Adds shell integration sequences for better terminal experience +# with marks for easy uninstallation +# Globals: +# HOME +# PENGWIN_SHELL_INTEGRATION_MARKER +# Arguments: +# None +####################################### +function install_shell_integration() { + echo "Installing Windows Terminal shell integration to ~/.bashrc" + + local bashrc="${HOME}/.bashrc" + + if [[ ! -f "${bashrc}" ]]; then + touch "${bashrc}" + fi + + # Check if already installed + if grep -q "${PENGWIN_SHELL_INTEGRATION_MARKER}" "${bashrc}" 2>/dev/null; then + echo "Previous Pengwin Windows Terminal shell integration detected. Cancelling install..." + message --title "Warning!" --msgbox "Previous install of Windows Terminal shell integration detected. To reinstall, please run the uninstaller first or manually edit \"${bashrc}\" and remove all text between (and including) the lines:\n${PENGWIN_SHELL_INTEGRATION_MARKER}" 10 95 + return 1 + fi + + # Add shell integration to .bashrc + # Based on: https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration + # and https://github.com/WhitewaterFoundry/pengwin-enterprise-rootfs-builds/blob/main/linux_files/bash-prompt-wsl.sh + cat >>"${bashrc}" </dev/null; then + inclusive_file_clean "${bashrc}" "${PENGWIN_SHELL_INTEGRATION_MARKER}" + echo "Windows Terminal shell integration removed successfully." + else + echo "... shell integration not found in ${bashrc}!" + fi + else + echo "... ${bashrc} not found!" + fi +} + +if show_warning "Windows Terminal shell integration" "$@"; then + main "$@" +fi diff --git a/tests/run_tests.sh b/tests/run_tests.sh index a45dbbb6..a45336e0 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -28,9 +28,11 @@ if [ -z "${CIRCLE_NODE_TOTAL}" ]; then run_test ./motd_settings.sh run_test ./kubernetes.sh run_test ./latex.sh + run_test ./shell-integration.sh elif [[ ${CIRCLE_NODE_INDEX} == $((i++)) ]]; then #0 run_test ./nodejs_nvm.sh run_test ./motd_settings.sh + run_test ./shell-integration.sh elif [[ ${CIRCLE_NODE_INDEX} == $((i++)) ]]; then #1 run_test ./desktop.sh run_test ./lamp.sh "BUILTIN" diff --git a/tests/shell-integration.sh b/tests/shell-integration.sh new file mode 100755 index 00000000..8e4b85a1 --- /dev/null +++ b/tests/shell-integration.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +source commons.sh + +declare TEST_USER + +readonly PENGWIN_SHELL_INTEGRATION_MARKER='### PENGWIN WINDOWS TERMINAL SHELL INTEGRATION' + +function test_main() { + run_pengwinsetup autoinstall SETTINGS SHELLS SHELLINT + + # Check that the shell integration was added to .bashrc + local bashrc="/home/${TEST_USER}/.bashrc" + + test -f "${bashrc}" + assertEquals ".bashrc file should exist" "0" "$?" + + grep -q "${PENGWIN_SHELL_INTEGRATION_MARKER}" "${bashrc}" + assertEquals "Shell integration marker should be present in .bashrc" "0" "$?" + + grep -q "__wt_update_prompt" "${bashrc}" + assertEquals "Shell integration function should be present in .bashrc" "0" "$?" + + grep -q "WT_SESSION" "${bashrc}" + assertEquals "WT_SESSION check should be present in .bashrc" "0" "$?" +} + +function test_uninstall() { + # First ensure it's installed + run_pengwinsetup autoinstall SETTINGS SHELLS SHELLINT + + # Then uninstall + run_pengwinsetup autoinstall UNINSTALL SHELLINT + + local bashrc="/home/${TEST_USER}/.bashrc" + + # Verify the shell integration was removed + if [[ -f "${bashrc}" ]]; then + grep -q "${PENGWIN_SHELL_INTEGRATION_MARKER}" "${bashrc}" + assertNotEquals "Shell integration marker should NOT be present after uninstall" "0" "$?" + + grep -q "__wt_update_prompt" "${bashrc}" + assertNotEquals "Shell integration function should NOT be present after uninstall" "0" "$?" + fi +} + +# shellcheck disable=SC1091 +source shunit2 From ace9ef013ae7cd833d06430a907c5e6d556d03a5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 11:45:52 +0000 Subject: [PATCH 03/10] Add clarifying comment about WezTerm support Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com> --- pengwin-setup.d/shell-integration.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/pengwin-setup.d/shell-integration.sh b/pengwin-setup.d/shell-integration.sh index ce96a77b..ba907446 100755 --- a/pengwin-setup.d/shell-integration.sh +++ b/pengwin-setup.d/shell-integration.sh @@ -41,6 +41,7 @@ function install_shell_integration() { ${PENGWIN_SHELL_INTEGRATION_MARKER} # Windows Terminal shell integration # See: https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration +# Also supports WezTerm which implements the same OSC sequences if [[ "\${TERM_PROGRAM}" == "WezTerm" || -n "\${WT_SESSION}" ]]; then __wt_osc() { printf '\e]%s\e\\' "\$1"; } From d91a9f8c0e4c59796e55adea3a04135120613d95 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 12:46:59 +0000 Subject: [PATCH 04/10] Fix shell integration to use PS0 for command executed mark (133;C) Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com> --- pengwin-setup.d/shell-integration.sh | 43 +++++++++++----------------- tests/shell-integration.sh | 11 ++++--- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/pengwin-setup.d/shell-integration.sh b/pengwin-setup.d/shell-integration.sh index ba907446..3d78340f 100755 --- a/pengwin-setup.d/shell-integration.sh +++ b/pengwin-setup.d/shell-integration.sh @@ -35,40 +35,31 @@ function install_shell_integration() { fi # Add shell integration to .bashrc - # Based on: https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration - # and https://github.com/WhitewaterFoundry/pengwin-enterprise-rootfs-builds/blob/main/linux_files/bash-prompt-wsl.sh - cat >>"${bashrc}" <>"${bashrc}" <<'BASHRC_EOF' ${PENGWIN_SHELL_INTEGRATION_MARKER} # Windows Terminal shell integration +# Based on: https://github.com/WhitewaterFoundry/pengwin-enterprise-rootfs-builds/blob/main/linux_files/bash-prompt-wsl.sh # See: https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration # Also supports WezTerm which implements the same OSC sequences -if [[ "\${TERM_PROGRAM}" == "WezTerm" || -n "\${WT_SESSION}" ]]; then - __wt_osc() { printf '\e]%s\e\\' "\$1"; } - - __wt_mark_prompt_start() { __wt_osc '133;A'; } - __wt_mark_command_start() { __wt_osc '133;B'; } - __wt_mark_command_executed() { __wt_osc "133;C;\$1"; } - __wt_mark_command_finished() { __wt_osc "133;D;\$1"; } - __wt_set_cwd() { __wt_osc "9;9;\${PWD}"; } - - __wt_update_prompt() { - local last_exit_code="\$?" - __wt_mark_command_finished "\${last_exit_code}" - __wt_set_cwd - __wt_mark_prompt_start - PS1="\${__wt_original_ps1}" - return "\${last_exit_code}" - } - - if [[ -z "\${__wt_original_ps1}" ]]; then - __wt_original_ps1="\${PS1}" - PROMPT_COMMAND="__wt_update_prompt\${PROMPT_COMMAND:+;}\${PROMPT_COMMAND}" - PS1="\[\$(__wt_mark_command_start)\]\${PS1}" +if [[ "${TERM_PROGRAM}" == "WezTerm" || -n "${WT_SESSION}" ]]; then + if [[ -z "${__wt_original_ps1}" ]]; then + __wt_original_ps1="${PS1}" + # PS0: Executed after command is read, before execution (marks command executed) + PS0='\[\e]133;C\e\\\]' + # PS1: 133;D;$? = command finished with exit code + # 133;A = prompt start + # 9;9;path = set current working directory + # 133;B = command input start (end of prompt) + PS1='\[\e]133;D;$?\e\\\]\[\e]133;A\e\\\]'"${__wt_original_ps1}"'\[\e]9;9;"$(wslpath -w "${PWD}" 2>/dev/null || echo "${PWD}")"\e\\\]\[\e]133;B\e\\\]' fi fi ${PENGWIN_SHELL_INTEGRATION_MARKER} +BASHRC_EOF -EOF + # Replace the marker placeholder in the output + sed -i "s|\${PENGWIN_SHELL_INTEGRATION_MARKER}|${PENGWIN_SHELL_INTEGRATION_MARKER}|g" "${bashrc}" echo "Windows Terminal shell integration installed successfully." message --title "Shell Integration Installed" --msgbox "Windows Terminal shell integration has been installed to ${bashrc}.\n\nPlease close and re-open your terminal or run 'source ~/.bashrc' to apply the changes.\n\nThis provides:\n- Command marks for scroll-to-command\n- Current working directory tracking\n- Command exit status reporting" 14 80 diff --git a/tests/shell-integration.sh b/tests/shell-integration.sh index 8e4b85a1..f2898927 100755 --- a/tests/shell-integration.sh +++ b/tests/shell-integration.sh @@ -18,8 +18,11 @@ function test_main() { grep -q "${PENGWIN_SHELL_INTEGRATION_MARKER}" "${bashrc}" assertEquals "Shell integration marker should be present in .bashrc" "0" "$?" - grep -q "__wt_update_prompt" "${bashrc}" - assertEquals "Shell integration function should be present in .bashrc" "0" "$?" + grep -q "PS0=" "${bashrc}" + assertEquals "PS0 should be set in .bashrc for command executed mark" "0" "$?" + + grep -q "133;C" "${bashrc}" + assertEquals "Command executed mark (133;C) should be present in .bashrc" "0" "$?" grep -q "WT_SESSION" "${bashrc}" assertEquals "WT_SESSION check should be present in .bashrc" "0" "$?" @@ -39,8 +42,8 @@ function test_uninstall() { grep -q "${PENGWIN_SHELL_INTEGRATION_MARKER}" "${bashrc}" assertNotEquals "Shell integration marker should NOT be present after uninstall" "0" "$?" - grep -q "__wt_update_prompt" "${bashrc}" - assertNotEquals "Shell integration function should NOT be present after uninstall" "0" "$?" + grep -q "PS0=" "${bashrc}" + assertNotEquals "PS0 should NOT be present after uninstall" "0" "$?" fi } From f562e00f6f0420493210fedaba21524e8f0c8a0e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 12:52:03 +0000 Subject: [PATCH 05/10] Restore cleaner implementation with wrapper functions, add missing PS0 Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com> --- pengwin-setup.d/shell-integration.sh | 45 +++++++++++++++++----------- tests/shell-integration.sh | 12 ++++---- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/pengwin-setup.d/shell-integration.sh b/pengwin-setup.d/shell-integration.sh index 3d78340f..08c275cd 100755 --- a/pengwin-setup.d/shell-integration.sh +++ b/pengwin-setup.d/shell-integration.sh @@ -35,31 +35,42 @@ function install_shell_integration() { fi # Add shell integration to .bashrc - # Based on: https://github.com/WhitewaterFoundry/pengwin-enterprise-rootfs-builds/blob/main/linux_files/bash-prompt-wsl.sh - # and https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration - cat >>"${bashrc}" <<'BASHRC_EOF' + # Based on: https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration + # and https://github.com/WhitewaterFoundry/pengwin-enterprise-rootfs-builds/blob/main/linux_files/bash-prompt-wsl.sh + cat >>"${bashrc}" </dev/null || echo "${PWD}")"\e\\\]\[\e]133;B\e\\\]' +if [[ "\${TERM_PROGRAM}" == "WezTerm" || -n "\${WT_SESSION}" ]]; then + __wt_osc() { printf '\e]%s\e\\' "\$1"; } + + __wt_mark_prompt_start() { __wt_osc '133;A'; } + __wt_mark_command_start() { __wt_osc '133;B'; } + __wt_mark_command_executed() { __wt_osc "133;C;\$1"; } + __wt_mark_command_finished() { __wt_osc "133;D;\$1"; } + __wt_set_cwd() { __wt_osc "9;9;\${PWD}"; } + + __wt_update_prompt() { + local last_exit_code="\$?" + __wt_mark_command_finished "\${last_exit_code}" + __wt_set_cwd + __wt_mark_prompt_start + PS1="\${__wt_original_ps1}" + return "\${last_exit_code}" + } + + if [[ -z "\${__wt_original_ps1}" ]]; then + __wt_original_ps1="\${PS1}" + PROMPT_COMMAND="__wt_update_prompt\${PROMPT_COMMAND:+;}\${PROMPT_COMMAND}" + PS1="\[\$(__wt_mark_command_start)\]\${PS1}" + # PS0 is executed after reading a command but before executing it + PS0='\[\$(__wt_mark_command_executed)\]' fi fi ${PENGWIN_SHELL_INTEGRATION_MARKER} -BASHRC_EOF - # Replace the marker placeholder in the output - sed -i "s|\${PENGWIN_SHELL_INTEGRATION_MARKER}|${PENGWIN_SHELL_INTEGRATION_MARKER}|g" "${bashrc}" +EOF echo "Windows Terminal shell integration installed successfully." message --title "Shell Integration Installed" --msgbox "Windows Terminal shell integration has been installed to ${bashrc}.\n\nPlease close and re-open your terminal or run 'source ~/.bashrc' to apply the changes.\n\nThis provides:\n- Command marks for scroll-to-command\n- Current working directory tracking\n- Command exit status reporting" 14 80 diff --git a/tests/shell-integration.sh b/tests/shell-integration.sh index f2898927..b4ac596b 100755 --- a/tests/shell-integration.sh +++ b/tests/shell-integration.sh @@ -18,11 +18,11 @@ function test_main() { grep -q "${PENGWIN_SHELL_INTEGRATION_MARKER}" "${bashrc}" assertEquals "Shell integration marker should be present in .bashrc" "0" "$?" - grep -q "PS0=" "${bashrc}" - assertEquals "PS0 should be set in .bashrc for command executed mark" "0" "$?" + grep -q "__wt_update_prompt" "${bashrc}" + assertEquals "Shell integration function should be present in .bashrc" "0" "$?" - grep -q "133;C" "${bashrc}" - assertEquals "Command executed mark (133;C) should be present in .bashrc" "0" "$?" + grep -q "PS0=" "${bashrc}" + assertEquals "PS0 should be set for command executed mark" "0" "$?" grep -q "WT_SESSION" "${bashrc}" assertEquals "WT_SESSION check should be present in .bashrc" "0" "$?" @@ -42,8 +42,8 @@ function test_uninstall() { grep -q "${PENGWIN_SHELL_INTEGRATION_MARKER}" "${bashrc}" assertNotEquals "Shell integration marker should NOT be present after uninstall" "0" "$?" - grep -q "PS0=" "${bashrc}" - assertNotEquals "PS0 should NOT be present after uninstall" "0" "$?" + grep -q "__wt_update_prompt" "${bashrc}" + assertNotEquals "Shell integration function should NOT be present after uninstall" "0" "$?" fi } From c74cfcdc8f1397c328fa46fd952feed3f9befae6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 12:57:17 +0000 Subject: [PATCH 06/10] Move shell integration to separate file in /etc/profile.d to reduce .bashrc clutter Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com> --- pengwin-setup.d/shell-integration.sh | 59 +++++++++++-------- .../uninstall/shell-integration.sh | 20 ++++++- tests/shell-integration.sh | 29 +++++---- 3 files changed, 72 insertions(+), 36 deletions(-) diff --git a/pengwin-setup.d/shell-integration.sh b/pengwin-setup.d/shell-integration.sh index 08c275cd..09be9c74 100755 --- a/pengwin-setup.d/shell-integration.sh +++ b/pengwin-setup.d/shell-integration.sh @@ -7,19 +7,20 @@ source "$(dirname "$0")/common.sh" "$@" declare HOME readonly PENGWIN_SHELL_INTEGRATION_MARKER='### PENGWIN WINDOWS TERMINAL SHELL INTEGRATION' +readonly SHELL_INTEGRATION_SCRIPT='/etc/profile.d/wt-shell-integration.sh' ####################################### -# Install Windows Terminal shell integration to ~/.bashrc -# Adds shell integration sequences for better terminal experience -# with marks for easy uninstallation +# Install Windows Terminal shell integration +# Installs script to /etc/profile.d and adds source line to ~/.bashrc # Globals: # HOME # PENGWIN_SHELL_INTEGRATION_MARKER +# SHELL_INTEGRATION_SCRIPT # Arguments: # None ####################################### function install_shell_integration() { - echo "Installing Windows Terminal shell integration to ~/.bashrc" + echo "Installing Windows Terminal shell integration" local bashrc="${HOME}/.bashrc" @@ -30,50 +31,62 @@ function install_shell_integration() { # Check if already installed if grep -q "${PENGWIN_SHELL_INTEGRATION_MARKER}" "${bashrc}" 2>/dev/null; then echo "Previous Pengwin Windows Terminal shell integration detected. Cancelling install..." - message --title "Warning!" --msgbox "Previous install of Windows Terminal shell integration detected. To reinstall, please run the uninstaller first or manually edit \"${bashrc}\" and remove all text between (and including) the lines:\n${PENGWIN_SHELL_INTEGRATION_MARKER}" 10 95 + message --title "Warning!" --msgbox "Previous install of Windows Terminal shell integration detected. To reinstall, please run the uninstaller first or manually edit \"${bashrc}\" and remove the lines between:\n${PENGWIN_SHELL_INTEGRATION_MARKER}" 10 95 return 1 fi - # Add shell integration to .bashrc + # Install shell integration script to /etc/profile.d # Based on: https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration # and https://github.com/WhitewaterFoundry/pengwin-enterprise-rootfs-builds/blob/main/linux_files/bash-prompt-wsl.sh - cat >>"${bashrc}" </dev/null <<'SCRIPT_EOF' +#!/bin/bash # Windows Terminal shell integration # See: https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration # Also supports WezTerm which implements the same OSC sequences -if [[ "\${TERM_PROGRAM}" == "WezTerm" || -n "\${WT_SESSION}" ]]; then - __wt_osc() { printf '\e]%s\e\\' "\$1"; } + +# Only run for bash in Windows Terminal or WezTerm +if [[ -z "${BASH_VERSION}" ]]; then + return 0 +fi + +if [[ "${TERM_PROGRAM}" == "WezTerm" || -n "${WT_SESSION}" ]]; then + __wt_osc() { printf '\e]%s\e\\' "$1"; } __wt_mark_prompt_start() { __wt_osc '133;A'; } __wt_mark_command_start() { __wt_osc '133;B'; } - __wt_mark_command_executed() { __wt_osc "133;C;\$1"; } - __wt_mark_command_finished() { __wt_osc "133;D;\$1"; } - __wt_set_cwd() { __wt_osc "9;9;\${PWD}"; } + __wt_mark_command_executed() { __wt_osc '133;C'; } + __wt_mark_command_finished() { __wt_osc "133;D;$1"; } + __wt_set_cwd() { __wt_osc "9;9;${PWD}"; } __wt_update_prompt() { - local last_exit_code="\$?" - __wt_mark_command_finished "\${last_exit_code}" + local last_exit_code="$?" + __wt_mark_command_finished "${last_exit_code}" __wt_set_cwd __wt_mark_prompt_start - PS1="\${__wt_original_ps1}" - return "\${last_exit_code}" + PS1="${__wt_original_ps1}" + return "${last_exit_code}" } - if [[ -z "\${__wt_original_ps1}" ]]; then - __wt_original_ps1="\${PS1}" - PROMPT_COMMAND="__wt_update_prompt\${PROMPT_COMMAND:+;}\${PROMPT_COMMAND}" - PS1="\[\$(__wt_mark_command_start)\]\${PS1}" + if [[ -z "${__wt_original_ps1}" ]]; then + __wt_original_ps1="${PS1}" + PROMPT_COMMAND="__wt_update_prompt${PROMPT_COMMAND:+;}${PROMPT_COMMAND}" + PS1="\[\$(__wt_mark_command_start)\]${PS1}" # PS0 is executed after reading a command but before executing it PS0='\[\$(__wt_mark_command_executed)\]' fi fi -${PENGWIN_SHELL_INTEGRATION_MARKER} +SCRIPT_EOF + # Add minimal source line to .bashrc (since PS1 modifications need to happen after .bashrc sets PS1) + cat >>"${bashrc}" </dev/null; then inclusive_file_clean "${bashrc}" "${PENGWIN_SHELL_INTEGRATION_MARKER}" - echo "Windows Terminal shell integration removed successfully." + echo "Source line removed from ${bashrc}" else echo "... shell integration not found in ${bashrc}!" fi else echo "... ${bashrc} not found!" fi + + # Remove the shell integration script from /etc/profile.d + echo "Removing ${SHELL_INTEGRATION_SCRIPT}" + if [[ -f "${SHELL_INTEGRATION_SCRIPT}" ]]; then + sudo rm -f "${SHELL_INTEGRATION_SCRIPT}" + echo "Shell integration script removed." + else + echo "... script not found!" + fi + + echo "Windows Terminal shell integration uninstalled successfully." } if show_warning "Windows Terminal shell integration" "$@"; then diff --git a/tests/shell-integration.sh b/tests/shell-integration.sh index b4ac596b..d29b658c 100755 --- a/tests/shell-integration.sh +++ b/tests/shell-integration.sh @@ -5,11 +5,12 @@ source commons.sh declare TEST_USER readonly PENGWIN_SHELL_INTEGRATION_MARKER='### PENGWIN WINDOWS TERMINAL SHELL INTEGRATION' +readonly SHELL_INTEGRATION_SCRIPT='/etc/profile.d/wt-shell-integration.sh' function test_main() { run_pengwinsetup autoinstall SETTINGS SHELLS SHELLINT - # Check that the shell integration was added to .bashrc + # Check that the source line was added to .bashrc local bashrc="/home/${TEST_USER}/.bashrc" test -f "${bashrc}" @@ -18,14 +19,21 @@ function test_main() { grep -q "${PENGWIN_SHELL_INTEGRATION_MARKER}" "${bashrc}" assertEquals "Shell integration marker should be present in .bashrc" "0" "$?" - grep -q "__wt_update_prompt" "${bashrc}" - assertEquals "Shell integration function should be present in .bashrc" "0" "$?" + grep -q "wt-shell-integration.sh" "${bashrc}" + assertEquals "Source line for shell integration script should be present in .bashrc" "0" "$?" - grep -q "PS0=" "${bashrc}" + # Check that the script was installed to /etc/profile.d + test -f "${SHELL_INTEGRATION_SCRIPT}" + assertEquals "Shell integration script should exist in /etc/profile.d" "0" "$?" + + grep -q "__wt_update_prompt" "${SHELL_INTEGRATION_SCRIPT}" + assertEquals "Shell integration function should be present in script" "0" "$?" + + grep -q "PS0=" "${SHELL_INTEGRATION_SCRIPT}" assertEquals "PS0 should be set for command executed mark" "0" "$?" - grep -q "WT_SESSION" "${bashrc}" - assertEquals "WT_SESSION check should be present in .bashrc" "0" "$?" + grep -q "WT_SESSION" "${SHELL_INTEGRATION_SCRIPT}" + assertEquals "WT_SESSION check should be present in script" "0" "$?" } function test_uninstall() { @@ -37,14 +45,15 @@ function test_uninstall() { local bashrc="/home/${TEST_USER}/.bashrc" - # Verify the shell integration was removed + # Verify the source line was removed from .bashrc if [[ -f "${bashrc}" ]]; then grep -q "${PENGWIN_SHELL_INTEGRATION_MARKER}" "${bashrc}" assertNotEquals "Shell integration marker should NOT be present after uninstall" "0" "$?" - - grep -q "__wt_update_prompt" "${bashrc}" - assertNotEquals "Shell integration function should NOT be present after uninstall" "0" "$?" fi + + # Verify the script was removed from /etc/profile.d + test -f "${SHELL_INTEGRATION_SCRIPT}" + assertNotEquals "Shell integration script should NOT exist after uninstall" "0" "$?" } # shellcheck disable=SC1091 From 71a9a7b9ba63991e0f5107c8b11e5264da1c30cf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 13:02:47 +0000 Subject: [PATCH 07/10] Move shell integration script to /usr/local/share/pengwin to avoid profile.d execution order issues Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com> --- pengwin-setup.d/shell-integration.sh | 11 ++++++++--- pengwin-setup.d/uninstall/shell-integration.sh | 7 ++++--- tests/shell-integration.sh | 8 ++++---- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/pengwin-setup.d/shell-integration.sh b/pengwin-setup.d/shell-integration.sh index 09be9c74..28859407 100755 --- a/pengwin-setup.d/shell-integration.sh +++ b/pengwin-setup.d/shell-integration.sh @@ -7,14 +7,16 @@ source "$(dirname "$0")/common.sh" "$@" declare HOME readonly PENGWIN_SHELL_INTEGRATION_MARKER='### PENGWIN WINDOWS TERMINAL SHELL INTEGRATION' -readonly SHELL_INTEGRATION_SCRIPT='/etc/profile.d/wt-shell-integration.sh' +readonly SHELL_INTEGRATION_DIR='/usr/local/share/pengwin' +readonly SHELL_INTEGRATION_SCRIPT="${SHELL_INTEGRATION_DIR}/wt-shell-integration.sh" ####################################### # Install Windows Terminal shell integration -# Installs script to /etc/profile.d and adds source line to ~/.bashrc +# Installs script to /usr/local/share/pengwin and adds source line to ~/.bashrc # Globals: # HOME # PENGWIN_SHELL_INTEGRATION_MARKER +# SHELL_INTEGRATION_DIR # SHELL_INTEGRATION_SCRIPT # Arguments: # None @@ -35,7 +37,10 @@ function install_shell_integration() { return 1 fi - # Install shell integration script to /etc/profile.d + # Create the directory if it doesn't exist + sudo mkdir -p "${SHELL_INTEGRATION_DIR}" + + # Install shell integration script # Based on: https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration # and https://github.com/WhitewaterFoundry/pengwin-enterprise-rootfs-builds/blob/main/linux_files/bash-prompt-wsl.sh sudo tee "${SHELL_INTEGRATION_SCRIPT}" >/dev/null <<'SCRIPT_EOF' diff --git a/pengwin-setup.d/uninstall/shell-integration.sh b/pengwin-setup.d/uninstall/shell-integration.sh index 4e3b2098..f393c94f 100755 --- a/pengwin-setup.d/uninstall/shell-integration.sh +++ b/pengwin-setup.d/uninstall/shell-integration.sh @@ -8,11 +8,12 @@ declare HOME # We need to delete everything between 2 instances of this string readonly PENGWIN_SHELL_INTEGRATION_MARKER='### PENGWIN WINDOWS TERMINAL SHELL INTEGRATION' -readonly SHELL_INTEGRATION_SCRIPT='/etc/profile.d/wt-shell-integration.sh' +readonly SHELL_INTEGRATION_DIR='/usr/local/share/pengwin' +readonly SHELL_INTEGRATION_SCRIPT="${SHELL_INTEGRATION_DIR}/wt-shell-integration.sh" ####################################### # Uninstall Windows Terminal shell integration -# Removes the source line from ~/.bashrc and the script from /etc/profile.d +# Removes the source line from ~/.bashrc and the script from /usr/local/share/pengwin # Globals: # HOME # PENGWIN_SHELL_INTEGRATION_MARKER @@ -38,7 +39,7 @@ function main() { echo "... ${bashrc} not found!" fi - # Remove the shell integration script from /etc/profile.d + # Remove the shell integration script echo "Removing ${SHELL_INTEGRATION_SCRIPT}" if [[ -f "${SHELL_INTEGRATION_SCRIPT}" ]]; then sudo rm -f "${SHELL_INTEGRATION_SCRIPT}" diff --git a/tests/shell-integration.sh b/tests/shell-integration.sh index d29b658c..47c82d4b 100755 --- a/tests/shell-integration.sh +++ b/tests/shell-integration.sh @@ -5,7 +5,7 @@ source commons.sh declare TEST_USER readonly PENGWIN_SHELL_INTEGRATION_MARKER='### PENGWIN WINDOWS TERMINAL SHELL INTEGRATION' -readonly SHELL_INTEGRATION_SCRIPT='/etc/profile.d/wt-shell-integration.sh' +readonly SHELL_INTEGRATION_SCRIPT='/usr/local/share/pengwin/wt-shell-integration.sh' function test_main() { run_pengwinsetup autoinstall SETTINGS SHELLS SHELLINT @@ -22,9 +22,9 @@ function test_main() { grep -q "wt-shell-integration.sh" "${bashrc}" assertEquals "Source line for shell integration script should be present in .bashrc" "0" "$?" - # Check that the script was installed to /etc/profile.d + # Check that the script was installed to /usr/local/share/pengwin test -f "${SHELL_INTEGRATION_SCRIPT}" - assertEquals "Shell integration script should exist in /etc/profile.d" "0" "$?" + assertEquals "Shell integration script should exist" "0" "$?" grep -q "__wt_update_prompt" "${SHELL_INTEGRATION_SCRIPT}" assertEquals "Shell integration function should be present in script" "0" "$?" @@ -51,7 +51,7 @@ function test_uninstall() { assertNotEquals "Shell integration marker should NOT be present after uninstall" "0" "$?" fi - # Verify the script was removed from /etc/profile.d + # Verify the script was removed test -f "${SHELL_INTEGRATION_SCRIPT}" assertNotEquals "Shell integration script should NOT exist after uninstall" "0" "$?" } From c5e2e15f11d736fb9374af1c15ee70116dc0bf5b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 13:13:36 +0000 Subject: [PATCH 08/10] Use sudo_rem_file helper, add enable_should_restart, remove redundant comment Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com> --- pengwin-setup.d/shell-integration.sh | 4 ++-- pengwin-setup.d/uninstall/shell-integration.sh | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/pengwin-setup.d/shell-integration.sh b/pengwin-setup.d/shell-integration.sh index 28859407..a2147399 100755 --- a/pengwin-setup.d/shell-integration.sh +++ b/pengwin-setup.d/shell-integration.sh @@ -42,7 +42,6 @@ function install_shell_integration() { # Install shell integration script # Based on: https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration - # and https://github.com/WhitewaterFoundry/pengwin-enterprise-rootfs-builds/blob/main/linux_files/bash-prompt-wsl.sh sudo tee "${SHELL_INTEGRATION_SCRIPT}" >/dev/null <<'SCRIPT_EOF' #!/bin/bash # Windows Terminal shell integration @@ -91,7 +90,8 @@ ${PENGWIN_SHELL_INTEGRATION_MARKER} EOF echo "Windows Terminal shell integration installed successfully." - message --title "Shell Integration Installed" --msgbox "Windows Terminal shell integration has been installed.\n\nScript location: ${SHELL_INTEGRATION_SCRIPT}\nSource added to: ${bashrc}\n\nPlease close and re-open your terminal or run 'source ~/.bashrc' to apply the changes.\n\nThis provides:\n- Command marks for scroll-to-command\n- Current working directory tracking\n- Command exit status reporting" 16 80 + enable_should_restart + message --title "Shell Integration Installed" --msgbox "Windows Terminal shell integration has been installed.\n\nScript location: ${SHELL_INTEGRATION_SCRIPT}\nSource added to: ${bashrc}\n\nPlease close and re-open Pengwin to apply the changes.\n\nThis provides:\n- Command marks for scroll-to-command\n- Current working directory tracking\n- Command exit status reporting" 16 80 } if (confirm --title "Windows Terminal Shell Integration" --yesno "Would you like to install Windows Terminal shell integration?\n\nThis adds special escape sequences to your bash prompt that enable:\n- Scroll to command feature in Windows Terminal\n- Current working directory tracking\n- Command exit status tracking\n\nThe changes will be added to ~/.bashrc with markers for easy removal." 15 80); then diff --git a/pengwin-setup.d/uninstall/shell-integration.sh b/pengwin-setup.d/uninstall/shell-integration.sh index f393c94f..99187d71 100755 --- a/pengwin-setup.d/uninstall/shell-integration.sh +++ b/pengwin-setup.d/uninstall/shell-integration.sh @@ -41,12 +41,7 @@ function main() { # Remove the shell integration script echo "Removing ${SHELL_INTEGRATION_SCRIPT}" - if [[ -f "${SHELL_INTEGRATION_SCRIPT}" ]]; then - sudo rm -f "${SHELL_INTEGRATION_SCRIPT}" - echo "Shell integration script removed." - else - echo "... script not found!" - fi + sudo_rem_file "${SHELL_INTEGRATION_SCRIPT}" echo "Windows Terminal shell integration uninstalled successfully." } From 0178160bb50565320b4e95ddf1b30ee7316e6191 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 16:15:07 +0000 Subject: [PATCH 09/10] Fix PS0 command substitution - remove backslash before $ in single quotes Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com> --- pengwin-setup.d/shell-integration.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pengwin-setup.d/shell-integration.sh b/pengwin-setup.d/shell-integration.sh index a2147399..42fa3c96 100755 --- a/pengwin-setup.d/shell-integration.sh +++ b/pengwin-setup.d/shell-integration.sh @@ -76,7 +76,7 @@ if [[ "${TERM_PROGRAM}" == "WezTerm" || -n "${WT_SESSION}" ]]; then PROMPT_COMMAND="__wt_update_prompt${PROMPT_COMMAND:+;}${PROMPT_COMMAND}" PS1="\[\$(__wt_mark_command_start)\]${PS1}" # PS0 is executed after reading a command but before executing it - PS0='\[\$(__wt_mark_command_executed)\]' + PS0='\[$(__wt_mark_command_executed)\]' fi fi SCRIPT_EOF From e5e903fd995ced69e6f739601e8e23f4c4d0de57 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 16:19:34 +0000 Subject: [PATCH 10/10] Fix: Preserve command-start OSC marker in prompt updates Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com> --- pengwin-setup.d/shell-integration.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pengwin-setup.d/shell-integration.sh b/pengwin-setup.d/shell-integration.sh index 42fa3c96..2a9a7fd2 100755 --- a/pengwin-setup.d/shell-integration.sh +++ b/pengwin-setup.d/shell-integration.sh @@ -67,7 +67,7 @@ if [[ "${TERM_PROGRAM}" == "WezTerm" || -n "${WT_SESSION}" ]]; then __wt_mark_command_finished "${last_exit_code}" __wt_set_cwd __wt_mark_prompt_start - PS1="${__wt_original_ps1}" + PS1="\[\$(__wt_mark_command_start)\]${__wt_original_ps1}" return "${last_exit_code}" }