Skip to content
Merged
Show file tree
Hide file tree
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
20 changes: 17 additions & 3 deletions crates/goose-cli/src/session/input.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::completion::GooseCompleter;
use anyhow::Result;
use goose::config::Config;
use rustyline::Editor;
use shlex;
use std::collections::HashMap;
Expand Down Expand Up @@ -54,12 +55,24 @@ impl rustyline::ConditionalEventHandler for CtrlCHandler {
}
}

pub fn get_newline_key() -> char {
Config::global()
.get_param::<String>("GOOSE_CLI_NEWLINE_KEY")
.ok()
.and_then(|s| s.chars().next())
.map(|c| c.to_ascii_lowercase())
.unwrap_or('j')
}
Comment on lines +58 to +65
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

The get_newline_key() function lacks test coverage. Consider adding tests to verify: (1) default behavior when the environment variable is not set, (2) custom single-character values (both uppercase and lowercase), (3) empty string handling, (4) multi-character strings (verifying only the first character is used), and (5) non-ASCII character handling.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@DOsinga taking a look at other usages of settings, it seems like it's not typical to test this sort of logic like https://github.com/block/goose/blob/main/crates/goose-cli/src/session/builder.rs#L500

Though that's not in a separate function. What are your thoughts on these tests?

Loved the blog post btw.


pub fn get_input(
editor: &mut Editor<GooseCompleter, rustyline::history::DefaultHistory>,
) -> Result<InputResult> {
// Ensure Ctrl-J binding is set for newlines
let newline_key = get_newline_key();
editor.bind_sequence(
rustyline::KeyEvent(rustyline::KeyCode::Char('j'), rustyline::Modifiers::CTRL),
rustyline::KeyEvent(
rustyline::KeyCode::Char(newline_key),
rustyline::Modifiers::CTRL,
),
rustyline::EventHandler::Simple(rustyline::Cmd::Newline),
);

Expand Down Expand Up @@ -295,6 +308,7 @@ fn get_input_prompt_string() -> String {
}

fn print_help() {
let newline_key = get_newline_key().to_ascii_uppercase();
println!(
"Available commands:
/exit or /quit - Exit the session
Expand All @@ -319,7 +333,7 @@ fn print_help() {

Navigation:
Ctrl+C - Clear current line if text is entered, otherwise exit the session
Ctrl+J - Add a newline
Ctrl+{newline_key} - Add a newline (configurable via GOOSE_CLI_NEWLINE_KEY)
Up/Down arrows - Navigate through command history"
);
}
Expand Down
5 changes: 3 additions & 2 deletions crates/goose-cli/src/session/prompt.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// Returns a system prompt extension that explains CLI-specific functionality
pub fn get_cli_prompt() -> String {
String::from(
let newline_key = super::input::get_newline_key().to_ascii_uppercase();
format!(
"You are being accessed through a command-line interface. The following slash commands are available
- you can let the user know about them if they need help:

Expand All @@ -10,7 +11,7 @@ pub fn get_cli_prompt() -> String {

Additional keyboard shortcuts:
- Ctrl+C - Interrupt the current interaction (resets to before the interrupted request)
- Ctrl+J - Add a newline
- Ctrl+{newline_key} - Add a newline
- Up/Down arrows - Navigate command history"
)
}