Merge pull request #431 from ueokande/command-completions
Command completions
This commit is contained in:
commit
28bfa3ac81
12 changed files with 111 additions and 61 deletions
|
@ -6,7 +6,7 @@ import IndicatorComponent from 'background/components/indicator';
|
|||
import reducers from 'background/reducers';
|
||||
import { createStore, applyMiddleware } from 'redux';
|
||||
import promise from 'redux-promise';
|
||||
import * as versions from 'shared/versions';
|
||||
import * as versions from './shared/versions';
|
||||
|
||||
const store = createStore(
|
||||
reducers,
|
||||
|
|
|
@ -1,17 +1,8 @@
|
|||
import settingReducer from './setting';
|
||||
import findReducer from './find';
|
||||
import tabReducer from './tab';
|
||||
import { combineReducers } from 'redux';
|
||||
import setting from './setting';
|
||||
import find from './find';
|
||||
import tab from './tab';
|
||||
|
||||
// Make setting reducer instead of re-use
|
||||
const defaultState = {
|
||||
setting: settingReducer(undefined, {}),
|
||||
find: findReducer(undefined, {}),
|
||||
tab: tabReducer(undefined, {}),
|
||||
};
|
||||
|
||||
export default function reducer(state = defaultState, action = {}) {
|
||||
return { ...state,
|
||||
setting: settingReducer(state.setting, action),
|
||||
find: findReducer(state.find, action),
|
||||
tab: tabReducer(state.tab, action), };
|
||||
}
|
||||
export default combineReducers({
|
||||
setting, find, tab,
|
||||
});
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
import commandDocs from 'shared/commands/docs';
|
||||
import * as tabs from './tabs';
|
||||
import * as histories from './histories';
|
||||
import * as bookmarks from './bookmarks';
|
||||
import * as properties from 'shared/settings/properties';
|
||||
|
||||
const completeCommands = (typing) => {
|
||||
let keys = Object.keys(commandDocs);
|
||||
return keys
|
||||
.filter(name => name.startsWith(typing))
|
||||
.map(name => ({
|
||||
caption: name,
|
||||
content: name,
|
||||
url: commandDocs[name],
|
||||
}));
|
||||
};
|
||||
|
||||
const getSearchCompletions = (command, keywords, searchConfig) => {
|
||||
let engineNames = Object.keys(searchConfig.engines);
|
||||
|
@ -74,20 +87,63 @@ const getBufferCompletions = async(command, keywords, excludePinned) => {
|
|||
];
|
||||
};
|
||||
|
||||
const getCompletions = (line, settings) => {
|
||||
let typedWords = line.trim().split(/ +/);
|
||||
let typing = '';
|
||||
if (!line.endsWith(' ')) {
|
||||
typing = typedWords.pop();
|
||||
}
|
||||
|
||||
if (typedWords.length === 0) {
|
||||
const getSetCompletions = (command, keywords) => {
|
||||
let keys = Object.keys(properties.docs).filter(
|
||||
name => name.startsWith(keywords)
|
||||
);
|
||||
let items = keys.map((key) => {
|
||||
if (properties.types[key] === 'boolean') {
|
||||
return [
|
||||
{
|
||||
caption: key,
|
||||
content: command + ' ' + key,
|
||||
url: 'Enable ' + properties.docs[key],
|
||||
}, {
|
||||
caption: 'no' + key,
|
||||
content: command + ' no' + key,
|
||||
url: 'Disable ' + properties.docs[key],
|
||||
}
|
||||
];
|
||||
}
|
||||
return [
|
||||
{
|
||||
caption: key,
|
||||
content: command + ' ' + key,
|
||||
url: 'Set ' + properties.docs[key],
|
||||
}
|
||||
];
|
||||
});
|
||||
items = items.reduce((acc, val) => acc.concat(val), []);
|
||||
if (items.length === 0) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
let name = typedWords.shift();
|
||||
let keywords = typedWords.concat(typing).join(' ');
|
||||
return Promise.resolve([
|
||||
{
|
||||
name: 'Properties',
|
||||
items,
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
switch (name) {
|
||||
const complete = (line, settings) => {
|
||||
let trimmed = line.trimStart();
|
||||
let words = trimmed.split(/ +/);
|
||||
let name = words[0];
|
||||
if (words.length === 1) {
|
||||
let items = completeCommands(name);
|
||||
if (items.length === 0) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return Promise.resolve([
|
||||
{
|
||||
name: 'Console Command',
|
||||
items: completeCommands(name),
|
||||
}
|
||||
]);
|
||||
}
|
||||
let keywords = trimmed.slice(name.length).trimStart();
|
||||
|
||||
switch (words[0]) {
|
||||
case 'o':
|
||||
case 'open':
|
||||
case 't':
|
||||
|
@ -108,12 +164,10 @@ const getCompletions = (line, settings) => {
|
|||
case 'bdelete':
|
||||
case 'bdeletes':
|
||||
return getBufferCompletions(name, keywords, true);
|
||||
case 'set':
|
||||
return getSetCompletions(name, keywords);
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
};
|
||||
|
||||
const complete = (line, settings) => {
|
||||
return getCompletions(line, settings);
|
||||
};
|
||||
|
||||
export { complete };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as storage from './storage';
|
||||
import * as releaseNotes from './release-notes';
|
||||
import manifest from '../../../manifest.json';
|
||||
import manifest from '../../../../manifest.json';
|
||||
|
||||
const NOTIFICATION_ID = 'vimvixen-update';
|
||||
|
|
@ -11,6 +11,9 @@ const defaultState = {
|
|||
};
|
||||
|
||||
const nextSelection = (state) => {
|
||||
if (state.completions.length === 0) {
|
||||
return [-1, -1];
|
||||
}
|
||||
if (state.groupSelection < 0) {
|
||||
return [0, 0];
|
||||
}
|
||||
|
|
|
@ -1,25 +1,10 @@
|
|||
import addonReducer from './addon';
|
||||
import findReducer from './find';
|
||||
import settingReducer from './setting';
|
||||
import inputReducer from './input';
|
||||
import followControllerReducer from './follow-controller';
|
||||
import { combineReducers } from 'redux';
|
||||
import addon from './addon';
|
||||
import find from './find';
|
||||
import setting from './setting';
|
||||
import input from './input';
|
||||
import followController from './follow-controller';
|
||||
|
||||
// Make setting reducer instead of re-use
|
||||
const defaultState = {
|
||||
addon: addonReducer(undefined, {}),
|
||||
find: findReducer(undefined, {}),
|
||||
setting: settingReducer(undefined, {}),
|
||||
input: inputReducer(undefined, {}),
|
||||
followController: followControllerReducer(undefined, {}),
|
||||
};
|
||||
|
||||
export default function reducer(state = defaultState, action = {}) {
|
||||
return {
|
||||
...state,
|
||||
addon: addonReducer(state.addon, action),
|
||||
find: findReducer(state.find, action),
|
||||
setting: settingReducer(state.setting, action),
|
||||
input: inputReducer(state.input, action),
|
||||
followController: followControllerReducer(state.followController, action),
|
||||
};
|
||||
}
|
||||
export default combineReducers({
|
||||
addon, find, setting, input, followController,
|
||||
});
|
||||
|
|
11
src/shared/commands/docs.js
Normal file
11
src/shared/commands/docs.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
export default {
|
||||
set: 'Set a value of the property',
|
||||
open: 'Open a URL or search by keywords in current tab',
|
||||
tabopen: 'Open a URL or search by keywords in new tab',
|
||||
winopen: 'Open a URL or search by keywords in new window',
|
||||
buffer: 'Sekect tabs by matched keywords',
|
||||
bdelete: 'Close a certain tab matched by keywords',
|
||||
bdeletes: 'Close all tabs matched by keywords',
|
||||
quit: 'Close the current tab',
|
||||
quitall: 'Close all tabs',
|
||||
};
|
|
@ -15,4 +15,10 @@ const defaults = {
|
|||
adjacenttab: true,
|
||||
};
|
||||
|
||||
export { types, defaults };
|
||||
const docs = {
|
||||
hintchars: 'Hint characters on follow mode',
|
||||
smoothscroll: 'smooth scroll',
|
||||
adjacenttab: 'open adjacent tabs',
|
||||
};
|
||||
|
||||
export { types, defaults, docs };
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as versions from 'shared/versions';
|
||||
import manifest from '../../../manifest.json';
|
||||
import * as versions from 'background/shared/versions';
|
||||
import manifest from '../../../../manifest.json';
|
||||
|
||||
describe("shared/versions/storage", () => {
|
||||
describe('#checkUpdated', () => {
|
|
@ -1,4 +1,4 @@
|
|||
import * as storage from 'shared/versions/storage';
|
||||
import * as storage from 'background/shared/versions/storage';
|
||||
|
||||
describe("shared/versions/storage", () => {
|
||||
describe('#load', () => {
|
Reference in a new issue