Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a85773cef0 | ||
|
|
a8d693c0a3 | ||
|
|
6c1bcf042c |
@@ -238,6 +238,26 @@ mod tests {
|
|||||||
assert!(s.contains("ctrl-glorb"), "diagnostic: {s}");
|
assert!(s.contains("ctrl-glorb"), "diagnostic: {s}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Regression for #70: the previous canonical form of a real Shift+S
|
||||||
|
/// keypress was `"shift-S"`, which the default `"S"` binding never
|
||||||
|
/// matched. Drive the actual crossterm event, not the binding string,
|
||||||
|
/// so the dead-key bug can't come back unnoticed.
|
||||||
|
#[test]
|
||||||
|
fn real_shift_s_keypress_resolves_to_fast_forward_spawn() {
|
||||||
|
use crossterm::event::{Event as CtEvent, KeyCode, KeyEvent, KeyModifiers};
|
||||||
|
|
||||||
|
use crate::input::{canonicalise, Region};
|
||||||
|
|
||||||
|
let cfg = TuiConfig::load(&TuiSection::default()).unwrap();
|
||||||
|
let ev = CtEvent::Key(KeyEvent::new(KeyCode::Char('S'), KeyModifiers::SHIFT));
|
||||||
|
let key = canonicalise(&ev, |_, _| Region::Unknown).expect("key event canonicalises");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
cfg.keymap.resolve(Mode::Normal, &key.canonical()),
|
||||||
|
Some(Action::FastForwardSpawn),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn custom_chord_timeout_is_applied() {
|
fn custom_chord_timeout_is_applied() {
|
||||||
let mut section = TuiSection::default();
|
let mut section = TuiSection::default();
|
||||||
|
|||||||
@@ -117,7 +117,9 @@ impl InputKey {
|
|||||||
if *alt {
|
if *alt {
|
||||||
out.push_str("alt-");
|
out.push_str("alt-");
|
||||||
}
|
}
|
||||||
if *shift {
|
// Uppercase already implies shift; crossterm sets the flag
|
||||||
|
// on every such char, so skip the redundant prefix (#70).
|
||||||
|
if *shift && !c.is_uppercase() {
|
||||||
out.push_str("shift-");
|
out.push_str("shift-");
|
||||||
}
|
}
|
||||||
out.push(*c);
|
out.push(*c);
|
||||||
@@ -580,12 +582,28 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn canonical_round_trips_simple_chars() {
|
fn canonical_round_trips_simple_chars() {
|
||||||
for s in ["a", "ctrl-a", "ctrl-w", "alt-x", "shift-A"] {
|
for s in ["a", "ctrl-a", "ctrl-w", "alt-x"] {
|
||||||
let k = InputKey::parse(s).unwrap();
|
let k = InputKey::parse(s).unwrap();
|
||||||
assert_eq!(k.canonical(), s, "round-trip {s:?}");
|
assert_eq!(k.canonical(), s, "round-trip {s:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// crossterm 0.28 attaches `KeyModifiers::SHIFT` to any uppercase char,
|
||||||
|
/// so a real Shift+S delivers `Char { c: 'S', shift: true }`. Its
|
||||||
|
/// canonical form must be the bare `"S"` a keymap binds, not `"shift-S"` —
|
||||||
|
/// the uppercase letter already says "shifted"; a redundant prefix would
|
||||||
|
/// make the default `S` binding unreachable from the keyboard (#70).
|
||||||
|
#[test]
|
||||||
|
fn shift_flag_is_redundant_for_an_already_uppercase_char() {
|
||||||
|
let k = InputKey::Char {
|
||||||
|
c: 'S',
|
||||||
|
ctrl: false,
|
||||||
|
alt: false,
|
||||||
|
shift: true,
|
||||||
|
};
|
||||||
|
assert_eq!(k.canonical(), "S");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn canonical_round_trips_specials() {
|
fn canonical_round_trips_specials() {
|
||||||
for s in [
|
for s in [
|
||||||
|
|||||||
@@ -125,7 +125,7 @@
|
|||||||
pnpmDeps = (pkgs.fetchPnpmDeps.override { pnpm = pkgs.pnpm_10; }) {
|
pnpmDeps = (pkgs.fetchPnpmDeps.override { pnpm = pkgs.pnpm_10; }) {
|
||||||
inherit (finalAttrs) pname version src;
|
inherit (finalAttrs) pname version src;
|
||||||
fetcherVersion = 3;
|
fetcherVersion = 3;
|
||||||
hash = "sha256-Lhi41AtCK69SM4+7zih19+Njf7o2hyXrAV0W6VO9YxU=";
|
hash = "sha256-D9JdgI92vzAY8en2zGEEPd4hwOLVi3sr1joT4b17Be4=";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
|
|||||||
Reference in New Issue
Block a user