Skip to content
Merged
Changes from 1 commit
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
39 changes: 35 additions & 4 deletions crates/chat-cli/src/cli/chat/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,19 +473,19 @@ pub fn rl(
EventHandler::Simple(Cmd::Insert(1, "\n".to_string())),
);

// Add custom keybinding for Ctrl+J to insert a newline
// Add custom keybinding for Ctrl+j to insert a newline
rl.bind_sequence(
KeyEvent(KeyCode::Char('j'), Modifiers::CTRL),
EventHandler::Simple(Cmd::Insert(1, "\n".to_string())),
);

// Add custom keybinding for Ctrl+F to accept hint (like fish shell)
// Add custom keybinding for Ctrl+g to accept hint (like fish shell)
rl.bind_sequence(
KeyEvent(KeyCode::Char('f'), Modifiers::CTRL),
KeyEvent(KeyCode::Char('g'), Modifiers::CTRL),
Copy link
Contributor

Choose a reason for hiding this comment

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

We have precedent to make shortcuts customizable. We should probably follow suit there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah that feels like a separate feature request. Looking at the "TangentModeKey" code below we already have a mechanism to configure the key. My goal in this PR is to just make ctrl-f available.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah we can just copy the mechanism there and the whole debate about the right key ends. We had the same discussion during tangent mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the problem of setting up a good default value will not go away though, even when user can configure everything in the future. I am trying to solve the default value problem here.

Copy link
Contributor

Choose a reason for hiding this comment

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

https://fishshell.com/docs/current/interactive.html

Arguably the shortcut comment here is no longer accurate, as a fish user would expect Ctrl+f. Rather than just change the default key, I think we may want to just spend the time to build the config feature.

If we're strongly set on changing the key, we should remove that comment on L482, as it's not accurate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the latest PR I am allowing user to configure the key for autocompletion through:

cargo run --bin chat_cli -- settings chat.autocompletionKey o

This is following the existing config system built for tangent mode, fuzzy search, etc.

I am also changing the default from f to g

Choose a reason for hiding this comment

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

I don't think the issue is that Ctrl+f is a bad default, the issue is that Ctrl-f incorrectly attempts to autocomplete when an autocomplete suggestion isn't available. fish doesn't shadow the ability to move forward under normal circumstances. So the fundamental issue is a bug in the way Ctrl+f autocomplete behavior is implemented, not the default key.

EventHandler::Simple(Cmd::CompleteHint),
);

// Add custom keybinding for Ctrl+T to toggle tangent mode (configurable)
// Add custom keybinding for Ctrl+t to toggle tangent mode (configurable)
let tangent_key_char = match os.database.settings.get_string(Setting::TangentModeKey) {
Some(key) if key.len() == 1 => key.chars().next().unwrap_or('t'),
_ => 't', // Default to 't' if setting is missing or invalid
Expand Down Expand Up @@ -721,4 +721,35 @@ mod tests {
let hint = hinter.hint(line, pos, &ctx);
assert_eq!(hint, None);
}

#[tokio::test]
// If you get a unit test failure for key override, please consider using a new key binding instead.
// The list of reserved keybindings here are the standard in UNIX world so please don't take them
async fn test_no_emacs_keybindings_overridden() {
let (sender, _) = tokio::sync::broadcast::channel::<PromptQuery>(1);
let (_, receiver) = tokio::sync::broadcast::channel::<PromptQueryResult>(1);

// Create a mock Os for testing
let mock_os = crate::os::Os::new().await.unwrap();
let mut test_editor = rl(&mock_os, sender, receiver).unwrap();

// Reserved Emacs keybindings that should not be overridden
let reserved_keys = ['a', 'e', 'f', 'b', 'k'];

for &key in &reserved_keys {
let key_event = KeyEvent(KeyCode::Char(key), Modifiers::CTRL);

// Try to bind and get the previous handler
let previous_handler = test_editor.bind_sequence(
key_event,
EventHandler::Simple(Cmd::Noop)
);

// If there was a previous handler, it means the key was already bound
// (which could be our custom binding overriding Emacs)
if previous_handler.is_some() {
panic!("Ctrl+{} appears to be overridden (found existing binding)", key);
}
}
}
}