2022-04-10 02:20:59 +03:00
|
|
|
use crate::commands::CommandDef;
|
|
|
|
use config::keyassignment::{
|
|
|
|
ClipboardCopyDestination, ClipboardPasteSource, KeyAssignment, KeyTableEntry, KeyTables,
|
|
|
|
MouseEventTrigger, SelectionMode,
|
|
|
|
};
|
|
|
|
use config::ConfigHandle;
|
2022-06-22 19:14:34 +03:00
|
|
|
use std::collections::{BTreeMap, HashMap};
|
2022-04-10 02:20:59 +03:00
|
|
|
use std::time::Duration;
|
|
|
|
use wezterm_term::input::MouseButton;
|
|
|
|
use window::{KeyCode, Modifiers};
|
|
|
|
|
|
|
|
pub struct InputMap {
|
|
|
|
pub keys: KeyTables,
|
|
|
|
pub mouse: HashMap<(MouseEventTrigger, Modifiers), KeyAssignment>,
|
|
|
|
leader: Option<(KeyCode, Modifiers, Duration)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl InputMap {
|
|
|
|
pub fn new(config: &ConfigHandle) -> Self {
|
|
|
|
let mut mouse = config.mouse_bindings();
|
|
|
|
|
|
|
|
let mut keys = config.key_bindings();
|
|
|
|
|
|
|
|
let leader = config.leader.as_ref().map(|leader| {
|
|
|
|
(
|
|
|
|
leader.key.key.resolve(config.key_map_preference).clone(),
|
|
|
|
leader.key.mods,
|
|
|
|
Duration::from_millis(leader.timeout_milliseconds),
|
|
|
|
)
|
|
|
|
});
|
|
|
|
|
|
|
|
let ctrl_shift = Modifiers::CTRL | Modifiers::SHIFT;
|
|
|
|
|
|
|
|
macro_rules! m {
|
|
|
|
($([$mod:expr, $code:expr, $action:expr]),* $(,)?) => {
|
|
|
|
$(
|
|
|
|
mouse.entry(($code, $mod)).or_insert($action);
|
|
|
|
)*
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
use KeyAssignment::*;
|
|
|
|
|
|
|
|
if !config.disable_default_key_bindings {
|
|
|
|
for (mods, code, action) in CommandDef::default_key_assignments(config) {
|
|
|
|
keys.default
|
|
|
|
.entry((code, mods))
|
|
|
|
.or_insert(KeyTableEntry { action });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !config.disable_default_mouse_bindings {
|
|
|
|
m!(
|
|
|
|
[
|
|
|
|
Modifiers::NONE,
|
|
|
|
MouseEventTrigger::Down {
|
|
|
|
streak: 3,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
|
|
|
SelectTextAtMouseCursor(SelectionMode::Line)
|
|
|
|
],
|
|
|
|
[
|
|
|
|
Modifiers::NONE,
|
|
|
|
MouseEventTrigger::Down {
|
|
|
|
streak: 2,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
|
|
|
SelectTextAtMouseCursor(SelectionMode::Word)
|
|
|
|
],
|
|
|
|
[
|
|
|
|
Modifiers::NONE,
|
|
|
|
MouseEventTrigger::Down {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
|
|
|
SelectTextAtMouseCursor(SelectionMode::Cell)
|
|
|
|
],
|
2022-05-06 06:49:22 +03:00
|
|
|
[
|
|
|
|
Modifiers::ALT,
|
|
|
|
MouseEventTrigger::Down {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
|
|
|
SelectTextAtMouseCursor(SelectionMode::Block)
|
|
|
|
],
|
2022-04-10 02:20:59 +03:00
|
|
|
[
|
|
|
|
Modifiers::SHIFT,
|
|
|
|
MouseEventTrigger::Down {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
new: exec_domains
An ExecDomain is a variation on WslDomain with the key difference
being that you can control how to map the command that would be
executed.
The idea is that the user can define eg: a domain for a docker
container, or a domain that chooses to run every command in its
own cgroup.
The example below shows a really crappy implementation as a
demonstration:
```
local wezterm = require 'wezterm'
return {
exec_domains = {
-- Commands executed in the woot domain have "WOOT" echoed
-- first and are then run via bash.
-- `cmd` is a SpawnCommand
wezterm.exec_domain("woot", function(cmd)
if cmd.args then
cmd.args = {
"bash",
"-c",
"echo WOOT && " .. wezterm.shell_join_args(cmd.args)
}
end
-- you must return the SpawnCommand that will be run
return cmd
end),
},
default_domain = "woot",
}
```
This commit unfortunately does more than should go into a single
commit, but I'm a bit too lazy to wrangle splitting it up.
* Reverts the nil/null stuff from #2177 and makes the
`ExtendSelectionToMouseCursor` parameter mandatory to dodge
a whole load of urgh around nil in table values. That is
necessary because SpawnCommand uses optional fields and the
userdata proxy was making that a PITA.
* Adds some shell quoting helper functions
* Adds ExecDomain itself, which is really just a way to
to run a callback to fixup the command that will be run.
That command is converted to a SpawnCommand for the callback
to process in lua and return an adjusted version of it,
then converted back to a command builder for execution.
refs: https://github.com/wez/wezterm/issues/1776
2022-07-08 02:38:14 +03:00
|
|
|
ExtendSelectionToMouseCursor(SelectionMode::Cell)
|
2022-04-10 02:20:59 +03:00
|
|
|
],
|
|
|
|
[
|
|
|
|
Modifiers::SHIFT,
|
|
|
|
MouseEventTrigger::Up {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
|
|
|
CompleteSelectionOrOpenLinkAtMouseCursor(
|
|
|
|
ClipboardCopyDestination::PrimarySelection
|
|
|
|
)
|
|
|
|
],
|
|
|
|
[
|
|
|
|
Modifiers::NONE,
|
|
|
|
MouseEventTrigger::Up {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
|
|
|
CompleteSelectionOrOpenLinkAtMouseCursor(
|
|
|
|
ClipboardCopyDestination::PrimarySelection
|
|
|
|
)
|
|
|
|
],
|
2022-05-06 06:49:22 +03:00
|
|
|
[
|
|
|
|
Modifiers::ALT,
|
|
|
|
MouseEventTrigger::Up {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
|
|
|
CompleteSelection(ClipboardCopyDestination::PrimarySelection)
|
|
|
|
],
|
2022-05-14 23:52:28 +03:00
|
|
|
[
|
|
|
|
Modifiers::ALT | Modifiers::SHIFT,
|
|
|
|
MouseEventTrigger::Down {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
new: exec_domains
An ExecDomain is a variation on WslDomain with the key difference
being that you can control how to map the command that would be
executed.
The idea is that the user can define eg: a domain for a docker
container, or a domain that chooses to run every command in its
own cgroup.
The example below shows a really crappy implementation as a
demonstration:
```
local wezterm = require 'wezterm'
return {
exec_domains = {
-- Commands executed in the woot domain have "WOOT" echoed
-- first and are then run via bash.
-- `cmd` is a SpawnCommand
wezterm.exec_domain("woot", function(cmd)
if cmd.args then
cmd.args = {
"bash",
"-c",
"echo WOOT && " .. wezterm.shell_join_args(cmd.args)
}
end
-- you must return the SpawnCommand that will be run
return cmd
end),
},
default_domain = "woot",
}
```
This commit unfortunately does more than should go into a single
commit, but I'm a bit too lazy to wrangle splitting it up.
* Reverts the nil/null stuff from #2177 and makes the
`ExtendSelectionToMouseCursor` parameter mandatory to dodge
a whole load of urgh around nil in table values. That is
necessary because SpawnCommand uses optional fields and the
userdata proxy was making that a PITA.
* Adds some shell quoting helper functions
* Adds ExecDomain itself, which is really just a way to
to run a callback to fixup the command that will be run.
That command is converted to a SpawnCommand for the callback
to process in lua and return an adjusted version of it,
then converted back to a command builder for execution.
refs: https://github.com/wez/wezterm/issues/1776
2022-07-08 02:38:14 +03:00
|
|
|
ExtendSelectionToMouseCursor(SelectionMode::Block)
|
2022-05-14 23:52:28 +03:00
|
|
|
],
|
|
|
|
[
|
|
|
|
Modifiers::ALT | Modifiers::SHIFT,
|
|
|
|
MouseEventTrigger::Up {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
|
|
|
CompleteSelectionOrOpenLinkAtMouseCursor(
|
|
|
|
ClipboardCopyDestination::PrimarySelection
|
|
|
|
)
|
|
|
|
],
|
2022-04-10 02:20:59 +03:00
|
|
|
[
|
|
|
|
Modifiers::NONE,
|
|
|
|
MouseEventTrigger::Up {
|
|
|
|
streak: 2,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
|
|
|
CompleteSelection(ClipboardCopyDestination::PrimarySelection)
|
|
|
|
],
|
|
|
|
[
|
|
|
|
Modifiers::NONE,
|
|
|
|
MouseEventTrigger::Up {
|
|
|
|
streak: 3,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
|
|
|
CompleteSelection(ClipboardCopyDestination::PrimarySelection)
|
|
|
|
],
|
|
|
|
[
|
|
|
|
Modifiers::NONE,
|
|
|
|
MouseEventTrigger::Drag {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
new: exec_domains
An ExecDomain is a variation on WslDomain with the key difference
being that you can control how to map the command that would be
executed.
The idea is that the user can define eg: a domain for a docker
container, or a domain that chooses to run every command in its
own cgroup.
The example below shows a really crappy implementation as a
demonstration:
```
local wezterm = require 'wezterm'
return {
exec_domains = {
-- Commands executed in the woot domain have "WOOT" echoed
-- first and are then run via bash.
-- `cmd` is a SpawnCommand
wezterm.exec_domain("woot", function(cmd)
if cmd.args then
cmd.args = {
"bash",
"-c",
"echo WOOT && " .. wezterm.shell_join_args(cmd.args)
}
end
-- you must return the SpawnCommand that will be run
return cmd
end),
},
default_domain = "woot",
}
```
This commit unfortunately does more than should go into a single
commit, but I'm a bit too lazy to wrangle splitting it up.
* Reverts the nil/null stuff from #2177 and makes the
`ExtendSelectionToMouseCursor` parameter mandatory to dodge
a whole load of urgh around nil in table values. That is
necessary because SpawnCommand uses optional fields and the
userdata proxy was making that a PITA.
* Adds some shell quoting helper functions
* Adds ExecDomain itself, which is really just a way to
to run a callback to fixup the command that will be run.
That command is converted to a SpawnCommand for the callback
to process in lua and return an adjusted version of it,
then converted back to a command builder for execution.
refs: https://github.com/wez/wezterm/issues/1776
2022-07-08 02:38:14 +03:00
|
|
|
ExtendSelectionToMouseCursor(SelectionMode::Cell)
|
2022-04-10 02:20:59 +03:00
|
|
|
],
|
2022-05-06 06:49:22 +03:00
|
|
|
[
|
|
|
|
Modifiers::ALT,
|
|
|
|
MouseEventTrigger::Drag {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
new: exec_domains
An ExecDomain is a variation on WslDomain with the key difference
being that you can control how to map the command that would be
executed.
The idea is that the user can define eg: a domain for a docker
container, or a domain that chooses to run every command in its
own cgroup.
The example below shows a really crappy implementation as a
demonstration:
```
local wezterm = require 'wezterm'
return {
exec_domains = {
-- Commands executed in the woot domain have "WOOT" echoed
-- first and are then run via bash.
-- `cmd` is a SpawnCommand
wezterm.exec_domain("woot", function(cmd)
if cmd.args then
cmd.args = {
"bash",
"-c",
"echo WOOT && " .. wezterm.shell_join_args(cmd.args)
}
end
-- you must return the SpawnCommand that will be run
return cmd
end),
},
default_domain = "woot",
}
```
This commit unfortunately does more than should go into a single
commit, but I'm a bit too lazy to wrangle splitting it up.
* Reverts the nil/null stuff from #2177 and makes the
`ExtendSelectionToMouseCursor` parameter mandatory to dodge
a whole load of urgh around nil in table values. That is
necessary because SpawnCommand uses optional fields and the
userdata proxy was making that a PITA.
* Adds some shell quoting helper functions
* Adds ExecDomain itself, which is really just a way to
to run a callback to fixup the command that will be run.
That command is converted to a SpawnCommand for the callback
to process in lua and return an adjusted version of it,
then converted back to a command builder for execution.
refs: https://github.com/wez/wezterm/issues/1776
2022-07-08 02:38:14 +03:00
|
|
|
ExtendSelectionToMouseCursor(SelectionMode::Block)
|
2022-05-06 06:49:22 +03:00
|
|
|
],
|
2022-04-10 02:20:59 +03:00
|
|
|
[
|
|
|
|
Modifiers::NONE,
|
|
|
|
MouseEventTrigger::Drag {
|
|
|
|
streak: 2,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
new: exec_domains
An ExecDomain is a variation on WslDomain with the key difference
being that you can control how to map the command that would be
executed.
The idea is that the user can define eg: a domain for a docker
container, or a domain that chooses to run every command in its
own cgroup.
The example below shows a really crappy implementation as a
demonstration:
```
local wezterm = require 'wezterm'
return {
exec_domains = {
-- Commands executed in the woot domain have "WOOT" echoed
-- first and are then run via bash.
-- `cmd` is a SpawnCommand
wezterm.exec_domain("woot", function(cmd)
if cmd.args then
cmd.args = {
"bash",
"-c",
"echo WOOT && " .. wezterm.shell_join_args(cmd.args)
}
end
-- you must return the SpawnCommand that will be run
return cmd
end),
},
default_domain = "woot",
}
```
This commit unfortunately does more than should go into a single
commit, but I'm a bit too lazy to wrangle splitting it up.
* Reverts the nil/null stuff from #2177 and makes the
`ExtendSelectionToMouseCursor` parameter mandatory to dodge
a whole load of urgh around nil in table values. That is
necessary because SpawnCommand uses optional fields and the
userdata proxy was making that a PITA.
* Adds some shell quoting helper functions
* Adds ExecDomain itself, which is really just a way to
to run a callback to fixup the command that will be run.
That command is converted to a SpawnCommand for the callback
to process in lua and return an adjusted version of it,
then converted back to a command builder for execution.
refs: https://github.com/wez/wezterm/issues/1776
2022-07-08 02:38:14 +03:00
|
|
|
ExtendSelectionToMouseCursor(SelectionMode::Word)
|
2022-04-10 02:20:59 +03:00
|
|
|
],
|
|
|
|
[
|
|
|
|
Modifiers::NONE,
|
|
|
|
MouseEventTrigger::Drag {
|
|
|
|
streak: 3,
|
|
|
|
button: MouseButton::Left
|
|
|
|
},
|
new: exec_domains
An ExecDomain is a variation on WslDomain with the key difference
being that you can control how to map the command that would be
executed.
The idea is that the user can define eg: a domain for a docker
container, or a domain that chooses to run every command in its
own cgroup.
The example below shows a really crappy implementation as a
demonstration:
```
local wezterm = require 'wezterm'
return {
exec_domains = {
-- Commands executed in the woot domain have "WOOT" echoed
-- first and are then run via bash.
-- `cmd` is a SpawnCommand
wezterm.exec_domain("woot", function(cmd)
if cmd.args then
cmd.args = {
"bash",
"-c",
"echo WOOT && " .. wezterm.shell_join_args(cmd.args)
}
end
-- you must return the SpawnCommand that will be run
return cmd
end),
},
default_domain = "woot",
}
```
This commit unfortunately does more than should go into a single
commit, but I'm a bit too lazy to wrangle splitting it up.
* Reverts the nil/null stuff from #2177 and makes the
`ExtendSelectionToMouseCursor` parameter mandatory to dodge
a whole load of urgh around nil in table values. That is
necessary because SpawnCommand uses optional fields and the
userdata proxy was making that a PITA.
* Adds some shell quoting helper functions
* Adds ExecDomain itself, which is really just a way to
to run a callback to fixup the command that will be run.
That command is converted to a SpawnCommand for the callback
to process in lua and return an adjusted version of it,
then converted back to a command builder for execution.
refs: https://github.com/wez/wezterm/issues/1776
2022-07-08 02:38:14 +03:00
|
|
|
ExtendSelectionToMouseCursor(SelectionMode::Line)
|
2022-04-10 02:20:59 +03:00
|
|
|
],
|
|
|
|
[
|
|
|
|
Modifiers::NONE,
|
|
|
|
MouseEventTrigger::Down {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Middle
|
|
|
|
},
|
|
|
|
PasteFrom(ClipboardPasteSource::PrimarySelection)
|
|
|
|
],
|
|
|
|
[
|
|
|
|
Modifiers::SUPER,
|
|
|
|
MouseEventTrigger::Drag {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left,
|
|
|
|
},
|
|
|
|
StartWindowDrag
|
|
|
|
],
|
|
|
|
[
|
|
|
|
ctrl_shift,
|
|
|
|
MouseEventTrigger::Drag {
|
|
|
|
streak: 1,
|
|
|
|
button: MouseButton::Left,
|
|
|
|
},
|
|
|
|
StartWindowDrag
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
keys.default
|
|
|
|
.retain(|_, v| v.action != KeyAssignment::DisableDefaultAssignment);
|
|
|
|
mouse.retain(|_, v| *v != KeyAssignment::DisableDefaultAssignment);
|
|
|
|
|
2022-05-05 08:49:58 +03:00
|
|
|
keys.by_name
|
|
|
|
.entry("copy_mode".to_string())
|
2022-05-05 17:36:32 +03:00
|
|
|
.or_insert_with(crate::overlay::copy::copy_key_table);
|
|
|
|
keys.by_name
|
|
|
|
.entry("search_mode".to_string())
|
|
|
|
.or_insert_with(crate::overlay::copy::search_key_table);
|
2022-05-05 08:49:58 +03:00
|
|
|
|
2022-04-10 02:20:59 +03:00
|
|
|
Self {
|
|
|
|
keys,
|
|
|
|
leader,
|
|
|
|
mouse,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_leader(&self, key: &KeyCode, mods: Modifiers) -> Option<std::time::Duration> {
|
|
|
|
if let Some((leader_key, leader_mods, timeout)) = self.leader.as_ref() {
|
2022-06-08 17:38:02 +03:00
|
|
|
if *leader_key == *key && *leader_mods == mods.remove_positional_mods() {
|
2022-04-10 02:20:59 +03:00
|
|
|
return Some(timeout.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn has_table(&self, name: &str) -> bool {
|
|
|
|
self.keys.by_name.contains_key(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn lookup_key(
|
|
|
|
&self,
|
|
|
|
key: &KeyCode,
|
|
|
|
mods: Modifiers,
|
|
|
|
table_name: Option<&str>,
|
|
|
|
) -> Option<KeyTableEntry> {
|
|
|
|
let table = match table_name {
|
|
|
|
Some(name) => self.keys.by_name.get(name)?,
|
|
|
|
None => &self.keys.default,
|
|
|
|
};
|
|
|
|
|
|
|
|
table
|
2022-06-08 17:38:02 +03:00
|
|
|
.get(&key.normalize_shift(mods.remove_positional_mods()))
|
2022-04-10 02:20:59 +03:00
|
|
|
.cloned()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn lookup_mouse(&self, event: MouseEventTrigger, mods: Modifiers) -> Option<KeyAssignment> {
|
|
|
|
self.mouse
|
2022-06-08 17:38:02 +03:00
|
|
|
.get(&(event, mods.remove_positional_mods()))
|
2022-04-10 02:20:59 +03:00
|
|
|
.cloned()
|
|
|
|
}
|
2022-06-22 19:14:34 +03:00
|
|
|
|
|
|
|
pub fn show_keys(&self) {
|
|
|
|
if let Some((key, mods, duration)) = &self.leader {
|
|
|
|
println!("Leader: {key:?} {mods:?} {duration:?}");
|
|
|
|
}
|
|
|
|
|
|
|
|
section_header("Default key table");
|
|
|
|
show_key_table(&self.keys.default);
|
|
|
|
println!();
|
|
|
|
|
|
|
|
let mut table_names = self.keys.by_name.keys().collect::<Vec<_>>();
|
|
|
|
table_names.sort();
|
|
|
|
for name in table_names {
|
|
|
|
if let Some(table) = self.keys.by_name.get(name) {
|
|
|
|
section_header(&format!("Key Table: {name}"));
|
|
|
|
show_key_table(table);
|
|
|
|
println!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
section_header("Mouse");
|
|
|
|
self.show_mouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn show_mouse(&self) {
|
|
|
|
let ordered = self.mouse.iter().collect::<BTreeMap<_, _>>();
|
|
|
|
|
|
|
|
let mut trigger_width = 0;
|
|
|
|
let mut mod_width = 0;
|
|
|
|
for (trigger, mods) in ordered.keys() {
|
|
|
|
mod_width = mod_width.max(format!("{mods:?}").len());
|
|
|
|
trigger_width = trigger_width.max(format!("{trigger:?}").len());
|
|
|
|
}
|
|
|
|
|
|
|
|
for ((trigger, mods), action) in ordered {
|
|
|
|
let mods = if *mods == Modifiers::NONE {
|
|
|
|
String::new()
|
|
|
|
} else {
|
|
|
|
format!("{mods:?}")
|
|
|
|
};
|
|
|
|
let trigger = format!("{trigger:?}");
|
|
|
|
println!("\t{mods:mod_width$} {trigger:trigger_width$} -> {action:?}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn section_header(title: &str) {
|
|
|
|
let dash = "-".repeat(title.len());
|
|
|
|
println!("{title}");
|
|
|
|
println!("{dash}");
|
|
|
|
println!();
|
|
|
|
}
|
|
|
|
|
2022-06-22 21:33:25 +03:00
|
|
|
fn human_key(key: &KeyCode) -> String {
|
|
|
|
match key {
|
|
|
|
KeyCode::Char('\x1b') => "Escape".to_string(),
|
|
|
|
KeyCode::Char('\x7f') => "Escape".to_string(),
|
|
|
|
KeyCode::Char('\x08') => "Backspace".to_string(),
|
|
|
|
KeyCode::Char('\r') => "Enter".to_string(),
|
|
|
|
KeyCode::Char(' ') => "Space".to_string(),
|
|
|
|
KeyCode::Char('\t') => "Tab".to_string(),
|
|
|
|
KeyCode::Char(c) if c.is_ascii_control() => c.escape_debug().to_string(),
|
|
|
|
KeyCode::Char(c) => c.to_string(),
|
|
|
|
KeyCode::Function(n) => format!("F{n}"),
|
|
|
|
KeyCode::Numpad(n) => format!("Numpad{n}"),
|
|
|
|
KeyCode::Physical(phys) => format!("{} (Physical)", phys.to_string()),
|
|
|
|
_ => format!("{key:?}"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-22 19:14:34 +03:00
|
|
|
fn show_key_table(table: &config::keyassignment::KeyTable) {
|
|
|
|
let ordered = table.iter().collect::<BTreeMap<_, _>>();
|
|
|
|
|
|
|
|
let mut key_width = 0;
|
|
|
|
let mut mod_width = 0;
|
|
|
|
for (key, mods) in ordered.keys() {
|
|
|
|
mod_width = mod_width.max(format!("{mods:?}").len());
|
2022-06-22 21:33:25 +03:00
|
|
|
key_width = key_width.max(human_key(key).len());
|
2022-06-22 19:14:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
for ((key, mods), entry) in ordered {
|
|
|
|
let action = &entry.action;
|
|
|
|
let mods = if *mods == Modifiers::NONE {
|
|
|
|
String::new()
|
|
|
|
} else {
|
|
|
|
format!("{mods:?}")
|
|
|
|
};
|
2022-06-22 21:33:25 +03:00
|
|
|
let key = human_key(key);
|
2022-06-22 19:14:34 +03:00
|
|
|
println!("\t{mods:mod_width$} {key:key_width$} -> {action:?}");
|
|
|
|
}
|
2022-04-10 02:20:59 +03:00
|
|
|
}
|