Substitute marks (#744)

* add synonym for '<,'>

* support Marks in substitute

* support ; and update roadmap
This commit is contained in:
Peng Lyu 2016-09-11 15:25:02 -07:00 committed by GitHub
parent bf2a1ec2c4
commit 1b69c8bb96
7 changed files with 60 additions and 33 deletions

View File

@ -485,20 +485,20 @@ Status | Command | Description
:arrow_down: | :!{command} | execute {command} with a shell
:arrow_down: | K | lookup keyword under the cursor with 'keywordprg' program (default: "man")
## Ex rangs
## Ex ranges
Status | Command | Description
---|--------|-------|------------------------------
Status | Command | Description | Note
---|--------|-------|------------|------------------
:white_check_mark: | , | separates two line numbers|
| ; | idem, set cursor to the first line number before interpreting the second one
:white_check_mark: :star: :warning: | ; | idem, set cursor to the first line number before interpreting the second one | The cursor movement is not included.
:white_check_mark: | {number} | an absolute line number
:white_check_mark: | . | the current line
:white_check_mark: | $ | the last line in the file
:white_check_mark: | % | equal to 1,$ (the entire file)
| * | equal to '<,'> (visual area)
| 't | position of mark t
| /{pattern}[/] | the next line where {pattern} matches
| ?{pattern}[?] | the previous line where {pattern} matches
:white_check_mark: | * | equal to '<,'> (visual area)
:white_check_mark: | 't | position of mark t
:arrow_down: | /{pattern}[/] | the next line where {pattern} matches
:arrow_down: | ?{pattern}[?] | the previous line where {pattern} matches
:white_check_mark: | +[num] | add [num] to the preceding line number (default: 1)
:white_check_mark: | -[num] | subtract [num] from the preceding line number (default: 1)
@ -528,7 +528,7 @@ Status | Command | Description | Note
:white_check_mark: | {count}&lt;C-PageDown&gt;, {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}&lt;C-PageUp&gt;, {count}gT | Same as above
:white_check_mark: | {count}&lt;C-PageUp&gt;, {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.
:white_check_mark: | :tabe[dit] {file} | Open a new tab page with an empty window, after the current tab page

View File

@ -99,8 +99,8 @@ export class SubstituteCommand extends node.CommandBase {
startLine = new vscode.Position(0, 0);
endLine = new vscode.Position(TextEditor.getLineCount() - 1, 0);
} else {
startLine = range.lineRefToPosition(vscode.window.activeTextEditor, range.left);
endLine = range.lineRefToPosition(vscode.window.activeTextEditor, range.right);
startLine = range.lineRefToPosition(vscode.window.activeTextEditor, range.left, modeHandler);
endLine = range.lineRefToPosition(vscode.window.activeTextEditor, range.right, modeHandler);
}
if (this._arguments.count && this._arguments.count >= 0) {

View File

@ -36,6 +36,7 @@ module LexerFunctions {
var c = state.next();
switch (c) {
case ",":
case ";":
tokens.push(emitToken(TokenType.Comma, state)!);
continue;
case "%":
@ -68,6 +69,12 @@ module LexerFunctions {
case "-":
tokens.push(emitToken(TokenType.Minus, state)!);
continue;
case "*":
state.emit();
tokens.push(new Token(TokenType.SelectionFirstLine, '<')!);
tokens.push(new Token(TokenType.Comma, ',')!);
tokens.push(new Token(TokenType.SelectionLastLine, '>')!);
continue;
case "'":
return lexMark;
default:
@ -80,24 +87,29 @@ module LexerFunctions {
function lexMark(state: Scanner, tokens: Token[]): ILexFunction | null {
// The first token has already been lexed.
while (true) {
if (state.isAtEof) {
return null;
}
var c = state.next();
switch (c) {
case '<':
tokens.push(emitToken(TokenType.SelectionFirstLine, state)!);
break;
case '>':
tokens.push(emitToken(TokenType.SelectionLastLine, state)!);
break;
default:
state.backup();
return lexRange;
}
if (state.isAtEof) {
return null;
}
var c = state.next();
switch (c) {
case '<':
tokens.push(emitToken(TokenType.SelectionFirstLine, state) !);
break;
case '>':
tokens.push(emitToken(TokenType.SelectionLastLine, state) !);
break;
default:
if (/[a-zA-Z]/.test(c)) {
state.emit();
tokens.push(new Token(TokenType.Mark, c) !);
} else {
state.backup();
}
break;
}
return lexRange;
}
function lexLineRef(state : Scanner, tokens: Token[]): ILexFunction | null {

View File

@ -43,16 +43,16 @@ export class LineRange {
return this.left.toString() + this.separator.content + this.right.toString();
}
execute(document : vscode.TextEditor) : void {
execute(document : vscode.TextEditor, modeHandler: ModeHandler) : void {
if (this.isEmpty) {
return;
}
var lineRef = this.right.length === 0 ? this.left : this.right;
var pos = this.lineRefToPosition(document, lineRef);
var pos = this.lineRefToPosition(document, lineRef, modeHandler);
document.selection = new vscode.Selection(pos, pos);
}
lineRefToPosition(doc : vscode.TextEditor, toks : token.Token[]) : vscode.Position {
lineRefToPosition(doc : vscode.TextEditor, toks : token.Token[], modeHandler: ModeHandler) : vscode.Position {
var first = toks[0];
switch (first.type) {
case token.TokenType.Dollar:
@ -71,6 +71,8 @@ export class LineRange {
case token.TokenType.SelectionLastLine:
let end = doc.selection.start.isAfter(doc.selection.end) ? doc.selection.start : doc.selection.end;
return new vscode.Position(end.line, 0);
case token.TokenType.Mark:
return modeHandler.vimState.historyTracker.getMark(first.content).position;
default:
throw new Error("not implemented");
}
@ -95,7 +97,7 @@ export class CommandLine {
async execute(document : vscode.TextEditor, modeHandler : ModeHandler) : Promise<void> {
if (!this.command) {
this.range.execute(document);
this.range.execute(document, modeHandler);
return;
}

View File

@ -32,6 +32,7 @@ function parseLineRange(state: ParserState, commandLine: node.CommandLine): IPar
case token.TokenType.LineNumber:
case token.TokenType.SelectionFirstLine:
case token.TokenType.SelectionLastLine:
case token.TokenType.Mark:
commandLine.range.addToken(tok);
continue;
case token.TokenType.CommandName:

View File

@ -22,7 +22,8 @@ export enum TokenType {
*
*/
SelectionFirstLine,
SelectionLastLine
SelectionLastLine,
Mark
}
export class Token {

View File

@ -71,4 +71,15 @@ suite("Basic substitute", () => {
"db"
]);
});
test("Substitute support marks", async () => {
await modeHandler.handleMultipleKeyEvents(['i', 'a', 'b', 'c', '<Esc>', 'y', 'y', '2', 'p', 'g', 'g', 'm', 'a', 'j', 'm', 'b']);
await runCmdLine("'a,'bs/a/d/g", modeHandler);
assertEqualLines([
"dbc",
"dbc",
"abc"
]);
});
});