keymap: use US spelling in the shortcuts dialog

This commit is contained in:
aiongg committed 2026-10-20 03:28:24 +00:00
1 parent cf9e10a90a
commit 4674ab7c85
14 files changed
+65 -65

No files matched your search

+4 -4
View File
@@ -7,11 +7,11 @@
//! use craft_keymap::editor::holders;
//! use craft_keymap::{AssignError, Bindable, Binding, Chord, EditSession, Keymap, Platform, Policy, Recorded, Recorder, Scope, Scopes};
//!
//! let catalogue = vec![
//! let catalog = vec![
//! Bindable::new("file.save", "Save", Scope::app()).with_default(Binding::parse("Cmd+S").unwrap()),
//! Bindable::new("edit.copy", "Copy", Scope::app()).with_default(Binding::parse("Cmd+C").unwrap()),
//! ];
//! let mut keymap = Keymap::new(catalogue, Scopes::new(), Platform::Mac);
//! let mut keymap = Keymap::new(catalog, Scopes::new(), Platform::Mac);
//! let now = 12.5;
//!
//! let mut session = EditSession::begin(&keymap);
@@ -231,13 +231,13 @@ impl Recorder {
}
}
/// The bindables matching `query`, in catalogue order: a case-insensitive substring of the label,
/// The bindables matching `query`, in catalog order: a case-insensitive substring of the label,
/// an alias, a menu path segment, the command id, or a binding's canonical or `platform` display
/// text. An empty query matches everything.
pub fn search<'a>(keymap: &'a Keymap, query: &str, platform: Platform) -> Vec<&'a Bindable> {
let q = query.trim().to_lowercase();
keymap
.catalogue()
.catalog()
.iter()
.filter(|b| {
if q.is_empty() {
+1 -1
View File
@@ -36,7 +36,7 @@ const FORMAT: &str = "craft-keymap";
const VERSION: u64 = 1;
const IMPORTED: &str = "Imported";
/// The app's built-in sets: name and overrides against the catalogue defaults.
/// The app's built-in sets: name and overrides against the catalog defaults.
pub type Builtins<'a> = [(&'a str, Overrides)];
/// Why a set operation was refused.
+2 -2
View File
@@ -1,5 +1,5 @@
//! The on-screen keyboard pane (§2.9 of the dialog plan, `Options::keyboard`): a US ANSI layout
//! coloured by who holds each key with the chosen modifiers, modifier toggles that also follow the
//! colored by who holds each key with the chosen modifiers, modifier toggles that also follow the
//! held modifiers, the shortcuts of the clicked key, and Assign to Selected.
use std::collections::HashMap;
@@ -242,7 +242,7 @@ impl KeyboardState {
}
let platform = keymap.platform();
let mut map: HashMap<Chord, Vec<KeyHolder>> = HashMap::new();
for b in keymap.catalogue() {
for b in keymap.catalog() {
for binding in keymap.bindings(&b.command) {
let scope = binding.scope_or(&b.scope).clone();
let holder = Holder { command: b.command.clone(), binding };
+4 -4
View File
@@ -1,4 +1,4 @@
//! The Keyboard Shortcuts dialog (feature `ui`): a table of the catalogue with recording,
//! The Keyboard Shortcuts dialog (feature `ui`): a table of the catalog with recording,
//! conflicts, undo, named sets and import review, over [`Keymap`] and optionally [`Profiles`].
//!
//! The app keeps a [`DialogState`] while the dialog is open and calls [`ShortcutsDialog::show`]
@@ -72,14 +72,14 @@ pub struct Area {
pub rows: fn(&Bindable) -> bool,
}
/// A read-only row for a key outside the catalogue.
/// A read-only row for a key outside the catalog.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FixedRow {
pub group: String,
pub label: String,
/// The keys as shown.
pub keys: String,
/// The trigger, when the row has one, so a catalogue binding on it can be pointed out.
/// The trigger, when the row has one, so a catalog binding on it can be pointed out.
pub chord: Option<Trigger>,
}
@@ -114,7 +114,7 @@ pub struct Options {
pub backspace_clears: bool,
/// false: Enter when idle is OK.
pub enter_is_ok: bool,
/// false: rows sort by translated label instead of catalogue order.
/// false: rows sort by translated label instead of catalog order.
pub sort_by_label: bool,
/// false: Show as tabs instead of a dropdown.
pub area_tabs: bool,
+2 -2
View File
@@ -16,7 +16,7 @@ struct Entry {
line: Option<usize>,
keys: String,
note: String,
/// The note is what the item becomes (Will change), drawn in the text colour, not dimmed.
/// The note is what the item becomes (Will change), drawn in the text color, not dimmed.
to: bool,
/// Chord text inside the note, kept out of bidi reordering.
note_chord: String,
@@ -55,7 +55,7 @@ impl Draw<'_, '_> {
line.map(|n| fill(self.ui("line {n}"), &[("n", &n.to_string())]))
}
/// "item · line n · keys — note" on one wrapping line, the item in the strong colour.
/// "item · line n · keys — note" on one wrapping line, the item in the strong color.
fn entry(&self, ui: &mut Ui, e: &Entry) {
let font = TextStyle::Body.resolve(ui.style());
let strong = ui.visuals().strong_text_color();
+18 -18
View File
@@ -69,7 +69,7 @@ pub(crate) struct Chip {
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct Row {
/// Position in the catalogue.
/// Position in the catalog.
pub index: usize,
pub command: CommandRef,
/// [`CommandRef::key`], for automation ids and the overrides.
@@ -92,7 +92,7 @@ pub(crate) struct Row {
pub(crate) struct FixedLine {
pub label: String,
pub keys: String,
/// The label of a catalogue command now bound to the row's chord: drawn struck through.
/// The label of a catalog command now bound to the row's chord: drawn struck through.
pub now_used_by: Option<String>,
}
@@ -186,12 +186,12 @@ fn is_tool(b: &Bindable) -> bool {
matches!(b.kind, Kind::Tool { .. })
}
/// The Show entries, in catalogue order, leaving out areas with no rows.
/// The Show entries, in catalog order, leaving out areas with no rows.
pub(crate) fn areas(keymap: &Keymap, options: &Options, text: &dyn Text) -> Vec<AreaEntry> {
let catalogue = keymap.catalogue();
let catalog = keymap.catalog();
let mut out = vec![AreaEntry { id: AreaId::All, label: text.ui("All Commands").into_owned() }];
let mut menus: Vec<&str> = Vec::new();
for m in catalogue.iter().filter_map(top_menu) {
for m in catalog.iter().filter_map(top_menu) {
if !menus.contains(&m) {
menus.push(m);
}
@@ -200,19 +200,19 @@ pub(crate) fn areas(keymap: &Keymap, options: &Options, text: &dyn Text) -> Vec<
let label = craft_i18n::fmt(&text.ui("{menu} Menu"), &[("menu", &text.segment(m))]);
out.push(AreaEntry { id: AreaId::Menu(m.to_string()), label });
}
if catalogue.iter().any(is_tool) {
if catalog.iter().any(is_tool) {
out.push(AreaEntry { id: AreaId::Tools, label: text.ui("Tools").into_owned() });
}
let mut panels: Vec<&str> = keymap.scopes().panels().iter().map(String::as_str).collect();
for b in catalogue.iter().filter(|b| !b.scope.is_app()) {
for b in catalog.iter().filter(|b| !b.scope.is_app()) {
if !panels.contains(&b.scope.as_str()) {
panels.push(b.scope.as_str());
}
}
for p in panels.into_iter().filter(|p| catalogue.iter().any(|b| b.scope.as_str() == *p)) {
for p in panels.into_iter().filter(|p| catalog.iter().any(|b| b.scope.as_str() == *p)) {
out.push(AreaEntry { id: AreaId::Panel(p.to_string()), label: panel_label(text, p) });
}
if catalogue.iter().any(|b| top_menu(b).is_none() && !is_tool(b)) {
if catalog.iter().any(|b| top_menu(b).is_none() && !is_tool(b)) {
out.push(AreaEntry { id: AreaId::Other, label: text.ui("Other").into_owned() });
}
for a in &options.areas {
@@ -240,7 +240,7 @@ fn in_area(area: &AreaId, b: &Bindable, options: &Options) -> bool {
}
}
/// The first id segment, capitalised: `layer.lock` → `Layer`.
/// The first id segment, capitalized: `layer.lock` → `Layer`.
fn id_group(id: &str) -> String {
let first = id.split('.').next().unwrap_or(id);
let mut chars = first.chars();
@@ -314,7 +314,7 @@ impl Query {
fn build(keymap: &Keymap, options: &Options, text: &dyn Text, view: &View) -> Built {
let platform = keymap.platform();
let catalogue = keymap.catalogue();
let catalog = keymap.catalog();
let mut built = Built::default();
let mut clashing: HashSet<String> = HashSet::new();
for c in keymap.conflicts() {
@@ -333,10 +333,10 @@ fn build(keymap: &Keymap, options: &Options, text: &dyn Text, view: &View) -> Bu
return built;
}
let bindings: Vec<Vec<Binding>> = catalogue.iter().map(|b| keymap.bindings(&b.command)).collect();
let bindings: Vec<Vec<Binding>> = catalog.iter().map(|b| keymap.bindings(&b.command)).collect();
// How many tools of a group hold each effective trigger.
let mut tool_keys: HashMap<(Option<&str>, Trigger), usize> = HashMap::new();
for (b, list) in catalogue.iter().zip(&bindings) {
for (b, list) in catalog.iter().zip(&bindings) {
if let Kind::Tool { group } = &b.kind {
for x in list {
*tool_keys.entry((group.as_deref(), x.trigger.effective(platform))).or_default() += 1;
@@ -344,13 +344,13 @@ fn build(keymap: &Keymap, options: &Options, text: &dyn Text, view: &View) -> Bu
}
}
let submenus = match view.area {
AreaId::Menu(m) => catalogue.iter().any(|b| top_menu(b) == Some(m.as_str()) && b.paths.first().is_some_and(|p| p.len() >= 3)),
AreaId::Menu(m) => catalog.iter().any(|b| top_menu(b) == Some(m.as_str()) && b.paths.first().is_some_and(|p| p.len() >= 3)),
_ => false,
};
// Groups in first-seen order within their rank.
let mut groups: Vec<(u8, Option<String>, Vec<Row>)> = Vec::new();
for (index, (b, list)) in catalogue.iter().zip(&bindings).enumerate() {
for (index, (b, list)) in catalog.iter().zip(&bindings).enumerate() {
if !in_area(view.area, b, options) || !query.matches(b, list, text, platform) {
continue;
}
@@ -427,7 +427,7 @@ fn build_fixed(keymap: &Keymap, options: &Options, text: &dyn Text, view: &View,
let now_used_by = f.chord.and_then(|c| {
let c = c.effective(platform);
keymap
.catalogue()
.catalog()
.iter()
.find(|b| keymap.bindings(&b.command).iter().any(|x| x.trigger.effective(platform) == c))
.map(|b| text.command(b).into_owned())
@@ -468,7 +468,7 @@ pub(crate) mod tests {
let tool = Kind::Tool { group: Some("Marquee".into()) };
let path = |p: &[&str]| p.iter().map(|s| s.to_string()).collect::<Vec<_>>();
let timeline = Scope::new("Timeline").unwrap_or_else(Scope::app);
let catalogue = vec![
let catalog = vec![
Bindable::new("file.save", "Save", Scope::app()).with_path(path(&["File", "Save"])).with_default(key("Cmd+S")),
Bindable::new("file.saveAs", "Save As…", Scope::app()).with_path(path(&["File", "Save As…"])).with_default(key("Cmd+Shift+S")),
Bindable::new("file.export", "Export…", Scope::app()).with_path(path(&["File", "Export…"])).with_default(key("Cmd+E")),
@@ -478,7 +478,7 @@ pub(crate) mod tests {
Bindable::new("timeline.loop", "Loop", timeline).with_default(key("L")),
Bindable::new("type.bold", "Bold", Scope::app()).with_default(key("Text: Cmd+B")),
];
Keymap::new(catalogue, Scopes::new().with_panel("Timeline").with_context("Text"), platform)
Keymap::new(catalog, Scopes::new().with_panel("Timeline").with_context("Text"), platform)
}
fn view<'a>(query: &'a str, area: &'a AreaId, filter: Filter, collapsed: &'a BTreeSet<String>) -> View<'a> {
+1 -1
View File
@@ -473,7 +473,7 @@ impl DialogState {
let platform = env.keymap.platform();
let want = trigger.effective(platform);
let mut shadows = Vec::new();
for b in env.keymap.catalogue() {
for b in env.keymap.catalog() {
if b.command == command {
continue;
}
+3 -3
View File
@@ -1,10 +1,10 @@
//! The dialog's colours and the icon-button style built from them.
//! The dialog's colors and the icon-button style built from them.
use craft_ui::buttons::{ButtonVisuals, IconButtonStyle};
use craft_ui::layout::ResizeHandleStyle;
use egui::{Color32, Stroke, Visuals};
/// The dialog's colours.
/// The dialog's colors.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct DialogStyle {
pub accent: Color32,
@@ -35,7 +35,7 @@ impl DialogStyle {
}
}
/// Icon buttons (+, ×, ↺, ⌨, ✕) in the colours of the app's visuals.
/// Icon buttons (+, ×, ↺, ⌨, ✕) in the colors of the app's visuals.
pub(crate) fn icon_buttons(v: &Visuals) -> IconButtonStyle {
let w = &v.widgets;
IconButtonStyle {
+2 -2
View File
@@ -27,10 +27,10 @@ fn binding_text(km: &Keymap, text: &dyn Text, b: &Binding, home: &Scope) -> Stri
}
}
/// Groups in the table's order; commands in catalogue order within a group.
/// Groups in the table's order; commands in catalog order within a group.
fn groups(km: &Keymap, text: &dyn Text) -> Vec<Group> {
let mut out: Vec<Group> = Vec::new();
for b in km.catalogue() {
for b in km.catalog() {
let bindings = km.bindings(&b.command);
if bindings.is_empty() {
continue;
+1 -1
View File
@@ -261,7 +261,7 @@ impl Draw<'_, '_> {
IconButton::new(label, Vec2::splat(ICON), &self.icons).selected(selected).show(ui, |ui, rect, color| paint(ui.painter(), rect, color))
}
/// A row control: clickable and labelled but not a Tab stop (the table is one).
/// A row control: clickable and labeled but not a Tab stop (the table is one).
fn row_button(&self, ui: &mut Ui, rect: Rect, id: Id, label: &str, enabled: bool, paint: fn(&Painter, Rect, Color32)) -> Response {
let resp = ui.interact(rect, id, if enabled { Sense::CLICK } else { Sense::hover() });
resp.widget_info(|| WidgetInfo::labeled(WidgetType::Button, enabled, label));
+3 -3
View File
@@ -13,13 +13,13 @@ fn b(text: &str) -> Binding {
}
fn keymap(platform: Platform) -> Keymap {
let catalogue = vec![
let catalog = vec![
Bindable::new("file.save", "Save", Scope::app()).with_default(b("Cmd+S")).with_path(vec!["File".into(), "Save".into()]),
Bindable::new("edit.copy", "Copy", Scope::app()).with_default(b("Cmd+C")).with_alias("Kopieren"),
Bindable::new("view.zoomIn", "Zoom In", Scope::app()).with_default(b("Cmd+=")),
Bindable::new("tool.brush", "Brush", Scope::app()).with_default(b("B")).with_path(vec!["Tools".into(), "Paint".into()]),
];
Keymap::new(catalogue, Scopes::new(), platform)
Keymap::new(catalog, Scopes::new(), platform)
}
fn keys(km: &Keymap, id: &str) -> Vec<String> {
@@ -87,7 +87,7 @@ fn undo_keeps_the_newest_steps() {
fn undo_history_is_capped_by_size() {
let mut km = keymap(Platform::Windows);
let mut session = EditSession::begin(&km);
// Full-size snapshots of entries for commands the catalogue does not have.
// Full-size snapshots of entries for commands the catalog does not have.
let big = |tag: char| {
let mut o = Overrides::new();
for n in 0..MAX_COMMANDS {
+3 -3
View File
@@ -9,13 +9,13 @@ fn b(text: &str) -> Binding {
}
fn keymap() -> Keymap {
let catalogue = vec![
let catalog = vec![
Bindable::new("file.save", "Save", Scope::app()).with_path(vec!["File".into(), "Save".into()]).with_default(b("Cmd+S")),
Bindable::new("edit.copy", "Copy", Scope::app()).with_path(vec!["Edit".into(), "Copy".into()]).with_default(b("Cmd+C")),
Bindable::new(CommandRef::with_params("window.panel", json!({"panel": "layers"})), "Layers", Scope::app()).with_default(b("F7")),
Bindable::new("timeline.loop", "Loop", Scope::new("Timeline").unwrap()).with_default(b("L")),
];
Keymap::new(catalogue, Scopes::new().with_panel("Timeline"), Platform::Mac)
Keymap::new(catalog, Scopes::new().with_panel("Timeline"), Platform::Mac)
}
#[test]
@@ -132,7 +132,7 @@ fn an_exported_set_imports_as_a_new_set_with_the_same_keymap() {
let mut again = keymap();
again.set_overrides(p.active_overrides(&builtins).clone());
for bindable in km.catalogue() {
for bindable in km.catalog() {
assert_eq!(again.bindings(&bindable.command), km.bindings(&bindable.command), "{}", bindable.command.key());
}
assert_eq!(again.overrides(), km.overrides());
+15 -15
View File
@@ -59,7 +59,7 @@ impl Fx {
self.km.bindings(&CommandRef::from(id)).iter().map(|b| b.to_string()).collect()
}
fn cancelled(&self) -> bool {
fn canceled(&self) -> bool {
self.outcomes.iter().any(|o| matches!(o, Outcome::Cancel))
}
}
@@ -162,10 +162,10 @@ fn escape_cancels_recording_only() {
press(&mut h, Modifiers::NONE, EguiKey::Escape);
assert!(h.state().state.is_open());
assert!(!h.state().state.is_recording());
assert!(!h.state().cancelled());
assert!(!h.state().canceled());
assert_eq!(h.state().bindings("file.save"), ["Cmd+S"]);
press(&mut h, Modifiers::NONE, EguiKey::Escape);
assert!(h.state().cancelled());
assert!(h.state().canceled());
assert!(!h.state().state.is_open());
}
@@ -432,9 +432,9 @@ fn table_keys_move_record_and_delete() {
fn small_window_keeps_ok_and_long_labels_truncate() {
let long = "A very long command label ".repeat(12);
let mut km = fixture(Platform::Mac);
let mut catalogue = km.catalogue().to_vec();
catalogue.insert(0, Bindable::new("file.long", long.trim(), Scope::app()).with_path(vec!["File".into(), long.trim().into()]));
km = Keymap::new(catalogue, Scopes::new().with_panel("Timeline").with_context("Text"), Platform::Mac);
let mut catalog = km.catalog().to_vec();
catalog.insert(0, Bindable::new("file.long", long.trim(), Scope::app()).with_path(vec!["File".into(), long.trim().into()]));
km = Keymap::new(catalog, Scopes::new().with_panel("Timeline").with_context("Text"), Platform::Mac);
let mut fx = Fx::new(km);
fx.window = true;
let size = vec2(480.0, 360.0);
@@ -460,7 +460,7 @@ fn window_close_is_cancel() {
press(&mut h, Modifiers::NONE, EguiKey::F2);
assert_eq!(h.state().bindings("file.save"), ["F2"]);
click(&mut h, "Cancel");
assert!(h.state().cancelled());
assert!(h.state().canceled());
assert_eq!(h.state().bindings("file.save"), ["Cmd+S"]);
}
@@ -587,7 +587,7 @@ fn cancel_restores_keymap_and_sets() {
click_last(&mut h, "Delete");
assert!(!profiles(&h).sets.contains_key("Other"));
click(&mut h, "Cancel");
assert!(h.state().cancelled());
assert!(h.state().canceled());
assert_eq!(profiles(&h), &before);
assert!(h.state().km.overrides().is_empty());
}
@@ -691,14 +691,14 @@ fn picking_a_suggestion_replans_and_is_remembered() {
#[test]
fn summary_escapes_html_and_keeps_text_lines() {
let mut km = fixture(Platform::Mac);
let mut catalogue = km.catalogue().to_vec();
let mut catalog = km.catalog().to_vec();
let label = "<b>\"Tom\" & 'Jerry'</b>\nNext";
catalogue.push(
catalog.push(
Bindable::new("edit.tricky", label, Scope::app())
.with_path(vec!["Edit".into(), "Tricky".into()])
.with_default(craft_keymap::Binding::parse("F6").expect("F6")),
);
km = Keymap::new(catalogue, Scopes::new().with_panel("Timeline").with_context("Text"), Platform::Mac);
km = Keymap::new(catalog, Scopes::new().with_panel("Timeline").with_context("Text"), Platform::Mac);
let mut h = open(Fx::new(km));
click(&mut h, "Summarize…");
let (html, text) = h
@@ -734,13 +734,13 @@ fn with_keyboard(options: impl FnOnce(&mut Fx)) -> Harness<'static, Fx> {
open(fx)
}
/// What a key's colour means, as its accessibility description says it.
/// What a key's color means, as its accessibility description says it.
fn holders_class(h: &Harness<'_, Fx>, key: &str) -> String {
h.get_by_role_and_label(Role::Button, key).accesskit_node().description().unwrap_or_default().to_string()
}
#[test]
fn keyboard_colours_keys_and_assigns_to_the_selected_command() {
fn keyboard_colors_keys_and_assigns_to_the_selected_command() {
let mut h = with_keyboard(|_| {});
assert_eq!(holders_class(&h, "M: Marquee Tool, Elliptical Marquee Tool"), "Application");
assert_eq!(holders_class(&h, "L: Loop (Timeline)"), "Panel or context");
@@ -831,7 +831,7 @@ fn read_only_has_no_edit_controls() {
click(&mut h, "Summarize…");
assert!(h.state().outcomes.iter().any(|o| matches!(o, Outcome::Summary { .. })));
click(&mut h, "Close");
assert!(h.state().cancelled());
assert!(h.state().canceled());
}
// ---- Pseudo locale ----
@@ -864,7 +864,7 @@ fn check_pseudo(h: &Harness<'_, Fx>, width: f32, step: &str) {
let words = rest.split(|c: char| !c.is_ascii_lowercase()).any(|w| w.len() > 1);
assert!(!words, "{step}: {label:?} has text that did not go through Text");
}
assert!(seen > 15, "{step}: {seen} labelled nodes");
assert!(seen > 15, "{step}: {seen} labeled nodes");
}
#[test]
+6 -6
View File
@@ -1,4 +1,4 @@
//! The catalogue the dialog tests and screenshots use.
//! The catalog the dialog tests and screenshots use.
use std::borrow::Cow;
use std::cell::RefCell;
@@ -16,7 +16,7 @@ pub fn fixture(platform: Platform) -> Keymap {
let tool = Kind::Tool { group: Some("Marquee".into()) };
let path = |p: &[&str]| p.iter().map(|s| s.to_string()).collect::<Vec<_>>();
let timeline = Scope::new("Timeline").unwrap_or_else(Scope::app);
let catalogue = vec![
let catalog = vec![
Bindable::new("file.save", "Save", Scope::app()).with_path(path(&["File", "Save"])).with_default(binding("Cmd+S")),
Bindable::new("file.saveAs", "Save As…", Scope::app()).with_path(path(&["File", "Save As…"])).with_default(binding("Cmd+Shift+S")),
Bindable::new("file.export", "Export…", Scope::app()).with_path(path(&["File", "Export…"])).with_default(binding("Cmd+E")),
@@ -26,22 +26,22 @@ pub fn fixture(platform: Platform) -> Keymap {
Bindable::new("timeline.loop", "Loop", timeline).with_default(binding("L")),
Bindable::new("type.bold", "Bold", Scope::app()).with_default(binding("Text: Cmd+B")),
];
Keymap::new(catalogue, Scopes::new().with_panel("Timeline").with_context("Text"), platform)
Keymap::new(catalog, Scopes::new().with_panel("Timeline").with_context("Text"), platform)
}
/// `km` with a command whose label and menu path are far too long for a row.
#[allow(dead_code)]
pub fn with_long_label(km: Keymap) -> Keymap {
let long = "Distribute Selected Objects Evenly Along the Active Guide Path and Keep Their Spacing".to_string();
let mut catalogue = km.catalogue().to_vec();
catalogue.insert(
let mut catalog = km.catalog().to_vec();
catalog.insert(
3,
Bindable::new("object.distribute", long.as_str(), Scope::app())
.with_path(vec!["Object".into(), "Arrange and Distribute Along a Path".into(), long.clone()])
.with_default(binding("Cmd+Alt+Shift+D"))
.with_default(binding("Ctrl+Alt+Shift+F12")),
);
Keymap::new(catalogue, Scopes::new().with_panel("Timeline").with_context("Text"), km.platform())
Keymap::new(catalog, Scopes::new().with_panel("Timeline").with_context("Text"), km.platform())
}
/// A pseudo translation: every string about 40 % longer, accented, between right-to-left marks and