From c4fb6f01319ca2d0cb71da2f3ed41de1ff35130c Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Thu, 10 May 2018 21:56:49 +0900 Subject: [PATCH 1/5] Add :bdeletes command --- src/background/actions/command.js | 2 ++ src/background/shared/completions/index.js | 1 + src/background/shared/tabs.js | 10 +++++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/background/actions/command.js b/src/background/actions/command.js index 2b77507..020a57f 100644 --- a/src/background/actions/command.js +++ b/src/background/actions/command.js @@ -84,6 +84,8 @@ const exec = (tab, line, settings) => { case 'b': case 'buffer': return bufferCommand(args); + case 'bdeletes': + return tabs.closeTabsByKeywords(args.join(' ')); case 'addbookmark': return addBookmarkCommand(tab, args).then((item) => { if (!item) { diff --git a/src/background/shared/completions/index.js b/src/background/shared/completions/index.js index 8ecdcfc..43af23d 100644 --- a/src/background/shared/completions/index.js +++ b/src/background/shared/completions/index.js @@ -88,6 +88,7 @@ const getCompletions = (line, settings) => { return getOpenCompletions(name, keywords, settings.search); case 'b': case 'buffer': + case 'bdeletes': return tabs.getCompletions(keywords).then((gotTabs) => { let items = gotTabs.map((tab) => { return { diff --git a/src/background/shared/tabs.js b/src/background/shared/tabs.js index f1dcc73..1e5e3e4 100644 --- a/src/background/shared/tabs.js +++ b/src/background/shared/tabs.js @@ -1,3 +1,5 @@ +import * as tabCompletions from './completions/tabs'; + const closeTab = (id) => { return browser.tabs.get(id).then((tab) => { if (!tab.pinned) { @@ -10,6 +12,12 @@ const closeTabForce = (id) => { return browser.tabs.remove(id); }; +const closeTabsByKeywords = (keyword) => { + tabCompletions.getCompletions(keyword).then((tabs) => { + browser.tabs.remove(tabs.map(tab => tab.id)); + }); +}; + const reopenTab = () => { return browser.sessions.getRecentlyClosed({ maxResults: 1 @@ -119,7 +127,7 @@ const duplicate = (id) => { }; export { - closeTab, closeTabForce, reopenTab, selectAt, selectByKeyword, + closeTab, closeTabForce, closeTabsByKeywords, reopenTab, selectAt, selectByKeyword, selectPrevTab, selectNextTab, selectFirstTab, selectLastTab, selectTab, reload, updateTabPinned, toggleTabPinned, duplicate From 9b3d12eb31483898dd3ae527a31dd6602f79e718 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Thu, 10 May 2018 22:04:42 +0900 Subject: [PATCH 2/5] Add bdeletes! comand --- src/background/actions/command.js | 2 ++ src/background/shared/completions/index.js | 1 + src/background/shared/tabs.js | 10 +++++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/background/actions/command.js b/src/background/actions/command.js index 020a57f..fa040ff 100644 --- a/src/background/actions/command.js +++ b/src/background/actions/command.js @@ -86,6 +86,8 @@ const exec = (tab, line, settings) => { return bufferCommand(args); case 'bdeletes': return tabs.closeTabsByKeywords(args.join(' ')); + case 'bdeletes!': + return tabs.closeTabsByKeywordsForce(args.join(' ')); case 'addbookmark': return addBookmarkCommand(tab, args).then((item) => { if (!item) { diff --git a/src/background/shared/completions/index.js b/src/background/shared/completions/index.js index 43af23d..77394bc 100644 --- a/src/background/shared/completions/index.js +++ b/src/background/shared/completions/index.js @@ -89,6 +89,7 @@ const getCompletions = (line, settings) => { case 'b': case 'buffer': case 'bdeletes': + case 'bdeletes!': return tabs.getCompletions(keywords).then((gotTabs) => { let items = gotTabs.map((tab) => { return { diff --git a/src/background/shared/tabs.js b/src/background/shared/tabs.js index 1e5e3e4..c90ac4b 100644 --- a/src/background/shared/tabs.js +++ b/src/background/shared/tabs.js @@ -13,6 +13,13 @@ const closeTabForce = (id) => { }; const closeTabsByKeywords = (keyword) => { + tabCompletions.getCompletions(keyword).then((tabs) => { + let tabs2 = tabs.filter(tab => !tab.pinned); + browser.tabs.remove(tabs2.map(tab => tab.id)); + }); +}; + +const closeTabsByKeywordsForce = (keyword) => { tabCompletions.getCompletions(keyword).then((tabs) => { browser.tabs.remove(tabs.map(tab => tab.id)); }); @@ -127,7 +134,8 @@ const duplicate = (id) => { }; export { - closeTab, closeTabForce, closeTabsByKeywords, reopenTab, selectAt, selectByKeyword, + closeTab, closeTabForce, closeTabsByKeywords, closeTabsByKeywordsForce, + reopenTab, selectAt, selectByKeyword, selectPrevTab, selectNextTab, selectFirstTab, selectLastTab, selectTab, reload, updateTabPinned, toggleTabPinned, duplicate From b91e53e5feff66c1744faa930f4a79f493f91875 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Thu, 10 May 2018 22:16:38 +0900 Subject: [PATCH 3/5] Add bdlete/bdelete! commands --- src/background/actions/command.js | 8 +++++ src/background/shared/completions/index.js | 6 ++++ src/background/shared/tabs.js | 37 +++++++++++++++++++++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/background/actions/command.js b/src/background/actions/command.js index fa040ff..888b46f 100644 --- a/src/background/actions/command.js +++ b/src/background/actions/command.js @@ -84,6 +84,14 @@ const exec = (tab, line, settings) => { case 'b': case 'buffer': return bufferCommand(args); + case 'bd': + case 'bdel': + case 'bdelete': + return tabs.closeTabByKeywords(args.join(' ')); + case 'bd!': + case 'bdel!': + case 'bdelete!': + return tabs.closeTabByKeywordsForce(args.join(' ')); case 'bdeletes': return tabs.closeTabsByKeywords(args.join(' ')); case 'bdeletes!': diff --git a/src/background/shared/completions/index.js b/src/background/shared/completions/index.js index 77394bc..21c3dd2 100644 --- a/src/background/shared/completions/index.js +++ b/src/background/shared/completions/index.js @@ -88,6 +88,12 @@ const getCompletions = (line, settings) => { return getOpenCompletions(name, keywords, settings.search); case 'b': case 'buffer': + case 'bd': + case 'bdel': + case 'bdelete': + case 'bd!': + case 'bdel!': + case 'bdelete!': case 'bdeletes': case 'bdeletes!': return tabs.getCompletions(keywords).then((gotTabs) => { diff --git a/src/background/shared/tabs.js b/src/background/shared/tabs.js index c90ac4b..a9a677a 100644 --- a/src/background/shared/tabs.js +++ b/src/background/shared/tabs.js @@ -12,6 +12,40 @@ const closeTabForce = (id) => { return browser.tabs.remove(id); }; +const closeTabByKeywords = (keyword) => { + return browser.tabs.query({ currentWindow: true }).then((tabs) => { + let matched = tabs.filter((t) => { + return t.url.includes(keyword) || t.title.includes(keyword); + }); + + if (matched.length === 0) { + throw new Error('No matching buffer for ' + keyword); + } else if (matched.length > 1) { + throw new Error('More than one match for ' + keyword); + } + if (matched[0].pinned) { + throw new Error('Cannot close a pinned tab (add ! to override)'); + } + browser.tabs.remove(matched[0].id); + }); +}; + +const closeTabByKeywordsForce = (keyword) => { + return browser.tabs.query({ currentWindow: true }).then((tabs) => { + let matched = tabs.filter((t) => { + return t.url.includes(keyword) || t.title.includes(keyword); + }); + + if (matched.length === 0) { + throw new Error('No matching buffer for ' + keyword); + } else if (matched.length > 1) { + throw new Error('More than one match for ' + keyword); + } + browser.tabs.remove(matched[0].id); + }); +}; + + const closeTabsByKeywords = (keyword) => { tabCompletions.getCompletions(keyword).then((tabs) => { let tabs2 = tabs.filter(tab => !tab.pinned); @@ -134,7 +168,8 @@ const duplicate = (id) => { }; export { - closeTab, closeTabForce, closeTabsByKeywords, closeTabsByKeywordsForce, + closeTab, closeTabForce, closeTabByKeywords, closeTabByKeywordsForce, + closeTabsByKeywords, closeTabsByKeywordsForce, reopenTab, selectAt, selectByKeyword, selectPrevTab, selectNextTab, selectFirstTab, selectLastTab, selectTab, reload, updateTabPinned, From 4116d0864213e30a6157edb6e573b0c880a4ec66 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 12 May 2018 09:12:25 +0900 Subject: [PATCH 4/5] Add bdelete and bdeletes command to README --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d08d33..5c9c5e0 100644 --- a/README.md +++ b/README.md @@ -85,10 +85,18 @@ To adjust the search engine default and add/remove search engines, see the [sear Open a URL or search keywords by search engine in new tab. -#### `:q` command +#### `:quit` command Close the current tab. +#### `:bdelete` command + +Close a certain tab. + +#### `:bdeletes` command + +Close tabs matches with keywords. + #### `:winopen` command Open a URL or search keywords by search engine in new window. From a8ac7415f8b5e9e9dc36318a04b7da7775796a88 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 12 May 2018 09:47:21 +0900 Subject: [PATCH 5/5] Fix tab completions --- src/background/actions/command.js | 1 + src/background/shared/completions/index.js | 46 ++++++++++++---------- src/background/shared/completions/tabs.js | 4 +- src/background/shared/tabs.js | 5 +-- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/background/actions/command.js b/src/background/actions/command.js index 888b46f..39e880d 100644 --- a/src/background/actions/command.js +++ b/src/background/actions/command.js @@ -68,6 +68,7 @@ const setCommand = (args) => { }; }; +// eslint-disable-next-line complexity const exec = (tab, line, settings) => { let [name, args] = parsers.parseCommandLine(line); diff --git a/src/background/shared/completions/index.js b/src/background/shared/completions/index.js index 21c3dd2..728cee7 100644 --- a/src/background/shared/completions/index.js +++ b/src/background/shared/completions/index.js @@ -65,6 +65,25 @@ const getOpenCompletions = (command, keywords, searchConfig) => { }); }; +const getBufferCompletions = (command, keywords, excludePinned) => { + return tabs.getCompletions(keywords, excludePinned).then((got) => { + let items = got.map((tab) => { + return { + caption: tab.title, + content: command + ' ' + tab.title, + url: tab.url, + icon: tab.favIconUrl + }; + }); + return [ + { + name: 'Buffers', + items: items + } + ]; + }); +}; + const getCompletions = (line, settings) => { let typedWords = line.trim().split(/ +/); let typing = ''; @@ -88,30 +107,17 @@ const getCompletions = (line, settings) => { return getOpenCompletions(name, keywords, settings.search); case 'b': case 'buffer': - case 'bd': - case 'bdel': - case 'bdelete': + return getBufferCompletions(name, keywords, false); case 'bd!': case 'bdel!': case 'bdelete!': - case 'bdeletes': case 'bdeletes!': - return tabs.getCompletions(keywords).then((gotTabs) => { - let items = gotTabs.map((tab) => { - return { - caption: tab.title, - content: name + ' ' + tab.title, - url: tab.url, - icon: tab.favIconUrl - }; - }); - return [ - { - name: 'Buffers', - items: items - } - ]; - }); + return getBufferCompletions(name, keywords, false); + case 'bd': + case 'bdel': + case 'bdelete': + case 'bdeletes': + return getBufferCompletions(name, keywords, true); } return Promise.resolve([]); }; diff --git a/src/background/shared/completions/tabs.js b/src/background/shared/completions/tabs.js index 5edddca..8c0f1f9 100644 --- a/src/background/shared/completions/tabs.js +++ b/src/background/shared/completions/tabs.js @@ -1,7 +1,9 @@ -const getCompletions = (keyword) => { +const getCompletions = (keyword, excludePinned) => { return browser.tabs.query({ currentWindow: true }).then((tabs) => { let matched = tabs.filter((t) => { return t.url.includes(keyword) || t.title && t.title.includes(keyword); + }).filter((t) => { + return !(excludePinned && t.pinned); }); return matched; }); diff --git a/src/background/shared/tabs.js b/src/background/shared/tabs.js index a9a677a..d09f676 100644 --- a/src/background/shared/tabs.js +++ b/src/background/shared/tabs.js @@ -16,16 +16,13 @@ const closeTabByKeywords = (keyword) => { return browser.tabs.query({ currentWindow: true }).then((tabs) => { let matched = tabs.filter((t) => { return t.url.includes(keyword) || t.title.includes(keyword); - }); + }).filter(t => !t.pinned); if (matched.length === 0) { throw new Error('No matching buffer for ' + keyword); } else if (matched.length > 1) { throw new Error('More than one match for ' + keyword); } - if (matched[0].pinned) { - throw new Error('Cannot close a pinned tab (add ! to override)'); - } browser.tabs.remove(matched[0].id); }); };