diff --git a/package.json b/package.json index c2cd8faf..c8f43a21 100644 --- a/package.json +++ b/package.json @@ -1,233 +1,233 @@ { - "name": "vim", - "displayName": "Vim", - "description": "Vim emulation for Visual Studio Code", - "icon": "images/icon.png", - "version": "0.1.6", - "publisher": "vscodevim", - "galleryBanner": { - "color": "#a5c9a2", - "theme": "light" - }, - "license": "MIT", - "keywords": [ - "vim", - "vi", - "vscodevim", - "vsc-vim" + "name": "vim", + "displayName": "Vim", + "description": "Vim emulation for Visual Studio Code", + "icon": "images/icon.png", + "version": "0.1.6", + "publisher": "vscodevim", + "galleryBanner": { + "color": "#a5c9a2", + "theme": "light" + }, + "license": "MIT", + "keywords": [ + "vim", + "vi", + "vscodevim", + "vsc-vim" + ], + "repository": { + "type": "git", + "url": "https://github.com/VSCodeVim/Vim.git" + }, + "homepage": "https://github.com/VSCodeVim/Vim", + "bugs": { + "url": "https://github.com/VSCodeVim/Vim/issues" + }, + "engines": { + "vscode": "^1.0.0" + }, + "categories": [ + "Other" + ], + "activationEvents": [ + "*" + ], + "main": "./out/extension", + "contributes": { + "commands": [ + { + "command": "extension.showCmdLine", + "title": "Vim: Show Command Line" + } ], - "repository": { - "type": "git", - "url": "https://github.com/VSCodeVim/Vim.git" - }, - "homepage": "https://github.com/VSCodeVim/Vim", - "bugs": { - "url": "https://github.com/VSCodeVim/Vim/issues" - }, - "engines": { - "vscode": "^1.0.0" - }, - "categories": [ - "Other" + "keybindings": [ + { + "key": "Escape", + "command": "extension.vim_escape", + "when": "editorTextFocus" + }, + { + "key": "Backspace", + "command": "extension.vim_backspace", + "when": "editorTextFocus" + }, + { + "key": "Delete", + "command": "extension.vim_delete", + "when": "editorTextFocus && vim.mode == 'Normal Mode'" + }, + { + "key": "ctrl+r", + "command": "extension.vim_ctrl+r", + "when": "editorTextFocus" + }, + { + "key": "ctrl+f", + "command": "extension.vim_ctrl+f", + "when": "editorTextFocus && vim.useCtrlKeys" + }, + { + "key": "ctrl+b", + "command": "extension.vim_ctrl+b", + "when": "editorTextFocus && vim.mode != 'Insert Mode'" + }, + { + "key": "ctrl+e", + "command": "extension.vim_ctrl+e", + "when": "editorTextFocus && vim.useCtrlKeys" + }, + { + "key": "ctrl+y", + "command": "extension.vim_ctrl+y", + "when": "editorTextFocus && vim.useCtrlKeys" + }, + { + "key": "ctrl+u", + "command": "extension.vim_ctrl+u", + "when": "editorTextFocus" + }, + { + "key": "ctrl+v", + "command": "extension.vim_ctrl+v", + "when": "editorTextFocus && vim.mode != 'Insert Mode'" + }, + { + "key": "ctrl+d", + "command": "extension.vim_ctrl+d", + "when": "editorTextFocus" + }, + { + "key": "ctrl+[", + "command": "extension.vim_ctrl+[", + "when": "editorTextFocus" + }, + { + "key": "ctrl+w", + "command": "extension.vim_ctrl+w", + "when": "editorTextFocus" + }, + { + "key": "ctrl+c", + "command": "extension.vim_ctrl+c", + "when": "editorTextFocus && vim.useCtrlKeys" + }, + { + "key": "ctrl+a", + "command": "extension.vim_ctrl+a", + "when": "editorTextFocus && vim.useCtrlKeys" + }, + { + "key": "ctrl+x", + "command": "extension.vim_ctrl+x", + "when": "editorTextFocus && vim.useCtrlKeys" + }, + { + "key": "left", + "command": "extension.vim_left", + "when": "editorTextFocus && vim.mode != 'Insert Mode'" + }, + { + "key": "right", + "command": "extension.vim_right", + "when": "editorTextFocus && vim.mode != 'Insert Mode'" + }, + { + "key": "up", + "command": "extension.vim_up", + "when": "editorTextFocus && vim.mode != 'Insert Mode'" + }, + { + "key": "down", + "command": "extension.vim_down", + "when": "editorTextFocus && vim.mode != 'Insert Mode'" + } ], - "activationEvents": [ - "*" - ], - "main": "./out/extension", - "contributes": { - "commands": [ - { - "command": "extension.showCmdLine", - "title": "Vim: Show Command Line" - } - ], - "keybindings": [ - { - "key": "Escape", - "command": "extension.vim_escape", - "when": "editorTextFocus" - }, - { - "key": "Backspace", - "command": "extension.vim_backspace", - "when": "editorTextFocus" - }, - { - "key": "Delete", - "command": "extension.vim_delete", - "when": "editorTextFocus && vim.mode == 'Normal Mode'" - }, - { - "key": "ctrl+r", - "command": "extension.vim_ctrl+r", - "when": "editorTextFocus" - }, - { - "key": "ctrl+f", - "command": "extension.vim_ctrl+f", - "when": "editorTextFocus && vim.useCtrlKeys" - }, - { - "key": "ctrl+b", - "command": "extension.vim_ctrl+b", - "when": "editorTextFocus && vim.mode != 'Insert Mode'" - }, - { - "key": "ctrl+e", - "command": "extension.vim_ctrl+e", - "when": "editorTextFocus && vim.useCtrlKeys" - }, - { - "key": "ctrl+y", - "command": "extension.vim_ctrl+y", - "when": "editorTextFocus && vim.useCtrlKeys" - }, - { - "key": "ctrl+u", - "command": "extension.vim_ctrl+u", - "when": "editorTextFocus" - }, - { - "key": "ctrl+v", - "command": "extension.vim_ctrl+v", - "when": "editorTextFocus && vim.mode != 'Insert Mode'" - }, - { - "key": "ctrl+d", - "command": "extension.vim_ctrl+d", - "when": "editorTextFocus" - }, - { - "key": "ctrl+[", - "command": "extension.vim_ctrl+[", - "when": "editorTextFocus" - }, - { - "key": "ctrl+w", - "command": "extension.vim_ctrl+w", - "when": "editorTextFocus" - }, - { - "key": "ctrl+c", - "command": "extension.vim_ctrl+c", - "when": "editorTextFocus && vim.useCtrlKeys" - }, - { - "key": "ctrl+a", - "command": "extension.vim_ctrl+a", - "when": "editorTextFocus && vim.useCtrlKeys" - }, - { - "key": "ctrl+x", - "command": "extension.vim_ctrl+x", - "when": "editorTextFocus && vim.useCtrlKeys" - }, - { - "key": "left", - "command": "extension.vim_left", - "when": "editorTextFocus && vim.mode != 'Insert Mode'" - }, - { - "key": "right", - "command": "extension.vim_right", - "when": "editorTextFocus && vim.mode != 'Insert Mode'" - }, - { - "key": "up", - "command": "extension.vim_up", - "when": "editorTextFocus && vim.mode != 'Insert Mode'" - }, - { - "key": "down", - "command": "extension.vim_down", - "when": "editorTextFocus && vim.mode != 'Insert Mode'" - } - ], - "configuration": { - "title": "Vim Configuration", - "type": "object", - "properties": { - "vim.otherModesKeyBindings": { - "type": "array", - "description": "Keybinding overrides to use for normal mode." - }, - "vim.otherModesKeyBindingsNonRecursive": { - "type": "array", - "description": "Non-recursive keybinding overrides to use for normal mode." - }, - "vim.useCtrlKeys": { - "type": "boolean", - "description": "Enable some vim ctrl key commands that override otherwise common operations, like ctrl+c" - }, - "vim.insertModeKeyBindings": { - "type": "array", - "description": "Keybinding overrides to use for insert mode." - }, - "vim.insertModeKeyBindingsNonRecursive": { - "type": "array", - "description": "Non-recursive keybinding overrides to use for insert mode." - }, - "vim.useSolidBlockCursor": { - "type": "boolean", - "description": "Use a non blinking block cursor.", - "default": false - }, - "vim.scroll": { - "type": "number", - "description": "Number of lines to scroll with CTRL-U and CTRL-D commands.", - "default": 20 - }, - "vim.iskeyword": { - "type": "string", - "description": "keywords contain alphanumeric characters and '_'", - "default": "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-" - }, - "vim.ignorecase": { - "type": "boolean", - "description": "Ignore case in search patterns.", - "default": true - }, - "vim.smartcase": { - "type": "boolean", - "description": "Override the 'ignorecase' option if the search pattern contains upper case characters.", - "default": true - }, - "vim.hlsearch": { - "type": "boolean", - "description": "When there is a previous search pattern, highlight all its matches.", - "default": true - } - } + "configuration": { + "title": "Vim Configuration", + "type": "object", + "properties": { + "vim.otherModesKeyBindings": { + "type": "array", + "description": "Keybinding overrides to use for normal mode." + }, + "vim.otherModesKeyBindingsNonRecursive": { + "type": "array", + "description": "Non-recursive keybinding overrides to use for normal mode." + }, + "vim.useCtrlKeys": { + "type": "boolean", + "description": "Enable some vim ctrl key commands that override otherwise common operations, like ctrl+c" + }, + "vim.insertModeKeyBindings": { + "type": "array", + "description": "Keybinding overrides to use for insert mode." + }, + "vim.insertModeKeyBindingsNonRecursive": { + "type": "array", + "description": "Non-recursive keybinding overrides to use for insert mode." + }, + "vim.useSolidBlockCursor": { + "type": "boolean", + "description": "Use a non blinking block cursor.", + "default": false + }, + "vim.scroll": { + "type": "number", + "description": "Number of lines to scroll with CTRL-U and CTRL-D commands.", + "default": 20 + }, + "vim.iskeyword": { + "type": "string", + "description": "keywords contain alphanumeric characters and '_'", + "default": "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-" + }, + "vim.ignorecase": { + "type": "boolean", + "description": "Ignore case in search patterns.", + "default": true + }, + "vim.smartcase": { + "type": "boolean", + "description": "Override the 'ignorecase' option if the search pattern contains upper case characters.", + "default": true + }, + "vim.hlsearch": { + "type": "boolean", + "description": "When there is a previous search pattern, highlight all its matches.", + "default": true } - }, - "scripts": { - "vscode:prepublish": "node ./node_modules/vscode/bin/compile -p ./", - "compile": "node ./node_modules/vscode/bin/compile -watch -p ./", - "test": "node ./node_modules/vscode/bin/test", - "postinstall": "node ./node_modules/vscode/bin/install && gulp init" - }, - "dependencies": { - "copy-paste": "^1.3.0", - "diff": "^2.2.3", - "lodash": "^4.12.0" - }, - "devDependencies": { - "gulp": "^3.9.1", - "gulp-bump": "^2.1.0", - "gulp-filter": "^4.0.0", - "gulp-git": "^1.7.1", - "gulp-inject-string": "^1.1.0", - "gulp-shell": "^0.5.2", - "gulp-soften": "^0.0.1", - "gulp-tag-version": "^1.3.0", - "gulp-trimlines": "^1.0.0", - "gulp-tslint": "^5.0.0", - "gulp-typescript": "^2.13.4", - "gulp-typings": "^2.0.0", - "merge-stream": "^1.0.0", - "tslint": "^3.10.2", - "typescript": "2.0.0", - "typings": "^1.0.4", - "vscode": "^0.11.13" + } } + }, + "scripts": { + "vscode:prepublish": "node ./node_modules/vscode/bin/compile -p ./", + "compile": "node ./node_modules/vscode/bin/compile -watch -p ./", + "test": "node ./node_modules/vscode/bin/test", + "postinstall": "node ./node_modules/vscode/bin/install && gulp init" + }, + "dependencies": { + "copy-paste": "^1.3.0", + "diff-match-patch": "^1.0.0", + "lodash": "^4.12.0" + }, + "devDependencies": { + "gulp": "^3.9.1", + "gulp-bump": "^2.1.0", + "gulp-filter": "^4.0.0", + "gulp-git": "^1.7.1", + "gulp-inject-string": "^1.1.0", + "gulp-shell": "^0.5.2", + "gulp-soften": "^0.0.1", + "gulp-tag-version": "^1.3.0", + "gulp-trimlines": "^1.0.0", + "gulp-tslint": "^5.0.0", + "gulp-typescript": "^2.13.4", + "gulp-typings": "^2.0.0", + "merge-stream": "^1.0.0", + "tslint": "^3.10.2", + "typescript": "2.0.0", + "typings": "^1.0.4", + "vscode": "^0.11.13" + } } diff --git a/src/history/historyTracker.ts b/src/history/historyTracker.ts index 119931d1..b9af7194 100644 --- a/src/history/historyTracker.ts +++ b/src/history/historyTracker.ts @@ -16,7 +16,10 @@ import * as _ from "lodash"; import { Position } from './../motion/position'; import { TextEditor } from './../textEditor'; -import jsdiff = require('diff'); +import DiffMatchPatch = require("diff-match-patch"); + +const diffEngine = new DiffMatchPatch.diff_match_patch(); +diffEngine.Diff_Timeout = 1000; export class DocumentChange { start : Position; @@ -339,17 +342,30 @@ export class HistoryTracker { // multiple changes in different places simultaneously. For those, we could require // them to call addChange manually, I guess... - const diffs = jsdiff.diffChars(this.oldText, newText); + const diffs = diffEngine.diff_main(this.oldText, newText); + + /* + this.historySteps.push(new HistoryStep({ + changes : [new DocumentChange(new Position(0, 0), TextEditor.getAllText(), true)], + isFinished : true, + cursorStart: new Position(0, 0) + })); + */ let currentPosition = new Position(0, 0); for (const diff of diffs) { + const [whatHappened, text] = diff; + const added = whatHappened === DiffMatchPatch.DIFF_INSERT; + const removed = whatHappened === DiffMatchPatch.DIFF_DELETE; + const same = whatHappened === DiffMatchPatch.DIFF_EQUAL; + let change: DocumentChange; // let lastChange = this.currentHistoryStep.changes.length > 1 && // this.currentHistoryStep.changes[this.currentHistoryStep.changes.length - 2]; - if (diff.added || diff.removed) { - change = new DocumentChange(currentPosition, diff.value, !!diff.added); + if (added || removed) { + change = new DocumentChange(currentPosition, text, !!added); this.currentHistoryStep.changes.push(change); @@ -358,8 +374,8 @@ export class HistoryTracker { } } - if (!diff.removed) { - currentPosition = currentPosition.advancePositionByText(diff.value); + if (!removed) { + currentPosition = currentPosition.advancePositionByText(text); } } diff --git a/testing b/testing new file mode 100644 index 00000000..4f5828f0 --- /dev/null +++ b/testing @@ -0,0 +1,9 @@ + one two blah + one two blah + one two blah + one two blah two blah + one two blah + one two blah + one two blah + one two blah + one two blah \ No newline at end of file diff --git a/tsd.json b/tsd.json new file mode 100644 index 00000000..ebd3fb26 --- /dev/null +++ b/tsd.json @@ -0,0 +1,12 @@ +{ + "version": "v4", + "repo": "borisyankov/DefinitelyTyped", + "ref": "master", + "path": "typings", + "bundle": "typings/tsd.d.ts", + "installed": { + "diff-match-patch/diff-match-patch.d.ts": { + "commit": "67557f18a898462614ed14063a54ca33a1cfab12" + } + } +} diff --git a/typings/diff-match-patch/diff-match-patch.d.ts b/typings/diff-match-patch/diff-match-patch.d.ts new file mode 100644 index 00000000..028fe9d6 --- /dev/null +++ b/typings/diff-match-patch/diff-match-patch.d.ts @@ -0,0 +1,39 @@ +// Type definitions for diff-match-patch v1.0.0 +// Project: https://www.npmjs.com/package/diff-match-patch +// Definitions by: Asana +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare module "diff-match-patch" { + type Diff = [number, string]; + + export class diff_match_patch { + static new (): diff_match_patch; + + Diff_Timeout: number; + Diff_EditCost: number; + Match_Threshold: number; + Match_Distance: number; + Patch_DeleteThreshold: number; + Patch_Margin: number; + Match_MaxBits: number; + + diff_main(text1: string, text2: string, opt_checklines?: boolean, opt_deadline?: number): Diff[]; + diff_commonPrefix(text1: string, text2: string): number; + diff_commonSuffix(text1: string, text2: string): number; + diff_cleanupSemantic(diffs: Diff[]): void; + diff_cleanupSemanticLossless(diffs: Diff[]): void; + diff_cleanupEfficiency(diffs: Diff[]): void; + diff_cleanupMerge(diffs: Diff[]): void; + diff_xIndex(diffs: Diff[], loc: number): number; + diff_prettyHtml(diffs: Diff[]): string; + diff_text1(diffs: Diff[]): string; + diff_text2(diffs: Diff[]): string; + diff_levenshtein(diffs: Diff[]): number; + diff_toDelta(diffs: Diff[]): string; + diff_fromDelta(text1: string, delta: string): Diff[]; + } + + export var DIFF_DELETE: number; + export var DIFF_INSERT: number; + export var DIFF_EQUAL: number; +} diff --git a/typings/tsd.d.ts b/typings/tsd.d.ts new file mode 100644 index 00000000..15e31738 --- /dev/null +++ b/typings/tsd.d.ts @@ -0,0 +1 @@ +///