From cee7e175a7fbfa7c98d7523426ba143992413d27 Mon Sep 17 00:00:00 2001 From: t9md Date: Mon, 4 Dec 2017 00:47:57 +0900 Subject: [PATCH 1/3] Copy item's command-name and display-name from contextMenu --- lib/command-palette-view.js | 40 +++++++++++ menus/command-palette.cson | 6 ++ package.json | 9 +++ test/command-palette-view.test.js | 115 ++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+) diff --git a/lib/command-palette-view.js b/lib/command-palette-view.js index 403c4a4..2e6f48b 100644 --- a/lib/command-palette-view.js +++ b/lib/command-palette-view.js @@ -81,12 +81,52 @@ export default class CommandPaletteView { } }) this.selectListView.element.classList.add('command-palette') + this.registerCommands() } async destroy () { await this.selectListView.destroy() } + copyItemText (propertyName, event) { + const item = event + ? this.itemForElement(event.target.closest("li")) // by contextMenu + : this.selectListView.getSelectedItem() // by keyborad shortcut + if (item) atom.clipboard.write("`" + item[propertyName] + "`") + } + + itemForElement (element) { + if (element && this.selectListView.refs.items) { + const index = Array.from(this.selectListView.refs.items.children).indexOf(element) + if (index >= 0) { + return this.selectListView.items[index] + } + } + } + + registerCommands () { + atom.commands.add(this.selectListView.element, { + "command-palette:copy-display-name": () => this.copyItemText("displayName"), + "command-palette:copy-display-name-from-context-menu": event => this.copyItemText("displayName", event), + "command-palette:copy-command-name": () => this.copyItemText("name"), + "command-palette:copy-command-name-from-context-menu": event => this.copyItemText("name", event) + }) + const queryEditor = this.selectListView.refs.queryEditor + atom.commands.add(queryEditor.element, { + "core:copy": event => { + const propertyToCopy = atom.config.get('command-palette.copySelectedItemTextWhenEmptySelection') + if (propertyToCopy !== "none" && queryEditor.getSelectedBufferRange().isEmpty()) { + event.stopImmediatePropagation() + if (propertyToCopy === "display-name") { + this.copyItemText("displayName") + } else if (propertyToCopy === "command-name") { + this.copyItemText("name") + } + } + } + }) + } + toggle () { if (this.panel && this.panel.isVisible()) { this.hide() diff --git a/menus/command-palette.cson b/menus/command-palette.cson index 8df08e4..745adc5 100644 --- a/menus/command-palette.cson +++ b/menus/command-palette.cson @@ -23,3 +23,9 @@ ] } ] + +'context-menu': + '.command-palette .list-group': [ + {label: 'Copy Display Name', command: 'command-palette:copy-display-name-from-context-menu'} + {label: 'Copy Command Name', command: 'command-palette:copy-command-name-from-context-menu'} + ] diff --git a/package.json b/package.json index 0606389..bd7758d 100644 --- a/package.json +++ b/package.json @@ -29,14 +29,23 @@ }, "configSchema": { "useAlternateScoring": { + "order": 0, "type": "boolean", "default": true, "description": "Use an alternative scoring approach which prefers run of consecutive characters, acronyms and start of words." }, "preserveLastSearch": { + "order": 1, "type": "boolean", "default": false, "description": "Preserve the last search when reopening the command palette." + }, + "copySelectedItemTextWhenEmptySelection": { + "order": 2, + "type": "string", + "default": "none", + "enum": ["none", "command-name", "display-name"], + "description": "Copy selected item's command name or display name by `core:copy`." } } } diff --git a/test/command-palette-view.test.js b/test/command-palette-view.test.js index 93e3247..39d3afb 100644 --- a/test/command-palette-view.test.js +++ b/test/command-palette-view.test.js @@ -285,4 +285,119 @@ describe('CommandPaletteView', () => { }) }) }) + + describe('`command-palette:copy-display-name` and `command-palette:copy-command-name`', () => { + beforeEach(() => { + atom.commands.add('*', { + 'test-xxxxx-command:command-one': () => {}, + 'test-xxxxx-command:command-two': () => {}, + 'test-xxxxx-command:command-three': () => {}, + 'test-xxxxx-command:command-four': () => {}, + 'test-xxxxx-command:command-five': () => {}, + }) + }) + + it('[by keyboard shortcut] copy name for selected item', async () => { + const spy = sandbox.spy(atom.clipboard, 'write') + + const commandPalette = new CommandPaletteView() + const selectListView = commandPalette.selectListView + await commandPalette.toggle() + + selectListView.selectItem(selectListView.items.find(item => item.name === "test-xxxxx-command:command-one")) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-display-name') + assert(spy.calledWith("`Test Xxxxx Command: Command One`")) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-command-name') + assert(spy.calledWith("`test-xxxxx-command:command-one`")) + + spy.reset() + selectListView.selectItem(selectListView.items.find(item => item.name === "test-xxxxx-command:command-two")) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-display-name') + assert(spy.calledWith("`Test Xxxxx Command: Command Two`")) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-command-name') + assert(spy.calledWith("`test-xxxxx-command:command-two`")) + }) + + it('[by context menu] copy name for selected item', async () => { + const spy = sandbox.spy(atom.clipboard, 'write') + + const commandPalette = new CommandPaletteView() + const selectListView = commandPalette.selectListView + await commandPalette.toggle() + + selectListView.refs.queryEditor.setText('xxxxx') + await selectListView.update() + const elements = Array.from(selectListView.refs.items.children) + assert.equal(elements.length, 5) + + const elementOne = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-one']") + atom.commands.dispatch(elementOne, 'command-palette:copy-display-name-from-context-menu') + assert(spy.calledWith("`Test Xxxxx Command: Command One`")) + atom.commands.dispatch(elementOne, 'command-palette:copy-command-name-from-context-menu') + assert(spy.calledWith("`test-xxxxx-command:command-one`")) + + spy.reset() + const elementTwo = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-two']") + atom.commands.dispatch(elementTwo, 'command-palette:copy-display-name-from-context-menu') + assert(spy.calledWith("`Test Xxxxx Command: Command Two`")) + atom.commands.dispatch(elementTwo, 'command-palette:copy-command-name-from-context-menu') + assert(spy.calledWith("`test-xxxxx-command:command-two`")) + + spy.reset() + const elementThree = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-three']") + atom.commands.dispatch(elementThree, 'command-palette:copy-display-name-from-context-menu') + assert(spy.calledWith("`Test Xxxxx Command: Command Three`")) + atom.commands.dispatch(elementThree, 'command-palette:copy-command-name-from-context-menu') + assert(spy.calledWith("`test-xxxxx-command:command-three`")) + + spy.reset() + const elementFour = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-four']") + atom.commands.dispatch(elementFour, 'command-palette:copy-display-name-from-context-menu') + assert(spy.calledWith("`Test Xxxxx Command: Command Four`")) + atom.commands.dispatch(elementFour, 'command-palette:copy-command-name-from-context-menu') + assert(spy.calledWith("`test-xxxxx-command:command-four`")) + + spy.reset() + const elementFive = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-five']") + atom.commands.dispatch(elementFive, 'command-palette:copy-display-name-from-context-menu') + assert(spy.calledWith("`Test Xxxxx Command: Command Five`")) + atom.commands.dispatch(elementFive, 'command-palette:copy-command-name-from-context-menu') + assert(spy.calledWith("`test-xxxxx-command:command-five`")) + }) + + describe('core:copy behavior with command-palette.copySelectedItemTextWhenEmptySelection setting', () => { + let spy, selectListView + beforeEach(async () => { + spy = sandbox.spy(atom.clipboard, 'write') + + const commandPalette = new CommandPaletteView() + selectListView = commandPalette.selectListView + await commandPalette.toggle() + + selectListView.refs.queryEditor.setText('xxxxx') + await selectListView.update() + assert.equal(selectListView.getSelectedItem().name, 'test-xxxxx-command:command-one') + const elements = Array.from(selectListView.refs.items.children) + assert.equal(elements.length, 5) + }) + + it('[value = "none"]: copy line text', async () => { + atom.config.set("command-palette.copySelectedItemTextWhenEmptySelection", "none") + atom.commands.dispatch(selectListView.refs.queryEditor.element, 'core:copy') + assert(spy.calledWith("xxxxx")) // default behavoir of atom-text-editor + }) + + it('[value = "display-name"]: copy displayName of selected item', async () => { + atom.config.set("command-palette.copySelectedItemTextWhenEmptySelection", "display-name") + atom.commands.dispatch(selectListView.refs.queryEditor.element, 'core:copy') + assert(spy.calledWith("`Test Xxxxx Command: Command One`")) + }) + + it('[value = "command-name]": copy command name of selected item', async () => { + atom.config.set("command-palette.copySelectedItemTextWhenEmptySelection", "command-name") + atom.commands.dispatch(selectListView.refs.queryEditor.element, 'core:copy') + assert(spy.calledWith("`test-xxxxx-command:command-one`")) + }) + }) + }) }) From 8d779958039bcf8886bd092126f9491c5386d849 Mon Sep 17 00:00:00 2001 From: t9md Date: Wed, 28 Mar 2018 18:42:49 +0900 Subject: [PATCH 2/3] add config to control backtick surround, cleanup spec --- lib/command-palette-view.js | 15 ++- package.json | 14 ++- test/command-palette-view.test.js | 146 +++++++++++++++--------------- 3 files changed, 97 insertions(+), 78 deletions(-) diff --git a/lib/command-palette-view.js b/lib/command-palette-view.js index 2e6f48b..c819a60 100644 --- a/lib/command-palette-view.js +++ b/lib/command-palette-view.js @@ -92,7 +92,18 @@ export default class CommandPaletteView { const item = event ? this.itemForElement(event.target.closest("li")) // by contextMenu : this.selectListView.getSelectedItem() // by keyborad shortcut - if (item) atom.clipboard.write("`" + item[propertyName] + "`") + + if (item) { + let surroundByBacktick = false + + if (propertyName === "name") { + surroundByBacktick = atom.config.get('command-palette.surroundByBacktickWhenCopyCommandName') + } else if (propertyName === "displayName") { + surroundByBacktick = atom.config.get('command-palette.surroundByBacktickWhenCopyDisplayName') + } + const surroundChar = surroundByBacktick ? "`" : "" + atom.clipboard.write(surroundChar + item[propertyName] + surroundChar) + } } itemForElement (element) { @@ -114,7 +125,7 @@ export default class CommandPaletteView { const queryEditor = this.selectListView.refs.queryEditor atom.commands.add(queryEditor.element, { "core:copy": event => { - const propertyToCopy = atom.config.get('command-palette.copySelectedItemTextWhenEmptySelection') + const propertyToCopy = atom.config.get('command-palette.allowCoreCopyWithEmptySelectionCopySelectedItemText') if (propertyToCopy !== "none" && queryEditor.getSelectedBufferRange().isEmpty()) { event.stopImmediatePropagation() if (propertyToCopy === "display-name") { diff --git a/package.json b/package.json index bd7758d..5f979b4 100644 --- a/package.json +++ b/package.json @@ -40,12 +40,24 @@ "default": false, "description": "Preserve the last search when reopening the command palette." }, - "copySelectedItemTextWhenEmptySelection": { + "allowCoreCopyWithEmptySelectionCopySelectedItemText": { "order": 2, "type": "string", "default": "none", "enum": ["none", "command-name", "display-name"], "description": "Copy selected item's command name or display name by `core:copy`." + }, + "surroundByBacktickWhenCopyCommandName": { + "order": 3, + "type": "boolean", + "default": false, + "description": "Automatically surround by backtick when copying command name." + }, + "surroundByBacktickWhenCopyDisplayName": { + "order": 4, + "type": "boolean", + "default": false, + "description": "Automatically surround by backtick when copying display name." } } } diff --git a/test/command-palette-view.test.js b/test/command-palette-view.test.js index 39d3afb..af92cb8 100644 --- a/test/command-palette-view.test.js +++ b/test/command-palette-view.test.js @@ -287,7 +287,9 @@ describe('CommandPaletteView', () => { }) describe('`command-palette:copy-display-name` and `command-palette:copy-command-name`', () => { - beforeEach(() => { + let spy, commandPalette, selectListView + + beforeEach(async () => { atom.commands.add('*', { 'test-xxxxx-command:command-one': () => {}, 'test-xxxxx-command:command-two': () => {}, @@ -295,85 +297,79 @@ describe('CommandPaletteView', () => { 'test-xxxxx-command:command-four': () => {}, 'test-xxxxx-command:command-five': () => {}, }) - }) - it('[by keyboard shortcut] copy name for selected item', async () => { - const spy = sandbox.spy(atom.clipboard, 'write') - - const commandPalette = new CommandPaletteView() - const selectListView = commandPalette.selectListView + spy = sandbox.spy(atom.clipboard, 'write') + commandPalette = new CommandPaletteView() + selectListView = commandPalette.selectListView await commandPalette.toggle() + atom.config.set("command-palette.surroundByBacktickWhenCopyCommandName", false) + atom.config.set("command-palette.surroundByBacktickWhenCopyDisplayName", false) + }) - selectListView.selectItem(selectListView.items.find(item => item.name === "test-xxxxx-command:command-one")) - atom.commands.dispatch(selectListView.element, 'command-palette:copy-display-name') - assert(spy.calledWith("`Test Xxxxx Command: Command One`")) - atom.commands.dispatch(selectListView.element, 'command-palette:copy-command-name') - assert(spy.calledWith("`test-xxxxx-command:command-one`")) - - spy.reset() - selectListView.selectItem(selectListView.items.find(item => item.name === "test-xxxxx-command:command-two")) - atom.commands.dispatch(selectListView.element, 'command-palette:copy-display-name') - assert(spy.calledWith("`Test Xxxxx Command: Command Two`")) - atom.commands.dispatch(selectListView.element, 'command-palette:copy-command-name') - assert(spy.calledWith("`test-xxxxx-command:command-two`")) + describe('surroundByBacktickWhenCopyCommandName', () => { + it('auto-surround by backtick when copy-command-name', async () => { + selectListView.selectItem(selectListView.items.find(item => item.name === "test-xxxxx-command:command-one")) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-command-name') + assert(spy.calledWith("test-xxxxx-command:command-one")) + spy.reset() + atom.config.set("command-palette.surroundByBacktickWhenCopyCommandName", true) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-command-name') + assert(spy.calledWith("`test-xxxxx-command:command-one`")) + }) + }) + describe('surroundByBacktickWhenCopyDisCommandName', () => { + it('auto-surround by backtick when copy-display-name', async () => { + selectListView.selectItem(selectListView.items.find(item => item.name === "test-xxxxx-command:command-one")) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-display-name') + assert(spy.calledWith("Test Xxxxx Command: Command One")) + spy.reset() + atom.config.set("command-palette.surroundByBacktickWhenCopyDisplayName", true) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-display-name') + assert(spy.calledWith("`Test Xxxxx Command: Command One`")) + }) }) - it('[by context menu] copy name for selected item', async () => { - const spy = sandbox.spy(atom.clipboard, 'write') + describe('copy by keyboard shortcut', () => { + it('copy name for selected item', async () => { + selectListView.selectItem(selectListView.items.find(item => item.name === "test-xxxxx-command:command-one")) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-display-name') + assert(spy.calledWith("Test Xxxxx Command: Command One")) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-command-name') + assert(spy.calledWith("test-xxxxx-command:command-one")) + + spy.reset() + selectListView.selectItem(selectListView.items.find(item => item.name === "test-xxxxx-command:command-two")) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-display-name') + assert(spy.calledWith("Test Xxxxx Command: Command Two")) + atom.commands.dispatch(selectListView.element, 'command-palette:copy-command-name') + assert(spy.calledWith("test-xxxxx-command:command-two")) + }) + }) - const commandPalette = new CommandPaletteView() - const selectListView = commandPalette.selectListView - await commandPalette.toggle() + describe('copy from context menu', () => { + it('copy name or displayName of targeted item', async () => { + selectListView.refs.queryEditor.setText('xxxxx') + await selectListView.update() + const elements = Array.from(selectListView.refs.items.children) + assert.equal(elements.length, 5) - selectListView.refs.queryEditor.setText('xxxxx') - await selectListView.update() - const elements = Array.from(selectListView.refs.items.children) - assert.equal(elements.length, 5) - - const elementOne = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-one']") - atom.commands.dispatch(elementOne, 'command-palette:copy-display-name-from-context-menu') - assert(spy.calledWith("`Test Xxxxx Command: Command One`")) - atom.commands.dispatch(elementOne, 'command-palette:copy-command-name-from-context-menu') - assert(spy.calledWith("`test-xxxxx-command:command-one`")) - - spy.reset() - const elementTwo = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-two']") - atom.commands.dispatch(elementTwo, 'command-palette:copy-display-name-from-context-menu') - assert(spy.calledWith("`Test Xxxxx Command: Command Two`")) - atom.commands.dispatch(elementTwo, 'command-palette:copy-command-name-from-context-menu') - assert(spy.calledWith("`test-xxxxx-command:command-two`")) - - spy.reset() - const elementThree = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-three']") - atom.commands.dispatch(elementThree, 'command-palette:copy-display-name-from-context-menu') - assert(spy.calledWith("`Test Xxxxx Command: Command Three`")) - atom.commands.dispatch(elementThree, 'command-palette:copy-command-name-from-context-menu') - assert(spy.calledWith("`test-xxxxx-command:command-three`")) - - spy.reset() - const elementFour = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-four']") - atom.commands.dispatch(elementFour, 'command-palette:copy-display-name-from-context-menu') - assert(spy.calledWith("`Test Xxxxx Command: Command Four`")) - atom.commands.dispatch(elementFour, 'command-palette:copy-command-name-from-context-menu') - assert(spy.calledWith("`test-xxxxx-command:command-four`")) - - spy.reset() - const elementFive = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-five']") - atom.commands.dispatch(elementFive, 'command-palette:copy-display-name-from-context-menu') - assert(spy.calledWith("`Test Xxxxx Command: Command Five`")) - atom.commands.dispatch(elementFive, 'command-palette:copy-command-name-from-context-menu') - assert(spy.calledWith("`test-xxxxx-command:command-five`")) + const elementOne = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-one']") + atom.commands.dispatch(elementOne, 'command-palette:copy-display-name-from-context-menu') + assert(spy.calledWith("Test Xxxxx Command: Command One")) + atom.commands.dispatch(elementOne, 'command-palette:copy-command-name-from-context-menu') + assert(spy.calledWith("test-xxxxx-command:command-one")) + + spy.reset() + const elementTwo = selectListView.element.querySelector("[data-event-name='test-xxxxx-command:command-two']") + atom.commands.dispatch(elementTwo, 'command-palette:copy-display-name-from-context-menu') + assert(spy.calledWith("Test Xxxxx Command: Command Two")) + atom.commands.dispatch(elementTwo, 'command-palette:copy-command-name-from-context-menu') + assert(spy.calledWith("test-xxxxx-command:command-two")) + }) }) - describe('core:copy behavior with command-palette.copySelectedItemTextWhenEmptySelection setting', () => { - let spy, selectListView + describe('core:copy behavior with command-palette.allowCoreCopyWithEmptySelectionCopySelectedItemText setting', () => { beforeEach(async () => { - spy = sandbox.spy(atom.clipboard, 'write') - - const commandPalette = new CommandPaletteView() - selectListView = commandPalette.selectListView - await commandPalette.toggle() - selectListView.refs.queryEditor.setText('xxxxx') await selectListView.update() assert.equal(selectListView.getSelectedItem().name, 'test-xxxxx-command:command-one') @@ -382,21 +378,21 @@ describe('CommandPaletteView', () => { }) it('[value = "none"]: copy line text', async () => { - atom.config.set("command-palette.copySelectedItemTextWhenEmptySelection", "none") + atom.config.set("command-palette.allowCoreCopyWithEmptySelectionCopySelectedItemText", "none") atom.commands.dispatch(selectListView.refs.queryEditor.element, 'core:copy') assert(spy.calledWith("xxxxx")) // default behavoir of atom-text-editor }) it('[value = "display-name"]: copy displayName of selected item', async () => { - atom.config.set("command-palette.copySelectedItemTextWhenEmptySelection", "display-name") + atom.config.set("command-palette.allowCoreCopyWithEmptySelectionCopySelectedItemText", "display-name") atom.commands.dispatch(selectListView.refs.queryEditor.element, 'core:copy') - assert(spy.calledWith("`Test Xxxxx Command: Command One`")) + assert(spy.calledWith("Test Xxxxx Command: Command One")) }) it('[value = "command-name]": copy command name of selected item', async () => { - atom.config.set("command-palette.copySelectedItemTextWhenEmptySelection", "command-name") + atom.config.set("command-palette.allowCoreCopyWithEmptySelectionCopySelectedItemText", "command-name") atom.commands.dispatch(selectListView.refs.queryEditor.element, 'core:copy') - assert(spy.calledWith("`test-xxxxx-command:command-one`")) + assert(spy.calledWith("test-xxxxx-command:command-one")) }) }) }) From 52434f7e354a58d03786facb83bf4b122024b3b5 Mon Sep 17 00:00:00 2001 From: t9md Date: Wed, 28 Mar 2018 19:11:47 +0900 Subject: [PATCH 3/3] cleanup --- lib/command-palette-view.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/command-palette-view.js b/lib/command-palette-view.js index c819a60..ad2306f 100644 --- a/lib/command-palette-view.js +++ b/lib/command-palette-view.js @@ -94,15 +94,12 @@ export default class CommandPaletteView { : this.selectListView.getSelectedItem() // by keyborad shortcut if (item) { - let surroundByBacktick = false - - if (propertyName === "name") { - surroundByBacktick = atom.config.get('command-palette.surroundByBacktickWhenCopyCommandName') - } else if (propertyName === "displayName") { - surroundByBacktick = atom.config.get('command-palette.surroundByBacktickWhenCopyDisplayName') + const paramName = propertyName === "name" ? "surroundByBacktickWhenCopyCommandName" : "surroundByBacktickWhenCopyDisplayName" + let textToClip = item[propertyName] + if (atom.config.get(`command-palette.${paramName}`)) { + textToClip = "`" + textToClip + "`" } - const surroundChar = surroundByBacktick ? "`" : "" - atom.clipboard.write(surroundChar + item[propertyName] + surroundChar) + atom.clipboard.write(textToClip) } }