Add tabs movement and fix tab command with correct counting (#507)

This commit is contained in:
Peng Lyu 2016-07-26 16:26:38 +08:00 committed by Grant Mathews
parent 00f094af7c
commit caf3f0e859
4 changed files with 109 additions and 45 deletions

View File

@ -12,9 +12,9 @@
## Roadmap
These are the big Vim features, put generally in the order in which we plan to implement them.
These are the big Vim features, put generally in the order in which we plan to implement them.
Status | Command
Status | Command
---|--------
:white_check_mark: | Normal Mode
:white_check_mark: | Insert Mode
@ -23,16 +23,16 @@ Status | Command
:white_check_mark: | Number Prefixes
:white_check_mark: | . Operator
:warning: | Searching with / and ?
:white_check_mark: | Correct Undo/Redo
:white_check_mark: | Correct Undo/Redo
:warning: | Command Remapping
:warning: | Marks
:warning: | Text Objects
| Visual Block Mode
| Macros
:warning: | Buffer/Window/Tab
:warning: | Buffer/Window/Tab
Now follows an exhaustive list of every known Vim command that we could find.
Now follows an exhaustive list of every known Vim command that we could find.
## Left-right motions
@ -243,9 +243,9 @@ Status | Command | Description
Status | Command | Description
---|--------|------------------------------
:white_check_mark: | v | start highlighting characters
:white_check_mark: | V | start highlighting linewise
| CTRL-V | start highlighting blockwise
:white_check_mark: | v | start highlighting characters
:white_check_mark: | V | start highlighting linewise
| CTRL-V | start highlighting blockwise
| o | exchange cursor position with start of highlighting
| gv | start highlighting on previous visual area
:white_check_mark: | v | highlight characters or stop highlighting
@ -297,7 +297,7 @@ Status | Command | Description
:arrow_down: | :so[urce]! {file} | read Vim commands from {file}
:arrow_down: | :sl[eep] [sec] | don't do anything for [sec] seconds
:arrow_down: | :1234: gs | goto Sleep for N seconds
## Marks and motions
@ -359,8 +359,8 @@ Status | Command | Description
| CTRL-D | delete one shiftwidth of indent in front of the current line
| 0 CTRL-D | delete all indent in the current line
| ^ CTRL-D | delete all indent in the current line, restore indent in next line
## Scrolling
@ -397,17 +397,23 @@ Status | Command | Description
| :vne[w] | Create a new window vertically and start editing an empty file in it.
## Tabs
## Tabs
Status | Command | Description
---|--------|------------------------------
:warning: | :1234: :tabe[dit] | Open a new tab page with an empty window, after the current tab page
:warning: | :1234: :tabnew | Open a new tab page with an empty window, after the current tab page
:warning: | :tabc[lose][!] :1234: | Close current tab page.
:warning: | :tabo[nly][!] | Close all other tab pages.
:white_check_mark: | :tabn[ext] :1234: | Go to tab page {count}. The first tab page has number one.
:white_check_mark: | :tabn[ext] :1234: | Go to next tab page or tab page {count}. The first tab page has number one.
| {count}<C-PageDown>, {count}gt | Same as above
:white_check_mark: | :tabp[revious] :1234: | Go to the previous tab page. Wraps around from the first one to the last one.
:white_check_mark: | :tabN[ext] :1234: | Same as above
| {count}<C-PageUp>, {count}gT | Same as above
:white_check_mark: | :tabfir[st] | Go to the first tab page.
:white_check_mark: | :tabl[ast] | Go to the last tab page.
:x: | :tabls | List the tab pages and the windows they contain.
:x: | :tabm[ove] [N] | Move the current tab page to after tab page N.
:warning: | :tabe[dit] {file} | Open a new tab page with an empty window, after the current tab page
| :[count]tabe[dit], :[count]tabnew | Same as above
:warning: | :tabnew {file} | Open a new tab page with an empty window, after the current tab page
| :[count]tab {cmd} | Execute {cmd} and when it opens a new window open a new tab page instead.
:warning: | :tabc[lose][!] :1234: | Close current tab page or close tab page {count}.
:warning: | :tabo[nly][!] | Close all other tab pages.
:white_check_mark: | :tabm[ove] [N] | Move the current tab page to after tab page N.
:x: | :tabs | List the tab pages and the windows they contain.
| :tabd[o] {cmd} | Execute {cmd} in each tab page.

View File

@ -10,12 +10,13 @@ export enum Tab {
Last,
New,
Close,
Only
Only,
Move
}
export interface ITabCommandArguments extends node.ICommandArgs {
tab: Tab;
count: number;
count?: number;
}
//
@ -45,25 +46,56 @@ export class TabCommand extends node.CommandBase {
execute() : void {
switch (this._arguments.tab) {
case Tab.Next:
this.executeCommandWithCount(this._arguments.count, "workbench.action.nextEditor");
if (this._arguments.count /** not undefined or 0 */) {
vscode.commands.executeCommand("workbench.action.openEditorAtIndex1");
this.executeCommandWithCount(this._arguments.count! - 1, "workbench.action.nextEditor");
} else {
this.executeCommandWithCount(1, "workbench.action.nextEditor");
}
break;
case Tab.Previous:
this.executeCommandWithCount(this._arguments.count, "workbench.action.previousEditor");
if (this._arguments.count !== undefined && this._arguments.count <= 0) {
break;
}
this.executeCommandWithCount(this._arguments.count || 1, "workbench.action.previousEditor");
break;
case Tab.First:
this.executeCommandWithCount(this._arguments.count, "workbench.action.openEditorAtIndex1");
this.executeCommandWithCount(1, "workbench.action.openEditorAtIndex1");
break;
case Tab.Last:
this.executeCommandWithCount(this._arguments.count, "workbench.action.openLastEditorInGroup");
this.executeCommandWithCount(1, "workbench.action.openLastEditorInGroup");
break;
case Tab.New:
this.executeCommandWithCount(this._arguments.count, "workbench.action.files.newUntitledFile");
this.executeCommandWithCount(1, "workbench.action.files.newUntitledFile");
break;
case Tab.Close:
this.executeCommandWithCount(this._arguments.count, "workbench.action.closeActiveEditor");
// Navigate the correct position
if (this._arguments.count === undefined) {
vscode.commands.executeCommand("workbench.action.closeActiveEditor");
break;
}
if (this._arguments.count === 0) {
// Wrong paramter
break;
}
// TODO: Close Page {count}. Page count is one-based.
break;
case Tab.Only:
this.executeCommandWithCount(this._arguments.count, "workbench.action.closeOtherEditors");
this.executeCommandWithCount(1, "workbench.action.closeOtherEditors");
break;
case Tab.Move:
if (this._arguments.count !== undefined) {
if (this._arguments.count === 0) {
vscode.commands.executeCommand("activeEditorMove", { to: "first" });
} else {
vscode.commands.executeCommand("activeEditorMove", { to: "position", amount: this._arguments.count);
}
} else {
vscode.commands.executeCommand("activeEditorMove", { to: "last" });
}
break;
default:

View File

@ -23,6 +23,8 @@ export const commandParsers = {
tabp: tabCmd.parseTabPCommandArgs,
tabprevious: tabCmd.parseTabPCommandArgs,
tabN: tabCmd.parseTabPCommandArgs,
tabNext: tabCmd.parseTabPCommandArgs,
tabfirst: tabCmd.parseTabFirstCommandArgs,
tabfir: tabCmd.parseTabFirstCommandArgs,
@ -40,6 +42,8 @@ export const commandParsers = {
tabo: tabCmd.parseTabOnlyCommandArgs,
tabonly: tabCmd.parseTabOnlyCommandArgs,
tabm: tabCmd.parseTabMovementCommandArgs,
e: fileCmd.parseEditFileCommandArgs,
s: parseSubstituteCommandArgs,

View File

@ -3,22 +3,22 @@
import * as node from "../commands/tab";
import {Scanner} from '../scanner';
function parseCount(args: string): number {
function parseCount(args: string): number | undefined {
if (!args) {
return 1;
return undefined;
}
let scanner = new Scanner(args);
scanner.skipWhiteSpace();
if (scanner.isAtEof) {
return 1;
return undefined;
}
let c = scanner.next();
let count = Number.parseInt(c);
if (Number.isInteger(count) && count > 0 ) {
if (Number.isInteger(count) && count >= 0 ) {
if (count > 999) {
count = 999;
}
@ -29,6 +29,10 @@ function parseCount(args: string): number {
}
}
/**
* :tabn[ext] Go to the next tab page.
* :tabn[ext] {count} Go to tab page {count}.
*/
export function parseTabNCommandArgs(args : string) : node.TabCommand {
return new node.TabCommand({
tab: node.Tab.Next,
@ -36,6 +40,10 @@ export function parseTabNCommandArgs(args : string) : node.TabCommand {
});
}
/**
* :tabp[revious] Go to the previous tab page. Wraps around from the first one to the last one.
* :tabp[revious] {count} Go {count} tab pages back.
*/
export function parseTabPCommandArgs(args : string) : node.TabCommand {
return new node.TabCommand({
tab: node.Tab.Previous,
@ -43,41 +51,55 @@ export function parseTabPCommandArgs(args : string) : node.TabCommand {
});
}
/**
* :tabfir[st] Go to the first tab page.
*/
export function parseTabFirstCommandArgs(args : string) : node.TabCommand {
return new node.TabCommand({
tab: node.Tab.First,
count: 1
tab: node.Tab.First
});
}
/**
* :tabl[ast] Go to the last tab page.
*/
export function parseTabLastCommandArgs(args : string) : node.TabCommand {
return new node.TabCommand({
tab: node.Tab.Last,
count: 1
tab: node.Tab.Last
});
}
/**
* :tabe[dit]
* :tabnew Open a new tab page with an empty window, after the current tab page.
*/
export function parseTabNewCommandArgs(args: string) : node.TabCommand {
// New Tab command should support `count`
// And the new created Tab's position depends on `count`
// For now VS Code only allows open tab next to current Tab
// So `count == 0` is not possible. But we can workaround this once we can move tabs through API.
// TODO: Tab New takes parameter file name.
return new node.TabCommand({
tab: node.Tab.New,
count: 1
tab: node.Tab.New
});
}
/**
* :tabc[lose][!] Close current tab page.
* :tabc[lose][!] {count}. Close tab page {count}.
*/
export function parseTabCloseCommandArgs(args: string) : node.TabCommand {
return new node.TabCommand({
tab: node.Tab.Close,
count: 1
count: parseCount(args)
});
}
export function parseTabOnlyCommandArgs(args: string) : node.TabCommand {
return new node.TabCommand({
tab: node.Tab.Only,
count: 1
tab: node.Tab.Only
});
}
export function parseTabMovementCommandArgs(args: string) : node.TabCommand {
return new node.TabCommand({
tab: node.Tab.Move,
count: parseCount(args)
});
}