Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
6c685145
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,发现更多精彩内容 >>
提交
6c685145
编写于
6月 17, 2020
作者:
R
rebornix
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix #100329. Content providers can contribute to undo/redo stack of a notebook document.
上级
ba6892d6
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
300 addition
and
39 deletion
+300
-39
extensions/vscode-notebook-tests/src/notebook.test.ts
extensions/vscode-notebook-tests/src/notebook.test.ts
+64
-0
extensions/vscode-notebook-tests/src/notebookTestMain.ts
extensions/vscode-notebook-tests/src/notebookTestMain.ts
+25
-7
src/vs/vscode.proposed.d.ts
src/vs/vscode.proposed.d.ts
+34
-1
src/vs/workbench/api/browser/mainThreadNotebook.ts
src/vs/workbench/api/browser/mainThreadNotebook.ts
+43
-4
src/vs/workbench/api/common/extHost.protocol.ts
src/vs/workbench/api/common/extHost.protocol.ts
+6
-0
src/vs/workbench/api/common/extHostNotebook.ts
src/vs/workbench/api/common/extHostNotebook.ts
+80
-0
src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts
...kbench/contrib/notebook/common/model/notebookTextModel.ts
+38
-4
src/vs/workbench/contrib/notebook/common/notebookCommon.ts
src/vs/workbench/contrib/notebook/common/notebookCommon.ts
+0
-1
src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts
.../workbench/contrib/notebook/common/notebookEditorModel.ts
+10
-22
未找到文件。
extensions/vscode-notebook-tests/src/notebook.test.ts
浏览文件 @
6c685145
...
...
@@ -568,6 +568,70 @@ suite('notebook undo redo', () => {
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.files.save
'
);
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.closeActiveEditor
'
);
});
test
(
'
execute and then undo redo
'
,
async
function
()
{
const
resource
=
vscode
.
Uri
.
file
(
join
(
vscode
.
workspace
.
rootPath
||
''
,
'
./first.vsctestnb
'
));
await
vscode
.
commands
.
executeCommand
(
'
vscode.openWith
'
,
resource
,
'
notebookCoreTest
'
);
const
cellsChangeEvent
=
getEventOncePromise
<
vscode
.
NotebookCellsChangeEvent
>
(
vscode
.
notebook
.
onDidChangeNotebookCells
);
await
vscode
.
commands
.
executeCommand
(
'
notebook.cell.insertCodeCellBelow
'
);
const
cellChangeEventRet
=
await
cellsChangeEvent
;
assert
.
equal
(
cellChangeEventRet
.
document
,
vscode
.
notebook
.
activeNotebookEditor
?.
document
);
assert
.
equal
(
cellChangeEventRet
.
changes
.
length
,
1
);
assert
.
deepEqual
(
cellChangeEventRet
.
changes
[
0
],
{
start
:
1
,
deletedCount
:
0
,
deletedItems
:
[],
items
:
[
vscode
.
notebook
.
activeNotebookEditor
!
.
document
.
cells
[
1
]
]
});
const
secondCell
=
vscode
.
notebook
.
activeNotebookEditor
!
.
document
.
cells
[
1
];
const
moveCellEvent
=
getEventOncePromise
<
vscode
.
NotebookCellsChangeEvent
>
(
vscode
.
notebook
.
onDidChangeNotebookCells
);
await
vscode
.
commands
.
executeCommand
(
'
notebook.cell.moveUp
'
);
const
moveCellEventRet
=
await
moveCellEvent
;
assert
.
deepEqual
(
moveCellEventRet
,
{
document
:
vscode
.
notebook
.
activeNotebookEditor
!
.
document
,
changes
:
[
{
start
:
1
,
deletedCount
:
1
,
deletedItems
:
[
secondCell
],
items
:
[]
},
{
start
:
0
,
deletedCount
:
0
,
deletedItems
:
[],
items
:
[
vscode
.
notebook
.
activeNotebookEditor
?.
document
.
cells
[
0
]]
}
]
});
const
cellOutputChange
=
getEventOncePromise
<
vscode
.
NotebookCellOutputsChangeEvent
>
(
vscode
.
notebook
.
onDidChangeCellOutputs
);
await
vscode
.
commands
.
executeCommand
(
'
notebook.cell.execute
'
);
const
cellOutputsAddedRet
=
await
cellOutputChange
;
assert
.
deepEqual
(
cellOutputsAddedRet
,
{
document
:
vscode
.
notebook
.
activeNotebookEditor
!
.
document
,
cells
:
[
vscode
.
notebook
.
activeNotebookEditor
!
.
document
.
cells
[
0
]]
});
assert
.
equal
(
cellOutputsAddedRet
.
cells
[
0
].
outputs
.
length
,
1
);
const
cellOutputClear
=
getEventOncePromise
<
vscode
.
NotebookCellOutputsChangeEvent
>
(
vscode
.
notebook
.
onDidChangeCellOutputs
);
await
vscode
.
commands
.
executeCommand
(
'
notebook.undo
'
);
const
cellOutputsCleardRet
=
await
cellOutputClear
;
assert
.
deepEqual
(
cellOutputsCleardRet
,
{
document
:
vscode
.
notebook
.
activeNotebookEditor
!
.
document
,
cells
:
[
vscode
.
notebook
.
activeNotebookEditor
!
.
document
.
cells
[
0
]]
});
assert
.
equal
(
cellOutputsAddedRet
.
cells
[
0
].
outputs
.
length
,
0
);
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.files.save
'
);
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.closeAllEditors
'
);
});
});
suite
(
'
notebook working copy
'
,
()
=>
{
...
...
extensions/vscode-notebook-tests/src/notebookTestMain.ts
浏览文件 @
6c685145
...
...
@@ -10,8 +10,10 @@ import { smokeTestActivate } from './notebookSmokeTestMain';
export
function
activate
(
context
:
vscode
.
ExtensionContext
):
any
{
smokeTestActivate
(
context
);
const
_onDidChangeNotebook
=
new
vscode
.
EventEmitter
<
vscode
.
NotebookDocumentEditEvent
|
vscode
.
NotebookDocumentContentChangeEvent
>
();
context
.
subscriptions
.
push
(
_onDidChangeNotebook
);
context
.
subscriptions
.
push
(
vscode
.
notebook
.
registerNotebookContentProvider
(
'
notebookCoreTest
'
,
{
onDidChangeNotebook
:
new
vscode
.
EventEmitter
<
vscode
.
NotebookDocumentEditEvent
>
()
.
event
,
onDidChangeNotebook
:
_onDidChangeNotebook
.
event
,
openNotebook
:
async
(
_resource
:
vscode
.
Uri
)
=>
{
if
(
_resource
.
path
.
endsWith
(
'
empty.vsctestnb
'
))
{
return
{
...
...
@@ -71,13 +73,13 @@ export function activate(context: vscode.ExtensionContext): any {
}];
return
;
},
executeCell
:
async
(
_document
:
vscode
.
NotebookDocument
,
_
cell
:
vscode
.
NotebookCell
|
undefined
,
_token
:
vscode
.
CancellationToken
)
=>
{
if
(
!
_
cell
)
{
_cell
=
_
document
.
cells
[
0
];
executeCell
:
async
(
document
:
vscode
.
NotebookDocument
,
cell
:
vscode
.
NotebookCell
|
undefined
,
_token
:
vscode
.
CancellationToken
)
=>
{
if
(
!
cell
)
{
cell
=
document
.
cells
[
0
];
}
if
(
_
document
.
uri
.
path
.
endsWith
(
'
customRenderer.vsctestnb
'
))
{
_
cell
.
outputs
=
[{
if
(
document
.
uri
.
path
.
endsWith
(
'
customRenderer.vsctestnb
'
))
{
cell
.
outputs
=
[{
outputKind
:
vscode
.
CellOutputKind
.
Rich
,
data
:
{
'
text/custom
'
:
'
test
'
...
...
@@ -87,13 +89,29 @@ export function activate(context: vscode.ExtensionContext): any {
return
;
}
_cell
.
outputs
=
[{
const
previousOutputs
=
cell
.
outputs
;
const
newOutputs
:
vscode
.
CellOutput
[]
=
[{
outputKind
:
vscode
.
CellOutputKind
.
Rich
,
data
:
{
'
text/plain
'
:
[
'
my output
'
]
}
}];
cell
.
outputs
=
newOutputs
;
_onDidChangeNotebook
.
fire
({
document
:
document
,
undo
:
()
=>
{
if
(
cell
)
{
cell
.
outputs
=
previousOutputs
;
}
},
redo
:
()
=>
{
if
(
cell
)
{
cell
.
outputs
=
newOutputs
;
}
}
});
return
;
}
}));
...
...
src/vs/vscode.proposed.d.ts
浏览文件 @
6c685145
...
...
@@ -1604,12 +1604,45 @@ declare module 'vscode' {
readonly
metadata
:
NotebookDocumentMetadata
;
}
interface
NotebookDocumentContentChangeEvent
{
/**
* The document that the edit is for.
*/
readonly
document
:
NotebookDocument
;
}
interface
NotebookDocumentEditEvent
{
/**
* The document that the edit is for.
*/
readonly
document
:
NotebookDocument
;
/**
* Undo the edit operation.
*
* This is invoked by VS Code when the user undoes this edit. To implement `undo`, your
* extension should restore the document and editor to the state they were in just before this
* edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`.
*/
undo
():
Thenable
<
void
>
|
void
;
/**
* Redo the edit operation.
*
* This is invoked by VS Code when the user redoes this edit. To implement `redo`, your
* extension should restore the document and editor to the state they were in just after this
* edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`.
*/
redo
():
Thenable
<
void
>
|
void
;
/**
* Display name describing the edit.
*
* This will be shown to users in the UI for undo/redo operations.
*/
readonly
label
?:
string
;
}
interface
NotebookDocumentBackup
{
...
...
@@ -1660,7 +1693,7 @@ declare module 'vscode' {
}):
Promise
<
void
>
;
saveNotebook
(
document
:
NotebookDocument
,
cancellation
:
CancellationToken
):
Promise
<
void
>
;
saveNotebookAs
(
targetResource
:
Uri
,
document
:
NotebookDocument
,
cancellation
:
CancellationToken
):
Promise
<
void
>
;
readonly
onDidChangeNotebook
:
Event
<
NotebookDocument
Edit
Event
>
;
readonly
onDidChangeNotebook
:
Event
<
NotebookDocument
ContentChange
Event
>
;
backupNotebook
(
document
:
NotebookDocument
,
context
:
NotebookDocumentBackupContext
,
cancellation
:
CancellationToken
):
Promise
<
NotebookDocumentBackup
>
;
kernel
?:
NotebookKernel
;
...
...
src/vs/workbench/api/browser/mainThreadNotebook.ts
浏览文件 @
6c685145
...
...
@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
*
as
nls
from
'
vs/nls
'
;
import
{
extHostNamedCustomer
}
from
'
vs/workbench/api/common/extHostCustomers
'
;
import
{
MainContext
,
MainThreadNotebookShape
,
NotebookExtensionDescription
,
IExtHostContext
,
ExtHostNotebookShape
,
ExtHostContext
,
INotebookDocumentsAndEditorsDelta
,
INotebookModelAddedData
}
from
'
../common/extHost.protocol
'
;
import
{
Disposable
,
IDisposable
,
combinedDisposable
}
from
'
vs/base/common/lifecycle
'
;
...
...
@@ -17,6 +18,8 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import
{
IAccessibilityService
}
from
'
vs/platform/accessibility/common/accessibility
'
;
import
{
IRelativePattern
}
from
'
vs/base/common/glob
'
;
import
{
ExtensionIdentifier
}
from
'
vs/platform/extensions/common/extensions
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IUndoRedoService
,
UndoRedoElementType
}
from
'
vs/platform/undoRedo/common/undoRedo
'
;
export
class
MainThreadNotebookDocument
extends
Disposable
{
private
_textModel
:
NotebookTextModel
;
...
...
@@ -31,9 +34,12 @@ export class MainThreadNotebookDocument extends Disposable {
public
viewType
:
string
,
public
supportBackup
:
boolean
,
public
uri
:
URI
,
readonly
notebookService
:
INotebookService
@
INotebookService
readonly
notebookService
:
INotebookService
,
@
IUndoRedoService
readonly
undoRedoService
:
IUndoRedoService
)
{
super
();
this
.
_textModel
=
new
NotebookTextModel
(
handle
,
viewType
,
supportBackup
,
uri
);
this
.
_register
(
this
.
_textModel
.
onDidModelChangeProxy
(
e
=>
{
this
.
_proxy
.
$acceptModelChanged
(
this
.
uri
,
e
);
...
...
@@ -54,6 +60,22 @@ export class MainThreadNotebookDocument extends Disposable {
await
this
.
notebookService
.
transformSpliceOutputs
(
this
.
textModel
,
splices
);
this
.
_textModel
.
$spliceNotebookCellOutputs
(
cellHandle
,
splices
);
}
handleEdit
(
editId
:
number
,
label
:
string
|
undefined
):
void
{
this
.
undoRedoService
.
pushElement
({
type
:
UndoRedoElementType
.
Resource
,
resource
:
this
.
_textModel
.
uri
,
label
:
label
??
nls
.
localize
(
'
defaultEditLabel
'
,
"
Edit
"
),
undo
:
async
()
=>
{
await
this
.
_proxy
.
$undoNotebook
(
this
.
_textModel
.
viewType
,
this
.
_textModel
.
uri
,
editId
,
this
.
_textModel
.
isDirty
);
},
redo
:
async
()
=>
{
await
this
.
_proxy
.
$redoNotebook
(
this
.
_textModel
.
viewType
,
this
.
_textModel
.
uri
,
editId
,
this
.
_textModel
.
isDirty
);
},
});
this
.
_textModel
.
setDirty
(
true
);
}
dispose
()
{
this
.
_textModel
.
dispose
();
super
.
dispose
();
...
...
@@ -179,7 +201,8 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
@
INotebookService
private
_notebookService
:
INotebookService
,
@
IConfigurationService
private
readonly
configurationService
:
IConfigurationService
,
@
IEditorService
private
readonly
editorService
:
IEditorService
,
@
IAccessibilityService
private
readonly
accessibilityService
:
IAccessibilityService
@
IAccessibilityService
private
readonly
accessibilityService
:
IAccessibilityService
,
@
IInstantiationService
private
readonly
_instantiationService
:
IInstantiationService
)
{
super
();
...
...
@@ -388,7 +411,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
}
async
$registerNotebookProvider
(
extension
:
NotebookExtensionDescription
,
viewType
:
string
,
supportBackup
:
boolean
,
kernel
:
INotebookKernelInfoDto
|
undefined
):
Promise
<
void
>
{
let
controller
=
new
MainThreadNotebookController
(
this
.
_proxy
,
this
,
viewType
,
supportBackup
,
kernel
,
this
.
_notebookService
);
let
controller
=
new
MainThreadNotebookController
(
this
.
_proxy
,
this
,
viewType
,
supportBackup
,
kernel
,
this
.
_notebookService
,
this
.
_instantiationService
);
this
.
_notebookProviders
.
set
(
viewType
,
controller
);
this
.
_notebookService
.
registerNotebookController
(
viewType
,
extension
,
controller
);
return
;
...
...
@@ -467,6 +490,16 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
return
false
;
}
$onDidEdit
(
resource
:
UriComponents
,
viewType
:
string
,
editId
:
number
,
label
:
string
|
undefined
):
void
{
let
controller
=
this
.
_notebookProviders
.
get
(
viewType
);
controller
?.
handleEdit
(
resource
,
editId
,
label
);
}
$onContentChange
(
resource
:
UriComponents
,
viewType
:
string
):
void
{
let
controller
=
this
.
_notebookProviders
.
get
(
viewType
);
controller
?.
handleNotebookChange
(
resource
);
}
}
export
class
MainThreadNotebookController
implements
IMainNotebookController
{
...
...
@@ -480,6 +513,7 @@ export class MainThreadNotebookController implements IMainNotebookController {
private
_supportBackup
:
boolean
,
readonly
kernel
:
INotebookKernelInfoDto
|
undefined
,
readonly
notebookService
:
INotebookService
,
readonly
_instantiationService
:
IInstantiationService
)
{
}
...
...
@@ -504,7 +538,7 @@ export class MainThreadNotebookController implements IMainNotebookController {
return
mainthreadNotebook
.
textModel
;
}
let
document
=
new
MainThreadNotebookDocument
(
this
.
_proxy
,
MainThreadNotebookController
.
documentHandle
++
,
viewType
,
this
.
_supportBackup
,
uri
,
this
.
notebookService
);
let
document
=
this
.
_instantiationService
.
createInstance
(
MainThreadNotebookDocument
,
this
.
_proxy
,
MainThreadNotebookController
.
documentHandle
++
,
viewType
,
this
.
_supportBackup
,
uri
);
this
.
_mapping
.
set
(
document
.
uri
.
toString
(),
document
);
if
(
backup
)
{
...
...
@@ -635,6 +669,11 @@ export class MainThreadNotebookController implements IMainNotebookController {
document
?.
textModel
.
handleUnknownChange
();
}
handleEdit
(
resource
:
UriComponents
,
editId
:
number
,
label
:
string
|
undefined
):
void
{
let
document
=
this
.
_mapping
.
get
(
URI
.
from
(
resource
).
toString
());
document
?.
handleEdit
(
editId
,
label
);
}
updateLanguages
(
resource
:
UriComponents
,
languages
:
string
[])
{
let
document
=
this
.
_mapping
.
get
(
URI
.
from
(
resource
).
toString
());
document
?.
textModel
.
updateLanguages
(
languages
);
...
...
src/vs/workbench/api/common/extHost.protocol.ts
浏览文件 @
6c685145
...
...
@@ -710,6 +710,9 @@ export interface MainThreadNotebookShape extends IDisposable {
$updateNotebookCellMetadata
(
viewType
:
string
,
resource
:
UriComponents
,
handle
:
number
,
metadata
:
NotebookCellMetadata
|
undefined
):
Promise
<
void
>
;
$spliceNotebookCellOutputs
(
viewType
:
string
,
resource
:
UriComponents
,
cellHandle
:
number
,
splices
:
NotebookCellOutputsSplice
[],
renderers
:
number
[]):
Promise
<
void
>
;
$postMessage
(
handle
:
number
,
value
:
any
):
Promise
<
boolean
>
;
$onDidEdit
(
resource
:
UriComponents
,
viewType
:
string
,
editId
:
number
,
label
:
string
|
undefined
):
void
;
$onContentChange
(
resource
:
UriComponents
,
viewType
:
string
):
void
;
}
export
interface
MainThreadUrlsShape
extends
IDisposable
{
...
...
@@ -1596,6 +1599,9 @@ export interface ExtHostNotebookShape {
$acceptModelChanged
(
uriComponents
:
UriComponents
,
event
:
NotebookCellsChangedEvent
):
void
;
$acceptEditorPropertiesChanged
(
uriComponents
:
UriComponents
,
data
:
INotebookEditorPropertiesChangeData
):
void
;
$acceptDocumentAndEditorsDelta
(
delta
:
INotebookDocumentsAndEditorsDelta
):
Promise
<
void
>
;
$undoNotebook
(
viewType
:
string
,
uri
:
UriComponents
,
editId
:
number
,
isDirty
:
boolean
):
Promise
<
void
>
;
$redoNotebook
(
viewType
:
string
,
uri
:
UriComponents
,
editId
:
number
,
isDirty
:
boolean
):
Promise
<
void
>
;
}
export
interface
ExtHostStorageShape
{
...
...
src/vs/workbench/api/common/extHostNotebook.ts
浏览文件 @
6c685145
...
...
@@ -25,6 +25,7 @@ import { joinPath } from 'vs/base/common/resources';
import
{
Schemas
}
from
'
vs/base/common/network
'
;
import
{
hash
}
from
'
vs/base/common/hash
'
;
import
{
generateUuid
}
from
'
vs/base/common/uuid
'
;
import
{
Cache
}
from
'
./cache
'
;
interface
IObservable
<
T
>
{
proxy
:
T
;
...
...
@@ -250,6 +251,43 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
private
_backup
?:
vscode
.
NotebookDocumentBackup
;
private
readonly
_edits
=
new
Cache
<
vscode
.
NotebookDocumentEditEvent
>
(
'
notebook documents
'
);
addEdit
(
item
:
vscode
.
NotebookDocumentEditEvent
):
number
{
return
this
.
_edits
.
add
([
item
]);
}
async
undo
(
editId
:
number
,
isDirty
:
boolean
):
Promise
<
void
>
{
await
this
.
getEdit
(
editId
).
undo
();
// if (!isDirty) {
// this.disposeBackup();
// }
}
async
redo
(
editId
:
number
,
isDirty
:
boolean
):
Promise
<
void
>
{
await
this
.
getEdit
(
editId
).
redo
();
// if (!isDirty) {
// this.disposeBackup();
// }
}
private
getEdit
(
editId
:
number
):
vscode
.
NotebookDocumentEditEvent
{
const
edit
=
this
.
_edits
.
get
(
editId
,
0
);
if
(
!
edit
)
{
throw
new
Error
(
'
No edit found
'
);
}
return
edit
;
}
disposeEdits
(
editIds
:
number
[]):
void
{
for
(
const
id
of
editIds
)
{
this
.
_edits
.
delete
(
id
);
}
}
private
_disposed
=
false
;
constructor
(
...
...
@@ -906,8 +944,25 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
const
supportBackup
=
!!
provider
.
backupNotebook
;
this
.
_proxy
.
$registerNotebookProvider
({
id
:
extension
.
identifier
,
location
:
extension
.
extensionLocation
},
viewType
,
supportBackup
,
provider
.
kernel
?
{
id
:
viewType
,
label
:
provider
.
kernel
.
label
,
extensionLocation
:
extension
.
extensionLocation
,
preloads
:
provider
.
kernel
.
preloads
}
:
undefined
);
const
contentChangeListener
=
provider
.
onDidChangeNotebook
(
e
=>
{
const
document
=
this
.
_documents
.
get
(
URI
.
revive
(
e
.
document
.
uri
).
toString
());
if
(
!
document
)
{
throw
new
Error
(
`Notebook document
${
e
.
document
.
uri
.
toString
()}
not found`
);
}
if
(
isEditEvent
(
e
))
{
const
editId
=
document
.
addEdit
(
e
);
this
.
_proxy
.
$onDidEdit
(
e
.
document
.
uri
,
viewType
,
editId
,
e
.
label
);
}
else
{
this
.
_proxy
.
$onContentChange
(
e
.
document
.
uri
,
viewType
);
}
});
return
new
extHostTypes
.
Disposable
(()
=>
{
listener
.
dispose
();
contentChangeListener
.
dispose
();
this
.
_notebookContentProviders
.
delete
(
viewType
);
this
.
_proxy
.
$unregisterNotebookProvider
(
viewType
);
});
...
...
@@ -1080,6 +1135,26 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
return
false
;
}
async
$undoNotebook
(
viewType
:
string
,
uri
:
UriComponents
,
editId
:
number
,
isDirty
:
boolean
):
Promise
<
void
>
{
const
document
=
this
.
_documents
.
get
(
URI
.
revive
(
uri
).
toString
());
if
(
!
document
)
{
return
;
}
document
.
undo
(
editId
,
isDirty
);
}
async
$redoNotebook
(
viewType
:
string
,
uri
:
UriComponents
,
editId
:
number
,
isDirty
:
boolean
):
Promise
<
void
>
{
const
document
=
this
.
_documents
.
get
(
URI
.
revive
(
uri
).
toString
());
if
(
!
document
)
{
return
;
}
document
.
redo
(
editId
,
isDirty
);
}
async
$backup
(
viewType
:
string
,
uri
:
UriComponents
,
cancellation
:
CancellationToken
):
Promise
<
string
|
undefined
>
{
const
document
=
this
.
_documents
.
get
(
URI
.
revive
(
uri
).
toString
());
const
provider
=
this
.
_notebookContentProviders
.
get
(
viewType
);
...
...
@@ -1353,3 +1428,8 @@ function hashPath(resource: URI): string {
const
str
=
resource
.
scheme
===
Schemas
.
file
||
resource
.
scheme
===
Schemas
.
untitled
?
resource
.
fsPath
:
resource
.
toString
();
return
hash
(
str
)
+
''
;
}
function
isEditEvent
(
e
:
vscode
.
NotebookDocumentEditEvent
|
vscode
.
NotebookDocumentContentChangeEvent
):
e
is
vscode
.
NotebookDocumentEditEvent
{
return
typeof
(
e
as
vscode
.
NotebookDocumentEditEvent
).
undo
===
'
function
'
&&
typeof
(
e
as
vscode
.
NotebookDocumentEditEvent
).
redo
===
'
function
'
;
}
src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts
浏览文件 @
6c685145
...
...
@@ -78,8 +78,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
onDidChangeContent
:
Event
<
void
>
=
this
.
_onDidChangeContent
.
event
;
private
_onDidChangeMetadata
=
new
Emitter
<
NotebookDocumentMetadata
>
();
onDidChangeMetadata
:
Event
<
NotebookDocumentMetadata
>
=
this
.
_onDidChangeMetadata
.
event
;
private
readonly
_onDidChangeUnknown
=
new
Emitter
<
void
>
();
readonly
onDidChangeUnknown
:
Event
<
void
>
=
this
.
_onDidChangeUnknown
.
event
;
private
_mapping
:
Map
<
number
,
NotebookCellTextModel
>
=
new
Map
();
private
_cellListeners
:
Map
<
number
,
IDisposable
>
=
new
Map
();
cells
:
NotebookCellTextModel
[];
...
...
@@ -104,6 +102,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
this
.
_onDidSelectionChangeProxy
.
fire
(
this
.
_selections
);
}
private
_dirty
=
false
;
protected
readonly
_onDidChangeDirty
=
this
.
_register
(
new
Emitter
<
void
>
());
readonly
onDidChangeDirty
=
this
.
_onDidChangeDirty
.
event
;
constructor
(
public
handle
:
number
,
public
viewType
:
string
,
...
...
@@ -114,6 +116,17 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
this
.
cells
=
[];
}
get
isDirty
()
{
return
this
.
_dirty
;
}
setDirty
(
newState
:
boolean
)
{
if
(
this
.
_dirty
!==
newState
)
{
this
.
_dirty
=
newState
;
this
.
_onDidChangeDirty
.
fire
();
}
}
createCellTextModel
(
source
:
string
|
string
[],
language
:
string
,
...
...
@@ -135,7 +148,21 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
const
cellUri
=
CellUri
.
generate
(
this
.
uri
,
cellHandle
);
return
new
NotebookCellTextModel
(
cellUri
,
cellHandle
,
cell
.
source
,
cell
.
language
,
cell
.
cellKind
,
cell
.
outputs
||
[],
cell
.
metadata
);
});
this
.
insertNewCell
(
0
,
mainCells
,
false
);
this
.
_isUntitled
=
false
;
for
(
let
i
=
0
;
i
<
mainCells
.
length
;
i
++
)
{
this
.
_mapping
.
set
(
mainCells
[
i
].
handle
,
mainCells
[
i
]);
let
dirtyStateListener
=
mainCells
[
i
].
onDidChangeContent
(()
=>
{
this
.
setDirty
(
true
);
this
.
_onDidChangeContent
.
fire
();
});
this
.
_cellListeners
.
set
(
mainCells
[
i
].
handle
,
dirtyStateListener
);
}
this
.
cells
.
splice
(
0
,
0
,
...
mainCells
);
this
.
_increaseVersionId
();
}
$applyEdit
(
modelVersionId
:
number
,
rawEdits
:
ICellEditOperation
[],
emitToExtHost
:
boolean
=
true
):
boolean
{
...
...
@@ -228,7 +255,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
}
handleUnknownChange
()
{
this
.
_onDidChangeUnknown
.
fire
(
);
this
.
setDirty
(
true
);
}
updateLanguages
(
languages
:
string
[])
{
...
...
@@ -270,10 +297,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
let
dirtyStateListener
=
cell
.
onDidChangeContent
(()
=>
{
this
.
_isUntitled
=
false
;
this
.
setDirty
(
true
);
this
.
_onDidChangeContent
.
fire
();
});
this
.
_cellListeners
.
set
(
cell
.
handle
,
dirtyStateListener
);
this
.
setDirty
(
true
);
this
.
_onDidChangeContent
.
fire
();
this
.
_onDidModelChangeProxy
.
fire
({
...
...
@@ -303,6 +332,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
for
(
let
i
=
0
;
i
<
cells
.
length
;
i
++
)
{
this
.
_mapping
.
set
(
cells
[
i
].
handle
,
cells
[
i
]);
let
dirtyStateListener
=
cells
[
i
].
onDidChangeContent
(()
=>
{
this
.
setDirty
(
true
);
this
.
_onDidChangeContent
.
fire
();
});
...
...
@@ -310,7 +340,9 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
}
this
.
cells
.
splice
(
index
,
0
,
...
cells
);
this
.
setDirty
(
true
);
this
.
_onDidChangeContent
.
fire
();
this
.
_increaseVersionId
();
if
(
emitToExtHost
)
{
...
...
@@ -345,6 +377,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
this
.
_cellListeners
.
delete
(
cell
.
handle
);
}
this
.
cells
.
splice
(
index
,
count
);
this
.
setDirty
(
true
);
this
.
_onDidChangeContent
.
fire
();
this
.
_increaseVersionId
();
...
...
@@ -359,6 +392,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
const
cells
=
this
.
cells
.
splice
(
index
,
1
);
this
.
cells
.
splice
(
newIdx
,
0
,
...
cells
);
this
.
setDirty
(
true
);
this
.
_onDidChangeContent
.
fire
();
this
.
_increaseVersionId
();
...
...
src/vs/workbench/contrib/notebook/common/notebookCommon.ts
浏览文件 @
6c685145
...
...
@@ -271,7 +271,6 @@ export interface INotebookTextModel {
renderers
:
Set
<
string
>
;
onDidChangeCells
?:
Event
<
NotebookCellTextModelSplice
[]
>
;
onDidChangeContent
:
Event
<
void
>
;
onDidChangeUnknown
:
Event
<
void
>
;
onWillDispose
(
listener
:
()
=>
void
):
IDisposable
;
}
...
...
src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts
浏览文件 @
6c685145
...
...
@@ -35,7 +35,6 @@ export interface INotebookLoadOptions {
export
class
NotebookEditorModel
extends
EditorModel
implements
IWorkingCopy
,
INotebookEditorModel
{
private
_dirty
=
false
;
protected
readonly
_onDidChangeDirty
=
this
.
_register
(
new
Emitter
<
void
>
());
readonly
onDidChangeDirty
=
this
.
_onDidChangeDirty
.
event
;
private
readonly
_onDidChangeContent
=
this
.
_register
(
new
Emitter
<
void
>
());
...
...
@@ -113,7 +112,7 @@ export class NotebookEditorModel extends EditorModel implements IWorkingCopy, IN
await
this
.
load
({
forceReadFromDisk
:
true
});
this
.
_
dirty
=
false
;
this
.
_
notebook
.
setDirty
(
false
)
;
this
.
_onDidChangeDirty
.
fire
();
}
...
...
@@ -153,15 +152,14 @@ export class NotebookEditorModel extends EditorModel implements IWorkingCopy, IN
this
.
_name
=
basename
(
this
.
_notebook
!
.
uri
);
this
.
_register
(
this
.
_notebook
.
onDidChangeContent
(()
=>
{
this
.
setDirty
(
true
);
this
.
_onDidChangeContent
.
fire
();
}));
this
.
_register
(
this
.
_notebook
.
onDidChange
Unknown
(()
=>
{
this
.
setDirty
(
true
);
this
.
_register
(
this
.
_notebook
.
onDidChange
Dirty
(()
=>
{
this
.
_onDidChangeDirty
.
fire
(
);
}));
await
this
.
_backupFileService
.
discardBackup
(
this
.
_workingCopyResource
);
this
.
setDirty
(
true
);
this
.
_notebook
.
setDirty
(
true
);
return
this
;
}
...
...
@@ -173,16 +171,15 @@ export class NotebookEditorModel extends EditorModel implements IWorkingCopy, IN
this
.
_name
=
basename
(
this
.
_notebook
!
.
uri
);
this
.
_register
(
this
.
_notebook
.
onDidChangeContent
(()
=>
{
this
.
setDirty
(
true
);
this
.
_onDidChangeContent
.
fire
();
}));
this
.
_register
(
this
.
_notebook
.
onDidChange
Unknown
(()
=>
{
this
.
setDirty
(
true
);
this
.
_register
(
this
.
_notebook
.
onDidChange
Dirty
(()
=>
{
this
.
_onDidChangeDirty
.
fire
(
);
}));
if
(
backupId
)
{
await
this
.
_backupFileService
.
discardBackup
(
this
.
_workingCopyResource
);
this
.
setDirty
(
true
);
this
.
_notebook
.
setDirty
(
true
);
}
return
this
;
...
...
@@ -192,15 +189,8 @@ export class NotebookEditorModel extends EditorModel implements IWorkingCopy, IN
return
!!
this
.
_notebook
;
}
setDirty
(
newState
:
boolean
)
{
if
(
this
.
_dirty
!==
newState
)
{
this
.
_dirty
=
newState
;
this
.
_onDidChangeDirty
.
fire
();
}
}
isDirty
()
{
return
this
.
_
d
irty
;
return
this
.
_
notebook
?.
isD
irty
;
}
isUntitled
()
{
...
...
@@ -210,16 +200,14 @@ export class NotebookEditorModel extends EditorModel implements IWorkingCopy, IN
async
save
():
Promise
<
boolean
>
{
const
tokenSource
=
new
CancellationTokenSource
();
await
this
.
_notebookService
.
save
(
this
.
notebook
.
viewType
,
this
.
notebook
.
uri
,
tokenSource
.
token
);
this
.
_dirty
=
false
;
this
.
_onDidChangeDirty
.
fire
();
this
.
_notebook
.
setDirty
(
false
);
return
true
;
}
async
saveAs
(
targetResource
:
URI
):
Promise
<
boolean
>
{
const
tokenSource
=
new
CancellationTokenSource
();
await
this
.
_notebookService
.
saveAs
(
this
.
notebook
.
viewType
,
this
.
notebook
.
uri
,
targetResource
,
tokenSource
.
token
);
this
.
_dirty
=
false
;
this
.
_onDidChangeDirty
.
fire
();
this
.
_notebook
.
setDirty
(
false
);
return
true
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录