From 2758ed520dd5763cca39cb064b9bf36ce8fbd44e Mon Sep 17 00:00:00 2001 From: Jarle Mathiesen Date: Wed, 15 Nov 2017 12:05:34 +0100 Subject: [PATCH 1/4] cache element items on creation --- lib/command-palette-view.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/command-palette-view.js b/lib/command-palette-view.js index be6916e..19692e3 100644 --- a/lib/command-palette-view.js +++ b/lib/command-palette-view.js @@ -8,11 +8,22 @@ import fuzzaldrinPlus from 'fuzzaldrin-plus' export default class CommandPaletteView { constructor () { this.keyBindingsForActiveElement = [] + this.selectedElementCache = new WeakMap() + this.plainElementCache = new WeakMap() this.selectListView = new SelectListView({ items: [], filter: this.filter, emptyMessage: 'No matches found', elementForItem: (item, {index, selected}) => { + const query = this.selectListView.getQuery() + if(query.length === 0) { + if(selected && this.selectedElementCache.has(item)) { + return this.selectedElementCache.get(item) + } else if(!selected && this.plainElementCache.has(item)) { + return this.plainElementCache.get(item) + } + } + const li = document.createElement('li') li.classList.add('event', 'two-lines') li.dataset.eventName = item.name @@ -36,7 +47,6 @@ export default class CommandPaletteView { titleEl.title = item.name leftBlock.appendChild(titleEl) - const query = this.selectListView.getQuery() this.highlightMatchesInElement(item.displayName, query, titleEl) if (selected) { @@ -64,6 +74,13 @@ export default class CommandPaletteView { } li.appendChild(leftBlock) + if(query.length === 0) { + if(selected) { + this.selectedElementCache.set(item, li) + } else { + this.plainElementCache.set(item, li) + } + } return li }, didConfirmSelection: (keyBinding) => { From efa7af63551652dadb741cf50d87f9ede9e56026 Mon Sep 17 00:00:00 2001 From: Jarle Mathiesen Date: Wed, 15 Nov 2017 12:49:35 +0100 Subject: [PATCH 2/4] cache query-specific item elements --- lib/command-palette-view.js | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/lib/command-palette-view.js b/lib/command-palette-view.js index 19692e3..51443a9 100644 --- a/lib/command-palette-view.js +++ b/lib/command-palette-view.js @@ -8,20 +8,20 @@ import fuzzaldrinPlus from 'fuzzaldrin-plus' export default class CommandPaletteView { constructor () { this.keyBindingsForActiveElement = [] - this.selectedElementCache = new WeakMap() - this.plainElementCache = new WeakMap() + this.elementCache = new WeakMap() this.selectListView = new SelectListView({ items: [], filter: this.filter, emptyMessage: 'No matches found', elementForItem: (item, {index, selected}) => { const query = this.selectListView.getQuery() - if(query.length === 0) { - if(selected && this.selectedElementCache.has(item)) { - return this.selectedElementCache.get(item) - } else if(!selected && this.plainElementCache.has(item)) { - return this.plainElementCache.get(item) + const bufferKey = `${query}:${selected}` + if(this.elementCache.has(item)) { + if(this.elementCache.get(item).has(bufferKey)) { + return this.elementCache.get(item).get(bufferKey) } + } else { + this.elementCache.set(item, new Map()) } const li = document.createElement('li') @@ -74,13 +74,7 @@ export default class CommandPaletteView { } li.appendChild(leftBlock) - if(query.length === 0) { - if(selected) { - this.selectedElementCache.set(item, li) - } else { - this.plainElementCache.set(item, li) - } - } + this.elementCache.get(item).set(bufferKey, li) return li }, didConfirmSelection: (keyBinding) => { From 0b1e6260d3f913f7d0f8e987e1d8b29ee3e583c1 Mon Sep 17 00:00:00 2001 From: Jarle Mathiesen Date: Wed, 15 Nov 2017 12:51:58 +0100 Subject: [PATCH 3/4] rename variable to be more descriptive --- lib/command-palette-view.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/command-palette-view.js b/lib/command-palette-view.js index 51443a9..3c3b3dc 100644 --- a/lib/command-palette-view.js +++ b/lib/command-palette-view.js @@ -15,10 +15,10 @@ export default class CommandPaletteView { emptyMessage: 'No matches found', elementForItem: (item, {index, selected}) => { const query = this.selectListView.getQuery() - const bufferKey = `${query}:${selected}` + const queryKey = `${query}:${selected}` if(this.elementCache.has(item)) { - if(this.elementCache.get(item).has(bufferKey)) { - return this.elementCache.get(item).get(bufferKey) + if(this.elementCache.get(item).has(queryKey)) { + return this.elementCache.get(item).get(queryKey) } } else { this.elementCache.set(item, new Map()) @@ -74,7 +74,7 @@ export default class CommandPaletteView { } li.appendChild(leftBlock) - this.elementCache.get(item).set(bufferKey, li) + this.elementCache.get(item).set(queryKey, li) return li }, didConfirmSelection: (keyBinding) => { From 126c6bd1a9a851ee7c0825c959b08f93899cfbe3 Mon Sep 17 00:00:00 2001 From: Jarle Mathiesen Date: Wed, 15 Nov 2017 14:19:51 +0100 Subject: [PATCH 4/4] add tests for element caching --- test/command-palette-view.test.js | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/command-palette-view.test.js b/test/command-palette-view.test.js index e2e0917..49c6014 100644 --- a/test/command-palette-view.test.js +++ b/test/command-palette-view.test.js @@ -137,6 +137,43 @@ describe('CommandPaletteView', () => { }) }) + describe('element caching', () => { + it('caches all items when the query is changed', async () => { + const commandPalette = new CommandPaletteView() + const spy = sinon.spy(commandPalette.selectListView.props, 'elementForItem') + await commandPalette.toggle() + commandPalette.selectListView.items.forEach(item => { + const selected = commandPalette.selectListView.getSelectedItem() === item + assert(spy.calledWithMatch(item)) + assert(commandPalette.elementCache.has(item)) + assert(commandPalette.elementCache.get(item).has(`:${selected}`)) + assert(spy.returned(commandPalette.elementCache.get(item).get(`:${selected}`))) + }) + + spy.reset() + await commandPalette.selectListView.update({query: 'Z'}) + commandPalette.selectListView.items.forEach(item => { + const selected = commandPalette.selectListView.getSelectedItem() === item + assert(spy.calledWithMatch(item)) + assert(commandPalette.elementCache.has(item)) + assert(commandPalette.elementCache.get(item).has(`Z:${selected}`)) + assert(spy.returned(commandPalette.elementCache.get(item).get(`Z:${selected}`))) + }) + }) + + it('caches items incrementally when state is changed', async () => { + const commandPalette = new CommandPaletteView() + const spy = sinon.spy(commandPalette.selectListView.props, 'elementForItem') + await commandPalette.toggle() + commandPalette.selectListView.selectIndex((commandPalette.selectListView.selectionIndex + 1), false) + const selectedItem = commandPalette.selectListView.getSelectedItem() + assert(!commandPalette.elementCache.get(selectedItem).has(':true')) + await commandPalette.selectListView.update() + assert(commandPalette.elementCache.get(selectedItem).has(':true')) + }) + }) + + describe('hidden commands', () => { it('does not show commands that are marked as `hiddenInCommandPalette` by default, then *only* shows those commands when showHiddenCommands is invoked', async () => { const commandsDisposable = atom.commands.add('*', 'foo:hidden-in-command-palette', {