Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
a6710757
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
a6710757
编写于
5月 07, 2020
作者:
P
Peng Lyu
提交者:
GitHub
5月 07, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #97043 from microsoft/rebornix/hotexit
Notebook document creation from UI side and hot exit
上级
f50f16e9
ddbaab0f
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
617 addition
and
258 deletion
+617
-258
extensions/vscode-notebook-tests/src/notebook.test.ts
extensions/vscode-notebook-tests/src/notebook.test.ts
+49
-1
extensions/vscode-notebook-tests/src/notebookTestMain.ts
extensions/vscode-notebook-tests/src/notebookTestMain.ts
+21
-8
src/vs/vscode.proposed.d.ts
src/vs/vscode.proposed.d.ts
+0
-11
src/vs/workbench/api/browser/mainThreadNotebook.ts
src/vs/workbench/api/browser/mainThreadNotebook.ts
+64
-47
src/vs/workbench/api/common/extHost.api.impl.ts
src/vs/workbench/api/common/extHost.api.impl.ts
+0
-4
src/vs/workbench/api/common/extHost.protocol.ts
src/vs/workbench/api/common/extHost.protocol.ts
+19
-5
src/vs/workbench/api/common/extHostNotebook.ts
src/vs/workbench/api/common/extHostNotebook.ts
+153
-143
src/vs/workbench/contrib/notebook/browser/media/notebook.css
src/vs/workbench/contrib/notebook/browser/media/notebook.css
+4
-0
src/vs/workbench/contrib/notebook/browser/notebookEditorInput.ts
...workbench/contrib/notebook/browser/notebookEditorInput.ts
+53
-3
src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts
...workbench/contrib/notebook/browser/notebookServiceImpl.ts
+47
-4
src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts
...rkbench/contrib/notebook/browser/view/notebookCellList.ts
+15
-3
src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts
...h/contrib/notebook/browser/viewModel/notebookViewModel.ts
+10
-5
src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts
...kbench/contrib/notebook/common/model/notebookTextModel.ts
+70
-8
src/vs/workbench/contrib/notebook/common/notebookCommon.ts
src/vs/workbench/contrib/notebook/common/notebookCommon.ts
+8
-1
src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts
.../workbench/contrib/notebook/common/notebookEditorModel.ts
+87
-6
src/vs/workbench/contrib/notebook/common/notebookService.ts
src/vs/workbench/contrib/notebook/common/notebookService.ts
+7
-4
src/vs/workbench/test/browser/api/extHostNotebookConcatDocument.test.ts
...ch/test/browser/api/extHostNotebookConcatDocument.test.ts
+10
-5
未找到文件。
extensions/vscode-notebook-tests/src/notebook.test.ts
浏览文件 @
a6710757
...
...
@@ -212,7 +212,7 @@ suite('notebook dirty state', () => {
await
vscode
.
commands
.
executeCommand
(
'
default:type
'
,
{
text
:
'
var abc = 0;
'
});
// await vscode.commands.executeCommand('workbench.action.files.sav
e');
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.files.newUntitledFil
e
'
);
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.closeActiveEditor
'
);
await
vscode
.
commands
.
executeCommand
(
'
vscode.openWith
'
,
resource
,
'
notebookCoreTest
'
);
...
...
@@ -272,3 +272,51 @@ suite('notebook undo redo', () => {
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.closeActiveEditor
'
);
});
});
suite
(
'
notebook working copy
'
,
()
=>
{
test
(
'
notebook revert on close
'
,
async
function
()
{
const
resource
=
vscode
.
Uri
.
parse
(
join
(
vscode
.
workspace
.
rootPath
||
''
,
'
./first.vsctestnb
'
));
await
vscode
.
commands
.
executeCommand
(
'
vscode.openWith
'
,
resource
,
'
notebookCoreTest
'
);
await
waitFor
(
500
);
await
vscode
.
commands
.
executeCommand
(
'
notebook.cell.insertCodeCellBelow
'
);
assert
.
equal
(
vscode
.
notebook
.
activeNotebookEditor
!
.
selection
?.
source
,
''
);
await
vscode
.
commands
.
executeCommand
(
'
notebook.cell.insertCodeCellAbove
'
);
await
vscode
.
commands
.
executeCommand
(
'
default:type
'
,
{
text
:
'
var abc = 0;
'
});
// close active editor from command will revert the file
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.closeActiveEditor
'
);
await
vscode
.
commands
.
executeCommand
(
'
vscode.openWith
'
,
resource
,
'
notebookCoreTest
'
);
await
waitFor
(
500
);
assert
.
equal
(
vscode
.
notebook
.
activeNotebookEditor
!==
undefined
,
true
);
assert
.
equal
(
vscode
.
notebook
.
activeNotebookEditor
?.
selection
!==
undefined
,
true
);
assert
.
deepEqual
(
vscode
.
notebook
.
activeNotebookEditor
?.
document
.
cells
[
0
],
vscode
.
notebook
.
activeNotebookEditor
?.
selection
);
assert
.
equal
(
vscode
.
notebook
.
activeNotebookEditor
?.
selection
?.
source
,
'
test
'
);
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.files.save
'
);
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.closeActiveEditor
'
);
});
test
(
'
notebook revert
'
,
async
function
()
{
const
resource
=
vscode
.
Uri
.
parse
(
join
(
vscode
.
workspace
.
rootPath
||
''
,
'
./first.vsctestnb
'
));
await
vscode
.
commands
.
executeCommand
(
'
vscode.openWith
'
,
resource
,
'
notebookCoreTest
'
);
await
waitFor
(
500
);
await
vscode
.
commands
.
executeCommand
(
'
notebook.cell.insertCodeCellBelow
'
);
assert
.
equal
(
vscode
.
notebook
.
activeNotebookEditor
!
.
selection
?.
source
,
''
);
await
vscode
.
commands
.
executeCommand
(
'
notebook.cell.insertCodeCellAbove
'
);
await
vscode
.
commands
.
executeCommand
(
'
default:type
'
,
{
text
:
'
var abc = 0;
'
});
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.files.revert
'
);
assert
.
equal
(
vscode
.
notebook
.
activeNotebookEditor
!==
undefined
,
true
);
assert
.
equal
(
vscode
.
notebook
.
activeNotebookEditor
?.
selection
!==
undefined
,
true
);
assert
.
deepEqual
(
vscode
.
notebook
.
activeNotebookEditor
?.
document
.
cells
[
0
],
vscode
.
notebook
.
activeNotebookEditor
?.
selection
);
assert
.
deepEqual
(
vscode
.
notebook
.
activeNotebookEditor
?.
document
.
cells
.
length
,
1
);
assert
.
equal
(
vscode
.
notebook
.
activeNotebookEditor
?.
selection
?.
source
,
'
test
'
);
await
vscode
.
commands
.
executeCommand
(
'
workbench.action.closeActiveEditor
'
);
});
});
extensions/vscode-notebook-tests/src/notebookTestMain.ts
浏览文件 @
a6710757
...
...
@@ -6,12 +6,22 @@
import
*
as
vscode
from
'
vscode
'
;
export
function
activate
(
context
:
vscode
.
ExtensionContext
):
any
{
context
.
subscriptions
.
push
(
vscode
.
notebook
.
registerNotebookProvider
(
'
notebookCoreTest
'
,
{
resolveNotebook
:
async
(
editor
:
vscode
.
NotebookEditor
)
=>
{
await
editor
.
edit
(
eb
=>
{
eb
.
insert
(
0
,
'
test
'
,
'
typescript
'
,
vscode
.
CellKind
.
Code
,
[],
{});
});
return
;
context
.
subscriptions
.
push
(
vscode
.
notebook
.
registerNotebookContentProvider
(
'
notebookCoreTest
'
,
{
onDidChangeNotebook
:
new
vscode
.
EventEmitter
<
void
>
().
event
,
openNotebook
:
async
(
_resource
:
vscode
.
Uri
)
=>
{
return
{
languages
:
[
'
typescript
'
],
metadata
:
{},
cells
:
[
{
source
:
'
test
'
,
language
:
'
typescript
'
,
cellKind
:
vscode
.
CellKind
.
Code
,
outputs
:
[],
metadata
:
{}
}
]
};
},
executeCell
:
async
(
_document
:
vscode
.
NotebookDocument
,
_cell
:
vscode
.
NotebookCell
|
undefined
,
_token
:
vscode
.
CancellationToken
)
=>
{
if
(
!
_cell
)
{
...
...
@@ -26,8 +36,11 @@ export function activate(context: vscode.ExtensionContext): any {
}];
return
;
},
save
:
async
(
_document
:
vscode
.
NotebookDocument
)
=>
{
return
true
;
saveNotebook
:
async
(
_document
:
vscode
.
NotebookDocument
,
_cancellation
:
vscode
.
CancellationToken
)
=>
{
return
;
},
saveNotebookAs
:
async
(
_targetResource
:
vscode
.
Uri
,
_document
:
vscode
.
NotebookDocument
,
_cancellation
:
vscode
.
CancellationToken
)
=>
{
return
;
}
}));
}
src/vs/vscode.proposed.d.ts
浏览文件 @
a6710757
...
...
@@ -1640,12 +1640,6 @@ declare module 'vscode' {
edit
(
callback
:
(
editBuilder
:
NotebookEditorCellEdit
)
=>
void
):
Thenable
<
boolean
>
;
}
export
interface
NotebookProvider
{
resolveNotebook
(
editor
:
NotebookEditor
):
Promise
<
void
>
;
executeCell
(
document
:
NotebookDocument
,
cell
:
NotebookCell
|
undefined
,
token
:
CancellationToken
):
Promise
<
void
>
;
save
(
document
:
NotebookDocument
):
Promise
<
boolean
>
;
}
export
interface
NotebookOutputSelector
{
type
:
string
;
subTypes
?:
string
[];
...
...
@@ -1708,11 +1702,6 @@ declare module 'vscode' {
provider
:
NotebookContentProvider
):
Disposable
;
export
function
registerNotebookProvider
(
notebookType
:
string
,
provider
:
NotebookProvider
):
Disposable
;
export
function
registerNotebookOutputRenderer
(
type
:
string
,
outputSelector
:
NotebookOutputSelector
,
...
...
src/vs/workbench/api/browser/mainThreadNotebook.ts
浏览文件 @
a6710757
...
...
@@ -8,7 +8,7 @@ import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IEx
import
{
Disposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
URI
,
UriComponents
}
from
'
vs/base/common/uri
'
;
import
{
INotebookService
,
IMainNotebookController
}
from
'
vs/workbench/contrib/notebook/common/notebookService
'
;
import
{
INotebookTextModel
,
INotebookMimeTypeSelector
,
NOTEBOOK_DISPLAY_ORDER
,
NotebookCellOutputsSplice
,
CellKind
,
NotebookDocumentMetadata
,
NotebookCellMetadata
,
ICellEditOperation
,
ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
INotebookTextModel
,
INotebookMimeTypeSelector
,
NOTEBOOK_DISPLAY_ORDER
,
NotebookCellOutputsSplice
,
NotebookDocumentMetadata
,
NotebookCellMetadata
,
ICellEditOperation
,
ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER
,
CellEditType
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
NotebookTextModel
}
from
'
vs/workbench/contrib/notebook/common/model/notebookTextModel
'
;
import
{
IEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
...
...
@@ -84,7 +84,9 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
registerListeners
()
{
this
.
_register
(
this
.
_notebookService
.
onDidChangeActiveEditor
(
e
=>
{
this
.
_proxy
.
$updateActiveEditor
(
e
.
viewType
,
e
.
uri
);
this
.
_proxy
.
$acceptDocumentAndEditorsDelta
({
newActiveEditor
:
e
.
uri
});
}));
const
updateOrder
=
()
=>
{
...
...
@@ -129,16 +131,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
return
;
}
async
$createNotebookDocument
(
handle
:
number
,
viewType
:
string
,
resource
:
UriComponents
):
Promise
<
void
>
{
let
controller
=
this
.
_notebookProviders
.
get
(
viewType
);
if
(
controller
)
{
controller
.
createNotebookDocument
(
handle
,
viewType
,
resource
);
}
return
;
}
async
$updateNotebookLanguages
(
viewType
:
string
,
resource
:
UriComponents
,
languages
:
string
[]):
Promise
<
void
>
{
let
controller
=
this
.
_notebookProviders
.
get
(
viewType
);
...
...
@@ -163,11 +155,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
}
}
async
resolveNotebook
(
viewType
:
string
,
uri
:
URI
):
Promise
<
number
|
undefined
>
{
let
handle
=
await
this
.
_proxy
.
$resolveNotebook
(
viewType
,
uri
);
return
handle
;
}
async
$spliceNotebookCellOutputs
(
viewType
:
string
,
resource
:
UriComponents
,
cellHandle
:
number
,
splices
:
NotebookCellOutputsSplice
[],
renderers
:
number
[]):
Promise
<
void
>
{
let
controller
=
this
.
_notebookProviders
.
get
(
viewType
);
controller
?.
spliceNotebookCellOutputs
(
resource
,
cellHandle
,
splices
,
renderers
);
...
...
@@ -195,6 +182,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
export
class
MainThreadNotebookController
implements
IMainNotebookController
{
private
_mapping
:
Map
<
string
,
MainThreadNotebookDocument
>
=
new
Map
();
static
documentHandle
:
number
=
0
;
constructor
(
private
readonly
_proxy
:
ExtHostNotebookShape
,
...
...
@@ -203,26 +191,44 @@ export class MainThreadNotebookController implements IMainNotebookController {
)
{
}
async
resolveNotebook
(
viewType
:
string
,
uri
:
URI
):
Promise
<
NotebookTextModel
|
undefined
>
{
// TODO: resolve notebook should wait for all notebook document destory operations to finish.
async
createNotebook
(
viewType
:
string
,
uri
:
URI
,
forBackup
:
boolean
,
forceReload
:
boolean
):
Promise
<
NotebookTextModel
|
undefined
>
{
let
mainthreadNotebook
=
this
.
_mapping
.
get
(
URI
.
from
(
uri
).
toString
());
if
(
mainthreadNotebook
)
{
if
(
forceReload
)
{
const
data
=
await
this
.
_proxy
.
$resolveNotebookData
(
viewType
,
uri
);
if
(
!
data
)
{
return
;
}
mainthreadNotebook
.
textModel
.
languages
=
data
.
languages
;
mainthreadNotebook
.
textModel
.
metadata
=
data
.
metadata
;
mainthreadNotebook
.
textModel
.
applyEdit
(
mainthreadNotebook
.
textModel
.
versionId
,
[
{
editType
:
CellEditType
.
Delete
,
count
:
mainthreadNotebook
.
textModel
.
cells
.
length
,
index
:
0
},
{
editType
:
CellEditType
.
Insert
,
index
:
0
,
cells
:
data
.
cells
}
]);
}
return
mainthreadNotebook
.
textModel
;
}
let
notebookHandle
=
await
this
.
_mainThreadNotebook
.
resolveNotebook
(
viewType
,
uri
);
if
(
notebookHandle
!==
undefined
)
{
mainthreadNotebook
=
this
.
_mapping
.
get
(
URI
.
from
(
uri
).
toString
());
if
(
mainthreadNotebook
&&
mainthreadNotebook
.
textModel
.
cells
.
length
===
0
)
{
// it's empty, we should create an empty template one
const
mainCell
=
mainthreadNotebook
.
textModel
.
createCellTextModel
([
''
],
mainthreadNotebook
.
textModel
.
languages
.
length
?
mainthreadNotebook
.
textModel
.
languages
[
0
]
:
''
,
CellKind
.
Code
,
[],
undefined
);
mainthreadNotebook
.
textModel
.
insertTemplateCell
(
mainCell
);
}
return
mainthreadNotebook
?.
textModel
;
let
document
=
new
MainThreadNotebookDocument
(
this
.
_proxy
,
MainThreadNotebookController
.
documentHandle
++
,
viewType
,
uri
);
await
this
.
createNotebookDocument
(
document
);
if
(
forBackup
)
{
return
document
.
textModel
;
}
// open notebook document
const
data
=
await
this
.
_proxy
.
$resolveNotebookData
(
viewType
,
uri
);
if
(
!
data
)
{
return
;
}
return
undefined
;
document
.
textModel
.
languages
=
data
.
languages
;
document
.
textModel
.
metadata
=
data
.
metadata
;
document
.
textModel
.
initialize
(
data
!
.
cells
);
return
document
.
textModel
;
}
async
tryApplyEdits
(
resource
:
UriComponents
,
modelVersionId
:
number
,
edits
:
ICellEditOperation
[],
renderers
:
number
[]):
Promise
<
boolean
>
{
...
...
@@ -250,12 +256,32 @@ export class MainThreadNotebookController implements IMainNotebookController {
this
.
_proxy
.
$onDidReceiveMessage
(
uri
,
message
);
}
// Methods for ExtHost
async
createNotebookDocument
(
handle
:
number
,
viewType
:
string
,
resource
:
UriComponents
):
Promise
<
void
>
{
let
document
=
new
MainThreadNotebookDocument
(
this
.
_proxy
,
handle
,
viewType
,
URI
.
revive
(
resource
));
this
.
_mapping
.
set
(
URI
.
revive
(
resource
).
toString
(),
document
);
async
createNotebookDocument
(
document
:
MainThreadNotebookDocument
):
Promise
<
void
>
{
this
.
_mapping
.
set
(
document
.
uri
.
toString
(),
document
);
await
this
.
_proxy
.
$acceptDocumentAndEditorsDelta
({
addedDocuments
:
[{
viewType
:
document
.
viewType
,
handle
:
document
.
handle
,
uri
:
document
.
uri
}]
});
}
async
removeNotebookDocument
(
notebook
:
INotebookTextModel
):
Promise
<
void
>
{
let
document
=
this
.
_mapping
.
get
(
URI
.
from
(
notebook
.
uri
).
toString
());
if
(
!
document
)
{
return
;
}
await
this
.
_proxy
.
$acceptDocumentAndEditorsDelta
({
removedDocuments
:
[
notebook
.
uri
]
});
document
.
dispose
();
this
.
_mapping
.
delete
(
URI
.
from
(
notebook
.
uri
).
toString
());
}
// Methods for ExtHost
updateLanguages
(
resource
:
UriComponents
,
languages
:
string
[])
{
let
document
=
this
.
_mapping
.
get
(
URI
.
from
(
resource
).
toString
());
document
?.
textModel
.
updateLanguages
(
languages
);
...
...
@@ -280,21 +306,12 @@ export class MainThreadNotebookController implements IMainNotebookController {
return
this
.
_proxy
.
$executeNotebook
(
this
.
_viewType
,
uri
,
handle
,
token
);
}
async
destoryNotebookDocument
(
notebook
:
INotebookTextModel
):
Promise
<
void
>
{
let
document
=
this
.
_mapping
.
get
(
URI
.
from
(
notebook
.
uri
).
toString
());
if
(
!
document
)
{
return
;
}
let
removeFromExtHost
=
await
this
.
_proxy
.
$destoryNotebookDocument
(
this
.
_viewType
,
notebook
.
uri
);
if
(
removeFromExtHost
)
{
document
.
dispose
();
this
.
_mapping
.
delete
(
URI
.
from
(
notebook
.
uri
).
toString
());
}
}
async
save
(
uri
:
URI
,
token
:
CancellationToken
):
Promise
<
boolean
>
{
return
this
.
_proxy
.
$saveNotebook
(
this
.
_viewType
,
uri
,
token
);
}
async
saveAs
(
uri
:
URI
,
target
:
URI
,
token
:
CancellationToken
):
Promise
<
boolean
>
{
return
this
.
_proxy
.
$saveNotebookAs
(
this
.
_viewType
,
uri
,
target
,
token
);
}
}
src/vs/workbench/api/common/extHost.api.impl.ts
浏览文件 @
a6710757
...
...
@@ -910,10 +910,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled
(
extension
);
return
extHostNotebook
.
onDidCloseNotebookDocument
;
},
registerNotebookProvider
:
(
viewType
:
string
,
provider
:
vscode
.
NotebookProvider
)
=>
{
checkProposedApiEnabled
(
extension
);
return
extHostNotebook
.
registerNotebookProvider
(
extension
,
viewType
,
provider
);
},
registerNotebookContentProvider
:
(
viewType
:
string
,
provider
:
vscode
.
NotebookContentProvider
)
=>
{
checkProposedApiEnabled
(
extension
);
return
extHostNotebook
.
registerNotebookContentProvider
(
extension
,
viewType
,
provider
);
...
...
src/vs/workbench/api/common/extHost.protocol.ts
浏览文件 @
a6710757
...
...
@@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import
{
TunnelOptions
}
from
'
vs/platform/remote/common/tunnel
'
;
import
{
Timeline
,
TimelineChangeEvent
,
TimelineOptions
,
TimelineProviderDescriptor
,
InternalTimelineOptions
}
from
'
vs/workbench/contrib/timeline/common/timeline
'
;
import
{
revive
}
from
'
vs/base/common/marshalling
'
;
import
{
INotebookMimeTypeSelector
,
IOutput
,
INotebookDisplayOrder
,
NotebookCellMetadata
,
NotebookDocumentMetadata
,
ICellEditOperation
,
NotebookCellsChangedEvent
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
INotebookMimeTypeSelector
,
IOutput
,
INotebookDisplayOrder
,
NotebookCellMetadata
,
NotebookDocumentMetadata
,
ICellEditOperation
,
NotebookCellsChangedEvent
,
NotebookDataDto
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
CallHierarchyItem
}
from
'
vs/workbench/contrib/callHierarchy/common/callHierarchy
'
;
import
{
Dto
}
from
'
vs/base/common/types
'
;
import
{
ISerializableEnvironmentVariableCollection
}
from
'
vs/workbench/contrib/terminal/common/environmentVariable
'
;
...
...
@@ -691,7 +691,6 @@ export interface MainThreadNotebookShape extends IDisposable {
$unregisterNotebookProvider
(
viewType
:
string
):
Promise
<
void
>
;
$registerNotebookRenderer
(
extension
:
NotebookExtensionDescription
,
type
:
string
,
selectors
:
INotebookMimeTypeSelector
,
handle
:
number
,
preloads
:
UriComponents
[]):
Promise
<
void
>
;
$unregisterNotebookRenderer
(
handle
:
number
):
Promise
<
void
>
;
$createNotebookDocument
(
handle
:
number
,
viewType
:
string
,
resource
:
UriComponents
):
Promise
<
void
>
;
$tryApplyEdits
(
viewType
:
string
,
resource
:
UriComponents
,
modelVersionId
:
number
,
edits
:
ICellEditOperation
[],
renderers
:
number
[]):
Promise
<
boolean
>
;
$updateNotebookLanguages
(
viewType
:
string
,
resource
:
UriComponents
,
languages
:
string
[]):
Promise
<
void
>
;
$updateNotebookMetadata
(
viewType
:
string
,
resource
:
UriComponents
,
metadata
:
NotebookDocumentMetadata
):
Promise
<
void
>
;
...
...
@@ -1538,16 +1537,31 @@ export interface INotebookEditorPropertiesChangeData {
selections
:
INotebookSelectionChangeEvent
|
null
;
}
export
interface
INotebookModelAddedData
{
uri
:
UriComponents
;
handle
:
number
;
// versionId: number;
viewType
:
string
;
}
export
interface
INotebookDocumentsAndEditorsDelta
{
removedDocuments
?:
UriComponents
[];
addedDocuments
?:
INotebookModelAddedData
[];
// removedEditors?: string[];
// addedEditors?: ITextEditorAddData[];
newActiveEditor
?:
UriComponents
|
null
;
}
export
interface
ExtHostNotebookShape
{
$resolveNotebook
(
viewType
:
string
,
uri
:
UriComponents
):
Promise
<
number
|
undefined
>
;
$resolveNotebook
Data
(
viewType
:
string
,
uri
:
UriComponents
):
Promise
<
NotebookDataDto
|
undefined
>
;
$executeNotebook
(
viewType
:
string
,
uri
:
UriComponents
,
cellHandle
:
number
|
undefined
,
token
:
CancellationToken
):
Promise
<
void
>
;
$saveNotebook
(
viewType
:
string
,
uri
:
UriComponents
,
token
:
CancellationToken
):
Promise
<
boolean
>
;
$updateActiveEditor
(
viewType
:
string
,
uri
:
UriComponents
):
Promise
<
void
>
;
$destoryNotebookDocument
(
viewType
:
string
,
uri
:
UriComponents
):
Promise
<
boolean
>
;
$saveNotebookAs
(
viewType
:
string
,
uri
:
UriComponents
,
target
:
UriComponents
,
token
:
CancellationToken
):
Promise
<
boolean
>
;
$acceptDisplayOrder
(
displayOrder
:
INotebookDisplayOrder
):
void
;
$onDidReceiveMessage
(
uri
:
UriComponents
,
message
:
any
):
void
;
$acceptModelChanged
(
uriComponents
:
UriComponents
,
event
:
NotebookCellsChangedEvent
):
void
;
$acceptEditorPropertiesChanged
(
uriComponents
:
UriComponents
,
data
:
INotebookEditorPropertiesChangeData
):
void
;
$acceptDocumentAndEditorsDelta
(
delta
:
INotebookDocumentsAndEditorsDelta
):
Promise
<
void
>
;
}
export
interface
ExtHostStorageShape
{
...
...
src/vs/workbench/api/common/extHostNotebook.ts
浏览文件 @
a6710757
...
...
@@ -10,10 +10,10 @@ import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecyc
import
{
ISplice
}
from
'
vs/base/common/sequence
'
;
import
{
URI
,
UriComponents
}
from
'
vs/base/common/uri
'
;
import
{
IExtensionDescription
}
from
'
vs/platform/extensions/common/extensions
'
;
import
{
CellKind
,
CellOutputKind
,
ExtHostNotebookShape
,
IMainContext
,
MainContext
,
MainThreadNotebookShape
,
NotebookCellOutputsSplice
,
MainThreadDocumentsShape
,
INotebookEditorPropertiesChangeData
}
from
'
vs/workbench/api/common/extHost.protocol
'
;
import
{
CellKind
,
CellOutputKind
,
ExtHostNotebookShape
,
IMainContext
,
MainContext
,
MainThreadNotebookShape
,
NotebookCellOutputsSplice
,
MainThreadDocumentsShape
,
INotebookEditorPropertiesChangeData
,
INotebookDocumentsAndEditorsDelta
}
from
'
vs/workbench/api/common/extHost.protocol
'
;
import
{
ExtHostCommands
}
from
'
vs/workbench/api/common/extHostCommands
'
;
import
{
ExtHostDocumentsAndEditors
}
from
'
vs/workbench/api/common/extHostDocumentsAndEditors
'
;
import
{
CellEditType
,
CellUri
,
diff
,
ICellEditOperation
,
ICellInsertEdit
,
IErrorOutput
,
INotebookDisplayOrder
,
INotebookEditData
,
IOrderedMimeType
,
IStreamOutput
,
ITransformedDisplayOutputDto
,
mimeTypeSupportedByCore
,
NotebookCellsChangedEvent
,
NotebookCellsSplice2
,
sortMimeTypes
,
ICellDeleteEdit
,
notebookDocumentMetadataDefaults
,
NotebookCellsChangeType
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
CellEditType
,
CellUri
,
diff
,
ICellEditOperation
,
ICellInsertEdit
,
IErrorOutput
,
INotebookDisplayOrder
,
INotebookEditData
,
IOrderedMimeType
,
IStreamOutput
,
ITransformedDisplayOutputDto
,
mimeTypeSupportedByCore
,
NotebookCellsChangedEvent
,
NotebookCellsSplice2
,
sortMimeTypes
,
ICellDeleteEdit
,
notebookDocumentMetadataDefaults
,
NotebookCellsChangeType
,
NotebookDataDto
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
Disposable
as
VSCodeDisposable
}
from
'
./extHostTypes
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
ExtHostDocumentData
}
from
'
vs/workbench/api/common/extHostDocumentData
'
;
...
...
@@ -345,8 +345,6 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
transformMimeTypes
(
output
:
vscode
.
CellDisplayOutput
):
ITransformedDisplayOutputDto
{
let
mimeTypes
=
Object
.
keys
(
output
.
data
);
// TODO@rebornix, the document display order might be assigned a bit later. We need to postpone sending the outputs to the core side.
let
coreDisplayOrder
=
this
.
renderingHandler
.
outputDisplayOrder
;
const
sorted
=
sortMimeTypes
(
mimeTypes
,
coreDisplayOrder
?.
userOrder
||
[],
this
.
_displayOrder
,
coreDisplayOrder
?.
defaultOrder
||
[]);
...
...
@@ -415,7 +413,7 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
}
}
export
class
NotebookEditorCellEdit
{
export
class
NotebookEditorCellEdit
Builder
implements
vscode
.
NotebookEditorCellEdit
{
private
_finalized
:
boolean
=
false
;
private
readonly
_documentVersionId
:
number
;
private
_collectedEdits
:
ICellEditOperation
[]
=
[];
...
...
@@ -526,13 +524,13 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
}));
}
edit
(
callback
:
(
editBuilder
:
NotebookEditorCellEdit
)
=>
void
):
Thenable
<
boolean
>
{
const
edit
=
new
NotebookEditorCellEdit
(
this
);
edit
(
callback
:
(
editBuilder
:
NotebookEditorCellEdit
Builder
)
=>
void
):
Thenable
<
boolean
>
{
const
edit
=
new
NotebookEditorCellEdit
Builder
(
this
);
callback
(
edit
);
return
this
.
_applyEdit
(
edit
);
}
private
_applyEdit
(
editBuilder
:
NotebookEditorCellEdit
):
Promise
<
boolean
>
{
private
_applyEdit
(
editBuilder
:
NotebookEditorCellEdit
Builder
):
Promise
<
boolean
>
{
const
editData
=
editBuilder
.
finalize
();
// return when there is nothing to do
...
...
@@ -625,7 +623,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
private
static
_handlePool
:
number
=
0
;
private
readonly
_proxy
:
MainThreadNotebookShape
;
private
readonly
_notebookProviders
=
new
Map
<
string
,
{
readonly
provider
:
vscode
.
NotebookProvider
,
readonly
extension
:
IExtensionDescription
;
}
>
();
private
readonly
_notebookContentProviders
=
new
Map
<
string
,
{
readonly
provider
:
vscode
.
NotebookContentProvider
,
readonly
extension
:
IExtensionDescription
;
}
>
();
private
readonly
_documents
=
new
Map
<
string
,
ExtHostNotebookDocument
>
();
private
readonly
_editors
=
new
Map
<
string
,
{
editor
:
ExtHostNotebookEditor
,
onDidReceiveMessage
:
Emitter
<
any
>
;
}
>
();
...
...
@@ -706,31 +703,13 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
return
matches
;
}
registerNotebookProvider
(
extension
:
IExtensionDescription
,
viewType
:
string
,
provider
:
vscode
.
NotebookProvider
,
):
vscode
.
Disposable
{
if
(
this
.
_notebookProviders
.
has
(
viewType
))
{
throw
new
Error
(
`Notebook provider for '
${
viewType
}
' already registered`
);
}
this
.
_notebookProviders
.
set
(
viewType
,
{
extension
,
provider
});
this
.
_proxy
.
$registerNotebookProvider
({
id
:
extension
.
identifier
,
location
:
extension
.
extensionLocation
},
viewType
);
return
new
VSCodeDisposable
(()
=>
{
this
.
_notebookProviders
.
delete
(
viewType
);
this
.
_proxy
.
$unregisterNotebookProvider
(
viewType
);
});
}
registerNotebookContentProvider
(
extension
:
IExtensionDescription
,
viewType
:
string
,
provider
:
vscode
.
NotebookContentProvider
,
):
vscode
.
Disposable
{
if
(
this
.
_notebookProviders
.
has
(
viewType
))
{
if
(
this
.
_notebook
Content
Providers
.
has
(
viewType
))
{
throw
new
Error
(
`Notebook provider for '
${
viewType
}
' already registered`
);
}
...
...
@@ -742,97 +721,99 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
});
}
async
_resolveNotebookFromContentProvider
(
viewType
:
string
,
uri
:
UriComponents
):
Promise
<
number
|
undefined
>
{
async
$resolveNotebookData
(
viewType
:
string
,
uri
:
UriComponents
):
Promise
<
NotebookDataDto
|
undefined
>
{
let
provider
=
this
.
_notebookContentProviders
.
get
(
viewType
);
let
document
=
this
.
_documents
.
get
(
URI
.
revive
(
uri
).
toString
());
if
(
provider
)
{
const
revivedUri
=
URI
.
revive
(
uri
);
if
(
!
this
.
_documents
.
has
(
revivedUri
.
toString
()))
{
let
document
=
new
ExtHostNotebookDocument
(
this
.
_proxy
,
this
.
_documentsAndEditors
,
viewType
,
revivedUri
,
this
);
await
this
.
_proxy
.
$createNotebookDocument
(
document
.
handle
,
viewType
,
uri
);
this
.
_documents
.
set
(
revivedUri
.
toString
(),
document
);
}
if
(
provider
&&
document
)
{
const
rawCells
=
await
provider
.
provider
.
openNotebook
(
URI
.
revive
(
uri
));
const
renderers
=
new
Set
<
number
>
();
const
dto
=
{
metadata
:
{
...
notebookDocumentMetadataDefaults
,
...
rawCells
.
metadata
},
languages
:
rawCells
.
languages
,
cells
:
rawCells
.
cells
.
map
(
cell
=>
{
let
transformedOutputs
=
cell
.
outputs
.
map
(
output
=>
{
if
(
output
.
outputKind
===
CellOutputKind
.
Rich
)
{
// TODO display string[]
const
ret
=
this
.
_transformMimeTypes
(
document
!
,
(
rawCells
.
metadata
.
displayOrder
as
string
[])
||
[],
output
);
if
(
ret
.
orderedMimeTypes
[
ret
.
pickedMimeTypeIndex
].
isResolved
)
{
renderers
.
add
(
ret
.
orderedMimeTypes
[
ret
.
pickedMimeTypeIndex
].
rendererId
!
);
}
return
ret
;
}
else
{
return
output
as
IStreamOutput
|
IErrorOutput
;
}
});
const
onDidReceiveMessage
=
new
Emitter
<
any
>
();
let
editor
=
new
ExtHostNotebookEditor
(
viewType
,
`
${
ExtHostNotebookController
.
_handlePool
++
}
`
,
revivedUri
,
this
.
_proxy
,
onDidReceiveMessage
,
this
.
_documents
.
get
(
revivedUri
.
toString
())
!
,
this
.
_documentsAndEditors
);
this
.
_editors
.
set
(
revivedUri
.
toString
(),
{
editor
,
onDidReceiveMessage
});
const
data
=
await
provider
.
provider
.
openNotebook
(
revivedUri
);
editor
.
document
.
languages
=
data
.
languages
;
editor
.
document
.
metadata
=
{
...
notebookDocumentMetadataDefaults
,
...
data
.
metadata
return
{
language
:
cell
.
language
,
cellKind
:
cell
.
cellKind
,
metadata
:
cell
.
metadata
,
source
:
cell
.
source
,
outputs
:
transformedOutputs
};
})
};
await
editor
.
edit
(
editBuilder
=>
{
for
(
let
i
=
0
;
i
<
data
.
cells
.
length
;
i
++
)
{
const
cell
=
data
.
cells
[
i
];
editBuilder
.
insert
(
0
,
cell
.
source
,
cell
.
language
,
cell
.
cellKind
,
cell
.
outputs
,
cell
.
metadata
);
}
});
this
.
_onDidOpenNotebookDocument
.
fire
(
editor
.
document
);
return
editor
.
document
.
handle
;
}
else
{
return
Promise
.
resolve
(
undefined
);
return
dto
;
}
return
;
}
async
$resolveNotebook
(
viewType
:
string
,
uri
:
UriComponents
):
Promise
<
number
|
undefined
>
{
let
notebookFromNotebookContentProvider
=
await
this
.
_resolveNotebookFromContentProvider
(
viewType
,
uri
);
private
_transformMimeTypes
(
document
:
ExtHostNotebookDocument
,
displayOrder
:
string
[],
output
:
vscode
.
CellDisplayOutput
):
ITransformedDisplayOutputDto
{
let
mimeTypes
=
Object
.
keys
(
output
.
data
);
let
coreDisplayOrder
=
this
.
outputDisplayOrder
;
const
sorted
=
sortMimeTypes
(
mimeTypes
,
coreDisplayOrder
?.
userOrder
||
[],
displayOrder
,
coreDisplayOrder
?.
defaultOrder
||
[]);
if
(
notebookFromNotebookContentProvider
!==
undefined
)
{
return
notebookFromNotebookContentProvider
;
}
let
orderMimeTypes
:
IOrderedMimeType
[]
=
[];
let
provider
=
this
.
_notebookProviders
.
get
(
viewType
);
sorted
.
forEach
(
mimeType
=>
{
let
handlers
=
this
.
findBestMatchedRenderer
(
mimeType
);
if
(
provider
)
{
if
(
!
this
.
_documents
.
has
(
URI
.
revive
(
uri
).
toString
()))
{
let
document
=
new
ExtHostNotebookDocument
(
this
.
_proxy
,
this
.
_documentsAndEditors
,
viewType
,
URI
.
revive
(
uri
),
this
);
await
this
.
_proxy
.
$createNotebookDocument
(
document
.
handle
,
viewType
,
uri
);
if
(
handlers
.
length
)
{
let
renderedOutput
=
handlers
[
0
].
render
(
document
,
output
,
mimeType
);
this
.
_documents
.
set
(
URI
.
revive
(
uri
).
toString
(),
document
);
}
orderMimeTypes
.
push
({
mimeType
:
mimeType
,
isResolved
:
true
,
rendererId
:
handlers
[
0
].
handle
,
output
:
renderedOutput
});
const
onDidReceiveMessage
=
new
Emitter
<
any
>
();
let
editor
=
new
ExtHostNotebookEditor
(
viewType
,
`
${
ExtHostNotebookController
.
_handlePool
++
}
`
,
URI
.
revive
(
uri
),
this
.
_proxy
,
onDidReceiveMessage
,
this
.
_documents
.
get
(
URI
.
revive
(
uri
).
toString
())
!
,
this
.
_documentsAndEditors
);
this
.
_editors
.
set
(
URI
.
revive
(
uri
).
toString
(),
{
editor
,
onDidReceiveMessage
});
await
provider
.
provider
.
resolveNotebook
(
editor
);
// await editor.document.$updateCells();
return
editor
.
document
.
handle
;
}
for
(
let
i
=
1
;
i
<
handlers
.
length
;
i
++
)
{
orderMimeTypes
.
push
({
mimeType
:
mimeType
,
isResolved
:
false
,
rendererId
:
handlers
[
i
].
handle
});
}
return
Promise
.
resolve
(
undefined
);
if
(
mimeTypeSupportedByCore
(
mimeType
))
{
orderMimeTypes
.
push
({
mimeType
:
mimeType
,
isResolved
:
false
,
rendererId
:
-
1
});
}
}
else
{
orderMimeTypes
.
push
({
mimeType
:
mimeType
,
isResolved
:
false
});
}
});
return
{
outputKind
:
output
.
outputKind
,
data
:
output
.
data
,
orderedMimeTypes
:
orderMimeTypes
,
pickedMimeTypeIndex
:
0
};
}
async
$executeNotebook
(
viewType
:
string
,
uri
:
UriComponents
,
cellHandle
:
number
|
undefined
,
token
:
CancellationToken
):
Promise
<
void
>
{
...
...
@@ -847,15 +828,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
return
this
.
_notebookContentProviders
.
get
(
viewType
)
!
.
provider
.
executeCell
(
document
,
cell
,
token
);
}
let
provider
=
this
.
_notebookProviders
.
get
(
viewType
);
if
(
!
provider
)
{
return
;
}
let
cell
=
cellHandle
!==
undefined
?
document
.
getCell
(
cellHandle
)
:
undefined
;
return
provider
.
provider
.
executeCell
(
document
!
,
cell
,
token
);
}
async
$saveNotebook
(
viewType
:
string
,
uri
:
UriComponents
,
token
:
CancellationToken
):
Promise
<
boolean
>
{
...
...
@@ -874,44 +846,26 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
return
true
;
}
let
provider
=
this
.
_notebookProviders
.
get
(
viewType
);
if
(
provider
&&
document
)
{
return
await
provider
.
provider
.
save
(
document
);
}
return
false
;
}
async
$updateActiveEditor
(
viewType
:
string
,
uri
:
UriComponents
):
Promise
<
void
>
{
this
.
_activeNotebookDocument
=
this
.
_documents
.
get
(
URI
.
revive
(
uri
).
toString
());
this
.
_activeNotebookEditor
=
this
.
_editors
.
get
(
URI
.
revive
(
uri
).
toString
())?.
editor
;
}
async
$destoryNotebookDocument
(
viewType
:
string
,
uri
:
UriComponents
):
Promise
<
boolean
>
{
let
provider
=
this
.
_notebookProviders
.
get
(
viewType
);
if
(
!
provider
)
{
return
false
;
}
async
$saveNotebookAs
(
viewType
:
string
,
uri
:
UriComponents
,
target
:
UriComponents
,
token
:
CancellationToken
):
Promise
<
boolean
>
{
let
document
=
this
.
_documents
.
get
(
URI
.
revive
(
uri
).
toString
());
if
(
document
)
{
document
.
dispose
();
this
.
_documents
.
delete
(
URI
.
revive
(
uri
).
toString
());
this
.
_onDidCloseNotebookDocument
.
fire
(
document
);
if
(
!
document
)
{
return
false
;
}
let
editor
=
this
.
_editors
.
get
(
URI
.
revive
(
uri
).
toString
());
if
(
this
.
_notebookContentProviders
.
has
(
viewType
))
{
try
{
await
this
.
_notebookContentProviders
.
get
(
viewType
)
!
.
provider
.
saveNotebookAs
(
URI
.
revive
(
target
),
document
,
token
);
}
catch
(
e
)
{
return
false
;
}
if
(
editor
)
{
editor
.
editor
.
dispose
();
editor
.
onDidReceiveMessage
.
dispose
();
this
.
_editors
.
delete
(
URI
.
revive
(
uri
).
toString
());
return
true
;
}
return
tru
e
;
return
fals
e
;
}
$acceptDisplayOrder
(
displayOrder
:
INotebookDisplayOrder
):
void
{
...
...
@@ -957,4 +911,60 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
}
}
}
async
$acceptDocumentAndEditorsDelta
(
delta
:
INotebookDocumentsAndEditorsDelta
)
{
if
(
delta
.
removedDocuments
)
{
delta
.
removedDocuments
.
forEach
((
uri
)
=>
{
let
document
=
this
.
_documents
.
get
(
URI
.
revive
(
uri
).
toString
());
if
(
document
)
{
document
.
dispose
();
this
.
_documents
.
delete
(
URI
.
revive
(
uri
).
toString
());
this
.
_onDidCloseNotebookDocument
.
fire
(
document
);
}
let
editor
=
this
.
_editors
.
get
(
URI
.
revive
(
uri
).
toString
());
if
(
editor
)
{
editor
.
editor
.
dispose
();
editor
.
onDidReceiveMessage
.
dispose
();
this
.
_editors
.
delete
(
URI
.
revive
(
uri
).
toString
());
}
});
}
if
(
delta
.
addedDocuments
)
{
delta
.
addedDocuments
.
forEach
(
modelData
=>
{
const
revivedUri
=
URI
.
revive
(
modelData
.
uri
);
const
viewType
=
modelData
.
viewType
;
if
(
!
this
.
_documents
.
has
(
revivedUri
.
toString
()))
{
let
document
=
new
ExtHostNotebookDocument
(
this
.
_proxy
,
this
.
_documentsAndEditors
,
viewType
,
revivedUri
,
this
);
this
.
_documents
.
set
(
revivedUri
.
toString
(),
document
);
}
const
onDidReceiveMessage
=
new
Emitter
<
any
>
();
const
document
=
this
.
_documents
.
get
(
revivedUri
.
toString
())
!
;
let
editor
=
new
ExtHostNotebookEditor
(
viewType
,
`
${
ExtHostNotebookController
.
_handlePool
++
}
`
,
revivedUri
,
this
.
_proxy
,
onDidReceiveMessage
,
document
,
this
.
_documentsAndEditors
);
this
.
_onDidOpenNotebookDocument
.
fire
(
document
);
// TODO, does it already exist?
this
.
_editors
.
set
(
revivedUri
.
toString
(),
{
editor
,
onDidReceiveMessage
});
});
}
if
(
delta
.
newActiveEditor
)
{
this
.
_activeNotebookDocument
=
this
.
_documents
.
get
(
URI
.
revive
(
delta
.
newActiveEditor
).
toString
());
this
.
_activeNotebookEditor
=
this
.
_editors
.
get
(
URI
.
revive
(
delta
.
newActiveEditor
).
toString
())?.
editor
;
}
}
}
src/vs/workbench/contrib/notebook/browser/media/notebook.css
浏览文件 @
a6710757
...
...
@@ -21,6 +21,10 @@
overflow: visible !important;
} */
.monaco-workbench
.part.editor
>
.content
.notebook-editor
.simple-fr-find-part-wrapper.visible
{
z-index
:
100
;
}
.monaco-workbench
.part.editor
>
.content
.notebook-editor
.cell-list-container
.overflowingContentWidgets
>
div
{
z-index
:
600
!important
;
/* @rebornix: larger than the editor title bar */
...
...
src/vs/workbench/contrib/notebook/browser/notebookEditorInput.ts
浏览文件 @
a6710757
...
...
@@ -3,13 +3,14 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
EditorInput
,
IEditorInput
,
GroupIdentifier
,
ISaveOptions
}
from
'
vs/workbench/common/editor
'
;
import
{
EditorInput
,
IEditorInput
,
GroupIdentifier
,
ISaveOptions
,
IMoveResult
,
IRevertOptions
}
from
'
vs/workbench/common/editor
'
;
import
{
INotebookService
}
from
'
vs/workbench/contrib/notebook/common/notebookService
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
isEqual
}
from
'
vs/base/common/resources
'
;
import
{
isEqual
,
basename
}
from
'
vs/base/common/resources
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IFilesConfigurationService
,
AutoSaveMode
}
from
'
vs/workbench/services/filesConfiguration/common/filesConfigurationService
'
;
import
{
NotebookEditorModel
}
from
'
vs/workbench/contrib/notebook/common/notebookEditorModel
'
;
import
{
IFileDialogService
}
from
'
vs/platform/dialogs/common/dialogs
'
;
export
class
NotebookEditorInput
extends
EditorInput
{
...
...
@@ -39,7 +40,10 @@ export class NotebookEditorInput extends EditorInput {
public
name
:
string
,
public
readonly
viewType
:
string
|
undefined
,
@
INotebookService
private
readonly
notebookService
:
INotebookService
,
@
IFilesConfigurationService
private
readonly
filesConfigurationService
:
IFilesConfigurationService
@
IFilesConfigurationService
private
readonly
filesConfigurationService
:
IFilesConfigurationService
,
@
IFileDialogService
private
readonly
fileDialogService
:
IFileDialogService
,
// @IEditorService private readonly editorService: IEditorService,
@
IInstantiationService
private
readonly
instantiationService
:
IInstantiationService
)
{
super
();
}
...
...
@@ -85,6 +89,48 @@ export class NotebookEditorInput extends EditorInput {
return
undefined
;
}
async
saveAs
(
group
:
GroupIdentifier
,
options
?:
ISaveOptions
):
Promise
<
IEditorInput
|
undefined
>
{
if
(
!
this
.
textModel
)
{
return
undefined
;
}
const
dialogPath
=
this
.
textModel
.
resource
;
const
target
=
await
this
.
fileDialogService
.
pickFileToSave
(
dialogPath
,
options
?.
availableFileSystems
);
if
(
!
target
)
{
return
undefined
;
// save cancelled
}
if
(
!
await
this
.
textModel
.
saveAs
(
target
))
{
return
undefined
;
}
return
this
.
_move
(
group
,
target
)?.
editor
;
}
move
(
group
:
GroupIdentifier
,
target
:
URI
):
IMoveResult
|
undefined
{
if
(
this
.
textModel
)
{
const
contributedNotebookProviders
=
this
.
notebookService
.
getContributedNotebookProviders
(
target
);
if
(
contributedNotebookProviders
.
find
(
provider
=>
provider
.
id
===
this
.
textModel
!
.
viewType
))
{
return
this
.
_move
(
group
,
target
);
}
}
return
undefined
;
}
_move
(
group
:
GroupIdentifier
,
newResource
:
URI
):
{
editor
:
IEditorInput
}
|
undefined
{
const
editorInput
=
NotebookEditorInput
.
getOrCreate
(
this
.
instantiationService
,
newResource
,
basename
(
newResource
),
this
.
viewType
);
return
{
editor
:
editorInput
};
}
async
revert
(
group
:
GroupIdentifier
,
options
?:
IRevertOptions
):
Promise
<
void
>
{
if
(
this
.
textModel
)
{
await
this
.
textModel
.
revert
(
options
);
}
return
;
}
async
resolve
():
Promise
<
NotebookEditorModel
>
{
if
(
!
await
this
.
notebookService
.
canResolve
(
this
.
viewType
!
))
{
throw
new
Error
(
`Cannot open notebook of type '
${
this
.
viewType
}
'`
);
...
...
@@ -96,6 +142,10 @@ export class NotebookEditorInput extends EditorInput {
this
.
_onDidChangeDirty
.
fire
();
}));
if
(
this
.
textModel
.
isDirty
())
{
this
.
_onDidChangeDirty
.
fire
();
}
return
this
.
textModel
;
}
...
...
src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts
浏览文件 @
a6710757
...
...
@@ -11,7 +11,7 @@ import { notebookProviderExtensionPoint, notebookRendererExtensionPoint } from '
import
{
NotebookProviderInfo
}
from
'
vs/workbench/contrib/notebook/common/notebookProvider
'
;
import
{
NotebookExtensionDescription
}
from
'
vs/workbench/api/common/extHost.protocol
'
;
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
INotebookTextModel
,
INotebookMimeTypeSelector
,
INotebookRendererInfo
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
INotebookTextModel
,
INotebookMimeTypeSelector
,
INotebookRendererInfo
,
NotebookDocumentMetadata
,
CellEditType
,
ICellDto2
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
IExtensionService
}
from
'
vs/workbench/services/extensions/common/extensions
'
;
import
{
NotebookOutputRendererInfo
}
from
'
vs/workbench/contrib/notebook/common/notebookOutputRenderer
'
;
import
{
Iterable
}
from
'
vs/base/common/iterator
'
;
...
...
@@ -202,13 +202,13 @@ export class NotebookService extends Disposable implements INotebookService, ICu
return
;
}
async
resolveNotebook
(
viewType
:
string
,
uri
:
URI
):
Promise
<
NotebookTextModel
|
undefined
>
{
async
createNotebookFromBackup
(
viewType
:
string
,
uri
:
URI
,
metadata
:
NotebookDocumentMetadata
,
languages
:
string
[],
cells
:
ICellDto2
[]
):
Promise
<
NotebookTextModel
|
undefined
>
{
const
provider
=
this
.
_notebookProviders
.
get
(
viewType
);
if
(
!
provider
)
{
return
undefined
;
}
const
notebookModel
=
await
provider
.
controller
.
resolveNotebook
(
viewType
,
uri
);
const
notebookModel
=
await
provider
.
controller
.
createNotebook
(
viewType
,
uri
,
true
,
false
);
if
(
!
notebookModel
)
{
return
undefined
;
}
...
...
@@ -219,6 +219,39 @@ export class NotebookService extends Disposable implements INotebookService, ICu
notebookModel
,
(
model
)
=>
this
.
_onWillDispose
(
model
),
);
this
.
_models
[
modelId
]
=
modelData
;
notebookModel
.
metadata
=
metadata
;
notebookModel
.
languages
=
languages
;
notebookModel
.
applyEdit
(
notebookModel
.
versionId
,
[
{
editType
:
CellEditType
.
Insert
,
index
:
0
,
cells
:
cells
}
]);
return
modelData
.
model
;
}
async
resolveNotebook
(
viewType
:
string
,
uri
:
URI
,
forceReload
:
boolean
):
Promise
<
NotebookTextModel
|
undefined
>
{
const
provider
=
this
.
_notebookProviders
.
get
(
viewType
);
if
(
!
provider
)
{
return
undefined
;
}
let
notebookModel
:
NotebookTextModel
|
undefined
;
notebookModel
=
await
provider
.
controller
.
createNotebook
(
viewType
,
uri
,
false
,
forceReload
);
// new notebook model created
const
modelId
=
MODEL_ID
(
uri
);
const
modelData
=
new
ModelData
(
notebookModel
!
,
(
model
)
=>
this
.
_onWillDispose
(
model
),
);
this
.
_models
[
modelId
]
=
modelData
;
return
modelData
.
model
;
}
...
...
@@ -265,7 +298,7 @@ export class NotebookService extends Disposable implements INotebookService, ICu
let
provider
=
this
.
_notebookProviders
.
get
(
viewType
);
if
(
provider
)
{
provider
.
controller
.
destory
NotebookDocument
(
notebook
);
provider
.
controller
.
remove
NotebookDocument
(
notebook
);
}
}
...
...
@@ -291,6 +324,16 @@ export class NotebookService extends Disposable implements INotebookService, ICu
return
false
;
}
async
saveAs
(
viewType
:
string
,
resource
:
URI
,
target
:
URI
,
token
:
CancellationToken
):
Promise
<
boolean
>
{
let
provider
=
this
.
_notebookProviders
.
get
(
viewType
);
if
(
provider
)
{
return
provider
.
controller
.
saveAs
(
resource
,
target
,
token
);
}
return
false
;
}
onDidReceiveMessage
(
viewType
:
string
,
uri
:
URI
,
message
:
any
):
void
{
let
provider
=
this
.
_notebookProviders
.
get
(
viewType
);
...
...
src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts
浏览文件 @
a6710757
...
...
@@ -157,7 +157,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
for
(
let
i
=
diff
.
start
;
i
<
diff
.
start
+
diff
.
deleteCount
;
i
++
)
{
const
cell
=
this
.
element
(
i
);
if
(
this
.
_viewModel
!
.
hasCell
(
cell
))
{
if
(
this
.
_viewModel
!
.
hasCell
(
cell
.
handle
))
{
hideOutputs
.
push
(...
cell
?.
model
.
outputs
);
}
else
{
deletedOutputs
.
push
(...
cell
?.
model
.
outputs
);
...
...
@@ -177,7 +177,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
for
(
let
i
=
diff
.
start
;
i
<
diff
.
start
+
diff
.
deleteCount
;
i
++
)
{
const
cell
=
this
.
element
(
i
);
if
(
this
.
_viewModel
!
.
hasCell
(
cell
))
{
if
(
this
.
_viewModel
!
.
hasCell
(
cell
.
handle
))
{
hideOutputs
.
push
(...
cell
?.
model
.
outputs
);
}
else
{
deletedOutputs
.
push
(...
cell
?.
model
.
outputs
);
...
...
@@ -299,7 +299,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
for
(
let
i
=
diff
.
start
;
i
<
diff
.
start
+
diff
.
deleteCount
;
i
++
)
{
const
cell
=
this
.
element
(
i
);
if
(
this
.
_viewModel
!
.
hasCell
(
cell
))
{
if
(
this
.
_viewModel
!
.
hasCell
(
cell
.
handle
))
{
hideOutputs
.
push
(...
cell
?.
model
.
outputs
);
}
else
{
deletedOutputs
.
push
(...
cell
?.
model
.
outputs
);
...
...
@@ -316,6 +316,18 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
splice2
(
start
:
number
,
deleteCount
:
number
,
elements
:
CellViewModel
[]
=
[]):
void
{
// we need to convert start and delete count based on hidden ranges
super
.
splice
(
start
,
deleteCount
,
elements
);
const
selectionsLeft
=
[];
this
.
_viewModel
!
.
selectionHandles
.
forEach
(
handle
=>
{
if
(
this
.
_viewModel
!
.
hasCell
(
handle
))
{
selectionsLeft
.
push
(
handle
);
}
});
if
(
!
selectionsLeft
.
length
&&
this
.
_viewModel
!
.
viewCells
)
{
// after splice, the selected cells are deleted
this
.
_viewModel
!
.
selectionHandles
=
[
this
.
_viewModel
!
.
viewCells
[
0
].
handle
];
}
}
getViewIndex
(
cell
:
ICellViewModel
)
{
...
...
src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts
浏览文件 @
a6710757
...
...
@@ -268,7 +268,12 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
});
diffs
.
reverse
().
forEach
(
diff
=>
{
this
.
_viewCells
.
splice
(
diff
[
0
],
diff
[
1
],
...
diff
[
2
]);
const
deletedCells
=
this
.
_viewCells
.
splice
(
diff
[
0
],
diff
[
1
],
...
diff
[
2
]);
deletedCells
.
forEach
(
cell
=>
{
this
.
_handleToViewCellMapping
.
delete
(
cell
.
handle
);
});
diff
[
2
].
forEach
(
cell
=>
{
this
.
_handleToViewCellMapping
.
set
(
cell
.
handle
,
cell
);
this
.
_localStore
.
add
(
cell
);
...
...
@@ -456,8 +461,8 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
return
index
+
1
;
}
hasCell
(
cell
:
ICellViewModel
)
{
return
this
.
_handleToViewCellMapping
.
has
(
cell
.
handle
);
hasCell
(
handle
:
number
)
{
return
this
.
_handleToViewCellMapping
.
has
(
handle
);
}
getVersionId
()
{
...
...
@@ -586,7 +591,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
this
.
_viewCells
.
splice
(
deleteIndex
,
1
);
this
.
_handleToViewCellMapping
.
delete
(
deleteCell
.
handle
);
this
.
_notebook
.
removeCell
(
deleteIndex
);
this
.
_notebook
.
removeCell
(
deleteIndex
,
1
);
this
.
_onDidChangeViewCells
.
fire
({
synchronous
:
true
,
splices
:
[[
deleteIndex
,
1
,
[]]]
});
}
...
...
@@ -638,7 +643,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
this
.
_viewCells
.
splice
(
index
,
1
);
this
.
_handleToViewCellMapping
.
delete
(
viewCell
.
handle
);
this
.
_notebook
.
removeCell
(
index
);
this
.
_notebook
.
removeCell
(
index
,
1
);
let
endSelections
:
number
[]
=
[];
if
(
this
.
selectionHandles
.
length
)
{
...
...
src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts
浏览文件 @
a6710757
...
...
@@ -7,7 +7,8 @@ import { Emitter, Event } from 'vs/base/common/event';
import
{
Disposable
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
NotebookCellTextModel
}
from
'
vs/workbench/contrib/notebook/common/model/notebookCellTextModel
'
;
import
{
INotebookTextModel
,
NotebookCellOutputsSplice
,
NotebookCellTextModelSplice
,
NotebookDocumentMetadata
,
NotebookCellMetadata
,
ICellEditOperation
,
CellEditType
,
CellUri
,
ICellInsertEdit
,
NotebookCellsChangedEvent
,
CellKind
,
IOutput
,
notebookDocumentMetadataDefaults
,
diff
,
ICellDeleteEdit
,
NotebookCellsChangeType
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
INotebookTextModel
,
NotebookCellOutputsSplice
,
NotebookCellTextModelSplice
,
NotebookDocumentMetadata
,
NotebookCellMetadata
,
ICellEditOperation
,
CellEditType
,
CellUri
,
ICellInsertEdit
,
NotebookCellsChangedEvent
,
CellKind
,
IOutput
,
notebookDocumentMetadataDefaults
,
diff
,
ICellDeleteEdit
,
NotebookCellsChangeType
,
ICellDto2
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
ITextSnapshot
}
from
'
vs/editor/common/model
'
;
function
compareRangesUsingEnds
(
a
:
[
number
,
number
],
b
:
[
number
,
number
]):
number
{
if
(
a
[
1
]
===
b
[
1
])
{
...
...
@@ -17,6 +18,49 @@ function compareRangesUsingEnds(a: [number, number], b: [number, number]): numbe
return
a
[
1
]
-
b
[
1
];
}
export
class
NotebookTextModelSnapshot
implements
ITextSnapshot
{
// private readonly _pieces: Ce[] = [];
private
_index
:
number
=
-
1
;
constructor
(
private
_model
:
NotebookTextModel
)
{
// for (let i = 0; i < this._model.cells.length; i++) {
// const cell = this._model.cells[i];
// this._pieces.push(this._model.cells[i].textBuffer.createSnapshot(true));
// }
}
read
():
string
|
null
{
if
(
this
.
_index
===
-
1
)
{
this
.
_index
++
;
return
`{ "metadata":
${
JSON
.
stringify
(
this
.
_model
.
metadata
)}
, "languages":
${
JSON
.
stringify
(
this
.
_model
.
languages
)}
, "cells": [`
;
}
if
(
this
.
_index
<
this
.
_model
.
cells
.
length
)
{
const
cell
=
this
.
_model
.
cells
[
this
.
_index
];
const
data
=
{
source
:
cell
.
getValue
(),
metadata
:
cell
.
metadata
,
cellKind
:
cell
.
cellKind
,
language
:
cell
.
language
};
const
rawStr
=
JSON
.
stringify
(
data
);
const
isLastCell
=
this
.
_index
===
this
.
_model
.
cells
.
length
-
1
;
this
.
_index
++
;
return
isLastCell
?
rawStr
:
(
rawStr
+
'
,
'
);
}
else
if
(
this
.
_index
===
this
.
_model
.
cells
.
length
)
{
this
.
_index
++
;
return
`]}`
;
}
else
{
return
null
;
}
}
}
export
class
NotebookTextModel
extends
Disposable
implements
INotebookTextModel
{
private
static
_cellhandlePool
:
number
=
0
;
...
...
@@ -77,6 +121,18 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
return
new
NotebookCellTextModel
(
cellUri
,
cellHandle
,
source
,
language
,
cellKind
,
outputs
||
[],
metadata
);
}
initialize
(
cells
:
ICellDto2
[])
{
this
.
cells
=
[];
this
.
_versionId
=
0
;
const
mainCells
=
cells
.
map
(
cell
=>
{
const
cellHandle
=
NotebookTextModel
.
_cellhandlePool
++
;
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
);
}
applyEdit
(
modelVersionId
:
number
,
rawEdits
:
ICellEditOperation
[]):
boolean
{
if
(
modelVersionId
!==
this
.
_versionId
)
{
return
false
;
...
...
@@ -127,7 +183,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
this
.
insertNewCell
(
insertEdit
.
index
,
mainCells
);
break
;
case
CellEditType
.
Delete
:
this
.
removeCell
(
operations
[
i
].
index
);
this
.
removeCell
(
operations
[
i
].
index
,
operations
[
i
].
end
-
operations
[
i
].
start
);
break
;
}
}
...
...
@@ -142,6 +198,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
return
true
;
}
createSnapshot
(
preserveBOM
?:
boolean
):
ITextSnapshot
{
return
new
NotebookTextModelSnapshot
(
this
);
}
private
_increaseVersionId
():
void
{
this
.
_versionId
=
this
.
_versionId
+
1
;
}
...
...
@@ -250,17 +310,19 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
return
;
}
removeCell
(
index
:
number
)
{
removeCell
(
index
:
number
,
count
:
number
)
{
this
.
_isUntitled
=
false
;
let
cell
=
this
.
cells
[
index
];
this
.
_cellListeners
.
get
(
cell
.
handle
)?.
dispose
();
this
.
_cellListeners
.
delete
(
cell
.
handle
);
this
.
cells
.
splice
(
index
,
1
);
for
(
let
i
=
index
;
i
<
index
+
count
;
i
++
)
{
let
cell
=
this
.
cells
[
i
];
this
.
_cellListeners
.
get
(
cell
.
handle
)?.
dispose
();
this
.
_cellListeners
.
delete
(
cell
.
handle
);
}
this
.
cells
.
splice
(
index
,
count
);
this
.
_onDidChangeContent
.
fire
();
this
.
_increaseVersionId
();
this
.
_onDidModelChangeProxy
.
fire
({
kind
:
NotebookCellsChangeType
.
ModelChange
,
versionId
:
this
.
_versionId
,
changes
:
[[
index
,
1
,
[]]]
});
this
.
_onDidModelChangeProxy
.
fire
({
kind
:
NotebookCellsChangeType
.
ModelChange
,
versionId
:
this
.
_versionId
,
changes
:
[[
index
,
count
,
[]]]
});
}
moveCellToIdx
(
index
:
number
,
newIdx
:
number
)
{
...
...
src/vs/workbench/contrib/notebook/common/notebookCommon.ts
浏览文件 @
a6710757
...
...
@@ -273,7 +273,7 @@ export enum CellEditType {
}
export
interface
ICellDto2
{
source
:
string
[];
source
:
string
|
string
[];
language
:
string
;
cellKind
:
CellKind
;
outputs
:
IOutput
[];
...
...
@@ -300,6 +300,13 @@ export interface INotebookEditData {
renderers
:
number
[];
}
export
interface
NotebookDataDto
{
readonly
cells
:
ICellDto2
[];
readonly
languages
:
string
[];
readonly
metadata
:
NotebookDocumentMetadata
;
}
export
namespace
CellUri
{
export
const
scheme
=
'
vscode-notebook
'
;
...
...
src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts
浏览文件 @
a6710757
...
...
@@ -15,6 +15,8 @@ import { URI } from 'vs/base/common/uri';
import
{
IWorkingCopyService
,
IWorkingCopy
,
IWorkingCopyBackup
}
from
'
vs/workbench/services/workingCopy/common/workingCopyService
'
;
import
{
basename
}
from
'
vs/base/common/resources
'
;
import
{
CancellationTokenSource
}
from
'
vs/base/common/cancellation
'
;
import
{
IBackupFileService
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
DefaultEndOfLine
,
ITextBuffer
,
EndOfLinePreference
}
from
'
vs/editor/common/model
'
;
export
interface
INotebookEditorModelManager
{
models
:
NotebookEditorModel
[];
...
...
@@ -24,6 +26,13 @@ export interface INotebookEditorModelManager {
get
(
resource
:
URI
):
NotebookEditorModel
|
undefined
;
}
export
interface
INotebookRevertOptions
{
/**
* Go to disk bypassing any cache of the model if any.
*/
forceReadFromDisk
?:
boolean
;
}
export
class
NotebookEditorModel
extends
EditorModel
implements
IWorkingCopy
,
INotebookEditorModel
{
private
_dirty
=
false
;
...
...
@@ -47,7 +56,8 @@ export class NotebookEditorModel extends EditorModel implements IWorkingCopy, IN
public
readonly
resource
:
URI
,
public
readonly
viewType
:
string
,
@
INotebookService
private
readonly
notebookService
:
INotebookService
,
@
IWorkingCopyService
private
readonly
workingCopyService
:
IWorkingCopyService
@
IWorkingCopyService
private
readonly
workingCopyService
:
IWorkingCopyService
,
@
IBackupFileService
private
readonly
backupFileService
:
IBackupFileService
)
{
super
();
this
.
_register
(
this
.
workingCopyService
.
registerWorkingCopy
(
this
));
...
...
@@ -56,28 +66,91 @@ export class NotebookEditorModel extends EditorModel implements IWorkingCopy, IN
capabilities
=
0
;
async
backup
():
Promise
<
IWorkingCopyBackup
>
{
return
{};
return
{
content
:
this
.
_notebook
.
createSnapshot
(
true
)
};
}
async
revert
(
options
?:
IRevertOptions
|
undefined
):
Promise
<
void
>
{
if
(
options
?.
soft
)
{
await
this
.
backupFileService
.
discardBackup
(
this
.
resource
);
return
;
}
await
this
.
load
({
forceReadFromDisk
:
true
});
this
.
_dirty
=
false
;
this
.
_onDidChangeDirty
.
fire
();
return
;
}
async
load
():
Promise
<
NotebookEditorModel
>
{
const
notebook
=
await
this
.
notebookService
.
resolveNotebook
(
this
.
viewType
!
,
this
.
resource
);
async
load
(
options
?:
INotebookRevertOptions
):
Promise
<
NotebookEditorModel
>
{
if
(
options
?.
forceReadFromDisk
)
{
return
this
.
loadFromProvider
(
true
);
}
if
(
this
.
isResolved
())
{
return
this
;
}
const
backup
=
await
this
.
backupFileService
.
resolve
(
this
.
resource
);
if
(
this
.
isResolved
())
{
return
this
;
// Make sure meanwhile someone else did not succeed in loading
}
if
(
backup
)
{
try
{
return
await
this
.
loadFromBackup
(
backup
.
value
.
create
(
DefaultEndOfLine
.
LF
));
}
catch
(
error
)
{
// this.logService.error('[text file model] load() from backup', error); // ignore error and continue to load as file below
}
}
return
this
.
loadFromProvider
(
false
);
}
private
async
loadFromBackup
(
content
:
ITextBuffer
):
Promise
<
NotebookEditorModel
>
{
const
fullRange
=
content
.
getRangeAt
(
0
,
content
.
getLength
());
const
data
=
JSON
.
parse
(
content
.
getValueInRange
(
fullRange
,
EndOfLinePreference
.
LF
));
const
notebook
=
await
this
.
notebookService
.
createNotebookFromBackup
(
this
.
viewType
!
,
this
.
resource
,
data
.
metadata
,
data
.
languages
,
data
.
cells
);
this
.
_notebook
=
notebook
!
;
this
.
_name
=
basename
(
this
.
_notebook
!
.
uri
);
this
.
_register
(
this
.
_notebook
.
onDidChangeContent
(()
=>
{
this
.
_dirty
=
true
;
this
.
_onDidChangeDirty
.
fire
();
this
.
setDirty
(
true
);
this
.
_onDidChangeContent
.
fire
();
}));
await
this
.
backupFileService
.
discardBackup
(
this
.
resource
);
this
.
setDirty
(
true
);
return
this
;
}
private
async
loadFromProvider
(
forceReloadFromDisk
:
boolean
)
{
const
notebook
=
await
this
.
notebookService
.
resolveNotebook
(
this
.
viewType
!
,
this
.
resource
,
forceReloadFromDisk
);
this
.
_notebook
=
notebook
!
;
this
.
_name
=
basename
(
this
.
_notebook
!
.
uri
);
this
.
_register
(
this
.
_notebook
.
onDidChangeContent
(()
=>
{
this
.
setDirty
(
true
);
this
.
_onDidChangeContent
.
fire
();
}));
return
this
;
}
isResolved
():
boolean
{
return
!!
this
.
_notebook
;
}
setDirty
(
newState
:
boolean
)
{
if
(
this
.
_dirty
!==
newState
)
{
this
.
_dirty
=
newState
;
this
.
_onDidChangeDirty
.
fire
();
}
}
isDirty
()
{
return
this
.
_dirty
;
}
...
...
@@ -89,6 +162,14 @@ export class NotebookEditorModel extends EditorModel implements IWorkingCopy, IN
this
.
_onDidChangeDirty
.
fire
();
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
();
return
true
;
}
}
export
class
NotebookEditorModelManager
extends
Disposable
implements
INotebookEditorModelManager
{
...
...
src/vs/workbench/contrib/notebook/common/notebookService.ts
浏览文件 @
a6710757
...
...
@@ -8,7 +8,7 @@ import { URI } from 'vs/base/common/uri';
import
{
NotebookProviderInfo
}
from
'
vs/workbench/contrib/notebook/common/notebookProvider
'
;
import
{
NotebookExtensionDescription
}
from
'
vs/workbench/api/common/extHost.protocol
'
;
import
{
Event
}
from
'
vs/base/common/event
'
;
import
{
INotebookTextModel
,
INotebookMimeTypeSelector
,
INotebookRendererInfo
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
INotebookTextModel
,
INotebookMimeTypeSelector
,
INotebookRendererInfo
,
NotebookDocumentMetadata
,
ICellDto2
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
NotebookTextModel
}
from
'
vs/workbench/contrib/notebook/common/model/notebookTextModel
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
NotebookCellTextModel
}
from
'
vs/workbench/contrib/notebook/common/model/notebookCellTextModel
'
;
...
...
@@ -17,12 +17,13 @@ import { INotebookEditorModelManager } from 'vs/workbench/contrib/notebook/commo
export
const
INotebookService
=
createDecorator
<
INotebookService
>
(
'
notebookService
'
);
export
interface
IMainNotebookController
{
resolveNotebook
(
viewType
:
string
,
uri
:
URI
):
Promise
<
NotebookTextModel
|
undefined
>
;
createNotebook
(
viewType
:
string
,
uri
:
URI
,
forBackup
:
boolean
,
forceReload
:
boolean
):
Promise
<
NotebookTextModel
|
undefined
>
;
executeNotebook
(
viewType
:
string
,
uri
:
URI
,
token
:
CancellationToken
):
Promise
<
void
>
;
onDidReceiveMessage
(
uri
:
URI
,
message
:
any
):
void
;
executeNotebookCell
(
uri
:
URI
,
handle
:
number
,
token
:
CancellationToken
):
Promise
<
void
>
;
destory
NotebookDocument
(
notebook
:
INotebookTextModel
):
Promise
<
void
>
;
remove
NotebookDocument
(
notebook
:
INotebookTextModel
):
Promise
<
void
>
;
save
(
uri
:
URI
,
token
:
CancellationToken
):
Promise
<
boolean
>
;
saveAs
(
uri
:
URI
,
target
:
URI
,
token
:
CancellationToken
):
Promise
<
boolean
>
;
}
export
interface
INotebookService
{
...
...
@@ -35,7 +36,8 @@ export interface INotebookService {
registerNotebookRenderer
(
handle
:
number
,
extensionData
:
NotebookExtensionDescription
,
type
:
string
,
selectors
:
INotebookMimeTypeSelector
,
preloads
:
URI
[]):
void
;
unregisterNotebookRenderer
(
handle
:
number
):
void
;
getRendererInfo
(
handle
:
number
):
INotebookRendererInfo
|
undefined
;
resolveNotebook
(
viewType
:
string
,
uri
:
URI
):
Promise
<
NotebookTextModel
|
undefined
>
;
resolveNotebook
(
viewType
:
string
,
uri
:
URI
,
forceReload
:
boolean
):
Promise
<
NotebookTextModel
|
undefined
>
;
createNotebookFromBackup
(
viewType
:
string
,
uri
:
URI
,
metadata
:
NotebookDocumentMetadata
,
languages
:
string
[],
cells
:
ICellDto2
[]):
Promise
<
NotebookTextModel
|
undefined
>
;
executeNotebook
(
viewType
:
string
,
uri
:
URI
):
Promise
<
void
>
;
executeNotebookCell
(
viewType
:
string
,
uri
:
URI
,
handle
:
number
,
token
:
CancellationToken
):
Promise
<
void
>
;
...
...
@@ -45,6 +47,7 @@ export interface INotebookService {
destoryNotebookDocument
(
viewType
:
string
,
notebook
:
INotebookTextModel
):
void
;
updateActiveNotebookDocument
(
viewType
:
string
,
resource
:
URI
):
void
;
save
(
viewType
:
string
,
resource
:
URI
,
token
:
CancellationToken
):
Promise
<
boolean
>
;
saveAs
(
viewType
:
string
,
resource
:
URI
,
target
:
URI
,
token
:
CancellationToken
):
Promise
<
boolean
>
;
onDidReceiveMessage
(
viewType
:
string
,
uri
:
URI
,
message
:
any
):
void
;
setToCopy
(
items
:
NotebookCellTextModel
[]):
void
;
getToCopy
():
NotebookCellTextModel
[]
|
undefined
;
...
...
src/vs/workbench/test/browser/api/extHostNotebookConcatDocument.test.ts
浏览文件 @
a6710757
...
...
@@ -41,15 +41,20 @@ suite('NotebookConcatDocument', function () {
rpcProtocol
.
set
(
MainContext
.
MainThreadNotebook
,
new
class
extends
mock
<
MainThreadNotebookShape
>
()
{
async
$registerNotebookProvider
()
{
}
async
$unregisterNotebookProvider
()
{
}
async
$createNotebookDocument
()
{
}
});
extHostDocumentsAndEditors
=
new
ExtHostDocumentsAndEditors
(
rpcProtocol
,
new
NullLogService
());
extHostDocuments
=
new
ExtHostDocuments
(
rpcProtocol
,
extHostDocumentsAndEditors
);
extHostNotebooks
=
new
ExtHostNotebookController
(
rpcProtocol
,
new
ExtHostCommands
(
rpcProtocol
,
new
NullLogService
()),
extHostDocumentsAndEditors
);
let
reg
=
extHostNotebooks
.
registerNotebookProvider
(
nullExtensionDescription
,
'
test
'
,
new
class
extends
mock
<
vscode
.
NotebookProvider
>
()
{
async
resolveNotebook
()
{
}
let
reg
=
extHostNotebooks
.
registerNotebookContentProvider
(
nullExtensionDescription
,
'
test
'
,
new
class
extends
mock
<
vscode
.
NotebookContentProvider
>
()
{
// async openNotebook() { }
});
await
extHostNotebooks
.
$acceptDocumentAndEditorsDelta
({
addedDocuments
:
[{
handle
:
0
,
uri
:
notebookUri
,
viewType
:
'
test
'
}]
});
await
extHostNotebooks
.
$resolveNotebook
(
'
test
'
,
notebookUri
);
extHostNotebooks
.
$acceptModelChanged
(
notebookUri
,
{
kind
:
NotebookCellsChangeType
.
ModelChange
,
versionId
:
0
,
...
...
@@ -62,7 +67,7 @@ suite('NotebookConcatDocument', function () {
outputs
:
[],
}]]]
});
await
extHostNotebooks
.
$
updateActiveEditor
(
'
test
'
,
notebookUri
);
await
extHostNotebooks
.
$
acceptDocumentAndEditorsDelta
({
newActiveEditor
:
notebookUri
}
);
notebook
=
extHostNotebooks
.
activeNotebookDocument
!
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录