yoda: protocole clavier kitty, Shift+Entree pour Claude Code et Modjo
Claude Code (>= 2.1.269) n'active Shift+Entree que si le terminal repond a CSI ? u. alacritty_terminal sait tenir la pile des modes et repondre, mais seulement avec kitty_keyboard, et n'encode aucune touche : Shift+ Entree partait en \r, identique a Entree. - term::Config : kitty_keyboard active. - kitty_keyboard : encodeur du frontal (spec kitty, decoupe de l'encodeur d'Alacritty), utilise seulement quand l'application au premier plan a pousse le drapeau 1 ou 8 ; sinon l'encodage legacy reste seul. Gere desambiguisation, types d'evenements (repetition, relachement), touches alternatives, toutes les touches, texte associe, pave numerique, F1-F24, touches de modification. Shift+Entree -> CSI 13;2u. - terminal_box : raccourcis de l'appli toujours prioritaires ; Shift+PageUp/PageDown/Home/End et Echap sur selection gardent leur comportement local ; relachements envoyes si le drapeau 2 est pose. - Legacy : Shift+Entree envoie LF (comme Ctrl+J) au lieu de CR. rustyline le lit comme Ctrl+J, la touche de saut de ligne de Modjo/Goose ; pour un shell c'est toujours Entree. Connu, non corrige ici : alacritty_terminal 0.25.1 push_keyboard_mode vide title_stack au lieu de la pile des modes au-dela de 4096 empilements (panique du fil PTY de l'onglet seulement, panic=unwind). 10 tests, dont la reponse a CSI ? u et l'application de CSI > 5 u. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2414aaece3
commit
52b37cc2f8
3 changed files with 808 additions and 2 deletions
|
|
@ -47,7 +47,7 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
Action, Terminal, TerminalScroll,
|
||||
Action, Terminal, TerminalScroll, kitty_keyboard,
|
||||
menu::MenuState,
|
||||
terminal::{BlockFill, Metadata},
|
||||
};
|
||||
|
|
@ -940,6 +940,7 @@ where
|
|||
|
||||
let is_app_cursor = terminal.term.lock().mode().contains(TermMode::APP_CURSOR);
|
||||
let is_mouse_mode = terminal.term.lock().mode().intersects(TermMode::MOUSE_MODE);
|
||||
let term_mode = *terminal.term.lock().mode();
|
||||
match event {
|
||||
Event::Window(event) => match event {
|
||||
cosmic::iced::window::Event::Focused => {
|
||||
|
|
@ -979,6 +980,101 @@ where
|
|||
}
|
||||
_ => {}
|
||||
},
|
||||
// [yoda] Protocole clavier kitty, quand l'application au premier plan
|
||||
// l'a demandé (voir `kitty_keyboard`) ; sinon encodage legacy plus bas.
|
||||
Event::Keyboard(KeyEvent::KeyPressed {
|
||||
key,
|
||||
modified_key,
|
||||
physical_key,
|
||||
location,
|
||||
modifiers,
|
||||
text,
|
||||
repeat,
|
||||
}) if state.is_focused && kitty_keyboard::active(term_mode) => {
|
||||
for key_bind in self.key_binds.keys() {
|
||||
if key_bind.matches(*modifiers, key, Some(physical_key)) {
|
||||
shell.capture_event();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Comportements locaux conservés, comme en legacy : Shift+PageUp…
|
||||
// fait défiler l'historique, Échap annule une sélection.
|
||||
let local_scroll = match modified_key {
|
||||
Key::Named(Named::PageUp) if modifiers.shift() => Some(TerminalScroll::PageUp),
|
||||
Key::Named(Named::PageDown) if modifiers.shift() => {
|
||||
Some(TerminalScroll::PageDown)
|
||||
}
|
||||
Key::Named(Named::Home) if modifiers.shift() => Some(TerminalScroll::Top),
|
||||
Key::Named(Named::End) if modifiers.shift() => Some(TerminalScroll::Bottom),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(scroll) = local_scroll {
|
||||
terminal.scroll(scroll);
|
||||
shell.capture_event();
|
||||
return;
|
||||
}
|
||||
if *modified_key == Key::Named(Named::Escape) {
|
||||
let had_selection = terminal.term.lock().selection.take().is_some();
|
||||
if had_selection {
|
||||
terminal.update();
|
||||
shell.capture_event();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let input = kitty_keyboard::KeyInput {
|
||||
key,
|
||||
modified_key,
|
||||
location: *location,
|
||||
modifiers: *modifiers,
|
||||
text: text.as_deref(),
|
||||
action: if *repeat {
|
||||
kitty_keyboard::KeyAction::Repeat
|
||||
} else {
|
||||
kitty_keyboard::KeyAction::Press
|
||||
},
|
||||
};
|
||||
let bytes = kitty_keyboard::encode(&input, term_mode);
|
||||
if !bytes.is_empty() {
|
||||
// Une touche de modification seule (« toutes les touches »)
|
||||
// ne ramène pas la vue en bas.
|
||||
let modifier_only = matches!(
|
||||
modified_key,
|
||||
Key::Named(Named::Shift | Named::Control | Named::Alt | Named::Super)
|
||||
);
|
||||
if modifier_only {
|
||||
terminal.input_no_scroll(bytes);
|
||||
} else {
|
||||
terminal.input_scroll(bytes);
|
||||
}
|
||||
shell.capture_event();
|
||||
}
|
||||
}
|
||||
Event::Keyboard(KeyEvent::KeyReleased {
|
||||
key,
|
||||
modified_key,
|
||||
location,
|
||||
modifiers,
|
||||
..
|
||||
}) if state.is_focused
|
||||
&& kitty_keyboard::active(term_mode)
|
||||
&& term_mode.contains(TermMode::REPORT_EVENT_TYPES) =>
|
||||
{
|
||||
let input = kitty_keyboard::KeyInput {
|
||||
key,
|
||||
modified_key,
|
||||
location: *location,
|
||||
modifiers: *modifiers,
|
||||
text: None,
|
||||
action: kitty_keyboard::KeyAction::Release,
|
||||
};
|
||||
let bytes = kitty_keyboard::encode(&input, term_mode);
|
||||
if !bytes.is_empty() {
|
||||
terminal.input_no_scroll(bytes);
|
||||
shell.capture_event();
|
||||
}
|
||||
}
|
||||
Event::Keyboard(KeyEvent::KeyPressed {
|
||||
key: Key::Named(named),
|
||||
physical_key,
|
||||
|
|
@ -1094,7 +1190,15 @@ where
|
|||
shell.capture_event();
|
||||
}
|
||||
Named::Enter => {
|
||||
terminal.input_scroll(format!("{}{}", alt_prefix, "\x0D").into_bytes());
|
||||
// [yoda] Shift+Entrée envoie LF (`\n`, comme Ctrl+J) : saut de
|
||||
// ligne dans les éditeurs qui ne parlent pas le protocole kitty
|
||||
// (rustyline de Modjo/Goose) ; pour un shell, c'est Entrée.
|
||||
let code = if modifiers.shift() && !modifiers.control() {
|
||||
"\x0A"
|
||||
} else {
|
||||
"\x0D"
|
||||
};
|
||||
terminal.input_scroll(format!("{alt_prefix}{code}").into_bytes());
|
||||
shell.capture_event();
|
||||
}
|
||||
Named::Escape => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue