space and revert working properly well, also shift
This commit is contained in:
@@ -5,6 +5,7 @@ enter_command_mode = [":", "ctrl+;"]
|
|||||||
next_buffer = ["space+b+n"]
|
next_buffer = ["space+b+n"]
|
||||||
previous_buffer = ["space+b+p"]
|
previous_buffer = ["space+b+p"]
|
||||||
close_buffer = ["space+b+d"]
|
close_buffer = ["space+b+d"]
|
||||||
|
revert = ["space+b+r"]
|
||||||
|
|
||||||
[keybindings.general]
|
[keybindings.general]
|
||||||
up = ["k", "Up"]
|
up = ["k", "Up"]
|
||||||
@@ -27,7 +28,6 @@ move_up = ["Up"]
|
|||||||
move_down = ["Down"]
|
move_down = ["Down"]
|
||||||
toggle_sidebar = ["ctrl+t"]
|
toggle_sidebar = ["ctrl+t"]
|
||||||
toggle_buffer_list = ["ctrl+b"]
|
toggle_buffer_list = ["ctrl+b"]
|
||||||
revert = ["space+b+r"]
|
|
||||||
|
|
||||||
# MODE SPECIFIC
|
# MODE SPECIFIC
|
||||||
# READ ONLY MODE
|
# READ ONLY MODE
|
||||||
@@ -60,7 +60,7 @@ prev_field = ["Shift+Tab"]
|
|||||||
|
|
||||||
[keybindings.highlight]
|
[keybindings.highlight]
|
||||||
exit_highlight_mode = ["esc"]
|
exit_highlight_mode = ["esc"]
|
||||||
enter_highlight_mode_linewise = ["ctrl+v"]
|
enter_highlight_mode_linewise = ["shift+v"]
|
||||||
|
|
||||||
### AUTOGENERATED CANVAS CONFIG
|
### AUTOGENERATED CANVAS CONFIG
|
||||||
# Required
|
# Required
|
||||||
|
|||||||
@@ -250,28 +250,44 @@ impl Config {
|
|||||||
key: KeyCode,
|
key: KeyCode,
|
||||||
modifiers: KeyModifiers,
|
modifiers: KeyModifiers,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// Special handling for shift+character combinations
|
|
||||||
if binding.to_lowercase().starts_with("shift+") {
|
// Normalize binding once
|
||||||
|
let binding_lc = binding.to_lowercase();
|
||||||
|
|
||||||
|
// Robust handling for Shift+Tab
|
||||||
|
// Accept either BackTab (with or without SHIFT flagged) or Tab+SHIFT
|
||||||
|
if binding_lc == "shift+tab" || binding_lc == "backtab" {
|
||||||
|
return match key {
|
||||||
|
KeyCode::BackTab => true,
|
||||||
|
KeyCode::Tab => modifiers.contains(KeyModifiers::SHIFT),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Robust handling for shift+<char> (letters)
|
||||||
|
// Many terminals send uppercase Char without SHIFT bit.
|
||||||
|
if binding_lc.starts_with("shift+") {
|
||||||
let parts: Vec<&str> = binding.split('+').collect();
|
let parts: Vec<&str> = binding.split('+').collect();
|
||||||
if parts.len() == 2 && parts[1].len() == 1 {
|
if parts.len() == 2 && parts[1].chars().count() == 1 {
|
||||||
let expected_lowercase = parts[1].chars().next().unwrap().to_lowercase().next().unwrap();
|
let base = parts[1].chars().next().unwrap();
|
||||||
let expected_uppercase = expected_lowercase.to_uppercase().next().unwrap();
|
let upper = base.to_ascii_uppercase();
|
||||||
if let KeyCode::Char(actual_char) = key {
|
let lower = base.to_ascii_lowercase();
|
||||||
if actual_char == expected_uppercase && modifiers.contains(KeyModifiers::SHIFT) {
|
if let KeyCode::Char(actual) = key {
|
||||||
|
// Accept uppercase char regardless of SHIFT bit
|
||||||
|
if actual == upper {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Also accept lowercase char with SHIFT flagged (some terms do this)
|
||||||
|
if actual == lower && modifiers.contains(KeyModifiers::SHIFT) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Shift+Tab -> BackTab
|
|
||||||
if binding.to_lowercase() == "shift+tab" && key == KeyCode::BackTab && modifiers.is_empty() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle multi-character bindings (all standard keys without modifiers)
|
// Handle multi-character bindings (all standard keys without modifiers)
|
||||||
if binding.len() > 1 && !binding.contains('+') {
|
if binding.len() > 1 && !binding.contains('+') {
|
||||||
return match binding.to_lowercase().as_str() {
|
return match binding_lc.as_str() {
|
||||||
// Navigation keys
|
// Navigation keys
|
||||||
"left" => key == KeyCode::Left,
|
"left" => key == KeyCode::Left,
|
||||||
"right" => key == KeyCode::Right,
|
"right" => key == KeyCode::Right,
|
||||||
@@ -371,6 +387,7 @@ impl Config {
|
|||||||
let mut expected_key = None;
|
let mut expected_key = None;
|
||||||
|
|
||||||
for part in parts {
|
for part in parts {
|
||||||
|
let part_lc = part.to_lowercase();
|
||||||
match part.to_lowercase().as_str() {
|
match part.to_lowercase().as_str() {
|
||||||
// Modifiers
|
// Modifiers
|
||||||
"ctrl" | "control" => expected_modifiers |= KeyModifiers::CONTROL,
|
"ctrl" | "control" => expected_modifiers |= KeyModifiers::CONTROL,
|
||||||
@@ -789,12 +806,43 @@ impl Config {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normalize bindings for canvas consumption:
|
||||||
|
// - "shift+<char>" -> also add "<CHAR>"
|
||||||
|
// - "shift+tab" -> also add "backtab"
|
||||||
|
// This keeps your config human-friendly while making the canvas happy.
|
||||||
|
fn normalize_for_canvas(
|
||||||
|
map: &HashMap<String, Vec<String>>,
|
||||||
|
) -> HashMap<String, Vec<String>> {
|
||||||
|
let mut out: HashMap<String, Vec<String>> = HashMap::new();
|
||||||
|
for (action, bindings) in map {
|
||||||
|
let mut new_list: Vec<String> = Vec::new();
|
||||||
|
for b in bindings {
|
||||||
|
new_list.push(b.clone());
|
||||||
|
let blc = b.to_lowercase();
|
||||||
|
if blc.starts_with("shift+") {
|
||||||
|
let parts: Vec<&str> = b.split('+').collect();
|
||||||
|
if parts.len() == 2 && parts[1].chars().count() == 1 {
|
||||||
|
let ch = parts[1].chars().next().unwrap();
|
||||||
|
new_list.push(ch.to_ascii_uppercase().to_string());
|
||||||
|
}
|
||||||
|
if blc == "shift+tab" {
|
||||||
|
new_list.push("backtab".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if blc == "shift+tab" {
|
||||||
|
new_list.push("backtab".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.insert(action.clone(), new_list);
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build_canvas_keymap(&self) -> CanvasKeyMap {
|
pub fn build_canvas_keymap(&self) -> CanvasKeyMap {
|
||||||
CanvasKeyMap::from_mode_maps(
|
let ro = Self::normalize_for_canvas(&self.keybindings.read_only);
|
||||||
&self.keybindings.read_only,
|
let ed = Self::normalize_for_canvas(&self.keybindings.edit);
|
||||||
&self.keybindings.edit,
|
let hl = Self::normalize_for_canvas(&self.keybindings.highlight);
|
||||||
&self.keybindings.highlight,
|
CanvasKeyMap::from_mode_maps(&ro, &ed, &hl)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -574,6 +574,16 @@ impl EventHandler {
|
|||||||
);
|
);
|
||||||
return Ok(EventOutcome::Ok(message));
|
return Ok(EventOutcome::Ok(message));
|
||||||
}
|
}
|
||||||
|
"revert" | "save" | "force_quit" | "save_and_quit" => {
|
||||||
|
let outcome = self.handle_core_action(
|
||||||
|
action,
|
||||||
|
auth_state,
|
||||||
|
terminal,
|
||||||
|
app_state,
|
||||||
|
router,
|
||||||
|
).await?;
|
||||||
|
return Ok(outcome);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user