mirror of
https://github.com/openai/codex.git
synced 2026-10-21 07:42:01 +00:00
Show the voice toggle in the TUI shortcut overlay (#47082)
## What changed Add a Voice entry using the configured `toggle_voice` binding (`F8` by default). Show it only when voice commands are enabled and no side conversation is active. ## Testing Update footer and shortcut overlay snapshots to include the Voice entry. GitOrigin-RevId: ba92f5af1ce1a06d9700d31dcc90e5acb1613803
This commit is contained in:
@@ -761,6 +761,7 @@ impl ChatComposer {
|
||||
.primary_hint(KeymapContext::Chat, "decrease_reasoning_effort"),
|
||||
reasoning_up_key: default_keymap
|
||||
.primary_hint(KeymapContext::Chat, "increase_reasoning_effort"),
|
||||
toggle_voice_key: default_keymap.primary_hint(KeymapContext::Chat, "toggle_voice"),
|
||||
},
|
||||
has_focus: has_input_focus,
|
||||
frame_requester: None,
|
||||
@@ -1048,6 +1049,7 @@ impl ChatComposer {
|
||||
keymap.primary_hint(KeymapContext::Chat, "decrease_reasoning_effort");
|
||||
self.footer.reasoning_up_key =
|
||||
keymap.primary_hint(KeymapContext::Chat, "increase_reasoning_effort");
|
||||
self.footer.toggle_voice_key = keymap.primary_hint(KeymapContext::Chat, "toggle_voice");
|
||||
}
|
||||
|
||||
/// Return the contexts whose handlers can consume the next composer key.
|
||||
@@ -3865,6 +3867,10 @@ impl ChatComposer {
|
||||
history_search: self.footer.history_search_key,
|
||||
reasoning_down: self.footer.reasoning_down_key,
|
||||
reasoning_up: self.footer.reasoning_up_key,
|
||||
toggle_voice: self
|
||||
.footer
|
||||
.toggle_voice_key
|
||||
.filter(|_| self.voice_command_enabled && !self.side_conversation_active),
|
||||
},
|
||||
active_agent_label: self.footer.active_agent_label.clone(),
|
||||
}
|
||||
@@ -5088,50 +5094,6 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shortcut_footer_displays_configured_chords() {
|
||||
use codex_config::types::KeybindingSpec;
|
||||
use codex_config::types::KeybindingsSpec;
|
||||
use codex_config::types::TuiKeymap;
|
||||
|
||||
let mut config = TuiKeymap::default();
|
||||
config.global.open_external_editor = Some(KeybindingsSpec::One(KeybindingSpec(
|
||||
"ctrl-g ctrl-g".to_string(),
|
||||
)));
|
||||
config.editor.insert_newline = Some(KeybindingsSpec::One(KeybindingSpec(
|
||||
"ctrl-x enter".to_string(),
|
||||
)));
|
||||
let keymap = RuntimeKeymap::from_config(&config).expect("valid composer chords");
|
||||
let (mut composer, _rx) = new_test_composer();
|
||||
composer.set_keymap_bindings(&keymap);
|
||||
composer.footer.mode = FooterMode::ShortcutOverlay;
|
||||
|
||||
let hints = composer.footer_props().key_hints;
|
||||
assert_eq!(
|
||||
hints.external_editor,
|
||||
Some(ShortcutHint::Chord {
|
||||
prefix: key_hint::ctrl(KeyCode::Char('g')),
|
||||
completion: key_hint::ctrl(KeyCode::Char('g')),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
hints.insert_newline,
|
||||
Some(ShortcutHint::Chord {
|
||||
prefix: key_hint::ctrl(KeyCode::Char('x')),
|
||||
completion: key_hint::plain(KeyCode::Enter),
|
||||
})
|
||||
);
|
||||
|
||||
snapshot_composer_state(
|
||||
"footer_mode_configured_key_chords",
|
||||
/*enhanced_keys_supported*/ false,
|
||||
|composer| {
|
||||
composer.set_keymap_bindings(&keymap);
|
||||
composer.footer.mode = FooterMode::ShortcutOverlay;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parent_owned_thread_placeholder_snapshot() {
|
||||
snapshot_composer_state(
|
||||
|
||||
@@ -226,6 +226,7 @@ pub(super) struct FooterState {
|
||||
pub(super) history_search_key: Option<ShortcutHint>,
|
||||
pub(super) reasoning_down_key: Option<ShortcutHint>,
|
||||
pub(super) reasoning_up_key: Option<ShortcutHint>,
|
||||
pub(super) toggle_voice_key: Option<ShortcutHint>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
@@ -1,10 +1,62 @@
|
||||
//! Snapshot coverage for draft text and live voice controls in the composer.
|
||||
//! Snapshot coverage for draft text, shortcuts, and live voice controls in the composer.
|
||||
|
||||
use super::tests::new_test_composer;
|
||||
use super::tests::snapshot_composer_state_with_width;
|
||||
use crate::bottom_pane::footer::FooterMode;
|
||||
use crate::key_hint;
|
||||
use crate::key_hint::ShortcutHint;
|
||||
use crate::keymap::RuntimeKeymap;
|
||||
use crate::render::renderable::Renderable;
|
||||
use crossterm::event::KeyCode;
|
||||
use pretty_assertions::assert_eq;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::Rect;
|
||||
|
||||
#[test]
|
||||
fn shortcut_footer_displays_configured_chords() {
|
||||
use codex_config::types::KeybindingSpec;
|
||||
use codex_config::types::KeybindingsSpec;
|
||||
use codex_config::types::TuiKeymap;
|
||||
|
||||
let mut config = TuiKeymap::default();
|
||||
config.global.open_external_editor = Some(KeybindingsSpec::One(KeybindingSpec(
|
||||
"ctrl-g ctrl-g".to_string(),
|
||||
)));
|
||||
config.editor.insert_newline = Some(KeybindingsSpec::One(KeybindingSpec(
|
||||
"ctrl-x enter".to_string(),
|
||||
)));
|
||||
let keymap = RuntimeKeymap::from_config(&config).expect("valid composer chords");
|
||||
let (mut composer, _rx) = new_test_composer();
|
||||
composer.set_keymap_bindings(&keymap);
|
||||
composer.footer.mode = FooterMode::ShortcutOverlay;
|
||||
|
||||
let hints = composer.footer_props().key_hints;
|
||||
assert_eq!(
|
||||
hints.external_editor,
|
||||
Some(ShortcutHint::Chord {
|
||||
prefix: key_hint::ctrl(KeyCode::Char('g')),
|
||||
completion: key_hint::ctrl(KeyCode::Char('g')),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
hints.insert_newline,
|
||||
Some(ShortcutHint::Chord {
|
||||
prefix: key_hint::ctrl(KeyCode::Char('x')),
|
||||
completion: key_hint::plain(KeyCode::Enter),
|
||||
})
|
||||
);
|
||||
|
||||
snapshot_composer_state_with_width(
|
||||
"footer_mode_configured_key_chords",
|
||||
/*width*/ 100,
|
||||
/*enhanced_keys_supported*/ false,
|
||||
|composer| {
|
||||
composer.set_keymap_bindings(&keymap);
|
||||
composer.footer.mode = FooterMode::ShortcutOverlay;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn draft_and_voice_composer_snapshots() {
|
||||
use crate::bottom_pane::voice_strip::VoiceStripPhase;
|
||||
|
||||
@@ -123,6 +123,7 @@ pub(crate) struct FooterKeyHints {
|
||||
pub(crate) history_search: Option<ShortcutHint>,
|
||||
pub(crate) reasoning_down: Option<ShortcutHint>,
|
||||
pub(crate) reasoning_up: Option<ShortcutHint>,
|
||||
pub(crate) toggle_voice: Option<ShortcutHint>,
|
||||
}
|
||||
|
||||
impl FooterKeyHints {
|
||||
@@ -140,6 +141,7 @@ impl FooterKeyHints {
|
||||
history_search: Some(key_hint::ctrl(KeyCode::Char('r')).into()),
|
||||
reasoning_down: Some(key_hint::alt(KeyCode::Char(',')).into()),
|
||||
reasoning_up: Some(key_hint::alt(KeyCode::Char('.')).into()),
|
||||
toggle_voice: Some(key_hint::plain(KeyCode::F(8)).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ pub(super) fn lines(props: &FooterProps, width: u16) -> Vec<Line<'static>> {
|
||||
}
|
||||
session.push(hints.reasoning_down, "Less reasoning");
|
||||
session.push(hints.reasoning_up, "More reasoning");
|
||||
session.push(hints.toggle_voice, "Voice");
|
||||
session.push(hints.agents, "Agents (empty prompt)");
|
||||
session.entries.push(Shortcut::new(
|
||||
key_hint::ctrl(KeyCode::Char('c')),
|
||||
|
||||
+5
-4
@@ -10,10 +10,11 @@ expression: terminal.backend()
|
||||
" @ Mention files shift+tab Change mode "
|
||||
" ! Shell command ⌥+, Less reasoning "
|
||||
" ctrl+j New line ⌥+. More reasoning "
|
||||
" ctrl+v Paste image ctrl+c Quit "
|
||||
" ctrl+g External editor "
|
||||
" ctrl+r Search history Transcript (open first) "
|
||||
" esc esc Edit last message ctrl+t Open transcript "
|
||||
" ctrl+v Paste image f8 Voice "
|
||||
" ctrl+g External editor ctrl+c Quit "
|
||||
" ctrl+r Search history "
|
||||
" esc esc Edit last message Transcript (open first) "
|
||||
" ctrl+t Open transcript "
|
||||
" f3 Find text "
|
||||
" pgup / pgdn Scroll "
|
||||
" ctrl+space Start selection "
|
||||
|
||||
+6
-5
@@ -9,11 +9,12 @@ expression: terminal.backend()
|
||||
" / Commands tab Queue message "
|
||||
" @ Mention files ⌥+, Less reasoning "
|
||||
" ! Shell command ⌥+. More reasoning "
|
||||
" ctrl+j New line ctrl+c Interrupt "
|
||||
" ctrl+v Paste image "
|
||||
" ctrl+g External editor Transcript (open first) "
|
||||
" ctrl+r Search history ctrl+t Open transcript "
|
||||
" esc esc Edit last message f3 Find text "
|
||||
" ctrl+j New line f8 Voice "
|
||||
" ctrl+v Paste image ctrl+c Interrupt "
|
||||
" ctrl+g External editor "
|
||||
" ctrl+r Search history Transcript (open first) "
|
||||
" esc esc Edit last message ctrl+t Open transcript "
|
||||
" f3 Find text "
|
||||
" pgup / pgdn Scroll "
|
||||
" ctrl+space Start selection "
|
||||
" ctrl+home / ctrl+end Top / latest "
|
||||
|
||||
+6
-5
@@ -9,11 +9,12 @@ expression: terminal.backend()
|
||||
" / Commands tab Send message "
|
||||
" @ Mention files ⌥+, Less reasoning "
|
||||
" ! Shell command ⌥+. More reasoning "
|
||||
" shift+enter New line ctrl+c Quit "
|
||||
" ctrl+v Paste image "
|
||||
" ctrl+g External editor Transcript (open first) "
|
||||
" ctrl+r Search history ctrl+t Open transcript "
|
||||
" esc Edit last message f3 Find text "
|
||||
" shift+enter New line f8 Voice "
|
||||
" ctrl+v Paste image ctrl+c Quit "
|
||||
" ctrl+g External editor "
|
||||
" ctrl+r Search history Transcript (open first) "
|
||||
" esc Edit last message ctrl+t Open transcript "
|
||||
" f3 Find text "
|
||||
" pgup / pgdn Scroll "
|
||||
" ctrl+space Start selection "
|
||||
" ctrl+home / ctrl+end Top / latest "
|
||||
|
||||
+5
-4
@@ -8,10 +8,11 @@ expression: terminal.backend()
|
||||
" / Commands tab Send message "
|
||||
" @ Mention files shift+tab Change mode "
|
||||
" ! Shell command ⌥+. More reasoning "
|
||||
" shift+enter New line ← Agents (empty prompt) "
|
||||
" ctrl+⌥+v Paste image ctrl+c Quit "
|
||||
" ctrl+x ctrl+e External editor "
|
||||
" esc Edit last message Transcript (open first) "
|
||||
" shift+enter New line f8 Voice "
|
||||
" ctrl+⌥+v Paste image ← Agents (empty prompt) "
|
||||
" ctrl+x ctrl+e External editor ctrl+c Quit "
|
||||
" esc Edit last message "
|
||||
" Transcript (open first) "
|
||||
" ctrl+t Open transcript "
|
||||
" f3 Find text "
|
||||
" pgup / pgdn Scroll "
|
||||
|
||||
Reference in New Issue
Block a user