parent
0846587baf
commit
c4afd7237b
10 changed files with 291 additions and 49 deletions
@ -0,0 +1,89 @@ |
||||
import CompletionsInteractor from '../usecases/completions'; |
||||
import CommandInteractor from '../usecases/command'; |
||||
import Completions from '../domains/completions'; |
||||
|
||||
export default class CommandController { |
||||
constructor() { |
||||
this.completionsInteractor = new CompletionsInteractor(); |
||||
this.commandIndicator = new CommandInteractor(); |
||||
} |
||||
|
||||
getCompletions(line) { |
||||
let trimmed = line.trimStart(); |
||||
let words = trimmed.split(/ +/); |
||||
let name = words[0]; |
||||
if (words.length === 1) { |
||||
return this.completionsInteractor.queryConsoleCommand(name); |
||||
} |
||||
let keywords = trimmed.slice(name.length).trimStart(); |
||||
switch (words[0]) { |
||||
case 'o': |
||||
case 'open': |
||||
case 't': |
||||
case 'tabopen': |
||||
case 'w': |
||||
case 'winopen': |
||||
return this.completionsInteractor.queryOpen(name, keywords); |
||||
case 'b': |
||||
case 'buffer': |
||||
return this.completionsInteractor.queryBuffer(name, keywords); |
||||
case 'bd': |
||||
case 'bdel': |
||||
case 'bdelete': |
||||
case 'bdeletes': |
||||
return this.completionsInteractor.queryBdelete(name, keywords); |
||||
case 'bd!': |
||||
case 'bdel!': |
||||
case 'bdelete!': |
||||
case 'bdeletes!': |
||||
return this.completionsInteractor.queryBdeleteForce(name, keywords); |
||||
case 'set': |
||||
return this.completionsInteractor.querySet(name, keywords); |
||||
} |
||||
return Promise.resolve(Completions.empty()); |
||||
} |
||||
|
||||
// eslint-disable-next-line complexity
|
||||
exec(line) { |
||||
let trimmed = line.trimStart(); |
||||
let words = trimmed.split(/ +/); |
||||
let name = words[0]; |
||||
let keywords = trimmed.slice(name.length).trimStart(); |
||||
switch (words[0]) { |
||||
case 'o': |
||||
case 'open': |
||||
return this.commandIndicator.open(keywords); |
||||
case 't': |
||||
case 'tabopen': |
||||
return this.commandIndicator.tabopen(keywords); |
||||
case 'w': |
||||
case 'winopen': |
||||
return this.commandIndicator.winopen(keywords); |
||||
case 'b': |
||||
case 'buffer': |
||||
return this.commandIndicator.buffer(keywords); |
||||
case 'bd': |
||||
case 'bdel': |
||||
case 'bdelete': |
||||
return this.commandIndicator.bdelete(false, keywords); |
||||
case 'bd!': |
||||
case 'bdel!': |
||||
case 'bdelete!': |
||||
return this.commandIndicator.bdelete(true, keywords); |
||||
case 'bdeletes': |
||||
return this.commandIndicator.bdeletes(false, keywords); |
||||
case 'bdeletes!': |
||||
return this.commandIndicator.bdeletes(true, keywords); |
||||
case 'addbookmark': |
||||
return this.commandIndicator.addbookmark(keywords); |
||||
case 'q': |
||||
case 'quit': |
||||
return this.commandIndicator.quit(); |
||||
case 'qa': |
||||
case 'quitall': |
||||
return this.commandIndicator.quitAll(); |
||||
case 'set': |
||||
return this.commandIndicator.set(keywords); |
||||
} |
||||
} |
||||
} |
@ -1,43 +0,0 @@ |
||||
import CompletionsInteractor from '../usecases/completions'; |
||||
import Completions from '../domains/completions'; |
||||
|
||||
export default class ContentMessageController { |
||||
constructor() { |
||||
this.completionsInteractor = new CompletionsInteractor(); |
||||
} |
||||
|
||||
getCompletions(line) { |
||||
let trimmed = line.trimStart(); |
||||
let words = trimmed.split(/ +/); |
||||
let name = words[0]; |
||||
if (words.length === 1) { |
||||
return this.completionsInteractor.queryConsoleCommand(name); |
||||
} |
||||
let keywords = trimmed.slice(name.length).trimStart(); |
||||
switch (words[0]) { |
||||
case 'o': |
||||
case 'open': |
||||
case 't': |
||||
case 'tabopen': |
||||
case 'w': |
||||
case 'winopen': |
||||
return this.completionsInteractor.queryOpen(name, keywords); |
||||
case 'b': |
||||
case 'buffer': |
||||
return this.completionsInteractor.queryBuffer(name, keywords); |
||||
case 'bd': |
||||
case 'bdel': |
||||
case 'bdelete': |
||||
case 'bdeletes': |
||||
return this.completionsInteractor.queryBdelete(name, keywords); |
||||
case 'bd!': |
||||
case 'bdel!': |
||||
case 'bdelete!': |
||||
case 'bdeletes!': |
||||
return this.completionsInteractor.queryBdeleteForce(name, keywords); |
||||
case 'set': |
||||
return this.completionsInteractor.querySet(name, keywords); |
||||
} |
||||
return Promise.resolve(Completions.empty()); |
||||
} |
||||
} |
@ -0,0 +1,16 @@ |
||||
import messages from '../../shared/messages'; |
||||
|
||||
export default class ConsolePresenter { |
||||
showInfo(tabId, message) { |
||||
return browser.tabs.sendMessage(tabId, { |
||||
type: messages.CONSOLE_SHOW_INFO, |
||||
text: message, |
||||
}); |
||||
} |
||||
showError(tabId, message) { |
||||
return browser.tabs.sendMessage(tabId, { |
||||
type: messages.CONSOLE_SHOW_ERROR, |
||||
text: message, |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,5 @@ |
||||
export default class WindowPresenter { |
||||
create(url) { |
||||
return browser.windows.create({ url }); |
||||
} |
||||
} |
@ -0,0 +1,13 @@ |
||||
export default class BookmarkRepository { |
||||
async create(title, url) { |
||||
let item = await browser.bookmarks.create({ |
||||
type: 'bookmark', |
||||
title, |
||||
url, |
||||
}); |
||||
if (!item) { |
||||
throw new Error('Could not create a bookmark'); |
||||
} |
||||
return item; |
||||
} |
||||
} |
@ -0,0 +1,114 @@ |
||||
import TabPresenter from '../presenters/tab'; |
||||
import WindowPresenter from '../presenters/window'; |
||||
import SettingRepository from '../repositories/setting'; |
||||
import BookmarkRepository from '../repositories/bookmark'; |
||||
import ConsolePresenter from '../presenters/console'; |
||||
|
||||
export default class CommandIndicator { |
||||
constructor() { |
||||
this.tabPresenter = new TabPresenter(); |
||||
this.windowPresenter = new WindowPresenter(); |
||||
this.settingRepository = new SettingRepository(); |
||||
this.bookmarkRepository = new BookmarkRepository(); |
||||
this.consolePresenter = new ConsolePresenter(); |
||||
} |
||||
|
||||
async open(keywords) { |
||||
let url = await this.urlOrSearch(keywords); |
||||
return this.tabPresenter.open(url); |
||||
} |
||||
|
||||
async tabopen(keywords) { |
||||
let url = await this.urlOrSearch(keywords); |
||||
return this.tabPresenter.create(url); |
||||
} |
||||
|
||||
async winopen(keywords) { |
||||
let url = await this.urlOrSearch(keywords); |
||||
return this.windowPresenter.create(url); |
||||
} |
||||
|
||||
async buffer(keywords) { |
||||
if (keywords.length === 0) { |
||||
return; |
||||
} |
||||
if (!isNaN(keywords)) { |
||||
let index = parseInt(keywords, 10) - 1; |
||||
return tabs.selectAt(index); |
||||
} |
||||
|
||||
let current = await this.tabPresenter.getCurrent(); |
||||
let tabs = await this.tabPresenter.getByKeyword(keywords); |
||||
if (tabs.length === 0) { |
||||
throw new RangeError('No matching buffer for ' + keywords); |
||||
} |
||||
for (let tab of tabs) { |
||||
if (tab.index > current.index) { |
||||
return this.tabPresenter.select(tab.id); |
||||
} |
||||
} |
||||
return this.tabPresenter.select(tabs[0].id); |
||||
} |
||||
|
||||
async bdelete(force, keywords) { |
||||
let excludePinned = !force; |
||||
let tabs = await this.tabPresenter.getByKeyword(keywords, excludePinned); |
||||
if (tabs.length === 0) { |
||||
throw new Error('No matching buffer for ' + keywords); |
||||
} else if (tabs.length > 1) { |
||||
throw new Error('More than one match for ' + keywords); |
||||
} |
||||
return this.tabPresenter.remove([tabs[0].id]); |
||||
} |
||||
|
||||
async bdeletes(force, keywords) { |
||||
let excludePinned = !force; |
||||
let tabs = await this.tabPresenter.getByKeyword(keywords, excludePinned); |
||||
let ids = tabs.map(tab => tab.id); |
||||
return this.tabPresenter.remove(ids); |
||||
} |
||||
|
||||
async quit() { |
||||
let tab = await this.tabPresenter.getCurrent(); |
||||
return this.tabPresenter.remove([tab.id]); |
||||
} |
||||
|
||||
async quitall() { |
||||
let tabs = await this.tabPresenter.getAll(); |
||||
let ids = tabs.map(tab => tab.id); |
||||
this.tabPresenter.tabPresenter.remove(ids); |
||||
} |
||||
|
||||
async addbookmark(title) { |
||||
let tab = await this.tabPresenter.getCurrent(); |
||||
let item = await this.bookmarkRepository.create(title, tab.url); |
||||
let message = 'Saved current page: ' + item.url; |
||||
return this.consolePresenter.showInfo(tab.id, message); |
||||
} |
||||
|
||||
set(keywords) { |
||||
// TODO implement set command
|
||||
} |
||||
|
||||
async urlOrSearch(keywords) { |
||||
try { |
||||
return new URL(keywords).href; |
||||
} catch (e) { |
||||
if (keywords.includes('.') && !keywords.includes(' ')) { |
||||
return 'http://' + keywords; |
||||
} |
||||
let settings = await this.settingRepository.get(); |
||||
let engines = settings.search.engines; |
||||
|
||||
let template = engines[settings.search.default]; |
||||
let query = keywords; |
||||
|
||||
let first = keywords.trimStart().split(' ')[0]; |
||||
if (Object.keys(engines).includes(first)) { |
||||
template = engines[first]; |
||||
query = keywords.trimStart().slice(first.length).trimStart(); |
||||
} |
||||
return template.replace('{}', encodeURIComponent(query)); |
||||
} |
||||
} |
||||
} |
Reference in new issue