Add an option to close the current tab and select the tab to the left
Add an option to tabs.close to close the current tab and select the tab to the left. Bound to `D` by default, which replaces the tabs.close.right command, which is rarely-used. [1] The old `D` behavior has been moved to `gd`. + update the README and fix some lint errors [1] https://tinyurl.com/y4mj7hjy
This commit is contained in:
parent
3db11041c5
commit
6605d3ea99
10 changed files with 163 additions and 120 deletions
|
@ -32,7 +32,7 @@ export default class OperationController {
|
|||
doOperation(operation: operations.Operation): Promise<any> {
|
||||
switch (operation.type) {
|
||||
case operations.TAB_CLOSE:
|
||||
return this.tabUseCase.close(false);
|
||||
return this.tabUseCase.close(false, operation.selectLeft);
|
||||
case operations.TAB_CLOSE_RIGHT:
|
||||
return this.tabUseCase.closeRight();
|
||||
case operations.TAB_CLOSE_FORCE:
|
||||
|
|
|
@ -12,11 +12,15 @@ export default class TabUseCase {
|
|||
) {
|
||||
}
|
||||
|
||||
async close(force: boolean): Promise<any> {
|
||||
async close(force: boolean, selectLeft = false): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
if (!force && tab.pinned) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (selectLeft && tab.index > 0) {
|
||||
let tabs = await this.tabPresenter.getAll();
|
||||
await this.tabPresenter.select(tabs[tab.index - 1].id as number);
|
||||
}
|
||||
return this.tabPresenter.remove([tab.id as number]);
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ class Scroller {
|
|||
clearTimeout(lastTimeoutId);
|
||||
lastTimeoutId = null;
|
||||
}
|
||||
lastTimeoutId = setTimeout(resetScrolling, 100);
|
||||
lastTimeoutId = window.setTimeout(resetScrolling, 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@ const fields = [
|
|||
['mark.set.prefix', 'Set mark at current position'],
|
||||
['mark.jump.prefix', 'Jump to the mark'],
|
||||
], [
|
||||
['tabs.close', 'Close a tab'],
|
||||
['tabs.close.right', 'Close tabs to the right'],
|
||||
['tabs.close?{"selectLeft":false}', 'Close a tab'],
|
||||
['tabs.close.right', 'Close all tabs to the right'],
|
||||
['tabs.reopen', 'Reopen closed tab'],
|
||||
['tabs.next', 'Select next Tab'],
|
||||
['tabs.prev', 'Select prev Tab'],
|
||||
['tabs.next', 'Select next tab'],
|
||||
['tabs.prev', 'Select prev tab'],
|
||||
['tabs.first', 'Select first tab'],
|
||||
['tabs.last', 'Select last tab'],
|
||||
['tabs.reload?{"cache":false}', 'Reload current tab'],
|
||||
|
@ -50,8 +50,8 @@ const fields = [
|
|||
['command.show', 'Open console'],
|
||||
['command.show.open?{"alter":false}', 'Open URL'],
|
||||
['command.show.open?{"alter":true}', 'Alter URL'],
|
||||
['command.show.tabopen?{"alter":false}', 'Open URL in new Tab'],
|
||||
['command.show.tabopen?{"alter":true}', 'Alter URL in new Tab'],
|
||||
['command.show.tabopen?{"alter":false}', 'Open URL in new tab'],
|
||||
['command.show.tabopen?{"alter":true}', 'Alter URL in new tab'],
|
||||
['command.show.winopen?{"alter":false}', 'Open URL in new window'],
|
||||
['command.show.winopen?{"alter":true}', 'Alter URL in new window'],
|
||||
['command.show.buffer', 'Open buffer command'],
|
||||
|
|
|
@ -353,7 +353,8 @@ export const DefaultSettingData: SettingData = SettingData.valueOf({
|
|||
"G": { "type": "scroll.bottom" },
|
||||
"$": { "type": "scroll.end" },
|
||||
"d": { "type": "tabs.close" },
|
||||
"D": { "type": "tabs.close.right" },
|
||||
"D": { "type": "tabs.close", "selectLeft": true },
|
||||
"gd": { "type": "tabs.close.right" },
|
||||
"!d": { "type": "tabs.close.force" },
|
||||
"u": { "type": "tabs.reopen" },
|
||||
"K": { "type": "tabs.prev" },
|
||||
|
|
|
@ -146,7 +146,8 @@ export const DefaultSetting: Settings = {
|
|||
'G': { 'type': 'scroll.bottom' },
|
||||
'$': { 'type': 'scroll.end' },
|
||||
'd': { 'type': 'tabs.close' },
|
||||
'D': { 'type': 'tabs.close.right' },
|
||||
'D': { 'type': 'tabs.close', 'selectLeft': true },
|
||||
'gd': { 'type': 'tabs.close.right' },
|
||||
'!d': { 'type': 'tabs.close.force' },
|
||||
'u': { 'type': 'tabs.reopen' },
|
||||
'K': { 'type': 'tabs.prev' },
|
||||
|
|
|
@ -201,6 +201,7 @@ export interface PageHomeOperation {
|
|||
|
||||
export interface TabCloseOperation {
|
||||
type: typeof TAB_CLOSE;
|
||||
selectLeft?: boolean;
|
||||
}
|
||||
|
||||
export interface TabCloseForceOperation {
|
||||
|
@ -367,28 +368,28 @@ export type Operation =
|
|||
const assertOptionalBoolean = (obj: any, name: string) => {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, name) &&
|
||||
typeof obj[name] !== 'boolean') {
|
||||
throw new TypeError(`Not a boolean parameter '${name}'`);
|
||||
throw new TypeError(`Not a boolean parameter: '${name}'`);
|
||||
}
|
||||
};
|
||||
|
||||
const assertRequiredNumber = (obj: any, name: string) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(obj, name) ||
|
||||
typeof obj[name] !== 'number') {
|
||||
throw new TypeError(`Missing number parameter '${name}`);
|
||||
throw new TypeError(`Missing number parameter: '${name}`);
|
||||
}
|
||||
};
|
||||
|
||||
const assertRequiredString = (obj: any, name: string) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(obj, name) ||
|
||||
typeof obj[name] !== 'string') {
|
||||
throw new TypeError(`Missing string parameter '${name}`);
|
||||
throw new TypeError(`Missing string parameter: '${name}`);
|
||||
}
|
||||
};
|
||||
|
||||
// eslint-disable-next-line complexity, max-lines-per-function
|
||||
export const valueOf = (o: any): Operation => {
|
||||
if (!Object.prototype.hasOwnProperty.call(o, 'type')) {
|
||||
throw new TypeError(`missing 'type' field`);
|
||||
throw new TypeError(`Missing 'type' field`);
|
||||
}
|
||||
switch (o.type) {
|
||||
case COMMAND_SHOW_OPEN:
|
||||
|
@ -416,6 +417,12 @@ export const valueOf = (o: any): Operation => {
|
|||
type: PAGE_HOME,
|
||||
newTab: Boolean(typeof o.newTab === undefined ? false : o.newTab),
|
||||
};
|
||||
case TAB_CLOSE:
|
||||
assertOptionalBoolean(o, 'selectLeft');
|
||||
return {
|
||||
type: TAB_CLOSE,
|
||||
selectLeft: Boolean(typeof o.selectLeft === undefined ? false : o.selectLeft), // eslint-disable-line max-len
|
||||
};
|
||||
case TAB_RELOAD:
|
||||
assertOptionalBoolean(o, 'cache');
|
||||
return {
|
||||
|
@ -458,7 +465,6 @@ export const valueOf = (o: any): Operation => {
|
|||
case NAVIGATE_ROOT:
|
||||
case FOCUS_INPUT:
|
||||
case PAGE_SOURCE:
|
||||
case TAB_CLOSE:
|
||||
case TAB_CLOSE_FORCE:
|
||||
case TAB_CLOSE_RIGHT:
|
||||
case TAB_REOPEN:
|
||||
|
@ -483,5 +489,5 @@ export const valueOf = (o: any): Operation => {
|
|||
case REPEAT_LAST:
|
||||
return { type: o.type };
|
||||
}
|
||||
throw new TypeError('unknown operation type: ' + o.type);
|
||||
throw new TypeError('Unknown operation type: ' + o.type);
|
||||
};
|
||||
|
|
Reference in a new issue