From 5454e931686af9828f8840327e891983bc67261d Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Thu, 14 Nov 2013 10:15:23 -0800 Subject: [PATCH 1/5] Make base menus platform dependent This fixes the most egrerious errors on Windows but there's still room for improvement. Refs #1085 --- menus/{base.cson => darwin.cson} | 0 menus/win32.cson | 172 +++++++++++++++++++++++++++++++ src/menu-manager.coffee | 11 +- 3 files changed, 177 insertions(+), 6 deletions(-) rename menus/{base.cson => darwin.cson} (100%) create mode 100644 menus/win32.cson diff --git a/menus/base.cson b/menus/darwin.cson similarity index 100% rename from menus/base.cson rename to menus/darwin.cson diff --git a/menus/win32.cson b/menus/win32.cson new file mode 100644 index 000000000..a78d0f183 --- /dev/null +++ b/menus/win32.cson @@ -0,0 +1,172 @@ +'menu': [ + { + label: 'File' + submenu: [ + { label: 'New Window', command: 'application:new-window' } + { label: 'New File', command: 'application:new-file' } + { label: 'Open...', command: 'application:open' } + { label: 'Reopen Last Item', command: 'pane:reopen-closed-item' } + { type: 'separator' } + { label: 'Preferences...', command: 'application:show-settings' } + { type: 'separator' } + { label: 'Save', command: 'core:save' } + { label: 'Save As...', command: 'core:save-as' } + { label: 'Save All', command: 'window:save-all' } + { type: 'separator' } + { label: 'Close Buffer', command: 'core:close' } + { label: 'Close All Buffers', command: 'pane:close' } + { label: 'Close Window', command: 'window:close' } + { type: 'separator' } + { label: 'Exit', command: 'application:quit' } + ] + } + + { + label: 'Edit' + submenu: [ + { label: 'Undo', command: 'core:undo' } + { label: 'Redo', command: 'core:redo' } + { type: 'separator' } + { label: 'Cut', command: 'core:cut' } + { label: 'Copy', command: 'core:copy' } + { label: 'Copy Path', command: 'editor:copy-path' } + { label: 'Paste', command: 'core:paste' } + { label: 'Select All', command: 'core:select-all' } + { type: 'separator' } + { label: 'Toggle Comments', command: 'editor:toggle-line-comments' } + { + label: 'Lines', + submenu: [ + { label: 'Indent', command: 'editor:indent-selected-rows' } + { label: 'Outdent', command: 'editor:outdent-selected-rows' } + { label: 'Auto Indent', command: 'editor:auto-indent' } + { type: 'separator' } + { label: 'Move Line Up', command: 'editor:move-line-up' } + { label: 'Move Line Down', command: 'editor:move-line-down' } + { label: 'Duplicate Line', command: 'editor:duplicate-line' } + { label: 'Delete Line', command: 'editor:delete-line' } + { label: 'Join Lines', command: 'editor:join-line' } + ] + } + { + label: 'Text', + submenu: [ + { label: 'Upper Case', command: 'editor:upper-case' } + { label: 'Lower Case', command: 'editor:lower-case' } + { type: 'separator' } + { label: 'Delete to End of Word', command: 'editor:delete-to-end-of-word' } + { label: 'Delete Line', command: 'editor:delete-line' } + { type: 'separator' } + { label: 'Transpose', command: 'editor:transpose' } + ] + } + { + label: 'Folding', + submenu: [ + { label: 'Fold', command: 'editor:fold-current-row' } + { label: 'Unfold', command: 'editor:unfold-current-row' } + { label: 'Unfold All', command: 'editor:unfold-all' } + { type: 'separator' } + { label: 'Fold All', command: 'editor:fold-all' } + { label: 'Fold Level 1', command: 'editor:fold-at-indent-level-1' } + { label: 'Fold Level 2', command: 'editor:fold-at-indent-level-2' } + { label: 'Fold Level 3', command: 'editor:fold-at-indent-level-3' } + { label: 'Fold Level 4', command: 'editor:fold-at-indent-level-4' } + { label: 'Fold Level 5', command: 'editor:fold-at-indent-level-5' } + { label: 'Fold Level 6', command: 'editor:fold-at-indent-level-6' } + { label: 'Fold Level 7', command: 'editor:fold-at-indent-level-7' } + { label: 'Fold Level 8', command: 'editor:fold-at-indent-level-8' } + { label: 'Fold Level 9', command: 'editor:fold-at-indent-level-9' } + ] + } + ] + } + + { + label: 'View' + submenu: [ + { label: 'Reload', command: 'window:reload' } + { label: 'Toggle Full Screen', command: 'window:toggle-full-screen' } + { + label: 'Developer' + submenu: [ + { label: 'Open In Dev Mode...', command: 'application:open-dev' } + { label: 'Run Atom Specs', command: 'application:run-all-specs' } + { label: 'Run Package Specs', command: 'window:run-package-specs' } + { label: 'Toggle Developer Tools', command: 'window:toggle-dev-tools' } + ] + } + { type: 'separator' } + { label: 'Toggle Soft Wrap', command: 'editor:toggle-soft-wrap' } + ] + } + + { + label: 'Selection' + submenu: [ + { label: 'Add Selection Above', command: 'editor:add-selection-above' } + { label: 'Add Selection Below', command: 'editor:add-selection-below' } + { type: 'separator' } + { label: 'Select to Top', command: 'core:select-to-top' } + { label: 'Select to Bottom', command: 'core:select-to-bottom' } + { type: 'separator' } + { label: 'Select Line', command: 'editor:select-line' } + { label: 'Select Word', command: 'editor:select-word' } + { label: 'Select to Beginning of Word', command: 'editor:select-to-beginning-of-word' } + { label: 'Select to Beginning of Line', command: 'editor:select-to-beginning-of-line' } + { label: 'Select to First Character of Line', command: 'editor:select-to-first-character-of-line' } + { label: 'Select to End of Word', command: 'editor:select-to-end-of-word' } + { label: 'Select to End of Line', command: 'editor:select-to-end-of-line' } + ] + } + + { + label: 'Movement' + submenu: [ + { label: 'Move to Top', command: 'core:move-to-top' } + { label: 'Move to Bottom', command: 'core:move-to-bottom' } + { type: 'separator' } + { label: 'Move to Beginning of Line', command: 'editor:move-to-beginning-of-line' } + { label: 'Move to First Character of Line', command: 'editor:move-to-first-character-of-line' } + { label: 'Move to End of Line', command: 'editor:move-to-end-of-line' } + { type: 'separator' } + { label: 'Move to Beginning of Word', command: 'editor:move-to-beginning-of-word' } + { label: 'Move to End of Word', command: 'editor:move-to-end-of-word' } + { label: 'Move to Next Word', command: 'editor:move-to-next-word-boundary' } + { label: 'Move to Previous Word', command: 'editor:move-to-previous-word-boundary' } + ] + } + + { + label: 'Find' + submenu: [] + } + + { + label: 'Packages' + submenu: [] + } + + { + label: 'Window' + submenu: [ + { label: 'Minimize', command: 'application:minimize' } + { label: 'Zoom', command: 'application:zoom' } + { type: 'separator' } + { label: 'Bring All to Front', command: 'application:bring-all-windows-to-front' } + ] + } + + { + label: 'Help' + submenu: [ + { label: 'About Atom', command: 'application:about' } + { label: "VERSION", enabled: false } + { label: "Install update", command: 'application:install-update', visible: false } + { type: 'separator' } + { label: 'Documentation', command: 'application:open-documentation' } + { label: 'Report an Issue', command: 'application:report-issue' } + { type: 'separator' } + ] + } +] diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index 5a3ce12cf..ef6162fe2 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -14,7 +14,7 @@ class MenuManager # Private: constructor: ({@resourcePath}) -> @template = [] - atom.keymap.on 'bundled-keymaps-loaded', => @loadCoreItems() + atom.keymap.on 'bundled-keymaps-loaded', => @loadPlatformItems() # Public: Adds the given item definition to the existing template. # @@ -35,12 +35,11 @@ class MenuManager @sendToBrowserProcess(@template, keystrokesByCommand) # Private - loadCoreItems: -> + loadPlatformItems: -> menusDirPath = path.join(@resourcePath, 'menus') - menuPaths = fs.listSync(menusDirPath, ['cson', 'json']) - for menuPath in menuPaths - data = CSON.readFileSync(menuPath) - @add(data.menu) + platformMenuPath = fs.resolve(menusDirPath, process.platform, ['cson', 'json']) + data = CSON.readFileSync(platformMenuPath) + @add(data.menu) # Private: Merges an item in a submenu aware way such that new items are always # appended to the bottom of existing menus where possible. From b6afc415f8b629a745f9cb3255b51558a9b2477b Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Thu, 14 Nov 2013 10:31:20 -0800 Subject: [PATCH 2/5] Merge menu items without regard to platform decorations --- src/menu-manager.coffee | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index ef6162fe2..518bb7573 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -46,10 +46,10 @@ class MenuManager merge: (menu, item) -> item = _.deepClone(item) - if item.submenu? and match = _.find(menu, (i) -> i.submenu? and i.label == item.label) + if item.submenu? and match = _.find(menu, (i) -> i.submenu? and @normalizeLabel(i.label) == @normalizeLabel(item.label)) @merge(match.submenu, i) for i in item.submenu else - menu.push(item) unless _.find(menu, (i) -> i.label == item.label) + menu.push(item) unless _.find(menu, (i) -> @normalizeLabel(i.label) == @normalizeLabel(item.label)) # Private: OSX can't handle displaying accelerators for multiple keystrokes. # If they are sent across, it will stop processing accelerators for the rest @@ -68,3 +68,10 @@ class MenuManager sendToBrowserProcess: (template, keystrokesByCommand) -> keystrokesByCommand = @filterMultipleKeystrokes(keystrokesByCommand) ipc.sendChannel 'update-application-menu', template, keystrokesByCommand + + # Private + normalizeLabel: (label) -> + if process.platform is 'win32' + label.replace(/\&/g, '') + else + label From cfab5c619d12b100431fabcb9b9c51d5db39e6a2 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Thu, 14 Nov 2013 10:39:09 -0800 Subject: [PATCH 3/5] Use fat arrow when necessary --- src/menu-manager.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index 518bb7573..93e8fb899 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -46,10 +46,10 @@ class MenuManager merge: (menu, item) -> item = _.deepClone(item) - if item.submenu? and match = _.find(menu, (i) -> i.submenu? and @normalizeLabel(i.label) == @normalizeLabel(item.label)) + if item.submenu? and match = _.find(menu, (i) => i.submenu? and @normalizeLabel(i.label) == @normalizeLabel(item.label)) @merge(match.submenu, i) for i in item.submenu else - menu.push(item) unless _.find(menu, (i) -> @normalizeLabel(i.label) == @normalizeLabel(item.label)) + menu.push(item) unless _.find(menu, (i) => @normalizeLabel(i.label) == @normalizeLabel(item.label)) # Private: OSX can't handle displaying accelerators for multiple keystrokes. # If they are sent across, it will stop processing accelerators for the rest From 1dac1f375cc3413e5d1557ec146a393a1d3dd9b0 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Thu, 14 Nov 2013 10:39:31 -0800 Subject: [PATCH 4/5] Provide keyboard navigation for base windows menus --- menus/win32.cson | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/menus/win32.cson b/menus/win32.cson index a78d0f183..0bd34f713 100644 --- a/menus/win32.cson +++ b/menus/win32.cson @@ -1,6 +1,6 @@ 'menu': [ { - label: 'File' + label: '&File' submenu: [ { label: 'New Window', command: 'application:new-window' } { label: 'New File', command: 'application:new-file' } @@ -22,7 +22,7 @@ } { - label: 'Edit' + label: '&Edit' submenu: [ { label: 'Undo', command: 'core:undo' } { label: 'Redo', command: 'core:redo' } @@ -83,7 +83,7 @@ } { - label: 'View' + label: '&View' submenu: [ { label: 'Reload', command: 'window:reload' } { label: 'Toggle Full Screen', command: 'window:toggle-full-screen' } @@ -102,7 +102,7 @@ } { - label: 'Selection' + label: '&Selection' submenu: [ { label: 'Add Selection Above', command: 'editor:add-selection-above' } { label: 'Add Selection Below', command: 'editor:add-selection-below' } @@ -121,7 +121,7 @@ } { - label: 'Movement' + label: '&Movement' submenu: [ { label: 'Move to Top', command: 'core:move-to-top' } { label: 'Move to Bottom', command: 'core:move-to-bottom' } @@ -138,17 +138,17 @@ } { - label: 'Find' + label: 'F&ind' submenu: [] } { - label: 'Packages' + label: '&Packages' submenu: [] } { - label: 'Window' + label: '&Window' submenu: [ { label: 'Minimize', command: 'application:minimize' } { label: 'Zoom', command: 'application:zoom' } @@ -158,7 +158,7 @@ } { - label: 'Help' + label: '&Help' submenu: [ { label: 'About Atom', command: 'application:about' } { label: "VERSION", enabled: false } From 569c3116a8cfa1be06060a5dd81d87a4ed03716f Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Thu, 14 Nov 2013 13:25:58 -0800 Subject: [PATCH 5/5] Add keyboard accelerators --- menus/win32.cson | 142 +++++++++++++++++++++++------------------------ 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/menus/win32.cson b/menus/win32.cson index 0bd34f713..2c9024401 100644 --- a/menus/win32.cson +++ b/menus/win32.cson @@ -2,72 +2,72 @@ { label: '&File' submenu: [ - { label: 'New Window', command: 'application:new-window' } - { label: 'New File', command: 'application:new-file' } - { label: 'Open...', command: 'application:open' } - { label: 'Reopen Last Item', command: 'pane:reopen-closed-item' } + { label: 'New &Window', command: 'application:new-window' } + { label: '&New File', command: 'application:new-file' } + { label: '&Open...', command: 'application:open' } + { label: 'Reopen Last &Item', command: 'pane:reopen-closed-item' } { type: 'separator' } - { label: 'Preferences...', command: 'application:show-settings' } + { label: '&Preferences...', command: 'application:show-settings' } { type: 'separator' } - { label: 'Save', command: 'core:save' } - { label: 'Save As...', command: 'core:save-as' } - { label: 'Save All', command: 'window:save-all' } + { label: '&Save', command: 'core:save' } + { label: 'Save &As...', command: 'core:save-as' } + { label: 'Save A&ll', command: 'window:save-all' } { type: 'separator' } - { label: 'Close Buffer', command: 'core:close' } - { label: 'Close All Buffers', command: 'pane:close' } - { label: 'Close Window', command: 'window:close' } + { label: '&Close Buffer', command: 'core:close' } + { label: 'Close All &Buffers', command: 'pane:close' } + { label: 'Clos&e Window', command: 'window:close' } { type: 'separator' } - { label: 'Exit', command: 'application:quit' } + { label: 'E&xit', command: 'application:quit' } ] } { label: '&Edit' submenu: [ - { label: 'Undo', command: 'core:undo' } - { label: 'Redo', command: 'core:redo' } + { label: '&Undo', command: 'core:undo' } + { label: '&Redo', command: 'core:redo' } { type: 'separator' } - { label: 'Cut', command: 'core:cut' } - { label: 'Copy', command: 'core:copy' } - { label: 'Copy Path', command: 'editor:copy-path' } - { label: 'Paste', command: 'core:paste' } - { label: 'Select All', command: 'core:select-all' } + { label: '&Cut', command: 'core:cut' } + { label: 'C&opy', command: 'core:copy' } + { label: 'Copy Pat&h', command: 'editor:copy-path' } + { label: '&Paste', command: 'core:paste' } + { label: 'Select &All', command: 'core:select-all' } { type: 'separator' } - { label: 'Toggle Comments', command: 'editor:toggle-line-comments' } + { label: '&Toggle Comments', command: 'editor:toggle-line-comments' } { label: 'Lines', submenu: [ - { label: 'Indent', command: 'editor:indent-selected-rows' } - { label: 'Outdent', command: 'editor:outdent-selected-rows' } - { label: 'Auto Indent', command: 'editor:auto-indent' } + { label: '&Indent', command: 'editor:indent-selected-rows' } + { label: '&Outdent', command: 'editor:outdent-selected-rows' } + { label: '&Auto Indent', command: 'editor:auto-indent' } { type: 'separator' } - { label: 'Move Line Up', command: 'editor:move-line-up' } - { label: 'Move Line Down', command: 'editor:move-line-down' } - { label: 'Duplicate Line', command: 'editor:duplicate-line' } - { label: 'Delete Line', command: 'editor:delete-line' } - { label: 'Join Lines', command: 'editor:join-line' } + { label: 'Move Line &Up', command: 'editor:move-line-up' } + { label: 'Move Line &Down', command: 'editor:move-line-down' } + { label: 'Du&plicate Line', command: 'editor:duplicate-line' } + { label: 'D&elete Line', command: 'editor:delete-line' } + { label: '&Join Lines', command: 'editor:join-line' } ] } { label: 'Text', submenu: [ - { label: 'Upper Case', command: 'editor:upper-case' } - { label: 'Lower Case', command: 'editor:lower-case' } + { label: '&Upper Case', command: 'editor:upper-case' } + { label: '&Lower Case', command: 'editor:lower-case' } { type: 'separator' } - { label: 'Delete to End of Word', command: 'editor:delete-to-end-of-word' } - { label: 'Delete Line', command: 'editor:delete-line' } + { label: 'Delete to End of &Word', command: 'editor:delete-to-end-of-word' } + { label: '&Delete Line', command: 'editor:delete-line' } { type: 'separator' } - { label: 'Transpose', command: 'editor:transpose' } + { label: '&Transpose', command: 'editor:transpose' } ] } { label: 'Folding', submenu: [ - { label: 'Fold', command: 'editor:fold-current-row' } - { label: 'Unfold', command: 'editor:unfold-current-row' } - { label: 'Unfold All', command: 'editor:unfold-all' } + { label: '&Fold', command: 'editor:fold-current-row' } + { label: '&Unfold', command: 'editor:unfold-current-row' } + { label: 'Unfold &All', command: 'editor:unfold-all' } { type: 'separator' } - { label: 'Fold All', command: 'editor:fold-all' } + { label: 'Fol&d All', command: 'editor:fold-all' } { label: 'Fold Level 1', command: 'editor:fold-at-indent-level-1' } { label: 'Fold Level 2', command: 'editor:fold-at-indent-level-2' } { label: 'Fold Level 3', command: 'editor:fold-at-indent-level-3' } @@ -85,55 +85,55 @@ { label: '&View' submenu: [ - { label: 'Reload', command: 'window:reload' } - { label: 'Toggle Full Screen', command: 'window:toggle-full-screen' } + { label: '&Reload', command: 'window:reload' } + { label: 'Toggle &Full Screen', command: 'window:toggle-full-screen' } { label: 'Developer' submenu: [ - { label: 'Open In Dev Mode...', command: 'application:open-dev' } - { label: 'Run Atom Specs', command: 'application:run-all-specs' } - { label: 'Run Package Specs', command: 'window:run-package-specs' } - { label: 'Toggle Developer Tools', command: 'window:toggle-dev-tools' } + { label: 'Open In &Dev Mode...', command: 'application:open-dev' } + { label: 'Run &Atom Specs', command: 'application:run-all-specs' } + { label: 'Run Package &Specs', command: 'window:run-package-specs' } + { label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' } ] } { type: 'separator' } - { label: 'Toggle Soft Wrap', command: 'editor:toggle-soft-wrap' } + { label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrap' } ] } { label: '&Selection' submenu: [ - { label: 'Add Selection Above', command: 'editor:add-selection-above' } - { label: 'Add Selection Below', command: 'editor:add-selection-below' } + { label: 'Add Selection &Above', command: 'editor:add-selection-above' } + { label: 'Add Selection &Below', command: 'editor:add-selection-below' } { type: 'separator' } - { label: 'Select to Top', command: 'core:select-to-top' } - { label: 'Select to Bottom', command: 'core:select-to-bottom' } + { label: 'Select to &Top', command: 'core:select-to-top' } + { label: 'Select to Botto&m', command: 'core:select-to-bottom' } { type: 'separator' } - { label: 'Select Line', command: 'editor:select-line' } - { label: 'Select Word', command: 'editor:select-word' } - { label: 'Select to Beginning of Word', command: 'editor:select-to-beginning-of-word' } - { label: 'Select to Beginning of Line', command: 'editor:select-to-beginning-of-line' } - { label: 'Select to First Character of Line', command: 'editor:select-to-first-character-of-line' } - { label: 'Select to End of Word', command: 'editor:select-to-end-of-word' } - { label: 'Select to End of Line', command: 'editor:select-to-end-of-line' } + { label: 'Select &Line', command: 'editor:select-line' } + { label: 'Select &Word', command: 'editor:select-word' } + { label: 'Select to Beginning of W&ord', command: 'editor:select-to-beginning-of-word' } + { label: 'Select to Beginning of L&ine', command: 'editor:select-to-beginning-of-line' } + { label: 'Select to First &Character of Line', command: 'editor:select-to-first-character-of-line' } + { label: 'Select to End of Wor&d', command: 'editor:select-to-end-of-word' } + { label: 'Select to End of Lin&e', command: 'editor:select-to-end-of-line' } ] } { label: '&Movement' submenu: [ - { label: 'Move to Top', command: 'core:move-to-top' } - { label: 'Move to Bottom', command: 'core:move-to-bottom' } + { label: 'Move to &Top', command: 'core:move-to-top' } + { label: 'Move to &Bottom', command: 'core:move-to-bottom' } { type: 'separator' } - { label: 'Move to Beginning of Line', command: 'editor:move-to-beginning-of-line' } - { label: 'Move to First Character of Line', command: 'editor:move-to-first-character-of-line' } - { label: 'Move to End of Line', command: 'editor:move-to-end-of-line' } + { label: 'Move to Beginning of &Line', command: 'editor:move-to-beginning-of-line' } + { label: 'Move to &First Character of Line', command: 'editor:move-to-first-character-of-line' } + { label: 'Move to &End of Line', command: 'editor:move-to-end-of-line' } { type: 'separator' } - { label: 'Move to Beginning of Word', command: 'editor:move-to-beginning-of-word' } - { label: 'Move to End of Word', command: 'editor:move-to-end-of-word' } - { label: 'Move to Next Word', command: 'editor:move-to-next-word-boundary' } - { label: 'Move to Previous Word', command: 'editor:move-to-previous-word-boundary' } + { label: 'Move to Beginning of &Word', command: 'editor:move-to-beginning-of-word' } + { label: 'Move to End of Wor&d', command: 'editor:move-to-end-of-word' } + { label: 'Move to &Next Word', command: 'editor:move-to-next-word-boundary' } + { label: 'Move to &Previous Word', command: 'editor:move-to-previous-word-boundary' } ] } @@ -150,22 +150,22 @@ { label: '&Window' submenu: [ - { label: 'Minimize', command: 'application:minimize' } - { label: 'Zoom', command: 'application:zoom' } + { label: 'Mi&nimize', command: 'application:minimize' } + { label: 'Ma&ximize', command: 'application:zoom' } { type: 'separator' } - { label: 'Bring All to Front', command: 'application:bring-all-windows-to-front' } + { label: 'Bring &All to Front', command: 'application:bring-all-windows-to-front' } ] } { label: '&Help' submenu: [ - { label: 'About Atom', command: 'application:about' } + { label: '&About Atom...', command: 'application:about' } { label: "VERSION", enabled: false } - { label: "Install update", command: 'application:install-update', visible: false } + { label: "Install &update", command: 'application:install-update', visible: false } { type: 'separator' } - { label: 'Documentation', command: 'application:open-documentation' } - { label: 'Report an Issue', command: 'application:report-issue' } + { label: '&Documentation', command: 'application:open-documentation' } + { label: 'Report an &Issue', command: 'application:report-issue' } { type: 'separator' } ] }