Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions app/src/terminal/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,9 @@ use crate::terminal::shared_session::{
use crate::terminal::ssh::ssh_detection::SshInteractiveSessionDetected;
use crate::terminal::view::block_onboarding::onboarding_prompt_block::OnboardingPromptBlock;
use crate::terminal::warpify::{
render::render_subshell_separator, settings::WarpifySettings, SubshellSource,
render::render_subshell_separator,
settings::{WarpifySettings, PIPENV_SUBSHELL_COMMAND_REGEX, POETRY_SUBSHELL_COMMAND_REGEX},
SubshellSource,
};
use crate::terminal::ShellLaunchData;
use crate::terminal::{element_size_at_last_frame, HistoryEntry};
Expand Down Expand Up @@ -8036,7 +8038,12 @@ impl TerminalView {
}
}

self.write_init_subshell_bytes_to_pty(shell_type, ctx);
let is_pexpect_subshell = self.is_pexpect_subshell(ctx);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] This checks the already bootstrapped parent session, so subshell_info() is usually None before the poetry shell/pipenv shell subshell is initialized; the reported flow still falls back to sending Ctrl-U/Ctrl-K. Base this on the active block/banner command being warpified instead.

if is_pexpect_subshell {
self.write_init_subshell_bytes_to_pty_without_clearing(shell_type, ctx);
} else {
self.write_init_subshell_bytes_to_pty(shell_type, ctx);
}

if !self.env_vars.is_empty() {
self.start_bootstrap_timer(ENV_VAR_BOOTSTRAP_FAILED_DURATION, ctx);
Expand Down Expand Up @@ -13539,6 +13546,35 @@ impl TerminalView {
self.write_to_pty(vec![escape_sequences::C0::CR], ctx);
}

/// Writes the InitShell DCS hook to the PTY for pexpect-based subshells (poetry, pipenv).
/// Unlike `write_init_subshell_bytes_to_pty`, this method does not send Ctrl-U/Ctrl-K to clear
/// the line first, as these control characters interfere with pexpect's PTY management.
fn write_init_subshell_bytes_to_pty_without_clearing(
&mut self,
shell_type: Option<ShellType>,
ctx: &mut ViewContext<Self>,
) {
self.write_to_pty(
init_subshell_command(shell_type, &self.env_vars, ctx).into_bytes(),
ctx,
);
self.write_to_pty(vec![escape_sequences::C0::CR], ctx);
}

/// Returns true if the current subshell is a pexpect-based subshell (poetry or pipenv).
/// These subshells use pexpect's PTY management which is sensitive to control characters
/// like Ctrl-U and Ctrl-K.
fn is_pexpect_subshell(&self, ctx: &mut ViewContext<Self>) -> bool {
let Some(session) = self.active_session.session(ctx) else {
return false;
};
let Some(subshell_info) = session.subshell_info() else {
return false;
};
POETRY_SUBSHELL_COMMAND_REGEX.is_match(subshell_info.spawning_command.as_str())
|| PIPENV_SUBSHELL_COMMAND_REGEX.is_match(subshell_info.spawning_command.as_str())
}

/// If a command correction exists, generate the command correction banner.
fn after_command_correction_generation(
&mut self,
Expand Down