fix: Windows prompt cursor positioning issue with ANSI escape sequences (#4464)
Signed-off-by: Matt Donovan <mattddonovan@protonmail.com> Co-authored-by: Matt Donovan <mattddonovan@protonmail.com>
This commit is contained in:
@@ -68,7 +68,7 @@ pub fn get_input(
|
|||||||
rustyline::EventHandler::Conditional(Box::new(CtrlCHandler)),
|
rustyline::EventHandler::Conditional(Box::new(CtrlCHandler)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let prompt = format!("{} ", console::style("( O)>").cyan().bold());
|
let prompt = get_input_prompt_string();
|
||||||
|
|
||||||
let input = match editor.readline(&prompt) {
|
let input = match editor.readline(&prompt) {
|
||||||
Ok(text) => text,
|
Ok(text) => text,
|
||||||
@@ -271,6 +271,21 @@ fn parse_plan_command(input: String) -> Option<InputResult> {
|
|||||||
Some(InputResult::Plan(options))
|
Some(InputResult::Plan(options))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generates the input prompt string for the CLI interface.
|
||||||
|
/// Returns a styled prompt with the goose face "( O)>" followed by a space.
|
||||||
|
/// On Windows, returns plain text without ANSI styling for better compatibility.
|
||||||
|
/// On other platforms, applies styling using ANSI escape codes.
|
||||||
|
fn get_input_prompt_string() -> String {
|
||||||
|
let goose = "( O)>";
|
||||||
|
if cfg!(target_os = "windows") {
|
||||||
|
// Use plain text on Windows to avoid ANSI compatibility issues
|
||||||
|
format!("{goose} ")
|
||||||
|
} else {
|
||||||
|
// On other platforms, use styled prompt with ANSI colors
|
||||||
|
format!("{} ", console::style(goose).cyan().bold())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn print_help() {
|
fn print_help() {
|
||||||
println!(
|
println!(
|
||||||
"Available commands:
|
"Available commands:
|
||||||
@@ -536,4 +551,44 @@ mod tests {
|
|||||||
let result = handle_slash_command(" /summarize ");
|
let result = handle_slash_command(" /summarize ");
|
||||||
assert!(matches!(result, Some(InputResult::Summarize)));
|
assert!(matches!(result, Some(InputResult::Summarize)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_input_prompt_string() {
|
||||||
|
let prompt = get_input_prompt_string();
|
||||||
|
|
||||||
|
// Prompt should always end with a space
|
||||||
|
assert!(prompt.ends_with(" "));
|
||||||
|
|
||||||
|
// Prompt should contain the goose face
|
||||||
|
assert!(prompt.contains("( O)>"));
|
||||||
|
|
||||||
|
// On Windows, prompt should be plain text without ANSI codes
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
assert_eq!(prompt, "( O)> ");
|
||||||
|
// Ensure no ANSI escape sequences
|
||||||
|
assert!(!prompt.contains("\x1b["));
|
||||||
|
}
|
||||||
|
|
||||||
|
// On non-Windows, prompt behavior depends on terminal capabilities
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
{
|
||||||
|
// In CI environments, console crate may strip ANSI codes
|
||||||
|
let is_ci = std::env::var("CI").is_ok();
|
||||||
|
|
||||||
|
if is_ci {
|
||||||
|
// In CI, just verify basic structure - console crate handles ANSI detection
|
||||||
|
assert!(prompt.len() >= "( O)> ".len());
|
||||||
|
} else {
|
||||||
|
// In interactive terminals, expect styling to be applied
|
||||||
|
// Note: This may still vary based on terminal capabilities
|
||||||
|
assert!(prompt.len() >= "( O)> ".len());
|
||||||
|
|
||||||
|
// If ANSI codes are present, they should be valid
|
||||||
|
if prompt.contains("\x1b[") {
|
||||||
|
assert!(prompt.contains("36") || prompt.contains("1"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user