From 1c21e4fa2860d3dd57826e2b60a1443831eae15e Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Tue, 29 Aug 2017 21:55:18 +0900 Subject: [PATCH 1/9] simple buffer command --- src/background/commands.js | 2 -- src/background/index.js | 19 ++++++++++++++++--- src/background/tabs.js | 15 ++++++++++++++- 3 files changed, 30 insertions(+), 6 deletions(-) delete mode 100644 src/background/commands.js diff --git a/src/background/commands.js b/src/background/commands.js deleted file mode 100644 index 8bd52e5..0000000 --- a/src/background/commands.js +++ /dev/null @@ -1,2 +0,0 @@ -export const OPEN = 'open'; -export const TABOPEN = 'tabopen'; diff --git a/src/background/index.js b/src/background/index.js index 7618384..e5b08c5 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -1,6 +1,5 @@ import * as actions from '../shared/actions'; import * as tabs from './tabs'; -import * as commands from './commands'; import * as zooms from './zooms'; import KeyQueue from './key-queue'; @@ -59,15 +58,29 @@ const normalizeUrl = (string) => { } } +const cmdBuffer = (arg) => { + if (isNaN(arg)) { + // TODO support buffer identification by non-number value + throw new TypeError(`${arg} is not a number`); + } + + let index = parseInt(arg, 10) - 1; + tabs.selectAt(index); +} + const cmdEnterHandle = (request, sender) => { let words = request.text.split(' ').filter((s) => s.length > 0); switch (words[0]) { - case commands.OPEN: + case 'open': browser.tabs.update(sender.tab.id, { url: normalizeUrl(words[1]) }); return; - case commands.TABOPEN: + case 'tabopen': browser.tabs.create({ url: normalizeUrl(words[1]) }); return; + case 'b': + case 'buffer': + cmdBuffer(words[1]); + return; } }; diff --git a/src/background/tabs.js b/src/background/tabs.js index 56f86eb..532ad42 100644 --- a/src/background/tabs.js +++ b/src/background/tabs.js @@ -18,6 +18,19 @@ const reopenTab = () => { }); }; +const selectAt = (index) => { + chrome.tabs.query({ currentWindow: true }, (tabs) => { + if (tabs.length < 2) { + return; + } + if (index < 0 || tabs.length <= index) { + throw new RangeError(`buffer ${index} does not exist`) + } + let id = tabs[index].id; + chrome.tabs.update(id, { active: true }) + }); +} + const selectPrevTab = (current, count) => { chrome.tabs.query({ currentWindow: true }, (tabs) => { if (tabs.length < 2) { @@ -47,4 +60,4 @@ const reload = (current, cache) => { ); }; -export { closeTab, reopenTab, selectNextTab, selectPrevTab, reload }; +export { closeTab, reopenTab, selectAt, selectNextTab, selectPrevTab, reload }; From 3bb157c84c9757b5808c8316009d8ec84d7f0f85 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Tue, 29 Aug 2017 21:58:12 +0900 Subject: [PATCH 2/9] buffer by b command --- src/background/key-queue.js | 1 + src/content/index.js | 3 +++ src/shared/actions.js | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/background/key-queue.js b/src/background/key-queue.js index 3805305..d7f0984 100644 --- a/src/background/key-queue.js +++ b/src/background/key-queue.js @@ -4,6 +4,7 @@ const DEFAULT_KEYMAP = { ':': [ actions.CMD_OPEN ], 'o': [ actions.CMD_TABS_OPEN, false ], 'O': [ actions.CMD_TABS_OPEN, true ], + 'b': [ actions.CMD_BUFFER ], 'k': [ actions.SCROLL_LINES, -1 ], 'j': [ actions.SCROLL_LINES, 1 ], '': [ actions.SCROLL_LINES, -1 ], diff --git a/src/content/index.js b/src/content/index.js index 66b1121..710fbda 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -24,6 +24,9 @@ const invokeEvent = (action) => { vvConsole.showCommand('open '); } break; + case actions.CMD_BUFFER: + vvConsole.showCommand('buffer '); + break; case actions.SCROLL_LINES: scrolls.scrollLines(window, action[1]); break; diff --git a/src/shared/actions.js b/src/shared/actions.js index cd740c2..7151dd1 100644 --- a/src/shared/actions.js +++ b/src/shared/actions.js @@ -1,5 +1,6 @@ export const CMD_OPEN = 'cmd.open'; export const CMD_TABS_OPEN = 'cmd.tabs.open'; +export const CMD_BUFFER = 'cmd.buffer'; export const TABS_CLOSE = 'tabs.close'; export const TABS_REOPEN = 'tabs.reopen'; export const TABS_PREV = 'tabs.prev'; @@ -32,6 +33,7 @@ const BACKGROUND_ACTION_SET = new Set([ const CONTENT_ACTION_SET = new Set([ CMD_OPEN, CMD_TABS_OPEN, + CMD_BUFFER, SCROLL_LINES, SCROLL_PAGES, SCROLL_TOP, From bd66a670aa0edcddd2eda32d1e49c85a65ef91ea Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Wed, 30 Aug 2017 20:25:58 +0900 Subject: [PATCH 3/9] support :buffer swiching by keyword --- src/background/index.js | 9 ++++----- src/background/tabs.js | 22 ++++++++++++++++++++-- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/background/index.js b/src/background/index.js index e5b08c5..d8047a6 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -60,12 +60,11 @@ const normalizeUrl = (string) => { const cmdBuffer = (arg) => { if (isNaN(arg)) { - // TODO support buffer identification by non-number value - throw new TypeError(`${arg} is not a number`); + tabs.selectByKeyword(arg); + } else { + let index = parseInt(arg, 10) - 1; + tabs.selectAt(index); } - - let index = parseInt(arg, 10) - 1; - tabs.selectAt(index); } const cmdEnterHandle = (request, sender) => { diff --git a/src/background/tabs.js b/src/background/tabs.js index 532ad42..201fa73 100644 --- a/src/background/tabs.js +++ b/src/background/tabs.js @@ -24,11 +24,29 @@ const selectAt = (index) => { return; } if (index < 0 || tabs.length <= index) { - throw new RangeError(`buffer ${index} does not exist`) + throw new RangeError(`tab ${index} does not exist`) } let id = tabs[index].id; chrome.tabs.update(id, { active: true }) }); +}; + +const selectByKeyword = (keyword) => { + chrome.tabs.query({ currentWindow: true }, (tabs) => { + let tab = tabs.find((tab) => tab.url.includes(keyword)) + if (tab) { + chrome.tabs.update(tab.id, { active: true }); + return; + } + + tab = tabs.find((tab) => tab.title.includes(keyword)) + if (tab) { + chrome.tabs.update(tab.id, { active: true }); + return; + } + + throw new RangeError('No matching buffer for ' + keyword); + }) } const selectPrevTab = (current, count) => { @@ -60,4 +78,4 @@ const reload = (current, cache) => { ); }; -export { closeTab, reopenTab, selectAt, selectNextTab, selectPrevTab, reload }; +export { closeTab, reopenTab, selectAt, selectByKeyword, selectNextTab, selectPrevTab, reload }; From ed992e06748eb125c3cda04f18fe2e60102c4a19 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Wed, 30 Aug 2017 21:01:42 +0900 Subject: [PATCH 4/9] add tabs permission --- manifest.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 4922bd8..4e32964 100644 --- a/manifest.json +++ b/manifest.json @@ -15,7 +15,8 @@ ] }, "permissions": [ - "sessions" + "sessions", + "tabs" ], "web_accessible_resources": [ "build/console.html" From 3e2820a6b4404568a36ebe279a97bb0bf2617c74 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Wed, 30 Aug 2017 21:06:31 +0900 Subject: [PATCH 5/9] throw error on multiple buffer matched --- src/background/tabs.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/background/tabs.js b/src/background/tabs.js index 201fa73..617909e 100644 --- a/src/background/tabs.js +++ b/src/background/tabs.js @@ -33,19 +33,17 @@ const selectAt = (index) => { const selectByKeyword = (keyword) => { chrome.tabs.query({ currentWindow: true }, (tabs) => { - let tab = tabs.find((tab) => tab.url.includes(keyword)) - if (tab) { - chrome.tabs.update(tab.id, { active: true }); - return; - } + let matched = tabs.filter((t) => { + return t.url.includes(keyword) || t.title.includes(keyword) + }) - tab = tabs.find((tab) => tab.title.includes(keyword)) - if (tab) { - chrome.tabs.update(tab.id, { active: true }); - return; + if (matched.length == 0) { + throw new RangeError('No matching buffer for ' + keyword); + } else if (matched.length >= 2) { + throw new RangeError('More than one match for ' + keyword); } - throw new RangeError('No matching buffer for ' + keyword); + chrome.tabs.update(matched[0].id, { active: true }); }) } From 30999e0c651242d8071dca6a90f5739f22ac9afb Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 2 Sep 2017 10:17:44 +0900 Subject: [PATCH 6/9] rename command names --- src/console/console.js | 6 +++--- src/content/index.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/console/console.js b/src/console/console.js index a171ecc..61c5e24 100644 --- a/src/console/console.js +++ b/src/console/console.js @@ -8,20 +8,20 @@ var prevValue = ""; const blurMessage = () => { return { - type: 'vimvixen.commandline.blur' + type: 'vimvixen.command.blur' }; }; const keydownMessage = (input) => { return { - type: 'vimvixen.commandline.enter', + type: 'vimvixen.command.enter', value: input.value }; }; const keyupMessage = (input) => { return { - type: 'vimvixen.commandline.change', + type: 'vimvixen.command.change', value: input.value }; }; diff --git a/src/content/index.js b/src/content/index.js index 710fbda..731d6a5 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -77,16 +77,16 @@ window.addEventListener("keypress", (e) => { messages.receive(window, (message) => { switch (message.type) { - case 'vimvixen.commandline.blur': + case 'vimvixen.command.blur': vvConsole.hide(); break; - case 'vimvixen.commandline.enter': + case 'vimvixen.command.enter': browser.runtime.sendMessage({ type: 'event.cmd.enter', text: message.value }); break; - case 'vimvixen.commandline.change': + case 'vimvixen.command.change': browser.runtime.sendMessage({ type: 'event.cmd.suggest', text: message.value From 68753b3660f0d6996c9b5a3c433d2cdc275dd4e4 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 2 Sep 2017 21:48:26 +0900 Subject: [PATCH 7/9] response by type --- src/background/index.js | 5 ++++- src/content/index.js | 22 +++++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/background/index.js b/src/background/index.js index d8047a6..8f2e44c 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -17,7 +17,10 @@ const keyPressHandle = (request, sender, sendResponse) => { if (actions.isBackgroundAction(action[0])) { doBackgroundAction(sender, action); } else if (actions.isContentAction(action[0])) { - sendResponse(action); + sendResponse({ + type: 'response.action', + action: action + }); } }; diff --git a/src/content/index.js b/src/content/index.js index 731d6a5..12251a8 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -7,7 +7,7 @@ import Follow from './follow'; let vvConsole = new ConsoleFrame(window); -const invokeEvent = (action) => { +const doAction = (action) => { if (typeof action === 'undefined' || action === null) { return; } @@ -57,6 +57,18 @@ const invokeEvent = (action) => { } } +const handleResponse = (response) => { + if (!response) { + return; + } + + switch(response.type) { + case 'response.action': + doAction(response.action); + break; + } +}; + window.addEventListener("keypress", (e) => { if (e.target instanceof HTMLInputElement) { return; @@ -69,10 +81,10 @@ window.addEventListener("keypress", (e) => { } browser.runtime.sendMessage(request) - .then(invokeEvent, - (err) => { - console.log(`Vim Vixen: ${err}`); - }); + .then(handleResponse) + .catch((err) => { + console.log(`Vim Vixen: ${err}`); + }); }); messages.receive(window, (message) => { From e0bff54a827bcf15931ed651d4a5279b352a2961 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 3 Sep 2017 16:13:02 +0900 Subject: [PATCH 8/9] use promise and show errors --- src/background/index.js | 59 +++++++++++++++++------------------------ src/background/tabs.js | 28 +++++++++---------- src/background/zooms.js | 6 ++--- src/content/index.js | 5 ++++ 4 files changed, 47 insertions(+), 51 deletions(-) diff --git a/src/background/index.js b/src/background/index.js index 8f2e44c..15c8ab0 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -5,52 +5,46 @@ import KeyQueue from './key-queue'; const queue = new KeyQueue(); -const keyPressHandle = (request, sender, sendResponse) => { +const keyPressHandle = (request, sender) => { let action = queue.push({ code: request.code, ctrl: request.ctrl }); if (!action) { - return; + return Promise.resolve(); } if (actions.isBackgroundAction(action[0])) { - doBackgroundAction(sender, action); + return doBackgroundAction(sender, action); } else if (actions.isContentAction(action[0])) { - sendResponse({ + return Promise.resolve({ type: 'response.action', action: action }); } + return Promise.resolve(); }; const doBackgroundAction = (sender, action) => { switch(action[0]) { case actions.TABS_CLOSE: - tabs.closeTab(sender.tab.id); - break; + return tabs.closeTab(sender.tab.id); case actions.TABS_REOPEN: - tabs.reopenTab(); - break; + return tabs.reopenTab(); case actions.TABS_PREV: - tabs.selectPrevTab(sender.tab.index, actions[1] || 1); - break; + return tabs.selectPrevTab(sender.tab.index, actions[1] || 1); case actions.TABS_NEXT: - tabs.selectNextTab(sender.tab.index, actions[1] || 1); - break; + return tabs.selectNextTab(sender.tab.index, actions[1] || 1); case actions.TABS_RELOAD: - tabs.reload(sender.tab, actions[1] || false); - break; + return tabs.reload(sender.tab, actions[1] || false); case actions.ZOOM_IN: - zooms.zoomIn(); - break; + return zooms.zoomIn(); case actions.ZOOM_OUT: - zooms.zoomOut(); - break; + return zooms.zoomOut(); case actions.ZOOM_NEUTRAL: - zooms.neutral(); - break; + return zooms.neutral(); } + return Promise.resolve(); } const normalizeUrl = (string) => { @@ -63,10 +57,10 @@ const normalizeUrl = (string) => { const cmdBuffer = (arg) => { if (isNaN(arg)) { - tabs.selectByKeyword(arg); + return tabs.selectByKeyword(arg); } else { let index = parseInt(arg, 10) - 1; - tabs.selectAt(index); + return tabs.selectAt(index); } } @@ -74,28 +68,25 @@ const cmdEnterHandle = (request, sender) => { let words = request.text.split(' ').filter((s) => s.length > 0); switch (words[0]) { case 'open': - browser.tabs.update(sender.tab.id, { url: normalizeUrl(words[1]) }); - return; + return browser.tabs.update(sender.tab.id, { url: normalizeUrl(words[1]) }); case 'tabopen': - browser.tabs.create({ url: normalizeUrl(words[1]) }); - return; + return browser.tabs.create({ url: normalizeUrl(words[1]) }); case 'b': case 'buffer': - cmdBuffer(words[1]); - return; + return cmdBuffer(words[1]); } + throw new Error(words[0] + ' command is not defined'); }; -browser.runtime.onMessage.addListener((request, sender, sendResponse) => { +browser.runtime.onMessage.addListener((request, sender) => { switch (request.type) { case 'event.keypress': - keyPressHandle(request, sender, sendResponse); - break; + return keyPressHandle(request, sender); case 'event.cmd.enter': - cmdEnterHandle(request, sender, sendResponse); - break; + return cmdEnterHandle(request, sender); case 'event.cmd.suggest': - // TODO make suggestion and return via sendResponse + // TODO make suggestion and return break; } + return Promise.resolve(); }); diff --git a/src/background/tabs.js b/src/background/tabs.js index 617909e..efecdc4 100644 --- a/src/background/tabs.js +++ b/src/background/tabs.js @@ -1,9 +1,9 @@ const closeTab = (id) => { - browser.tabs.remove(id); + return browser.tabs.remove(id); }; const reopenTab = () => { - browser.sessions.getRecentlyClosed({ + return browser.sessions.getRecentlyClosed({ maxResults: 1 }).then((sessions) => { if (sessions.length === 0) { @@ -11,15 +11,15 @@ const reopenTab = () => { } let session = sessions[0]; if (session.tab) { - browser.sessions.restore(session.tab.sessionId); + return browser.sessions.restore(session.tab.sessionId); } else { - browser.sessions.restore(session.window.sessionId); + return browser.sessions.restore(session.window.sessionId); } }); }; const selectAt = (index) => { - chrome.tabs.query({ currentWindow: true }, (tabs) => { + return browser.tabs.query({ currentWindow: true }, (tabs) => { if (tabs.length < 2) { return; } @@ -27,12 +27,12 @@ const selectAt = (index) => { throw new RangeError(`tab ${index} does not exist`) } let id = tabs[index].id; - chrome.tabs.update(id, { active: true }) + return browser.tabs.update(id, { active: true }) }); }; const selectByKeyword = (keyword) => { - chrome.tabs.query({ currentWindow: true }, (tabs) => { + return browser.tabs.query({ currentWindow: true }).then((tabs) => { let matched = tabs.filter((t) => { return t.url.includes(keyword) || t.title.includes(keyword) }) @@ -43,34 +43,34 @@ const selectByKeyword = (keyword) => { throw new RangeError('More than one match for ' + keyword); } - chrome.tabs.update(matched[0].id, { active: true }); - }) + return browser.tabs.update(matched[0].id, { active: true }); + }); } const selectPrevTab = (current, count) => { - chrome.tabs.query({ currentWindow: true }, (tabs) => { + return browser.tabs.query({ currentWindow: true }, (tabs) => { if (tabs.length < 2) { return; } let select = (current - count) % tabs.length let id = tabs[select].id; - chrome.tabs.update(id, { active: true }) + return browser.tabs.update(id, { active: true }) }); }; const selectNextTab = (current, count) => { - chrome.tabs.query({ currentWindow: true }, (tabs) => { + return browser.tabs.query({ currentWindow: true }, (tabs) => { if (tabs.length < 2) { return; } let select = (current + count + tabs.length) % tabs.length let id = tabs[select].id; - chrome.tabs.update(id, { active: true }) + return browser.tabs.update(id, { active: true }) }); }; const reload = (current, cache) => { - browser.tabs.reload( + return browser.tabs.reload( current.id, { bypassCache: cache } ); diff --git a/src/background/zooms.js b/src/background/zooms.js index bb65030..e3e2aa6 100644 --- a/src/background/zooms.js +++ b/src/background/zooms.js @@ -10,7 +10,7 @@ const ZOOM_SETTINGS = [ ]; const zoomIn = (tabId = undefined) => { - browser.tabs.getZoom(tabId).then((factor) => { + return browser.tabs.getZoom(tabId).then((factor) => { for (let f of ZOOM_SETTINGS) { if (f > factor) { browser.tabs.setZoom(tabId, f); @@ -21,7 +21,7 @@ const zoomIn = (tabId = undefined) => { }; const zoomOut = (tabId = undefined) => { - browser.tabs.getZoom(tabId).then((factor) => { + return browser.tabs.getZoom(tabId).then((factor) => { for (let f of [].concat(ZOOM_SETTINGS).reverse()) { if (f < factor) { browser.tabs.setZoom(tabId, f); @@ -32,7 +32,7 @@ const zoomOut = (tabId = undefined) => { }; const neutral = (tabId = undefined) => { - browser.tabs.setZoom(tabId, 1); + return browser.tabs.setZoom(tabId, 1); }; export { zoomIn, zoomOut, neutral }; diff --git a/src/content/index.js b/src/content/index.js index 12251a8..26c3840 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -83,6 +83,7 @@ window.addEventListener("keypress", (e) => { browser.runtime.sendMessage(request) .then(handleResponse) .catch((err) => { + vvConsole.showError(err.message); console.log(`Vim Vixen: ${err}`); }); }); @@ -96,12 +97,16 @@ messages.receive(window, (message) => { browser.runtime.sendMessage({ type: 'event.cmd.enter', text: message.value + }).catch((e) => { + vvConsole.showError(e.message); }); break; case 'vimvixen.command.change': browser.runtime.sendMessage({ type: 'event.cmd.suggest', text: message.value + }).catch((e) => { + vvConsole.showError(e.message); }); break; default: From 29f82d3a7f339fa99759b589923f0d8657da28f5 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 3 Sep 2017 17:41:01 +0900 Subject: [PATCH 9/9] reopen command line after error --- src/console/console-frame.js | 10 ++++++++++ src/console/console.js | 8 ++++---- src/content/index.js | 4 +++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/console/console-frame.js b/src/console/console-frame.js index aabb96a..ea9f523 100644 --- a/src/console/console-frame.js +++ b/src/console/console-frame.js @@ -10,6 +10,8 @@ export default class ConsoleFrame { this.element = element; + this.errorShown = true; + this.hide(); } @@ -21,6 +23,7 @@ export default class ConsoleFrame { text: text }; messages.send(this.element.contentWindow, message); + this.errorShown = false; } showError(text) { @@ -31,6 +34,8 @@ export default class ConsoleFrame { text: text }; messages.send(this.element.contentWindow, message); + this.errorShown = true; + this.element.blur(); } showFrame() { @@ -40,5 +45,10 @@ export default class ConsoleFrame { hide() { this.element.style.display = 'none'; this.element.blur(); + this.errorShown = false; + } + + isErrorShown() { + return this.element.style.display === 'block' && this.errorShown; } } diff --git a/src/console/console.js b/src/console/console.js index 61c5e24..e0227aa 100644 --- a/src/console/console.js +++ b/src/console/console.js @@ -57,15 +57,15 @@ window.addEventListener('load', () => { }); const showCommand = (text) => { - let input = window.document.querySelector('#vimvixen-console-command-input'); - input.value = text; - input.focus(); - let command = window.document.querySelector('#vimvixen-console-command'); command.style.display = 'block'; let error = window.document.querySelector('#vimvixen-console-error'); error.style.display = 'none'; + + let input = window.document.querySelector('#vimvixen-console-command-input'); + input.value = text; + input.focus(); } const showError = (text) => { diff --git a/src/content/index.js b/src/content/index.js index 26c3840..8b3eb58 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -91,7 +91,9 @@ window.addEventListener("keypress", (e) => { messages.receive(window, (message) => { switch (message.type) { case 'vimvixen.command.blur': - vvConsole.hide(); + if (!vvConsole.isErrorShown()) { + vvConsole.hide(); + } break; case 'vimvixen.command.enter': browser.runtime.sendMessage({