mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 20:36:02 +00:00
Merge pull request #7431 from dotCooCoo/fix/shortcut-optional-typed-params
Keyboard Shortcuts: panel menu commands with typed optional params can take a shortcut
This commit is contained in:
@@ -765,12 +765,10 @@ fn chosen_path(items: &[(String, Value)]) -> Option<&str> {
|
||||
items.iter().find(|(_, p)| is_bare(p)).or(items.first()).map(|(path, _)| path.as_str())
|
||||
}
|
||||
|
||||
/// Does a command's params doc (`{a?, b?} …`) say it runs with no params, as a shortcut runs it?
|
||||
/// Does a command's params doc (`{a?, b?: bool} …`) say it runs with no params, as a shortcut runs
|
||||
/// it? It does when it starts with `{` and [`names_a_required_field`] finds no field a call must give.
|
||||
fn runs_without_params(params: &str) -> bool {
|
||||
params
|
||||
.strip_prefix('{')
|
||||
.and_then(|r| r.split_once('}'))
|
||||
.is_some_and(|(fields, _)| fields.split(',').all(|f| f.trim().is_empty() || f.trim_end().ends_with('?')))
|
||||
params.starts_with('{') && !names_a_required_field(params)
|
||||
}
|
||||
|
||||
/// Does the editor list `e` under `overrides`? An entry that [`needs_a_value`] is listed only while
|
||||
@@ -783,8 +781,13 @@ fn listed(overrides: &Overrides, e: &Entry) -> bool {
|
||||
/// with none, and that no item of the menu bar runs: Transparency and Opacity Mask Options need
|
||||
/// a value to set, Align and Distribute a direction, Delete Swatch and Move Swatch a swatch name,
|
||||
/// and the library, data set, text style and SVG filter loaders a file, which their menu items ask
|
||||
/// for.
|
||||
const NEEDS_A_PARAM: [&str; 20] = [
|
||||
/// for. The commands after them have no menu path: the setters of panels and dialogs (Fill, Stroke
|
||||
/// Options, Character, Set Bounds), the exports and saves that give the file back without a `path`
|
||||
/// (Save Document gives the file back when the document has no file yet; File › Save takes a key
|
||||
/// instead), the undo group's begin and end, and the commands that need a point, a value or a name
|
||||
/// (Create Dimension, Edit Freeform Point, Select by Color, Move Brush). New Symbol is left out
|
||||
/// because the Symbols panel runs it through the Symbol Options dialog.
|
||||
const NEEDS_A_PARAM: [&str; 74] = [
|
||||
"transparency.set",
|
||||
"transparency.setOpacityMask",
|
||||
"stroke.set",
|
||||
@@ -805,6 +808,60 @@ const NEEDS_A_PARAM: [&str; 20] = [
|
||||
"paraStyle.load",
|
||||
"textStyle.loadAll",
|
||||
"svgFilter.import",
|
||||
"addon.pathtools.setAnchor",
|
||||
"addon.shapes.configure",
|
||||
"appearance.addEffect",
|
||||
"artboard.align",
|
||||
"artboard.distribute",
|
||||
"assets.export",
|
||||
"assets.export3D",
|
||||
"assets.settings.set",
|
||||
"attributes.set",
|
||||
"brush.move",
|
||||
"css.export",
|
||||
"dimension.create",
|
||||
"document.export",
|
||||
"document.exportDxf",
|
||||
"document.exportEps",
|
||||
"document.exportForWeb",
|
||||
"document.exportPdf",
|
||||
"document.save",
|
||||
"document.setup",
|
||||
"edit.undoGroup.begin",
|
||||
"edit.undoGroup.end",
|
||||
"eyedropper.setOptions",
|
||||
"file.package",
|
||||
"library.createGroup",
|
||||
"links.placementOptions",
|
||||
"links.unembed",
|
||||
"livePaint.gapOptions",
|
||||
"object.blend.createSpine",
|
||||
"object.blend.setEasing",
|
||||
"object.intertwine.arrange",
|
||||
"object.objectsOnPath.options",
|
||||
"object.puppetWarp.pins",
|
||||
"object.setBounds",
|
||||
"object.setLiveShape",
|
||||
"object.setOverprint",
|
||||
"object.setProps",
|
||||
"object.slice.select",
|
||||
"paint.freeform.setPoint",
|
||||
"paint.setFill",
|
||||
"paint.setGradientGeom",
|
||||
"paint.setStroke",
|
||||
"perspective.grid.define",
|
||||
"perspective.grid.set",
|
||||
"perspective.plane.move",
|
||||
"print.setup",
|
||||
"select.color",
|
||||
"select.globalEditOptions",
|
||||
"stroke.setAdvanced",
|
||||
"symbol.new",
|
||||
"symbol.options",
|
||||
"text.setFormat",
|
||||
"text.setRangeStyle",
|
||||
"text.setStyle",
|
||||
"type.ruby",
|
||||
];
|
||||
|
||||
/// The (label, params) of each menu bar item, by command id.
|
||||
@@ -907,7 +964,7 @@ fn a_menu_bar_item_runs(id: &str, params: &str) -> bool {
|
||||
/// Is engine command `c` listed in Edit › Keyboard Shortcuts whether or not an item of the menu bar
|
||||
/// runs it? A command with a menu path of its own is. One without (a panel menu item) is when a key
|
||||
/// alone can run it: it has a default key, or it is an undoable command, not an alias, whose params
|
||||
/// doc ends each field with `?`.
|
||||
/// doc names no field a call must give ([`runs_without_params`]).
|
||||
fn listed_on_its_own(c: &vectorcraft_engine::CommandSpec) -> bool {
|
||||
!c.menu.is_empty() || c.shortcut.is_some() || (c.journal && !vectorcraft_engine::cmd::is_alias(c.id) && runs_without_params(c.params))
|
||||
}
|
||||
@@ -2309,11 +2366,39 @@ mod tests {
|
||||
for id in ["brush.duplicate", "path.convertAnchors", "document.json", "prefs.list"] {
|
||||
assert!(entry(id).is_none(), "{id}");
|
||||
}
|
||||
for (doc, bare) in
|
||||
[("{}", true), ("{dx?, dy?} x", true), ("{id?|ids?, clip?}", true), ("{name, newName?}", false), ("{a?: {b}}", false), ("same as", false)]
|
||||
{
|
||||
// The Symbols panel runs New Symbol through Symbol Options, so it waits for a key the user gives it.
|
||||
assert!(entry("symbol.new").is_some_and(|e| !listed(&Overrides::new(), &e)));
|
||||
for (doc, bare) in [
|
||||
("{}", true),
|
||||
("{dx?, dy?} x", true),
|
||||
("{id?|ids?, clip?}", true),
|
||||
("{name, newName?}", false),
|
||||
("{a?: {b}}", true),
|
||||
("{ids?|id?, on?: bool} turn it on or off", true),
|
||||
("{ids?: [id…] (the selection), anchors?: [index…]}", true),
|
||||
("{format?: a|b, size?: 1|3|5}", true),
|
||||
("{artboard?: index=0}", true),
|
||||
("{mode: a|b, on?: bool}", false),
|
||||
("same as", false),
|
||||
] {
|
||||
assert_eq!(runs_without_params(doc), bare, "{doc}");
|
||||
}
|
||||
// Panel menu commands whose params doc gives each optional field a type are listed too.
|
||||
let none = Overrides::new();
|
||||
for id in [
|
||||
"type.fractionalWidths",
|
||||
"type.systemLayout",
|
||||
"object.setPixelAligned",
|
||||
"links.embed",
|
||||
"links.update",
|
||||
"object.slice.delete",
|
||||
"artboard.switchOrientation",
|
||||
"appearance.targetContents",
|
||||
"paint.invert",
|
||||
"artboard.distributeSpacing",
|
||||
] {
|
||||
assert!(entry(id).is_some_and(|e| listed(&none, &e)), "{id}");
|
||||
}
|
||||
let mut ov = Overrides::new();
|
||||
assert!(assign(&mut ov, "symbol.breakLink", Some("Cmd+Alt+Shift+F9"), true).is_ok());
|
||||
assert_eq!(effective_in(&ov, "symbol.breakLink").as_deref(), Some("Cmd+Alt+Shift+F9"));
|
||||
|
||||
+25
-1
@@ -5728,6 +5728,15 @@ tool's active artboard in place, and the Distribute buttons then send the Distri
|
||||
can then be negative. Align to Selection sends `to: "selection"`. The Distribute buttons need two or more selected
|
||||
artboards with Align to Artboard, and three or more with Align to Selection.
|
||||
|
||||
Edit › Keyboard Shortcuts and `shortcuts.list` list an undoable command that is not an alias and has no menu path or
|
||||
default shortcut, such as a panel menu's Break Link to Symbol (`symbol.breakLink`), when its params doc names no
|
||||
required field and it is not one of the commands left out below. A field is optional when each of its names ends with
|
||||
`?`, whatever type follows it (`on?: bool`, `ids?: [id…]`), when its name is followed directly by an `=` default
|
||||
(`rows=10`), or when it starts with `…`. Such a command is listed in the group named by the first part of its id.
|
||||
Commands listed this way include `type.fractionalWidths`, `type.systemLayout`, `object.setPixelAligned`,
|
||||
`links.embed`, `links.update`, `object.slice.delete`, `artboard.switchOrientation`, `artboard.distributeSpacing`,
|
||||
`appearance.targetContents` and `paint.invert`.
|
||||
|
||||
Edit › Keyboard Shortcuts and `shortcuts.list` leave out a command with no default shortcut when a key press cannot
|
||||
run it: no item of the menu bar runs it, it opens no dialog when run without params, and it is one of these:
|
||||
|
||||
@@ -5737,7 +5746,22 @@ run it: no item of the menu bar runs it, it opens no dialog when run without par
|
||||
- a command that sets nothing or fails without a param: `transparency.set`, `transparency.setOpacityMask`,
|
||||
`stroke.set`, `layer.setProps`, `object.align`, `object.distribute`, `swatch.delete`, `swatch.move`,
|
||||
`swatch.spotOptions`, `edit.colors.adjustBalance`, `swatch.library.load`, `graphicStyle.loadLibrary`,
|
||||
`symbol.loadLibrary`, `brush.loadLibrary`, `dataset.import` and `variable.loadLibrary`.
|
||||
`symbol.loadLibrary`, `brush.loadLibrary`, `dataset.import`, `variable.loadLibrary`, `charStyle.load`,
|
||||
`paraStyle.load`, `textStyle.loadAll` and `svgFilter.import`;
|
||||
- a command without a menu path that sets nothing, fails or only gives data back without a param:
|
||||
`addon.pathtools.setAnchor`, `addon.shapes.configure`, `appearance.addEffect`, `artboard.align`,
|
||||
`artboard.distribute`, `assets.export`, `assets.export3D`, `assets.settings.set`,
|
||||
`attributes.set`, `brush.move`, `css.export`, `dimension.create`, `document.export`, `document.exportDxf`,
|
||||
`document.exportEps`, `document.exportForWeb`, `document.exportPdf`, `document.save`, `document.setup`,
|
||||
`edit.undoGroup.begin`, `edit.undoGroup.end`, `eyedropper.setOptions`, `file.package`, `library.createGroup`,
|
||||
`links.placementOptions`, `links.unembed`, `livePaint.gapOptions`, `object.blend.createSpine`,
|
||||
`object.blend.setEasing`, `object.intertwine.arrange`, `object.objectsOnPath.options`, `object.puppetWarp.pins`,
|
||||
`object.setBounds`, `object.setLiveShape`, `object.setOverprint`, `object.setProps`, `object.slice.select`,
|
||||
`paint.freeform.setPoint`, `paint.setFill`, `paint.setGradientGeom`, `paint.setStroke`, `perspective.grid.define`,
|
||||
`perspective.grid.set`, `perspective.plane.move`, `print.setup`, `select.color`, `select.globalEditOptions`,
|
||||
`stroke.setAdvanced`, `symbol.options`, `text.setFormat`, `text.setRangeStyle`, `text.setStyle` and `type.ruby`;
|
||||
- `symbol.new`, which the Symbols panel's New Symbol button and its New Symbol… menu item run through the Symbol
|
||||
Options dialog.
|
||||
|
||||
They list such a command while the user has changed its shortcut (`overridden: true` in `shortcuts.list`), and
|
||||
`shortcuts.set` can change or clear it. When every menu bar item that runs a command gives it the same params, a
|
||||
|
||||
Reference in New Issue
Block a user