Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
df4bd40d
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
df4bd40d
编写于
2月 20, 2020
作者:
A
Alex Dima
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Adopt the UndoRedo service in the editor
上级
757006f4
变更
18
隐藏空白更改
内联
并排
Showing
18 changed file
with
438 addition
and
456 deletion
+438
-456
src/vs/editor/browser/controller/coreCommands.ts
src/vs/editor/browser/controller/coreCommands.ts
+142
-125
src/vs/editor/browser/widget/codeEditorWidget.ts
src/vs/editor/browser/widget/codeEditorWidget.ts
+9
-2
src/vs/editor/common/controller/cursor.ts
src/vs/editor/common/controller/cursor.ts
+19
-24
src/vs/editor/common/editorCommon.ts
src/vs/editor/common/editorCommon.ts
+0
-4
src/vs/editor/common/model.ts
src/vs/editor/common/model.ts
+19
-2
src/vs/editor/common/model/editStack.ts
src/vs/editor/common/model/editStack.ts
+107
-170
src/vs/editor/common/model/textModel.ts
src/vs/editor/common/model/textModel.ts
+50
-54
src/vs/editor/common/model/textModelEvents.ts
src/vs/editor/common/model/textModelEvents.ts
+4
-0
src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts
...itor/contrib/linesOperations/test/linesOperations.test.ts
+4
-4
src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts
...editor/contrib/wordOperations/test/wordOperations.test.ts
+2
-1
src/vs/editor/test/browser/controller/cursor.test.ts
src/vs/editor/test/browser/controller/cursor.test.ts
+64
-66
src/vs/editor/test/browser/testCodeEditor.ts
src/vs/editor/test/browser/testCodeEditor.ts
+1
-0
src/vs/platform/undoRedo/common/undoRedo.ts
src/vs/platform/undoRedo/common/undoRedo.ts
+2
-2
src/vs/platform/undoRedo/common/undoRedoService.ts
src/vs/platform/undoRedo/common/undoRedoService.ts
+5
-2
src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts
...eybinding/test/electron-browser/keybindingEditing.test.ts
+3
-0
src/vs/workbench/test/browser/parts/editor/editorModel.test.ts
...s/workbench/test/browser/parts/editor/editorModel.test.ts
+3
-0
src/vs/workbench/test/browser/workbenchTestServices.ts
src/vs/workbench/test/browser/workbenchTestServices.ts
+3
-0
src/vs/workbench/workbench.common.main.ts
src/vs/workbench/workbench.common.main.ts
+1
-0
未找到文件。
src/vs/editor/browser/controller/coreCommands.ts
浏览文件 @
df4bd40d
...
...
@@ -25,6 +25,7 @@ import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands
import
{
ContextKeyExpr
}
from
'
vs/platform/contextkey/common/contextkey
'
;
import
{
ServicesAccessor
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
KeybindingWeight
}
from
'
vs/platform/keybinding/common/keybindingsRegistry
'
;
import
{
EditorOption
}
from
'
vs/editor/common/config/editorOptions
'
;
const
CORE_WEIGHT
=
KeybindingWeight
.
EditorCore
;
...
...
@@ -1529,6 +1530,102 @@ export namespace CoreNavigationCommands {
});
}
/**
* A command that will:
* 1. invoke a command on the focused editor.
* 2. otherwise, invoke a browser built-in command on the `activeElement`.
* 3. otherwise, invoke a command on the workbench active editor.
*/
abstract
class
EditorOrNativeTextInputCommand
extends
Command
{
public
runCommand
(
accessor
:
ServicesAccessor
,
args
:
any
):
void
{
const
focusedEditor
=
accessor
.
get
(
ICodeEditorService
).
getFocusedCodeEditor
();
// Only if editor text focus (i.e. not if editor has widget focus).
if
(
focusedEditor
&&
focusedEditor
.
hasTextFocus
())
{
return
this
.
runEditorCommand
(
accessor
,
focusedEditor
,
args
);
}
// Ignore this action when user is focused on an element that allows for entering text
const
activeElement
=
<
HTMLElement
>
document
.
activeElement
;
if
(
activeElement
&&
[
'
input
'
,
'
textarea
'
].
indexOf
(
activeElement
.
tagName
.
toLowerCase
())
>=
0
)
{
return
this
.
runDOMCommand
();
}
// Redirecting to active editor
const
activeEditor
=
accessor
.
get
(
ICodeEditorService
).
getActiveCodeEditor
();
if
(
activeEditor
)
{
activeEditor
.
focus
();
return
this
.
runEditorCommand
(
accessor
,
activeEditor
,
args
);
}
}
public
abstract
runDOMCommand
():
void
;
public
abstract
runEditorCommand
(
accessor
:
ServicesAccessor
,
editor
:
ICodeEditor
,
args
:
any
):
void
;
}
class
SelectAllCommand
extends
EditorOrNativeTextInputCommand
{
constructor
()
{
super
({
id
:
'
editor.action.selectAll
'
,
precondition
:
EditorContextKeys
.
textInputFocus
,
kbOpts
:
{
weight
:
CORE_WEIGHT
,
kbExpr
:
null
,
primary
:
KeyMod
.
CtrlCmd
|
KeyCode
.
KEY_A
},
menuOpts
:
[{
menuId
:
MenuId
.
MenubarSelectionMenu
,
group
:
'
1_basic
'
,
title
:
nls
.
localize
({
key
:
'
miSelectAll
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Select All
"
),
order
:
1
},
{
menuId
:
MenuId
.
CommandPalette
,
group
:
''
,
title
:
nls
.
localize
(
'
selectAll
'
,
"
Select All
"
),
order
:
1
}]
});
}
public
runDOMCommand
():
void
{
document
.
execCommand
(
'
selectAll
'
);
}
public
runEditorCommand
(
accessor
:
ServicesAccessor
,
editor
:
ICodeEditor
,
args
:
any
):
void
{
args
=
args
||
{};
args
.
source
=
'
keyboard
'
;
CoreNavigationCommands
.
SelectAll
.
runEditorCommand
(
accessor
,
editor
,
args
);
}
}
class
UndoCommand
extends
EditorOrNativeTextInputCommand
{
public
runDOMCommand
():
void
{
document
.
execCommand
(
'
undo
'
);
}
public
runEditorCommand
(
accessor
:
ServicesAccessor
|
null
,
editor
:
ICodeEditor
,
args
:
any
):
void
{
if
(
!
editor
.
hasModel
()
||
editor
.
getOption
(
EditorOption
.
readOnly
)
===
true
)
{
return
;
}
editor
.
getModel
().
undo
();
}
}
class
RedoCommand
extends
EditorOrNativeTextInputCommand
{
public
runDOMCommand
():
void
{
document
.
execCommand
(
'
redo
'
);
}
public
runEditorCommand
(
accessor
:
ServicesAccessor
|
null
,
editor
:
ICodeEditor
,
args
:
any
):
void
{
if
(
!
editor
.
hasModel
()
||
editor
.
getOption
(
EditorOption
.
readOnly
)
===
true
)
{
return
;
}
editor
.
getModel
().
redo
();
}
}
function
registerCommand
<
T
extends
Command
>
(
command
:
T
):
T
{
command
.
register
();
return
command
;
}
export
namespace
CoreEditingCommands
{
export
abstract
class
CoreEditingCommand
extends
EditorCommand
{
...
...
@@ -1659,62 +1756,53 @@ export namespace CoreEditingCommands {
}
});
}
function
registerCommand
(
command
:
Command
)
{
command
.
register
();
}
/**
* A command that will:
* 1. invoke a command on the focused editor.
* 2. otherwise, invoke a browser built-in command on the `activeElement`.
* 3. otherwise, invoke a command on the workbench active editor.
*/
class
EditorOrNativeTextInputCommand
extends
Command
{
private
readonly
_editorHandler
:
string
|
EditorCommand
;
private
readonly
_inputHandler
:
string
;
constructor
(
opts
:
ICommandOptions
&
{
editorHandler
:
string
|
EditorCommand
;
inputHandler
:
string
;
})
{
super
(
opts
);
this
.
_editorHandler
=
opts
.
editorHandler
;
this
.
_inputHandler
=
opts
.
inputHandler
;
}
public
runCommand
(
accessor
:
ServicesAccessor
,
args
:
any
):
void
{
const
focusedEditor
=
accessor
.
get
(
ICodeEditorService
).
getFocusedCodeEditor
();
// Only if editor text focus (i.e. not if editor has widget focus).
if
(
focusedEditor
&&
focusedEditor
.
hasTextFocus
())
{
return
this
.
_runEditorHandler
(
accessor
,
focusedEditor
,
args
);
}
export
const
Undo
:
UndoCommand
=
registerCommand
(
new
UndoCommand
({
id
:
'
undo
'
,
precondition
:
EditorContextKeys
.
writable
,
kbOpts
:
{
weight
:
CORE_WEIGHT
,
kbExpr
:
EditorContextKeys
.
textInputFocus
,
primary
:
KeyMod
.
CtrlCmd
|
KeyCode
.
KEY_Z
},
menuOpts
:
[{
menuId
:
MenuId
.
MenubarEditMenu
,
group
:
'
1_do
'
,
title
:
nls
.
localize
({
key
:
'
miUndo
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Undo
"
),
order
:
1
},
{
menuId
:
MenuId
.
CommandPalette
,
group
:
''
,
title
:
nls
.
localize
(
'
undo
'
,
"
Undo
"
),
order
:
1
}]
}));
// Ignore this action when user is focused on an element that allows for entering text
const
activeElement
=
<
HTMLElement
>
document
.
activeElement
;
if
(
activeElement
&&
[
'
input
'
,
'
textarea
'
].
indexOf
(
activeElement
.
tagName
.
toLowerCase
())
>=
0
)
{
document
.
execCommand
(
this
.
_inputHandler
);
return
;
}
export
const
DefaultUndo
:
UndoCommand
=
registerCommand
(
new
UndoCommand
({
id
:
'
default:undo
'
,
precondition
:
EditorContextKeys
.
writable
}));
// Redirecting to active editor
const
activeEditor
=
accessor
.
get
(
ICodeEditorService
).
getActiveCodeEditor
();
if
(
activeEditor
)
{
activeEditor
.
focus
();
return
this
.
_runEditorHandler
(
accessor
,
activeEditor
,
args
);
}
}
export
const
Redo
:
RedoCommand
=
registerCommand
(
new
RedoCommand
({
id
:
'
redo
'
,
precondition
:
EditorContextKeys
.
writable
,
kbOpts
:
{
weight
:
CORE_WEIGHT
,
kbExpr
:
EditorContextKeys
.
textInputFocus
,
primary
:
KeyMod
.
CtrlCmd
|
KeyCode
.
KEY_Y
,
secondary
:
[
KeyMod
.
CtrlCmd
|
KeyMod
.
Shift
|
KeyCode
.
KEY_Z
],
mac
:
{
primary
:
KeyMod
.
CtrlCmd
|
KeyMod
.
Shift
|
KeyCode
.
KEY_Z
}
},
menuOpts
:
[{
menuId
:
MenuId
.
MenubarEditMenu
,
group
:
'
1_do
'
,
title
:
nls
.
localize
({
key
:
'
miRedo
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Redo
"
),
order
:
2
},
{
menuId
:
MenuId
.
CommandPalette
,
group
:
''
,
title
:
nls
.
localize
(
'
redo
'
,
"
Redo
"
),
order
:
1
}]
}));
private
_runEditorHandler
(
accessor
:
ServicesAccessor
,
editor
:
ICodeEditor
,
args
:
any
):
void
{
const
HANDLER
=
this
.
_editorHandler
;
if
(
typeof
HANDLER
===
'
string
'
)
{
editor
.
trigger
(
'
keyboard
'
,
HANDLER
,
args
);
}
else
{
args
=
args
||
{};
args
.
source
=
'
keyboard
'
;
HANDLER
.
runEditorCommand
(
accessor
,
editor
,
args
);
}
}
export
const
DefaultRedo
:
RedoCommand
=
registerCommand
(
new
RedoCommand
({
id
:
'
default:redo
'
,
precondition
:
EditorContextKeys
.
writable
}));
}
/**
...
...
@@ -1743,78 +1831,7 @@ class EditorHandlerCommand extends Command {
}
}
registerCommand
(
new
EditorOrNativeTextInputCommand
({
editorHandler
:
CoreNavigationCommands
.
SelectAll
,
inputHandler
:
'
selectAll
'
,
id
:
'
editor.action.selectAll
'
,
precondition
:
EditorContextKeys
.
textInputFocus
,
kbOpts
:
{
weight
:
CORE_WEIGHT
,
kbExpr
:
null
,
primary
:
KeyMod
.
CtrlCmd
|
KeyCode
.
KEY_A
},
menuOpts
:
[{
menuId
:
MenuId
.
MenubarSelectionMenu
,
group
:
'
1_basic
'
,
title
:
nls
.
localize
({
key
:
'
miSelectAll
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Select All
"
),
order
:
1
},
{
menuId
:
MenuId
.
CommandPalette
,
group
:
''
,
title
:
nls
.
localize
(
'
selectAll
'
,
"
Select All
"
),
order
:
1
}]
}));
registerCommand
(
new
EditorOrNativeTextInputCommand
({
editorHandler
:
Handler
.
Undo
,
inputHandler
:
'
undo
'
,
id
:
Handler
.
Undo
,
precondition
:
EditorContextKeys
.
writable
,
kbOpts
:
{
weight
:
CORE_WEIGHT
,
kbExpr
:
EditorContextKeys
.
textInputFocus
,
primary
:
KeyMod
.
CtrlCmd
|
KeyCode
.
KEY_Z
},
menuOpts
:
[{
menuId
:
MenuId
.
MenubarEditMenu
,
group
:
'
1_do
'
,
title
:
nls
.
localize
({
key
:
'
miUndo
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Undo
"
),
order
:
1
},
{
menuId
:
MenuId
.
CommandPalette
,
group
:
''
,
title
:
nls
.
localize
(
'
undo
'
,
"
Undo
"
),
order
:
1
}]
}));
registerCommand
(
new
EditorHandlerCommand
(
'
default:
'
+
Handler
.
Undo
,
Handler
.
Undo
));
registerCommand
(
new
EditorOrNativeTextInputCommand
({
editorHandler
:
Handler
.
Redo
,
inputHandler
:
'
redo
'
,
id
:
Handler
.
Redo
,
precondition
:
EditorContextKeys
.
writable
,
kbOpts
:
{
weight
:
CORE_WEIGHT
,
kbExpr
:
EditorContextKeys
.
textInputFocus
,
primary
:
KeyMod
.
CtrlCmd
|
KeyCode
.
KEY_Y
,
secondary
:
[
KeyMod
.
CtrlCmd
|
KeyMod
.
Shift
|
KeyCode
.
KEY_Z
],
mac
:
{
primary
:
KeyMod
.
CtrlCmd
|
KeyMod
.
Shift
|
KeyCode
.
KEY_Z
}
},
menuOpts
:
[{
menuId
:
MenuId
.
MenubarEditMenu
,
group
:
'
1_do
'
,
title
:
nls
.
localize
({
key
:
'
miRedo
'
,
comment
:
[
'
&& denotes a mnemonic
'
]
},
"
&&Redo
"
),
order
:
2
},
{
menuId
:
MenuId
.
CommandPalette
,
group
:
''
,
title
:
nls
.
localize
(
'
redo
'
,
"
Redo
"
),
order
:
1
}]
}));
registerCommand
(
new
EditorHandlerCommand
(
'
default:
'
+
Handler
.
Redo
,
Handler
.
Redo
));
registerCommand
(
new
SelectAllCommand
());
function
registerOverwritableCommand
(
handlerId
:
string
,
description
?:
ICommandHandlerDescription
):
void
{
registerCommand
(
new
EditorHandlerCommand
(
'
default:
'
+
handlerId
,
handlerId
));
...
...
src/vs/editor/browser/widget/codeEditorWidget.ts
浏览文件 @
df4bd40d
...
...
@@ -1543,11 +1543,18 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
};
}
const
onDidChangeTextFocus
=
(
textFocus
:
boolean
)
=>
{
if
(
this
.
_modelData
)
{
this
.
_modelData
.
cursor
.
setHasFocus
(
textFocus
);
}
this
.
_editorTextFocus
.
setValue
(
textFocus
);
};
const
viewOutgoingEvents
=
new
ViewOutgoingEvents
(
viewModel
);
viewOutgoingEvents
.
onDidContentSizeChange
=
(
e
)
=>
this
.
_onDidContentSizeChange
.
fire
(
e
);
viewOutgoingEvents
.
onDidScroll
=
(
e
)
=>
this
.
_onDidScrollChange
.
fire
(
e
);
viewOutgoingEvents
.
onDidGainFocus
=
()
=>
this
.
_editorTextFocus
.
setValue
(
true
);
viewOutgoingEvents
.
onDidLoseFocus
=
()
=>
this
.
_editorTextFocus
.
setValue
(
false
);
viewOutgoingEvents
.
onDidGainFocus
=
()
=>
onDidChangeTextFocus
(
true
);
viewOutgoingEvents
.
onDidLoseFocus
=
()
=>
onDidChangeTextFocus
(
false
);
viewOutgoingEvents
.
onContextMenu
=
(
e
)
=>
this
.
_onContextMenu
.
fire
(
e
);
viewOutgoingEvents
.
onMouseDown
=
(
e
)
=>
this
.
_onMouseDown
.
fire
(
e
);
viewOutgoingEvents
.
onMouseUp
=
(
e
)
=>
this
.
_onMouseUp
.
fire
(
e
);
...
...
src/vs/editor/common/controller/cursor.ts
浏览文件 @
df4bd40d
...
...
@@ -16,7 +16,7 @@ import { Range, IRange } from 'vs/editor/common/core/range';
import
{
ISelection
,
Selection
,
SelectionDirection
}
from
'
vs/editor/common/core/selection
'
;
import
*
as
editorCommon
from
'
vs/editor/common/editorCommon
'
;
import
{
ITextModel
,
TrackedRangeStickiness
,
IModelDeltaDecoration
,
ICursorStateComputer
,
IIdentifiedSingleEditOperation
,
IValidEditOperation
}
from
'
vs/editor/common/model
'
;
import
{
RawContentChangedType
}
from
'
vs/editor/common/model/textModelEvents
'
;
import
{
RawContentChangedType
,
ModelRawContentChangedEvent
}
from
'
vs/editor/common/model/textModelEvents
'
;
import
*
as
viewEvents
from
'
vs/editor/common/view/viewEvents
'
;
import
{
IViewModel
}
from
'
vs/editor/common/viewModel/viewModel
'
;
import
{
dispose
}
from
'
vs/base/common/lifecycle
'
;
...
...
@@ -186,6 +186,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
public
context
:
CursorContext
;
private
_cursors
:
CursorCollection
;
private
_hasFocus
:
boolean
;
private
_isHandling
:
boolean
;
private
_isDoingComposition
:
boolean
;
private
_selectionsWhenCompositionStarted
:
Selection
[]
|
null
;
...
...
@@ -202,6 +203,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
this
.
context
=
new
CursorContext
(
this
.
_configuration
,
this
.
_model
,
this
.
_viewModel
);
this
.
_cursors
=
new
CursorCollection
(
this
.
context
);
this
.
_hasFocus
=
false
;
this
.
_isHandling
=
false
;
this
.
_isDoingComposition
=
false
;
this
.
_selectionsWhenCompositionStarted
=
null
;
...
...
@@ -215,8 +217,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
return
;
}
let
hadFlushEvent
=
e
.
containsEvent
(
RawContentChangedType
.
Flush
);
this
.
_onModelContentChanged
(
hadFlushEvent
);
this
.
_onModelContentChanged
(
e
);
}));
this
.
_register
(
viewModel
.
addEventListener
((
events
:
viewEvents
.
ViewEvent
[])
=>
{
...
...
@@ -264,6 +265,10 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
super
.
dispose
();
}
public
setHasFocus
(
hasFocus
:
boolean
):
void
{
this
.
_hasFocus
=
hasFocus
;
}
private
_validateAutoClosedActions
():
void
{
if
(
this
.
_autoClosedActions
.
length
>
0
)
{
let
selections
:
Range
[]
=
this
.
_cursors
.
getSelections
();
...
...
@@ -392,8 +397,9 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
this
.
reveal
(
'
restoreState
'
,
true
,
RevealTarget
.
Primary
,
editorCommon
.
ScrollType
.
Immediate
);
}
private
_onModelContentChanged
(
hadFlushEvent
:
boolean
):
void
{
private
_onModelContentChanged
(
e
:
ModelRawContentChangedEvent
):
void
{
const
hadFlushEvent
=
e
.
containsEvent
(
RawContentChangedType
.
Flush
);
this
.
_prevEditOperationType
=
EditOperationType
.
Other
;
if
(
hadFlushEvent
)
{
...
...
@@ -403,8 +409,13 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
this
.
_validateAutoClosedActions
();
this
.
_emitStateChangedIfNecessary
(
'
model
'
,
CursorChangeReason
.
ContentFlush
,
null
);
}
else
{
const
selectionsFromMarkers
=
this
.
_cursors
.
readSelectionFromMarkers
();
this
.
setStates
(
'
modelChange
'
,
CursorChangeReason
.
RecoverFromMarkers
,
CursorState
.
fromModelSelections
(
selectionsFromMarkers
));
if
(
this
.
_hasFocus
&&
e
.
resultingSelection
&&
e
.
resultingSelection
.
length
>
0
)
{
const
cursorState
=
CursorState
.
fromModelSelections
(
e
.
resultingSelection
);
this
.
setStates
(
'
modelChange
'
,
e
.
isUndoing
?
CursorChangeReason
.
Undo
:
e
.
isRedoing
?
CursorChangeReason
.
Redo
:
CursorChangeReason
.
RecoverFromMarkers
,
cursorState
);
}
else
{
const
selectionsFromMarkers
=
this
.
_cursors
.
readSelectionFromMarkers
();
this
.
setStates
(
'
modelChange
'
,
CursorChangeReason
.
RecoverFromMarkers
,
CursorState
.
fromModelSelections
(
selectionsFromMarkers
));
}
}
}
...
...
@@ -704,11 +715,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
const
oldState
=
new
CursorModelState
(
this
.
_model
,
this
);
let
cursorChangeReason
=
CursorChangeReason
.
NotSet
;
if
(
handlerId
!==
H
.
Undo
&&
handlerId
!==
H
.
Redo
)
{
// TODO@Alex: if the undo/redo stack contains non-null selections
// it would also be OK to stop tracking selections here
this
.
_cursors
.
stopTrackingSelections
();
}
this
.
_cursors
.
stopTrackingSelections
();
// ensure valid state on all cursors
this
.
_cursors
.
ensureValidState
();
...
...
@@ -734,16 +741,6 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
this
.
_cut
();
break
;
case
H
.
Undo
:
cursorChangeReason
=
CursorChangeReason
.
Undo
;
this
.
_interpretCommandResult
(
this
.
_model
.
undo
());
break
;
case
H
.
Redo
:
cursorChangeReason
=
CursorChangeReason
.
Redo
;
this
.
_interpretCommandResult
(
this
.
_model
.
redo
());
break
;
case
H
.
ExecuteCommand
:
this
.
_externalExecuteCommand
(
<
editorCommon
.
ICommand
>
payload
);
break
;
...
...
@@ -762,9 +759,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
this
.
_isHandling
=
false
;
if
(
handlerId
!==
H
.
Undo
&&
handlerId
!==
H
.
Redo
)
{
this
.
_cursors
.
startTrackingSelections
();
}
this
.
_cursors
.
startTrackingSelections
();
this
.
_validateAutoClosedActions
();
...
...
src/vs/editor/common/editorCommon.ts
浏览文件 @
df4bd40d
...
...
@@ -678,9 +678,5 @@ export const Handler = {
CompositionStart
:
'
compositionStart
'
,
CompositionEnd
:
'
compositionEnd
'
,
Paste
:
'
paste
'
,
Cut
:
'
cut
'
,
Undo
:
'
undo
'
,
Redo
:
'
redo
'
,
};
src/vs/editor/common/model.ts
浏览文件 @
df4bd40d
...
...
@@ -379,6 +379,13 @@ export interface IValidEditOperation {
forceMoveMarkers
:
boolean
;
}
/**
* @internal
*/
export
interface
IValidEditOperations
{
operations
:
IValidEditOperation
[];
}
/**
* A callback that can compute the cursor state after applying a series of edit operations.
*/
...
...
@@ -1086,18 +1093,28 @@ export interface ITextModel {
*/
applyEdits
(
operations
:
IIdentifiedSingleEditOperation
[]):
IValidEditOperation
[];
/**
* @internal
*/
_applyEdits
(
edits
:
IValidEditOperations
[],
isUndoing
:
boolean
,
isRedoing
:
boolean
,
resultingAlternativeVersionId
:
number
,
resultingSelection
:
Selection
[]
|
null
):
IValidEditOperations
[];
/**
* Change the end of line sequence without recording in the undo stack.
* This can have dire consequences on the undo stack! See @pushEOL for the preferred way.
*/
setEOL
(
eol
:
EndOfLineSequence
):
void
;
/**
* @internal
*/
_setEOL
(
eol
:
EndOfLineSequence
,
isUndoing
:
boolean
,
isRedoing
:
boolean
,
resultingAlternativeVersionId
:
number
,
resultingSelection
:
Selection
[]
|
null
):
void
;
/**
* Undo edit operations until the first previous stop point created by `pushStackElement`.
* The inverse edit operations will be pushed on the redo stack.
* @internal
*/
undo
():
Selection
[]
|
null
;
undo
():
void
;
/**
* Is there anything in the undo stack?
...
...
@@ -1110,7 +1127,7 @@ export interface ITextModel {
* The inverse edit operations will be pushed on the undo stack.
* @internal
*/
redo
():
Selection
[]
|
null
;
redo
():
void
;
/**
* Is there anything in the redo stack?
...
...
src/vs/editor/common/model/editStack.ts
浏览文件 @
df4bd40d
...
...
@@ -3,61 +3,72 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
*
as
nls
from
'
vs/nls
'
;
import
{
onUnexpectedError
}
from
'
vs/base/common/errors
'
;
import
{
Selection
}
from
'
vs/editor/common/core/selection
'
;
import
{
EndOfLineSequence
,
ICursorStateComputer
,
IIdentifiedSingleEditOperation
,
IValidEditOperation
}
from
'
vs/editor/common/model
'
;
import
{
EndOfLineSequence
,
ICursorStateComputer
,
IIdentifiedSingleEditOperation
,
IValidEditOperation
,
ITextModel
,
IValidEditOperations
}
from
'
vs/editor/common/model
'
;
import
{
TextModel
}
from
'
vs/editor/common/model/textModel
'
;
import
{
IUndoRedoService
,
IUndoRedoElement
,
IUndoRedoContext
}
from
'
vs/platform/undoRedo/common/undoRedo
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
interface
IEditOperation
{
operations
:
IValidEditOperation
[];
}
class
EditStackElement
implements
IUndoRedoElement
{
interface
IStackElement
{
readonly
beforeVersionId
:
number
;
readonly
beforeCursorState
:
Selection
[]
|
null
;
readonly
afterCursorState
:
Selection
[]
|
null
;
readonly
afterVersionId
:
number
;
public
readonly
label
:
string
;
private
_isOpen
:
boolean
;
private
readonly
_model
:
TextModel
;
private
readonly
_beforeVersionId
:
number
;
private
readonly
_beforeCursorState
:
Selection
[];
private
_afterVersionId
:
number
;
private
_afterCursorState
:
Selection
[]
|
null
;
private
_edits
:
IValidEditOperations
[];
undo
(
model
:
TextModel
):
void
;
redo
(
model
:
TextModel
):
void
;
}
public
get
resources
():
readonly
URI
[]
{
return
[
this
.
_model
.
uri
]
;
}
class
EditStackElement
implements
IStackElement
{
public
readonly
beforeVersionId
:
number
;
public
readonly
beforeCursorState
:
Selection
[];
public
afterCursorState
:
Selection
[]
|
null
;
public
afterVersionId
:
number
;
constructor
(
model
:
TextModel
,
beforeVersionId
:
number
,
beforeCursorState
:
Selection
[],
afterVersionId
:
number
,
afterCursorState
:
Selection
[]
|
null
,
operations
:
IValidEditOperation
[])
{
this
.
label
=
nls
.
localize
(
'
edit
'
,
"
Typing
"
);
this
.
_isOpen
=
true
;
this
.
_model
=
model
;
this
.
_beforeVersionId
=
beforeVersionId
;
this
.
_beforeCursorState
=
beforeCursorState
;
this
.
_afterVersionId
=
afterVersionId
;
this
.
_afterCursorState
=
afterCursorState
;
this
.
_edits
=
[{
operations
:
operations
}];
}
public
editOperations
:
IEditOperation
[];
public
isOpen
():
boolean
{
return
this
.
_isOpen
;
}
constructor
(
beforeVersionId
:
number
,
beforeCursorState
:
Selection
[])
{
this
.
beforeVersionId
=
beforeVersionId
;
this
.
beforeCursorState
=
beforeCursorState
;
this
.
afterCursorState
=
null
;
this
.
afterVersionId
=
-
1
;
this
.
editOperations
=
[];
public
append
(
operations
:
IValidEditOperation
[],
afterVersionId
:
number
,
afterCursorState
:
Selection
[]
|
null
):
void
{
this
.
_edits
.
push
({
operations
:
operations
});
this
.
_afterVersionId
=
afterVersionId
;
this
.
_afterCursorState
=
afterCursorState
;
}
public
undo
(
model
:
TextModel
):
void
{
// Apply all operations in reverse order
for
(
let
i
=
this
.
editOperations
.
length
-
1
;
i
>=
0
;
i
--
)
{
this
.
editOperations
[
i
]
=
{
operations
:
model
.
applyEdits
(
this
.
editOperations
[
i
].
operations
)
};
}
public
close
():
void
{
this
.
_isOpen
=
false
;
}
public
redo
(
model
:
TextModel
):
void
{
// Apply all operations
for
(
let
i
=
0
;
i
<
this
.
editOperations
.
length
;
i
++
)
{
this
.
editOperations
[
i
]
=
{
operations
:
model
.
applyEdits
(
this
.
editOperations
[
i
].
operations
)
};
}
undo
(
ctx
:
IUndoRedoContext
):
void
{
this
.
_isOpen
=
false
;
this
.
_edits
.
reverse
();
this
.
_edits
=
this
.
_model
.
_applyEdits
(
this
.
_edits
,
true
,
false
,
this
.
_beforeVersionId
,
this
.
_beforeCursorState
);
}
redo
(
ctx
:
IUndoRedoContext
):
void
{
this
.
_isOpen
=
false
;
this
.
_edits
.
reverse
();
this
.
_edits
=
this
.
_model
.
_applyEdits
(
this
.
_edits
,
false
,
true
,
this
.
_afterVersionId
,
this
.
_afterCursorState
);
}
invalidate
(
resource
:
URI
):
void
{
// nothing to do
}
}
function
getModelEOL
(
model
:
TextModel
):
EndOfLineSequence
{
function
getModelEOL
(
model
:
I
TextModel
):
EndOfLineSequence
{
const
eol
=
model
.
getEOL
();
if
(
eol
===
'
\n
'
)
{
return
EndOfLineSequence
.
LF
;
...
...
@@ -66,32 +77,40 @@ function getModelEOL(model: TextModel): EndOfLineSequence {
}
}
class
EOLStackElement
implements
IStackElement
{
public
readonly
beforeVersionId
:
number
;
public
readonly
beforeCursorState
:
Selection
[]
|
null
;
public
readonly
afterCursorState
:
Selection
[]
|
null
;
public
afterVersionId
:
number
;
class
EOLStackElement
implements
IUndoRedoElement
{
public
eol
:
EndOfLineSequence
;
public
readonly
label
:
string
;
private
readonly
_model
:
TextModel
;
private
readonly
_beforeVersionId
:
number
;
private
readonly
_afterVersionId
:
number
;
private
_eol
:
EndOfLineSequence
;
constructor
(
beforeVersionId
:
number
,
setEOL
:
EndOfLineSequence
)
{
this
.
beforeVersionId
=
beforeVersionId
;
this
.
beforeCursorState
=
null
;
this
.
afterCursorState
=
null
;
this
.
afterVersionId
=
-
1
;
this
.
eol
=
setEOL
;
public
get
resources
():
readonly
URI
[]
{
return
[
this
.
_model
.
uri
];
}
public
undo
(
model
:
TextModel
):
void
{
let
redoEOL
=
getModelEOL
(
model
);
model
.
setEOL
(
this
.
eol
);
this
.
eol
=
redoEOL
;
constructor
(
model
:
TextModel
,
beforeVersionId
:
number
,
afterVersionId
:
number
,
eol
:
EndOfLineSequence
)
{
this
.
label
=
nls
.
localize
(
'
eol
'
,
"
Change End Of Line Sequence
"
);
this
.
_model
=
model
;
this
.
_beforeVersionId
=
beforeVersionId
;
this
.
_afterVersionId
=
afterVersionId
;
this
.
_eol
=
eol
;
}
public
redo
(
model
:
TextModel
):
void
{
let
undoEOL
=
getModelEOL
(
model
);
model
.
setEOL
(
this
.
eol
);
this
.
eol
=
undoEOL
;
undo
(
ctx
:
IUndoRedoContext
):
void
{
const
redoEOL
=
getModelEOL
(
this
.
_model
);
this
.
_model
.
_setEOL
(
this
.
_eol
,
true
,
false
,
this
.
_beforeVersionId
,
null
);
this
.
_eol
=
redoEOL
;
}
redo
(
ctx
:
IUndoRedoContext
):
void
{
const
undoEOL
=
getModelEOL
(
this
.
_model
);
this
.
_model
.
_setEOL
(
this
.
_eol
,
false
,
true
,
this
.
_afterVersionId
,
null
);
this
.
_eol
=
undoEOL
;
}
invalidate
(
resource
:
URI
):
void
{
// nothing to do
}
}
...
...
@@ -102,76 +121,52 @@ export interface IUndoRedoResult {
export
class
EditStack
{
private
readonly
model
:
TextModel
;
private
currentOpenStackElement
:
IStackElement
|
null
;
private
past
:
IStackElement
[];
private
future
:
IStackElement
[];
private
readonly
_model
:
TextModel
;
private
readonly
_undoRedoService
:
IUndoRedoService
;
constructor
(
model
:
TextModel
)
{
this
.
model
=
model
;
this
.
currentOpenStackElement
=
null
;
this
.
past
=
[];
this
.
future
=
[];
constructor
(
model
:
TextModel
,
undoRedoService
:
IUndoRedoService
)
{
this
.
_model
=
model
;
this
.
_undoRedoService
=
undoRedoService
;
}
public
pushStackElement
():
void
{
if
(
this
.
currentOpenStackElement
!==
null
)
{
this
.
past
.
push
(
this
.
currentOpenStackElement
);
this
.
currentOpenStackElement
=
null
;
const
lastElement
=
this
.
_undoRedoService
.
getLastElement
(
this
.
_model
.
uri
);
if
(
lastElement
&&
lastElement
instanceof
EditStackElement
)
{
lastElement
.
close
()
;
}
}
public
clear
():
void
{
this
.
currentOpenStackElement
=
null
;
this
.
past
=
[];
this
.
future
=
[];
this
.
_undoRedoService
.
removeElements
(
this
.
_model
.
uri
);
}
public
pushEOL
(
eol
:
EndOfLineSequence
):
void
{
// No support for parallel universes :(
this
.
future
=
[];
if
(
this
.
currentOpenStackElement
)
{
this
.
pushStackElement
();
const
beforeVersionId
=
this
.
_model
.
getAlternativeVersionId
();
const
inverseEOL
=
getModelEOL
(
this
.
_model
);
this
.
_model
.
setEOL
(
eol
);
const
afterVersionId
=
this
.
_model
.
getAlternativeVersionId
();
const
lastElement
=
this
.
_undoRedoService
.
getLastElement
(
this
.
_model
.
uri
);
if
(
lastElement
&&
lastElement
instanceof
EditStackElement
)
{
lastElement
.
close
();
}
const
prevEOL
=
getModelEOL
(
this
.
model
);
let
stackElement
=
new
EOLStackElement
(
this
.
model
.
getAlternativeVersionId
(),
prevEOL
);
this
.
model
.
setEOL
(
eol
);
stackElement
.
afterVersionId
=
this
.
model
.
getVersionId
();
this
.
currentOpenStackElement
=
stackElement
;
this
.
pushStackElement
();
this
.
_undoRedoService
.
pushElement
(
new
EOLStackElement
(
this
.
_model
,
inverseEOL
,
beforeVersionId
,
afterVersionId
));
}
public
pushEditOperation
(
beforeCursorState
:
Selection
[],
editOperations
:
IIdentifiedSingleEditOperation
[],
cursorStateComputer
:
ICursorStateComputer
|
null
):
Selection
[]
|
null
{
// No support for parallel universes :(
this
.
future
=
[];
let
stackElement
:
EditStackElement
|
null
=
null
;
if
(
this
.
currentOpenStackElement
)
{
if
(
this
.
currentOpenStackElement
instanceof
EditStackElement
)
{
stackElement
=
this
.
currentOpenStackElement
;
}
else
{
this
.
pushStackElement
();
}
}
if
(
!
this
.
currentOpenStackElement
)
{
stackElement
=
new
EditStackElement
(
this
.
model
.
getAlternativeVersionId
(),
beforeCursorState
);
this
.
currentOpenStackElement
=
stackElement
;
const
beforeVersionId
=
this
.
_model
.
getAlternativeVersionId
();
const
inverseEditOperations
=
this
.
_model
.
applyEdits
(
editOperations
);
const
afterVersionId
=
this
.
_model
.
getAlternativeVersionId
();
const
afterCursorState
=
EditStack
.
_computeCursorState
(
cursorStateComputer
,
inverseEditOperations
);
const
lastElement
=
this
.
_undoRedoService
.
getLastElement
(
this
.
_model
.
uri
);
if
(
lastElement
&&
lastElement
instanceof
EditStackElement
&&
lastElement
.
isOpen
())
{
lastElement
.
append
(
inverseEditOperations
,
afterVersionId
,
afterCursorState
);
}
else
{
this
.
_undoRedoService
.
pushElement
(
new
EditStackElement
(
this
.
_model
,
beforeVersionId
,
beforeCursorState
,
afterVersionId
,
afterCursorState
,
inverseEditOperations
));
}
const
inverseEditOperation
:
IEditOperation
=
{
operations
:
this
.
model
.
applyEdits
(
editOperations
)
};
stackElement
!
.
editOperations
.
push
(
inverseEditOperation
);
stackElement
!
.
afterCursorState
=
EditStack
.
_computeCursorState
(
cursorStateComputer
,
inverseEditOperation
.
operations
);
stackElement
!
.
afterVersionId
=
this
.
model
.
getVersionId
();
return
stackElement
!
.
afterCursorState
;
return
afterCursorState
;
}
private
static
_computeCursorState
(
cursorStateComputer
:
ICursorStateComputer
|
null
,
inverseEditOperations
:
IValidEditOperation
[]):
Selection
[]
|
null
{
...
...
@@ -182,62 +177,4 @@ export class EditStack {
return
null
;
}
}
public
undo
():
IUndoRedoResult
|
null
{
this
.
pushStackElement
();
if
(
this
.
past
.
length
>
0
)
{
const
pastStackElement
=
this
.
past
.
pop
()
!
;
try
{
pastStackElement
.
undo
(
this
.
model
);
}
catch
(
e
)
{
onUnexpectedError
(
e
);
this
.
clear
();
return
null
;
}
this
.
future
.
push
(
pastStackElement
);
return
{
selections
:
pastStackElement
.
beforeCursorState
,
recordedVersionId
:
pastStackElement
.
beforeVersionId
};
}
return
null
;
}
public
canUndo
():
boolean
{
return
(
this
.
past
.
length
>
0
)
||
this
.
currentOpenStackElement
!==
null
;
}
public
redo
():
IUndoRedoResult
|
null
{
if
(
this
.
future
.
length
>
0
)
{
const
futureStackElement
=
this
.
future
.
pop
()
!
;
try
{
futureStackElement
.
redo
(
this
.
model
);
}
catch
(
e
)
{
onUnexpectedError
(
e
);
this
.
clear
();
return
null
;
}
this
.
past
.
push
(
futureStackElement
);
return
{
selections
:
futureStackElement
.
afterCursorState
,
recordedVersionId
:
futureStackElement
.
afterVersionId
};
}
return
null
;
}
public
canRedo
():
boolean
{
return
(
this
.
future
.
length
>
0
);
}
}
src/vs/editor/common/model/textModel.ts
浏览文件 @
df4bd40d
...
...
@@ -255,6 +255,7 @@ export class TextModel extends Disposable implements model.ITextModel {
public
readonly
id
:
string
;
public
readonly
isForSimpleWidget
:
boolean
;
private
readonly
_associatedResource
:
URI
;
private
readonly
_undoRedoService
:
IUndoRedoService
;
private
_attachedEditorCount
:
number
;
private
_buffer
:
model
.
ITextBuffer
;
private
_options
:
model
.
TextModelResolvedOptions
;
...
...
@@ -270,7 +271,7 @@ export class TextModel extends Disposable implements model.ITextModel {
private
readonly
_isTooLargeForTokenization
:
boolean
;
//#region Editing
private
_commandManager
:
EditStack
;
private
readonly
_commandManager
:
EditStack
;
private
_isUndoing
:
boolean
;
private
_isRedoing
:
boolean
;
private
_trimAutoWhitespaceLines
:
number
[]
|
null
;
...
...
@@ -313,6 +314,7 @@ export class TextModel extends Disposable implements model.ITextModel {
}
else
{
this
.
_associatedResource
=
associatedResource
;
}
this
.
_undoRedoService
=
undoRedoService
;
this
.
_attachedEditorCount
=
0
;
this
.
_buffer
=
createTextBuffer
(
source
,
creationOptions
.
defaultEOL
);
...
...
@@ -355,7 +357,7 @@ export class TextModel extends Disposable implements model.ITextModel {
this
.
_decorations
=
Object
.
create
(
null
);
this
.
_decorationsTree
=
new
DecorationsTrees
();
this
.
_commandManager
=
new
EditStack
(
this
);
this
.
_commandManager
=
new
EditStack
(
this
,
undoRedoService
);
this
.
_isUndoing
=
false
;
this
.
_isRedoing
=
false
;
this
.
_trimAutoWhitespaceLines
=
null
;
...
...
@@ -370,6 +372,7 @@ export class TextModel extends Disposable implements model.ITextModel {
this
.
_onWillDispose
.
fire
();
this
.
_languageRegistryListener
.
dispose
();
this
.
_tokenization
.
dispose
();
this
.
_undoRedoService
.
removeElements
(
this
.
uri
);
this
.
_isDisposed
=
true
;
super
.
dispose
();
this
.
_isDisposing
=
false
;
...
...
@@ -444,7 +447,7 @@ export class TextModel extends Disposable implements model.ITextModel {
this
.
_decorationsTree
=
new
DecorationsTrees
();
// Destroy my edit history and settings
this
.
_commandManager
=
new
EditStack
(
this
);
this
.
_commandManager
.
clear
(
);
this
.
_trimAutoWhitespaceLines
=
null
;
this
.
_emitContentChangedEvent
(
...
...
@@ -491,6 +494,21 @@ export class TextModel extends Disposable implements model.ITextModel {
);
}
_setEOL
(
eol
:
model
.
EndOfLineSequence
,
isUndoing
:
boolean
,
isRedoing
:
boolean
,
resultingAlternativeVersionId
:
number
,
resultingSelection
:
Selection
[]
|
null
):
void
{
try
{
this
.
_onDidChangeDecorations
.
beginDeferredEmit
();
this
.
_eventEmitter
.
beginDeferredEmit
();
this
.
_isUndoing
=
isUndoing
;
this
.
_isRedoing
=
isRedoing
;
this
.
setEOL
(
eol
);
this
.
_overwriteAlternativeVersionId
(
resultingAlternativeVersionId
);
}
finally
{
this
.
_isUndoing
=
false
;
this
.
_eventEmitter
.
endDeferredEmit
(
resultingSelection
);
this
.
_onDidChangeDecorations
.
endDeferredEmit
();
}
}
private
_onBeforeEOLChange
():
void
{
// Ensure all decorations get their `range` set.
const
versionId
=
this
.
getVersionId
();
...
...
@@ -1280,18 +1298,37 @@ export class TextModel extends Disposable implements model.ITextModel {
return
this
.
_commandManager
.
pushEditOperation
(
beforeCursorState
,
editOperations
,
cursorStateComputer
);
}
_applyEdits
(
edits
:
model
.
IValidEditOperations
[],
isUndoing
:
boolean
,
isRedoing
:
boolean
,
resultingAlternativeVersionId
:
number
,
resultingSelection
:
Selection
[]
|
null
):
model
.
IValidEditOperations
[]
{
try
{
this
.
_onDidChangeDecorations
.
beginDeferredEmit
();
this
.
_eventEmitter
.
beginDeferredEmit
();
this
.
_isUndoing
=
isUndoing
;
this
.
_isRedoing
=
isRedoing
;
let
reverseEdits
:
model
.
IValidEditOperations
[]
=
[];
for
(
let
i
=
0
,
len
=
edits
.
length
;
i
<
len
;
i
++
)
{
reverseEdits
[
i
]
=
{
operations
:
this
.
applyEdits
(
edits
[
i
].
operations
)
};
}
this
.
_overwriteAlternativeVersionId
(
resultingAlternativeVersionId
);
return
reverseEdits
;
}
finally
{
this
.
_isUndoing
=
false
;
this
.
_eventEmitter
.
endDeferredEmit
(
resultingSelection
);
this
.
_onDidChangeDecorations
.
endDeferredEmit
();
}
}
public
applyEdits
(
rawOperations
:
model
.
IIdentifiedSingleEditOperation
[]):
model
.
IValidEditOperation
[]
{
try
{
this
.
_onDidChangeDecorations
.
beginDeferredEmit
();
this
.
_eventEmitter
.
beginDeferredEmit
();
return
this
.
_
a
pplyEdits
(
this
.
_validateEditOperations
(
rawOperations
));
return
this
.
_
doA
pplyEdits
(
this
.
_validateEditOperations
(
rawOperations
));
}
finally
{
this
.
_eventEmitter
.
endDeferredEmit
();
this
.
_onDidChangeDecorations
.
endDeferredEmit
();
}
}
private
_
a
pplyEdits
(
rawOperations
:
model
.
ValidAnnotatedEditOperation
[]):
model
.
IValidEditOperation
[]
{
private
_
doA
pplyEdits
(
rawOperations
:
model
.
ValidAnnotatedEditOperation
[]):
model
.
IValidEditOperation
[]
{
const
oldLineCount
=
this
.
_buffer
.
getLineCount
();
const
result
=
this
.
_buffer
.
applyEdits
(
rawOperations
,
this
.
_options
.
trimAutoWhitespace
);
...
...
@@ -1372,62 +1409,20 @@ export class TextModel extends Disposable implements model.ITextModel {
return
result
.
reverseEdits
;
}
private
_undo
():
Selection
[]
|
null
{
this
.
_isUndoing
=
true
;
let
r
=
this
.
_commandManager
.
undo
();
this
.
_isUndoing
=
false
;
if
(
!
r
)
{
return
null
;
}
this
.
_overwriteAlternativeVersionId
(
r
.
recordedVersionId
);
return
r
.
selections
;
}
public
undo
():
Selection
[]
|
null
{
try
{
this
.
_onDidChangeDecorations
.
beginDeferredEmit
();
this
.
_eventEmitter
.
beginDeferredEmit
();
return
this
.
_undo
();
}
finally
{
this
.
_eventEmitter
.
endDeferredEmit
();
this
.
_onDidChangeDecorations
.
endDeferredEmit
();
}
public
undo
():
void
{
this
.
_undoRedoService
.
undo
(
this
.
uri
);
}
public
canUndo
():
boolean
{
return
this
.
_commandManager
.
canUndo
();
}
private
_redo
():
Selection
[]
|
null
{
this
.
_isRedoing
=
true
;
let
r
=
this
.
_commandManager
.
redo
();
this
.
_isRedoing
=
false
;
if
(
!
r
)
{
return
null
;
}
this
.
_overwriteAlternativeVersionId
(
r
.
recordedVersionId
);
return
r
.
selections
;
return
this
.
_undoRedoService
.
canUndo
(
this
.
uri
);
}
public
redo
():
Selection
[]
|
null
{
try
{
this
.
_onDidChangeDecorations
.
beginDeferredEmit
();
this
.
_eventEmitter
.
beginDeferredEmit
();
return
this
.
_redo
();
}
finally
{
this
.
_eventEmitter
.
endDeferredEmit
();
this
.
_onDidChangeDecorations
.
endDeferredEmit
();
}
public
redo
():
void
{
this
.
_undoRedoService
.
redo
(
this
.
uri
);
}
public
canRedo
():
boolean
{
return
this
.
_
commandManager
.
canRedo
(
);
return
this
.
_
undoRedoService
.
canRedo
(
this
.
uri
);
}
//#endregion
...
...
@@ -3199,10 +3194,11 @@ export class DidChangeContentEmitter extends Disposable {
this
.
_deferredCnt
++
;
}
public
endDeferredEmit
():
void
{
public
endDeferredEmit
(
resultingSelection
:
Selection
[]
|
null
=
null
):
void
{
this
.
_deferredCnt
--
;
if
(
this
.
_deferredCnt
===
0
)
{
if
(
this
.
_deferredEvent
!==
null
)
{
this
.
_deferredEvent
.
rawContentChangedEvent
.
resultingSelection
=
resultingSelection
;
const
e
=
this
.
_deferredEvent
;
this
.
_deferredEvent
=
null
;
this
.
_fastEmitter
.
fire
(
e
);
...
...
src/vs/editor/common/model/textModelEvents.ts
浏览文件 @
df4bd40d
...
...
@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import
{
IRange
}
from
'
vs/editor/common/core/range
'
;
import
{
Selection
}
from
'
vs/editor/common/core/selection
'
;
/**
* An event describing that the current mode associated with a model has changed.
...
...
@@ -225,11 +226,14 @@ export class ModelRawContentChangedEvent {
*/
public
readonly
isRedoing
:
boolean
;
public
resultingSelection
:
Selection
[]
|
null
;
constructor
(
changes
:
ModelRawChange
[],
versionId
:
number
,
isUndoing
:
boolean
,
isRedoing
:
boolean
)
{
this
.
changes
=
changes
;
this
.
versionId
=
versionId
;
this
.
isUndoing
=
isUndoing
;
this
.
isRedoing
=
isRedoing
;
this
.
resultingSelection
=
null
;
}
public
containsEvent
(
type
:
RawContentChangedType
):
boolean
{
...
...
src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts
浏览文件 @
df4bd40d
...
...
@@ -317,7 +317,7 @@ suite('Editor Contrib - Line Operations', () => {
assert
.
equal
(
model
.
getLineContent
(
1
),
'
one
'
);
assert
.
deepEqual
(
editor
.
getSelection
(),
new
Selection
(
1
,
1
,
1
,
1
));
editor
.
trigger
(
'
keyboard
'
,
Handler
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
Typing some text here on line one
'
);
assert
.
deepEqual
(
editor
.
getSelection
(),
new
Selection
(
1
,
31
,
1
,
31
));
});
...
...
@@ -447,7 +447,7 @@ suite('Editor Contrib - Line Operations', () => {
assert
.
equal
(
model
.
getLineContent
(
1
),
'
hello my dear world
'
);
assert
.
deepEqual
(
editor
.
getSelection
(),
new
Selection
(
1
,
14
,
1
,
14
));
editor
.
trigger
(
'
keyboard
'
,
Handler
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
hello my dear
'
);
assert
.
deepEqual
(
editor
.
getSelection
(),
new
Selection
(
1
,
14
,
1
,
14
));
});
...
...
@@ -815,13 +815,13 @@ suite('Editor Contrib - Line Operations', () => {
new
Selection
(
2
,
4
,
2
,
4
)
]);
editor
.
trigger
(
'
tests
'
,
Handler
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
deepEqual
(
editor
.
getSelections
(),
[
new
Selection
(
1
,
3
,
1
,
3
),
new
Selection
(
1
,
6
,
1
,
6
),
new
Selection
(
3
,
4
,
3
,
4
)
]);
editor
.
trigger
(
'
tests
'
,
Handler
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
deepEqual
(
editor
.
getSelections
(),
[
new
Selection
(
1
,
3
,
1
,
3
),
new
Selection
(
2
,
4
,
2
,
4
)
...
...
src/vs/editor/contrib/wordOperations/test/wordOperations.test.ts
浏览文件 @
df4bd40d
...
...
@@ -13,6 +13,7 @@ import { CursorWordEndLeft, CursorWordEndLeftSelect, CursorWordEndRight, CursorW
import
{
withTestCodeEditor
}
from
'
vs/editor/test/browser/testCodeEditor
'
;
import
{
Handler
}
from
'
vs/editor/common/editorCommon
'
;
import
{
Cursor
}
from
'
vs/editor/common/controller/cursor
'
;
import
{
CoreEditingCommands
}
from
'
vs/editor/browser/controller/coreCommands
'
;
suite
(
'
WordOperations
'
,
()
=>
{
...
...
@@ -216,7 +217,7 @@ suite('WordOperations', () => {
assert
.
equal
(
editor
.
getValue
(),
'
foo qbar baz
'
);
cursorCommand
(
cursor
,
Handler
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
editor
.
getValue
(),
'
foo bar baz
'
);
});
});
...
...
src/vs/editor/test/browser/controller/cursor.test.ts
浏览文件 @
df4bd40d
...
...
@@ -1240,22 +1240,22 @@ suite('Editor Controller - Regression tests', () => {
CoreEditingCommands
.
DeleteLeft
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
x
'
,
'
assert9
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
\n
x
'
,
'
assert10
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
\n\t\n
x
'
,
'
assert11
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
\n\t\n\t
x
'
,
'
assert12
'
);
cursorCommand
(
cursor
,
H
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
\n\t\n
x
'
,
'
assert13
'
);
cursorCommand
(
cursor
,
H
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
\n
x
'
,
'
assert14
'
);
cursorCommand
(
cursor
,
H
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
x
'
,
'
assert15
'
);
});
...
...
@@ -1263,12 +1263,12 @@ suite('Editor Controller - Regression tests', () => {
});
test
(
'
issue #23539: Setting model EOL isn
\'
t undoable
'
,
()
=>
{
usingCursor
({
text
:
[
'
Hello
'
,
'
world
'
]
},
(
model
,
cursor
)
=>
{
withTestCodeEditor
([
'
Hello
'
,
'
world
'
],
{},
(
editor
,
cursor
)
=>
{
const
model
=
editor
.
getModel
()
!
;
assertCursor
(
cursor
,
new
Position
(
1
,
1
));
model
.
setEOL
(
EndOfLineSequence
.
LF
);
assert
.
equal
(
model
.
getValue
(),
'
Hello
\n
world
'
);
...
...
@@ -1276,7 +1276,7 @@ suite('Editor Controller - Regression tests', () => {
model
.
pushEOL
(
EndOfLineSequence
.
CRLF
);
assert
.
equal
(
model
.
getValue
(),
'
Hello
\r\n
world
'
);
cursorCommand
(
cursor
,
H
.
Undo
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(),
'
Hello
\n
world
'
);
});
});
...
...
@@ -1301,7 +1301,7 @@ suite('Editor Controller - Regression tests', () => {
cursorCommand
(
cursor
,
H
.
Type
,
{
text
:
'
%
'
},
'
keyboard
'
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
%
\'
%👁
\'
'
,
'
assert1
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
\'
👁
\'
'
,
'
assert2
'
);
});
...
...
@@ -1327,39 +1327,39 @@ suite('Editor Controller - Regression tests', () => {
assert
.
equal
(
model
.
getLineContent
(
1
),
'
Hello world
'
);
assertCursor
(
cursor
,
new
Position
(
1
,
12
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
Hello world
'
);
assertCursor
(
cursor
,
new
Position
(
1
,
13
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
Hello world
'
);
assertCursor
(
cursor
,
new
Position
(
1
,
12
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
Hello
'
);
assertCursor
(
cursor
,
new
Position
(
1
,
6
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
''
);
assertCursor
(
cursor
,
new
Position
(
1
,
1
));
cursorCommand
(
cursor
,
H
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
Hello
'
);
assertCursor
(
cursor
,
new
Position
(
1
,
6
));
cursorCommand
(
cursor
,
H
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
Hello world
'
);
assertCursor
(
cursor
,
new
Position
(
1
,
12
));
cursorCommand
(
cursor
,
H
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
Hello world
'
);
assertCursor
(
cursor
,
new
Position
(
1
,
13
));
cursorCommand
(
cursor
,
H
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
Hello world
'
);
assertCursor
(
cursor
,
new
Position
(
1
,
12
));
cursorCommand
(
cursor
,
H
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
Hello world
'
);
assertCursor
(
cursor
,
new
Position
(
1
,
12
));
});
...
...
@@ -1735,21 +1735,21 @@ suite('Editor Controller - Regression tests', () => {
'
\t
just some text
'
].
join
(
'
\n
'
),
'
001
'
);
cursorCommand
(
cursor
,
H
.
Undo
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(),
[
'
some lines
'
,
'
and more lines
'
,
'
just some text
'
,
].
join
(
'
\n
'
),
'
002
'
);
cursorCommand
(
cursor
,
H
.
Undo
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(),
[
'
some lines
'
,
'
and more lines
'
,
'
just some text
'
,
].
join
(
'
\n
'
),
'
003
'
);
cursorCommand
(
cursor
,
H
.
Undo
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(),
[
'
some lines
'
,
'
and more lines
'
,
...
...
@@ -1935,10 +1935,8 @@ suite('Editor Controller - Regression tests', () => {
});
test
(
'
issue #9675: Undo/Redo adds a stop in between CHN Characters
'
,
()
=>
{
usingCursor
({
text
:
[
]
},
(
model
,
cursor
)
=>
{
withTestCodeEditor
([],
{},
(
editor
,
cursor
)
=>
{
const
model
=
editor
.
getModel
()
!
;
assertCursor
(
cursor
,
new
Position
(
1
,
1
));
// Typing sennsei in Japanese - Hiragana
...
...
@@ -1957,7 +1955,7 @@ suite('Editor Controller - Regression tests', () => {
assert
.
equal
(
model
.
getLineContent
(
1
),
'
せんせい
'
);
assertCursor
(
cursor
,
new
Position
(
1
,
5
));
cursorCommand
(
cursor
,
H
.
Undo
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
''
);
assertCursor
(
cursor
,
new
Position
(
1
,
1
));
});
...
...
@@ -2138,7 +2136,7 @@ suite('Editor Controller - Regression tests', () => {
}],
()
=>
[
new
Selection
(
1
,
1
,
1
,
1
)]);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
Hello world!
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
Hello world!
'
);
});
...
...
@@ -2229,12 +2227,12 @@ suite('Editor Controller - Regression tests', () => {
new
Selection
(
1
,
5
,
1
,
5
),
]);
cursorCommand
(
cursor
,
H
.
Undo
,
null
,
'
keyboard
'
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assertCursor
(
cursor
,
[
new
Selection
(
1
,
4
,
1
,
4
),
]);
cursorCommand
(
cursor
,
H
.
Redo
,
null
,
'
keyboard
'
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assertCursor
(
cursor
,
[
new
Selection
(
1
,
5
,
1
,
5
),
]);
...
...
@@ -2263,7 +2261,7 @@ suite('Editor Controller - Regression tests', () => {
new
Selection
(
1
,
1
,
1
,
1
),
]);
cursorCommand
(
cursor
,
H
.
Undo
,
null
,
'
keyboard
'
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assertCursor
(
cursor
,
[
new
Selection
(
1
,
1
,
1
,
1
),
]);
...
...
@@ -2378,49 +2376,49 @@ suite('Editor Controller - Cursor Configuration', () => {
CoreNavigationCommands
.
MoveTo
.
runCoreEditorCommand
(
cursor
,
{
position
:
new
Position
(
2
,
1
)
});
CoreEditingCommands
.
Tab
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My Second Line123
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
null
,
'
keyboard
'
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
// Tab on column 2
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My Second Line123
'
);
CoreNavigationCommands
.
MoveTo
.
runCoreEditorCommand
(
cursor
,
{
position
:
new
Position
(
2
,
2
)
});
CoreEditingCommands
.
Tab
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
M y Second Line123
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
null
,
'
keyboard
'
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
// Tab on column 3
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My Second Line123
'
);
CoreNavigationCommands
.
MoveTo
.
runCoreEditorCommand
(
cursor
,
{
position
:
new
Position
(
2
,
3
)
});
CoreEditingCommands
.
Tab
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My Second Line123
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
null
,
'
keyboard
'
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
// Tab on column 4
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My Second Line123
'
);
CoreNavigationCommands
.
MoveTo
.
runCoreEditorCommand
(
cursor
,
{
position
:
new
Position
(
2
,
4
)
});
CoreEditingCommands
.
Tab
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My Second Line123
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
null
,
'
keyboard
'
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
// Tab on column 5
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My Second Line123
'
);
CoreNavigationCommands
.
MoveTo
.
runCoreEditorCommand
(
cursor
,
{
position
:
new
Position
(
2
,
5
)
});
CoreEditingCommands
.
Tab
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My S econd Line123
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
null
,
'
keyboard
'
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
// Tab on column 5
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My Second Line123
'
);
CoreNavigationCommands
.
MoveTo
.
runCoreEditorCommand
(
cursor
,
{
position
:
new
Position
(
2
,
5
)
});
CoreEditingCommands
.
Tab
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My S econd Line123
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
null
,
'
keyboard
'
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
// Tab on column 13
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My Second Line123
'
);
CoreNavigationCommands
.
MoveTo
.
runCoreEditorCommand
(
cursor
,
{
position
:
new
Position
(
2
,
13
)
});
CoreEditingCommands
.
Tab
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My Second Li ne123
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
null
,
'
keyboard
'
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
// Tab on column 14
assert
.
equal
(
model
.
getLineContent
(
2
),
'
My Second Line123
'
);
...
...
@@ -2774,7 +2772,7 @@ suite('Editor Controller - Cursor Configuration', () => {
assert
.
equal
(
model
.
getLineContent
(
2
),
'
a
'
);
// Undo DeleteLeft - get us back to original indentation
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
a
'
);
// Nothing is broken when cursor is in (1,1)
...
...
@@ -2859,22 +2857,22 @@ suite('Editor Controller - Cursor Configuration', () => {
CoreEditingCommands
.
DeleteLeft
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
x
'
,
'
assert10
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
\n
x
'
,
'
assert11
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
\n\t
y
\n
x
'
,
'
assert12
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
\n\t
y
\n\t
x
'
,
'
assert13
'
);
cursorCommand
(
cursor
,
H
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
\n\t
y
\n
x
'
,
'
assert14
'
);
cursorCommand
(
cursor
,
H
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
\n
x
'
,
'
assert15
'
);
cursorCommand
(
cursor
,
H
.
Redo
,
{}
);
CoreEditingCommands
.
Redo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getValue
(
EndOfLinePreference
.
LF
),
'
x
'
,
'
assert16
'
);
});
...
...
@@ -2895,7 +2893,7 @@ suite('Editor Controller - Cursor Configuration', () => {
const
beforeVersion
=
model
.
getVersionId
();
const
beforeAltVersion
=
model
.
getAlternativeVersionId
();
cursorCommand
(
cursor
,
H
.
Type
,
{
text
:
'
Hello
'
},
'
keyboard
'
);
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
const
afterVersion
=
model
.
getVersionId
();
const
afterAltVersion
=
model
.
getAlternativeVersionId
();
...
...
@@ -4263,7 +4261,7 @@ suite('autoClosingPairs', () => {
moveTo
(
cursor
,
lineNumber
,
column
);
cursorCommand
(
cursor
,
H
.
Type
,
{
text
:
chr
},
'
keyboard
'
);
assert
.
deepEqual
(
model
.
getLineContent
(
lineNumber
),
expected
,
message
);
cursorCommand
(
cursor
,
H
.
Undo
);
model
.
undo
(
);
}
test
(
'
open parens: default
'
,
()
=>
{
...
...
@@ -5347,11 +5345,11 @@ suite('Undo stops', () => {
assert
.
equal
(
model
.
getLineContent
(
1
),
'
A fir line
'
);
assertCursor
(
cursor
,
new
Selection
(
1
,
6
,
1
,
6
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
A first line
'
);
assertCursor
(
cursor
,
new
Selection
(
1
,
8
,
1
,
8
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
A line
'
);
assertCursor
(
cursor
,
new
Selection
(
1
,
3
,
1
,
3
));
});
...
...
@@ -5376,11 +5374,11 @@ suite('Undo stops', () => {
assert
.
equal
(
model
.
getLineContent
(
1
),
'
A firstine
'
);
assertCursor
(
cursor
,
new
Selection
(
1
,
8
,
1
,
8
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
A first line
'
);
assertCursor
(
cursor
,
new
Selection
(
1
,
8
,
1
,
8
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
A line
'
);
assertCursor
(
cursor
,
new
Selection
(
1
,
3
,
1
,
3
));
});
...
...
@@ -5410,11 +5408,11 @@ suite('Undo stops', () => {
assert
.
equal
(
model
.
getLineContent
(
2
),
'
Second line
'
);
assertCursor
(
cursor
,
new
Selection
(
2
,
7
,
2
,
7
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
line
'
);
assertCursor
(
cursor
,
new
Selection
(
2
,
1
,
2
,
1
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
Another line
'
);
assertCursor
(
cursor
,
new
Selection
(
2
,
8
,
2
,
8
));
});
...
...
@@ -5448,11 +5446,11 @@ suite('Undo stops', () => {
assert
.
equal
(
model
.
getLineContent
(
2
),
''
);
assertCursor
(
cursor
,
new
Selection
(
2
,
1
,
2
,
1
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
line
'
);
assertCursor
(
cursor
,
new
Selection
(
2
,
1
,
2
,
1
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
Another line
'
);
assertCursor
(
cursor
,
new
Selection
(
2
,
8
,
2
,
8
));
});
...
...
@@ -5479,11 +5477,11 @@ suite('Undo stops', () => {
assert
.
equal
(
model
.
getLineContent
(
2
),
'
Another text
'
);
assertCursor
(
cursor
,
new
Selection
(
2
,
13
,
2
,
13
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
Another
'
);
assertCursor
(
cursor
,
new
Selection
(
2
,
9
,
2
,
9
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
Another line
'
);
assertCursor
(
cursor
,
new
Selection
(
2
,
9
,
2
,
9
));
});
...
...
@@ -5515,11 +5513,11 @@ suite('Undo stops', () => {
assert
.
equal
(
model
.
getLineContent
(
2
),
'
An
'
);
assertCursor
(
cursor
,
new
Selection
(
2
,
3
,
2
,
3
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
Another
'
);
assertCursor
(
cursor
,
new
Selection
(
2
,
9
,
2
,
9
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
2
),
'
Another line
'
);
assertCursor
(
cursor
,
new
Selection
(
2
,
9
,
2
,
9
));
});
...
...
@@ -5539,15 +5537,15 @@ suite('Undo stops', () => {
assert
.
equal
(
model
.
getLineContent
(
1
),
'
A first and interesting line
'
);
assertCursor
(
cursor
,
new
Selection
(
1
,
24
,
1
,
24
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
A first and line
'
);
assertCursor
(
cursor
,
new
Selection
(
1
,
12
,
1
,
12
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
A first line
'
);
assertCursor
(
cursor
,
new
Selection
(
1
,
8
,
1
,
8
));
cursorCommand
(
cursor
,
H
.
Undo
,
{}
);
CoreEditingCommands
.
Undo
.
runEditorCommand
(
null
,
editor
,
null
);
assert
.
equal
(
model
.
getLineContent
(
1
),
'
A line
'
);
assertCursor
(
cursor
,
new
Selection
(
1
,
3
,
1
,
3
));
});
...
...
src/vs/editor/test/browser/testCodeEditor.ts
浏览文件 @
df4bd40d
...
...
@@ -84,6 +84,7 @@ export function withTestCodeEditor(text: string | string[] | null, options: Test
}
let
editor
=
<
TestCodeEditor
>
createTestCodeEditor
(
options
);
editor
.
getCursor
()
!
.
setHasFocus
(
true
);
callback
(
editor
,
editor
.
getCursor
()
!
);
editor
.
dispose
();
...
...
src/vs/platform/undoRedo/common/undoRedo.ts
浏览文件 @
df4bd40d
...
...
@@ -16,7 +16,7 @@ export interface IUndoRedoElement {
/**
* None, one or multiple resources that this undo/redo element impacts.
*/
readonly
resources
:
URI
[];
readonly
resources
:
readonly
URI
[];
/**
* The label of the undo/redo element.
...
...
@@ -43,7 +43,7 @@ export interface IUndoRedoElement {
* Invalidate the edits concerning `resource`.
* i.e. the undo/redo stack for that particular resource has been destroyed.
*/
invalidate
(
resource
:
URI
):
boolean
;
invalidate
(
resource
:
URI
):
void
;
}
export
interface
IUndoRedoService
{
...
...
src/vs/platform/undoRedo/common/undoRedoService.ts
浏览文件 @
df4bd40d
...
...
@@ -7,11 +7,12 @@ import { IUndoRedoService, IUndoRedoElement } from 'vs/platform/undoRedo/common/
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
getComparisonKey
as
uriGetComparisonKey
}
from
'
vs/base/common/resources
'
;
import
{
onUnexpectedError
}
from
'
vs/base/common/errors
'
;
import
{
registerSingleton
}
from
'
vs/platform/instantiation/common/extensions
'
;
class
StackElement
{
public
readonly
actual
:
IUndoRedoElement
;
public
readonly
label
:
string
;
public
readonly
resources
:
URI
[];
public
readonly
resources
:
readonly
URI
[];
public
readonly
strResources
:
string
[];
constructor
(
actual
:
IUndoRedoElement
)
{
...
...
@@ -179,7 +180,7 @@ export class UndoRedoService implements IUndoRedoService {
return
false
;
}
redo
(
resource
:
URI
):
void
{
public
redo
(
resource
:
URI
):
void
{
const
strResource
=
uriGetComparisonKey
(
resource
);
if
(
!
this
.
_editStacks
.
has
(
strResource
))
{
return
;
...
...
@@ -239,3 +240,5 @@ export class UndoRedoService implements IUndoRedoService {
}
}
}
registerSingleton
(
IUndoRedoService
,
UndoRedoService
);
src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts
浏览文件 @
df4bd40d
...
...
@@ -52,6 +52,8 @@ import { ILabelService } from 'vs/platform/label/common/label';
import
{
LabelService
}
from
'
vs/workbench/services/label/common/labelService
'
;
import
{
IFilesConfigurationService
,
FilesConfigurationService
}
from
'
vs/workbench/services/filesConfiguration/common/filesConfigurationService
'
;
import
{
WorkingCopyFileService
,
IWorkingCopyFileService
}
from
'
vs/workbench/services/workingCopy/common/workingCopyFileService
'
;
import
{
IUndoRedoService
}
from
'
vs/platform/undoRedo/common/undoRedo
'
;
import
{
UndoRedoService
}
from
'
vs/platform/undoRedo/common/undoRedoService
'
;
class
TestEnvironmentService
extends
NativeWorkbenchEnvironmentService
{
...
...
@@ -103,6 +105,7 @@ suite('KeybindingsEditing', () => {
instantiationService
.
stub
(
ILabelService
,
instantiationService
.
createInstance
(
LabelService
));
instantiationService
.
stub
(
IFilesConfigurationService
,
instantiationService
.
createInstance
(
FilesConfigurationService
));
instantiationService
.
stub
(
ITextResourcePropertiesService
,
new
TestTextResourcePropertiesService
(
instantiationService
.
get
(
IConfigurationService
)));
instantiationService
.
stub
(
IUndoRedoService
,
instantiationService
.
createInstance
(
UndoRedoService
));
instantiationService
.
stub
(
IModelService
,
instantiationService
.
createInstance
(
ModelServiceImpl
));
const
fileService
=
new
FileService
(
new
NullLogService
());
const
diskFileSystemProvider
=
new
DiskFileSystemProvider
(
new
NullLogService
());
...
...
src/vs/workbench/test/browser/parts/editor/editorModel.test.ts
浏览文件 @
df4bd40d
...
...
@@ -18,6 +18,8 @@ import { URI } from 'vs/base/common/uri';
import
{
createTextBufferFactory
}
from
'
vs/editor/common/model/textModel
'
;
import
{
ITextResourcePropertiesService
}
from
'
vs/editor/common/services/textResourceConfigurationService
'
;
import
{
TestTextResourcePropertiesService
}
from
'
vs/workbench/test/browser/workbenchTestServices
'
;
import
{
IUndoRedoService
}
from
'
vs/platform/undoRedo/common/undoRedo
'
;
import
{
UndoRedoService
}
from
'
vs/platform/undoRedo/common/undoRedoService
'
;
class
MyEditorModel
extends
EditorModel
{
}
class
MyTextEditorModel
extends
BaseTextEditorModel
{
...
...
@@ -72,6 +74,7 @@ suite('Workbench editor model', () => {
function
stubModelService
(
instantiationService
:
TestInstantiationService
):
IModelService
{
instantiationService
.
stub
(
IConfigurationService
,
new
TestConfigurationService
());
instantiationService
.
stub
(
ITextResourcePropertiesService
,
new
TestTextResourcePropertiesService
(
instantiationService
.
get
(
IConfigurationService
)));
instantiationService
.
stub
(
IUndoRedoService
,
new
UndoRedoService
());
return
instantiationService
.
createInstance
(
ModelServiceImpl
);
}
});
src/vs/workbench/test/browser/workbenchTestServices.ts
浏览文件 @
df4bd40d
...
...
@@ -91,6 +91,8 @@ import { IRemotePathService } from 'vs/workbench/services/path/common/remotePath
import
{
Direction
}
from
'
vs/base/browser/ui/grid/grid
'
;
import
{
IProgressService
,
IProgressOptions
,
IProgressWindowOptions
,
IProgressNotificationOptions
,
IProgressCompositeOptions
,
IProgress
,
IProgressStep
,
emptyProgress
}
from
'
vs/platform/progress/common/progress
'
;
import
{
IWorkingCopyFileService
,
WorkingCopyFileService
}
from
'
vs/workbench/services/workingCopy/common/workingCopyFileService
'
;
import
{
UndoRedoService
}
from
'
vs/platform/undoRedo/common/undoRedoService
'
;
import
{
IUndoRedoService
}
from
'
vs/platform/undoRedo/common/undoRedo
'
;
export
import
TestTextResourcePropertiesService
=
CommonWorkbenchTestServices
.
TestTextResourcePropertiesService
;
export
import
TestContextService
=
CommonWorkbenchTestServices
.
TestContextService
;
...
...
@@ -194,6 +196,7 @@ export function workbenchInstantiationService(overrides?: { textFileService?: (i
instantiationService
.
stub
(
IModeService
,
instantiationService
.
createInstance
(
ModeServiceImpl
));
instantiationService
.
stub
(
IHistoryService
,
new
TestHistoryService
());
instantiationService
.
stub
(
ITextResourcePropertiesService
,
new
TestTextResourcePropertiesService
(
configService
));
instantiationService
.
stub
(
IUndoRedoService
,
instantiationService
.
createInstance
(
UndoRedoService
));
instantiationService
.
stub
(
IModelService
,
instantiationService
.
createInstance
(
ModelServiceImpl
));
instantiationService
.
stub
(
IFileService
,
new
TestFileService
());
instantiationService
.
stub
(
IBackupFileService
,
new
TestBackupFileService
());
...
...
src/vs/workbench/workbench.common.main.ts
浏览文件 @
df4bd40d
...
...
@@ -57,6 +57,7 @@ import 'vs/workbench/browser/parts/views/views';
//#region --- workbench services
import
'
vs/platform/undoRedo/common/undoRedoService
'
;
import
'
vs/workbench/services/extensions/browser/extensionUrlHandler
'
;
import
'
vs/workbench/services/bulkEdit/browser/bulkEditService
'
;
import
'
vs/workbench/services/keybinding/common/keybindingEditing
'
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录