Skip to content

Commit e8fdc51

Browse files
committed
Allow customizing the new line keybinding in the CLI
Signed-off-by: Trae Robrock <[email protected]>
1 parent 039a845 commit e8fdc51

File tree

2 files changed

+60
-5
lines changed

2 files changed

+60
-5
lines changed

crates/goose-cli/src/session/input.rs

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,24 @@ impl rustyline::ConditionalEventHandler for CtrlCHandler {
5454
}
5555
}
5656

57+
pub fn get_newline_key() -> char {
58+
std::env::var("GOOSE_CLI_NEWLINE_KEY")
59+
.ok()
60+
.and_then(|s| s.chars().next())
61+
.map(|c| c.to_ascii_lowercase())
62+
.unwrap_or('j')
63+
}
64+
5765
pub fn get_input(
5866
editor: &mut Editor<GooseCompleter, rustyline::history::DefaultHistory>,
5967
) -> Result<InputResult> {
60-
// Ensure Ctrl-J binding is set for newlines
68+
// Ensure Ctrl+<key> binding is set for newlines (configurable via GOOSE_CLI_NEWLINE_KEY)
69+
let newline_key = get_newline_key();
6170
editor.bind_sequence(
62-
rustyline::KeyEvent(rustyline::KeyCode::Char('j'), rustyline::Modifiers::CTRL),
71+
rustyline::KeyEvent(
72+
rustyline::KeyCode::Char(newline_key),
73+
rustyline::Modifiers::CTRL,
74+
),
6375
rustyline::EventHandler::Simple(rustyline::Cmd::Newline),
6476
);
6577

@@ -295,6 +307,7 @@ fn get_input_prompt_string() -> String {
295307
}
296308

297309
fn print_help() {
310+
let newline_key = get_newline_key().to_ascii_uppercase();
298311
println!(
299312
"Available commands:
300313
/exit or /quit - Exit the session
@@ -319,7 +332,7 @@ fn print_help() {
319332
320333
Navigation:
321334
Ctrl+C - Clear current line if text is entered, otherwise exit the session
322-
Ctrl+J - Add a newline
335+
Ctrl+{newline_key} - Add a newline (configurable via GOOSE_CLI_NEWLINE_KEY)
323336
Up/Down arrows - Navigate through command history"
324337
);
325338
}
@@ -588,4 +601,45 @@ mod tests {
588601
}
589602
}
590603
}
604+
605+
#[test]
606+
fn test_get_newline_key_default() {
607+
// Clear the env var to test default behavior
608+
std::env::remove_var("GOOSE_CLI_NEWLINE_KEY");
609+
assert_eq!(get_newline_key(), 'j');
610+
}
611+
612+
#[test]
613+
fn test_get_newline_key_custom() {
614+
// Test setting a custom key
615+
std::env::set_var("GOOSE_CLI_NEWLINE_KEY", "o");
616+
assert_eq!(get_newline_key(), 'o');
617+
618+
// Test uppercase is converted to lowercase
619+
std::env::set_var("GOOSE_CLI_NEWLINE_KEY", "N");
620+
assert_eq!(get_newline_key(), 'n');
621+
622+
// Clean up
623+
std::env::remove_var("GOOSE_CLI_NEWLINE_KEY");
624+
}
625+
626+
#[test]
627+
fn test_get_newline_key_empty_string() {
628+
// Test empty string falls back to default
629+
std::env::set_var("GOOSE_CLI_NEWLINE_KEY", "");
630+
assert_eq!(get_newline_key(), 'j');
631+
632+
// Clean up
633+
std::env::remove_var("GOOSE_CLI_NEWLINE_KEY");
634+
}
635+
636+
#[test]
637+
fn test_get_newline_key_first_char_only() {
638+
// Test only first character is used
639+
std::env::set_var("GOOSE_CLI_NEWLINE_KEY", "abc");
640+
assert_eq!(get_newline_key(), 'a');
641+
642+
// Clean up
643+
std::env::remove_var("GOOSE_CLI_NEWLINE_KEY");
644+
}
591645
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/// Returns a system prompt extension that explains CLI-specific functionality
22
pub fn get_cli_prompt() -> String {
3-
String::from(
3+
let newline_key = super::input::get_newline_key().to_ascii_uppercase();
4+
format!(
45
"You are being accessed through a command-line interface. The following slash commands are available
56
- you can let the user know about them if they need help:
67
@@ -10,7 +11,7 @@ pub fn get_cli_prompt() -> String {
1011
1112
Additional keyboard shortcuts:
1213
- Ctrl+C - Interrupt the current interaction (resets to before the interrupted request)
13-
- Ctrl+J - Add a newline
14+
- Ctrl+{newline_key} - Add a newline
1415
- Up/Down arrows - Navigate command history"
1516
)
1617
}

0 commit comments

Comments
 (0)