Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
8237428f
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,发现更多精彩内容 >>
未验证
提交
8237428f
编写于
7月 02, 2019
作者:
D
Daniel Imms
提交者:
GitHub
7月 02, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #76481 from microsoft/tyriar/virtual_process
Implement terminal virtual processes
上级
306be61f
fa74f76e
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
713 addition
and
278 deletion
+713
-278
extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts
.../vscode-api-tests/src/singlefolder-tests/terminal.test.ts
+298
-0
extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts
...ns/vscode-api-tests/src/singlefolder-tests/window.test.ts
+1
-198
src/vs/vscode.proposed.d.ts
src/vs/vscode.proposed.d.ts
+139
-2
src/vs/workbench/api/browser/mainThreadTerminalService.ts
src/vs/workbench/api/browser/mainThreadTerminalService.ts
+42
-20
src/vs/workbench/api/common/extHost.protocol.ts
src/vs/workbench/api/common/extHost.protocol.ts
+14
-1
src/vs/workbench/api/node/extHost.api.impl.ts
src/vs/workbench/api/node/extHost.api.impl.ts
+7
-3
src/vs/workbench/api/node/extHostTerminalService.ts
src/vs/workbench/api/node/extHostTerminalService.ts
+123
-14
src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
...vs/workbench/contrib/terminal/browser/terminalInstance.ts
+9
-5
src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts
...kbench/contrib/terminal/browser/terminalProcessManager.ts
+41
-25
src/vs/workbench/contrib/terminal/common/terminal.ts
src/vs/workbench/contrib/terminal/common/terminal.ts
+11
-2
src/vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy.ts
...ch/contrib/terminal/common/terminalProcessExtHostProxy.ts
+21
-8
src/vs/workbench/contrib/terminal/common/terminalService.ts
src/vs/workbench/contrib/terminal/common/terminalService.ts
+7
-0
未找到文件。
extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts
0 → 100644
浏览文件 @
8237428f
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
window
,
commands
,
Terminal
,
TerminalDimensionsChangeEvent
,
TerminalVirtualProcess
,
EventEmitter
,
TerminalDimensions
}
from
'
vscode
'
;
import
{
doesNotThrow
,
equal
,
ok
}
from
'
assert
'
;
suite
(
'
window namespace tests
'
,
()
=>
{
(
process
.
platform
===
'
win32
'
?
suite
.
skip
/* https://github.com/microsoft/vscode/issues/75689 */
:
suite
)(
'
Terminal
'
,
()
=>
{
test
(
'
sendText immediately after createTerminal should not throw
'
,
()
=>
{
const
terminal
=
window
.
createTerminal
();
doesNotThrow
(
terminal
.
sendText
.
bind
(
terminal
,
'
echo "foo"
'
));
terminal
.
dispose
();
});
test
(
'
onDidCloseTerminal event fires when terminal is disposed
'
,
(
done
)
=>
{
const
terminal
=
window
.
createTerminal
();
const
reg
=
window
.
onDidCloseTerminal
((
eventTerminal
)
=>
{
equal
(
terminal
,
eventTerminal
);
reg
.
dispose
();
done
();
});
terminal
.
dispose
();
});
test
(
'
processId immediately after createTerminal should fetch the pid
'
,
(
done
)
=>
{
const
terminal
=
window
.
createTerminal
();
terminal
.
processId
.
then
(
id
=>
{
ok
(
id
>
0
);
terminal
.
dispose
();
done
();
});
});
test
(
'
name in constructor should set terminal.name
'
,
()
=>
{
const
terminal
=
window
.
createTerminal
(
'
a
'
);
equal
(
terminal
.
name
,
'
a
'
);
terminal
.
dispose
();
});
test
(
'
onDidOpenTerminal should fire when a terminal is created
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
term
=>
{
equal
(
term
.
name
,
'
b
'
);
reg1
.
dispose
();
const
reg2
=
window
.
onDidCloseTerminal
(()
=>
{
reg2
.
dispose
();
done
();
});
terminal
.
dispose
();
});
const
terminal
=
window
.
createTerminal
(
'
b
'
);
});
test
(
'
Terminal.sendText should fire Terminal.onInput
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
terminal
=>
{
reg1
.
dispose
();
const
reg2
=
renderer
.
onDidAcceptInput
(
data
=>
{
equal
(
data
,
'
bar
'
);
reg2
.
dispose
();
const
reg3
=
window
.
onDidCloseTerminal
(()
=>
{
reg3
.
dispose
();
done
();
});
terminal
.
dispose
();
});
terminal
.
sendText
(
'
bar
'
,
false
);
});
const
renderer
=
window
.
createTerminalRenderer
(
'
foo
'
);
});
test
(
'
onDidChangeActiveTerminal should fire when new terminals are created
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidChangeActiveTerminal
((
active
:
Terminal
|
undefined
)
=>
{
equal
(
active
,
terminal
);
equal
(
active
,
window
.
activeTerminal
);
reg1
.
dispose
();
const
reg2
=
window
.
onDidChangeActiveTerminal
((
active
:
Terminal
|
undefined
)
=>
{
equal
(
active
,
undefined
);
equal
(
active
,
window
.
activeTerminal
);
reg2
.
dispose
();
done
();
});
terminal
.
dispose
();
});
const
terminal
=
window
.
createTerminal
();
terminal
.
show
();
});
test
(
'
onDidChangeTerminalDimensions should fire when new terminals are created
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidChangeTerminalDimensions
(
async
(
event
:
TerminalDimensionsChangeEvent
)
=>
{
equal
(
event
.
terminal
,
terminal1
);
equal
(
typeof
event
.
dimensions
.
columns
,
'
number
'
);
equal
(
typeof
event
.
dimensions
.
rows
,
'
number
'
);
ok
(
event
.
dimensions
.
columns
>
0
);
ok
(
event
.
dimensions
.
rows
>
0
);
reg1
.
dispose
();
let
terminal2
:
Terminal
;
const
reg2
=
window
.
onDidOpenTerminal
((
newTerminal
)
=>
{
// This is guarantees to fire before dimensions change event
if
(
newTerminal
!==
terminal1
)
{
terminal2
=
newTerminal
;
reg2
.
dispose
();
}
});
let
firstCalled
=
false
;
let
secondCalled
=
false
;
const
reg3
=
window
.
onDidChangeTerminalDimensions
((
event
:
TerminalDimensionsChangeEvent
)
=>
{
if
(
event
.
terminal
===
terminal1
)
{
// The original terminal should fire dimension change after a split
firstCalled
=
true
;
}
else
if
(
event
.
terminal
!==
terminal1
)
{
// The new split terminal should fire dimension change
secondCalled
=
true
;
}
if
(
firstCalled
&&
secondCalled
)
{
terminal1
.
dispose
();
terminal2
.
dispose
();
reg3
.
dispose
();
done
();
}
});
await
timeout
(
500
);
commands
.
executeCommand
(
'
workbench.action.terminal.split
'
);
});
const
terminal1
=
window
.
createTerminal
({
name
:
'
test
'
});
terminal1
.
show
();
});
suite
(
'
hideFromUser
'
,
()
=>
{
test
(
'
should fire onDidWriteData correctly
'
,
done
=>
{
const
terminal
=
window
.
createTerminal
({
name
:
'
bg
'
,
hideFromUser
:
true
});
let
data
=
''
;
terminal
.
onDidWriteData
(
e
=>
{
data
+=
e
;
if
(
data
.
indexOf
(
'
foo
'
)
!==
-
1
)
{
terminal
.
dispose
();
done
();
}
});
terminal
.
sendText
(
'
foo
'
);
});
test
(
'
should be available to terminals API
'
,
done
=>
{
const
terminal
=
window
.
createTerminal
({
name
:
'
bg
'
,
hideFromUser
:
true
});
window
.
onDidOpenTerminal
(
t
=>
{
equal
(
t
,
terminal
);
equal
(
t
.
name
,
'
bg
'
);
ok
(
window
.
terminals
.
indexOf
(
terminal
)
!==
-
1
);
done
();
});
});
});
suite
(
'
Terminal renderers (deprecated)
'
,
()
=>
{
test
(
'
should fire onDidOpenTerminal and onDidCloseTerminal from createTerminalRenderer terminal
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
term
=>
{
equal
(
term
.
name
,
'
c
'
);
reg1
.
dispose
();
const
reg2
=
window
.
onDidCloseTerminal
(()
=>
{
reg2
.
dispose
();
done
();
});
term
.
dispose
();
});
window
.
createTerminalRenderer
(
'
c
'
);
});
test
(
'
should get maximum dimensions set when shown
'
,
(
done
)
=>
{
let
terminal
:
Terminal
;
const
reg1
=
window
.
onDidOpenTerminal
(
term
=>
{
reg1
.
dispose
();
term
.
show
();
terminal
=
term
;
});
const
renderer
=
window
.
createTerminalRenderer
(
'
foo
'
);
const
reg2
=
renderer
.
onDidChangeMaximumDimensions
(
dimensions
=>
{
ok
(
dimensions
.
columns
>
0
);
ok
(
dimensions
.
rows
>
0
);
reg2
.
dispose
();
const
reg3
=
window
.
onDidCloseTerminal
(()
=>
{
reg3
.
dispose
();
done
();
});
terminal
.
dispose
();
});
});
test
(
'
should fire Terminal.onData on write
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
terminal
=>
{
reg1
.
dispose
();
const
reg2
=
terminal
.
onDidWriteData
(
data
=>
{
equal
(
data
,
'
bar
'
);
reg2
.
dispose
();
const
reg3
=
window
.
onDidCloseTerminal
(()
=>
{
reg3
.
dispose
();
done
();
});
terminal
.
dispose
();
});
renderer
.
write
(
'
bar
'
);
});
const
renderer
=
window
.
createTerminalRenderer
(
'
foo
'
);
});
})
suite
(
'
Virtual process terminals
'
,
()
=>
{
test
(
'
should fire onDidOpenTerminal and onDidCloseTerminal
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
term
=>
{
equal
(
term
.
name
,
'
c
'
);
reg1
.
dispose
();
const
reg2
=
window
.
onDidCloseTerminal
(()
=>
{
reg2
.
dispose
();
done
();
});
term
.
dispose
();
});
const
virtualProcess
:
TerminalVirtualProcess
=
{
write
:
new
EventEmitter
<
string
>
().
event
};
window
.
createTerminal
({
name
:
'
c
'
,
virtualProcess
});
});
test
(
'
should get dimensions event when shown
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
term
=>
{
reg1
.
dispose
();
equal
(
terminal
,
term
);
term
.
show
();
});
const
virtualProcess
:
TerminalVirtualProcess
=
{
write
:
new
EventEmitter
<
string
>
().
event
,
onDidChangeDimensions
:
dimensions
=>
{
ok
(
dimensions
.
columns
>
0
);
ok
(
dimensions
.
rows
>
0
);
const
reg2
=
window
.
onDidCloseTerminal
(()
=>
{
reg2
.
dispose
();
done
();
});
terminal
.
dispose
();
}
};
const
terminal
=
window
.
createTerminal
({
name
:
'
foo
'
,
virtualProcess
});
});
test
(
'
should fire Terminal.onData on write
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
term
=>
{
equal
(
terminal
,
term
);
reg1
.
dispose
();
const
reg2
=
terminal
.
onDidWriteData
(
data
=>
{
equal
(
data
,
'
bar
'
);
reg2
.
dispose
();
const
reg3
=
window
.
onDidCloseTerminal
(()
=>
{
reg3
.
dispose
();
done
();
});
terminal
.
dispose
();
});
writeEmitter
.
fire
(
'
bar
'
);
});
const
writeEmitter
=
new
EventEmitter
<
string
>
();
const
virtualProcess
:
TerminalVirtualProcess
=
{
write
:
writeEmitter
.
event
};
const
terminal
=
window
.
createTerminal
({
name
:
'
foo
'
,
virtualProcess
});
});
test
(
'
should respect dimension overrides
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
term
=>
{
equal
(
terminal
,
term
);
reg1
.
dispose
();
term
.
show
();
const
reg2
=
window
.
onDidChangeTerminalDimensions
(
e
=>
{
equal
(
e
.
dimensions
.
columns
,
10
);
equal
(
e
.
dimensions
.
rows
,
5
);
equal
(
e
.
terminal
,
terminal
)
reg2
.
dispose
();
const
reg3
=
window
.
onDidCloseTerminal
(()
=>
{
reg3
.
dispose
();
done
();
});
terminal
.
dispose
();
});
overrideDimensionsEmitter
.
fire
({
columns
:
10
,
rows
:
5
});
});
const
writeEmitter
=
new
EventEmitter
<
string
>
();
const
overrideDimensionsEmitter
=
new
EventEmitter
<
TerminalDimensions
>
();
const
virtualProcess
:
TerminalVirtualProcess
=
{
write
:
writeEmitter
.
event
,
overrideDimensions
:
overrideDimensionsEmitter
.
event
};
const
terminal
=
window
.
createTerminal
({
name
:
'
foo
'
,
virtualProcess
});
});
});
});
});
async
function
timeout
(
ms
=
0
):
Promise
<
void
>
{
return
new
Promise
<
void
>
(
resolve
=>
setTimeout
(()
=>
resolve
(),
ms
));
}
extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts
浏览文件 @
8237428f
...
...
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import
*
as
assert
from
'
assert
'
;
import
{
workspace
,
window
,
commands
,
ViewColumn
,
TextEditorViewColumnChangeEvent
,
Uri
,
Selection
,
Position
,
CancellationTokenSource
,
TextEditorSelectionChangeKind
,
Terminal
,
TerminalDimensionsChangeEvent
}
from
'
vscode
'
;
import
{
workspace
,
window
,
commands
,
ViewColumn
,
TextEditorViewColumnChangeEvent
,
Uri
,
Selection
,
Position
,
CancellationTokenSource
,
TextEditorSelectionChangeKind
}
from
'
vscode
'
;
import
{
join
}
from
'
path
'
;
import
{
closeAllEditors
,
pathEquals
,
createRandomFile
}
from
'
../utils
'
;
...
...
@@ -568,201 +568,4 @@ suite('window namespace tests', () => {
});
});
(
process
.
platform
===
'
win32
'
?
suite
.
skip
/* https://github.com/microsoft/vscode/issues/75689 */
:
suite
)(
'
Terminal
'
,
()
=>
{
test
(
'
sendText immediately after createTerminal should not throw
'
,
()
=>
{
const
terminal
=
window
.
createTerminal
();
assert
.
doesNotThrow
(
terminal
.
sendText
.
bind
(
terminal
,
'
echo "foo"
'
));
terminal
.
dispose
();
});
test
(
'
onDidCloseTerminal event fires when terminal is disposed
'
,
(
done
)
=>
{
const
terminal
=
window
.
createTerminal
();
const
reg
=
window
.
onDidCloseTerminal
((
eventTerminal
)
=>
{
assert
.
equal
(
terminal
,
eventTerminal
);
reg
.
dispose
();
done
();
});
terminal
.
dispose
();
});
test
(
'
processId immediately after createTerminal should fetch the pid
'
,
(
done
)
=>
{
const
terminal
=
window
.
createTerminal
();
terminal
.
processId
.
then
(
id
=>
{
assert
.
ok
(
id
>
0
);
terminal
.
dispose
();
done
();
});
});
test
(
'
name in constructor should set terminal.name
'
,
()
=>
{
const
terminal
=
window
.
createTerminal
(
'
a
'
);
assert
.
equal
(
terminal
.
name
,
'
a
'
);
terminal
.
dispose
();
});
test
(
'
onDidOpenTerminal should fire when a terminal is created
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
term
=>
{
assert
.
equal
(
term
.
name
,
'
b
'
);
reg1
.
dispose
();
const
reg2
=
window
.
onDidCloseTerminal
(()
=>
{
reg2
.
dispose
();
done
();
});
terminal
.
dispose
();
});
const
terminal
=
window
.
createTerminal
(
'
b
'
);
});
test
(
'
createTerminalRenderer should fire onDidOpenTerminal and onDidCloseTerminal
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
term
=>
{
assert
.
equal
(
term
.
name
,
'
c
'
);
reg1
.
dispose
();
const
reg2
=
window
.
onDidCloseTerminal
(()
=>
{
reg2
.
dispose
();
done
();
});
term
.
dispose
();
});
window
.
createTerminalRenderer
(
'
c
'
);
});
test
(
'
terminal renderers should get maximum dimensions set when shown
'
,
(
done
)
=>
{
let
terminal
:
Terminal
;
const
reg1
=
window
.
onDidOpenTerminal
(
term
=>
{
reg1
.
dispose
();
term
.
show
();
terminal
=
term
;
});
const
renderer
=
window
.
createTerminalRenderer
(
'
foo
'
);
const
reg2
=
renderer
.
onDidChangeMaximumDimensions
(
dimensions
=>
{
assert
.
ok
(
dimensions
.
columns
>
0
);
assert
.
ok
(
dimensions
.
rows
>
0
);
reg2
.
dispose
();
const
reg3
=
window
.
onDidCloseTerminal
(()
=>
{
reg3
.
dispose
();
done
();
});
terminal
.
dispose
();
});
});
test
(
'
TerminalRenderer.write should fire Terminal.onData
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
terminal
=>
{
reg1
.
dispose
();
const
reg2
=
terminal
.
onDidWriteData
(
data
=>
{
assert
.
equal
(
data
,
'
bar
'
);
reg2
.
dispose
();
const
reg3
=
window
.
onDidCloseTerminal
(()
=>
{
reg3
.
dispose
();
done
();
});
terminal
.
dispose
();
});
renderer
.
write
(
'
bar
'
);
});
const
renderer
=
window
.
createTerminalRenderer
(
'
foo
'
);
});
test
(
'
Terminal.sendText should fire Terminal.onInput
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidOpenTerminal
(
terminal
=>
{
reg1
.
dispose
();
const
reg2
=
renderer
.
onDidAcceptInput
(
data
=>
{
assert
.
equal
(
data
,
'
bar
'
);
reg2
.
dispose
();
const
reg3
=
window
.
onDidCloseTerminal
(()
=>
{
reg3
.
dispose
();
done
();
});
terminal
.
dispose
();
});
terminal
.
sendText
(
'
bar
'
,
false
);
});
const
renderer
=
window
.
createTerminalRenderer
(
'
foo
'
);
});
test
(
'
onDidChangeActiveTerminal should fire when new terminals are created
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidChangeActiveTerminal
((
active
:
Terminal
|
undefined
)
=>
{
assert
.
equal
(
active
,
terminal
);
assert
.
equal
(
active
,
window
.
activeTerminal
);
reg1
.
dispose
();
const
reg2
=
window
.
onDidChangeActiveTerminal
((
active
:
Terminal
|
undefined
)
=>
{
assert
.
equal
(
active
,
undefined
);
assert
.
equal
(
active
,
window
.
activeTerminal
);
reg2
.
dispose
();
done
();
});
terminal
.
dispose
();
});
const
terminal
=
window
.
createTerminal
();
terminal
.
show
();
});
test
(
'
onDidChangeTerminalDimensions should fire when new terminals are created
'
,
(
done
)
=>
{
const
reg1
=
window
.
onDidChangeTerminalDimensions
(
async
(
event
:
TerminalDimensionsChangeEvent
)
=>
{
assert
.
equal
(
event
.
terminal
,
terminal1
);
assert
.
equal
(
typeof
event
.
dimensions
.
columns
,
'
number
'
);
assert
.
equal
(
typeof
event
.
dimensions
.
rows
,
'
number
'
);
assert
.
ok
(
event
.
dimensions
.
columns
>
0
);
assert
.
ok
(
event
.
dimensions
.
rows
>
0
);
reg1
.
dispose
();
let
terminal2
:
Terminal
;
const
reg2
=
window
.
onDidOpenTerminal
((
newTerminal
)
=>
{
// This is guarantees to fire before dimensions change event
if
(
newTerminal
!==
terminal1
)
{
terminal2
=
newTerminal
;
reg2
.
dispose
();
}
});
let
firstCalled
=
false
;
let
secondCalled
=
false
;
const
reg3
=
window
.
onDidChangeTerminalDimensions
((
event
:
TerminalDimensionsChangeEvent
)
=>
{
if
(
event
.
terminal
===
terminal1
)
{
// The original terminal should fire dimension change after a split
firstCalled
=
true
;
}
else
if
(
event
.
terminal
!==
terminal1
)
{
// The new split terminal should fire dimension change
secondCalled
=
true
;
}
if
(
firstCalled
&&
secondCalled
)
{
terminal1
.
dispose
();
terminal2
.
dispose
();
reg3
.
dispose
();
done
();
}
});
await
timeout
(
500
);
commands
.
executeCommand
(
'
workbench.action.terminal.split
'
);
});
const
terminal1
=
window
.
createTerminal
({
name
:
'
test
'
});
terminal1
.
show
();
});
test
(
'
hideFromUser terminal: onDidWriteData should work
'
,
done
=>
{
const
terminal
=
window
.
createTerminal
({
name
:
'
bg
'
,
hideFromUser
:
true
});
let
data
=
''
;
terminal
.
onDidWriteData
(
e
=>
{
data
+=
e
;
if
(
data
.
indexOf
(
'
foo
'
)
!==
-
1
)
{
terminal
.
dispose
();
done
();
}
});
terminal
.
sendText
(
'
foo
'
);
});
test
(
'
hideFromUser terminal: should be available to terminals API
'
,
done
=>
{
const
terminal
=
window
.
createTerminal
({
name
:
'
bg
'
,
hideFromUser
:
true
});
window
.
onDidOpenTerminal
(
t
=>
{
assert
.
equal
(
t
,
terminal
);
assert
.
equal
(
t
.
name
,
'
bg
'
);
assert
.
ok
(
window
.
terminals
.
indexOf
(
terminal
)
!==
-
1
);
done
();
});
});
});
});
async
function
timeout
(
ms
=
0
):
Promise
<
void
>
{
return
new
Promise
<
void
>
(
resolve
=>
setTimeout
(()
=>
resolve
(),
ms
));
}
\ No newline at end of file
src/vs/vscode.proposed.d.ts
浏览文件 @
8237428f
...
...
@@ -1162,6 +1162,8 @@ declare module 'vscode' {
* [Terminal.sendText](#Terminal.sendText) is triggered that will fire the
* [TerminalRenderer.onDidAcceptInput](#TerminalRenderer.onDidAcceptInput) event.
*
* @deprecated Use [virtual processes](#TerminalVirtualProcess) instead.
*
* **Example:** Create a terminal renderer, show it and write hello world in red
* ```typescript
* const renderer = window.createTerminalRenderer('foo');
...
...
@@ -1172,6 +1174,7 @@ declare module 'vscode' {
export
interface
TerminalRenderer
{
/**
* The name of the terminal, this will appear in the terminal selector.
* @deprecated Use [virtual processes](#TerminalVirtualProcess) instead.
*/
name
:
string
;
...
...
@@ -1180,6 +1183,8 @@ declare module 'vscode' {
* a value smaller than the maximum value, if this is undefined the terminal will auto fit
* to the maximum value [maximumDimensions](TerminalRenderer.maximumDimensions).
*
* @deprecated Use [virtual processes](#TerminalVirtualProcess) instead.
*
* **Example:** Override the dimensions of a TerminalRenderer to 20 columns and 10 rows
* ```typescript
* terminalRenderer.dimensions = {
...
...
@@ -1195,11 +1200,15 @@ declare module 'vscode' {
* terminal renderer is created and also until the terminal becomes visible in the UI.
* Listen to [onDidChangeMaximumDimensions](TerminalRenderer.onDidChangeMaximumDimensions)
* to get notified when this value changes.
*
* @deprecated Use [virtual processes](#TerminalVirtualProcess) instead.
*/
readonly
maximumDimensions
:
TerminalDimensions
|
undefined
;
/**
* The corresponding [Terminal](#Terminal) for this TerminalRenderer.
*
* @deprecated Use [virtual processes](#TerminalVirtualProcess) instead.
*/
readonly
terminal
:
Terminal
;
...
...
@@ -1207,6 +1216,9 @@ declare module 'vscode' {
* Write text to the terminal. Unlike [Terminal.sendText](#Terminal.sendText) which sends
* text to the underlying _process_, this will write the text to the terminal itself.
*
* @param text The text to write.
* @deprecated Use [virtual processes](#TerminalVirtualProcess) instead.
*
* **Example:** Write red text to the terminal
* ```typescript
* terminalRenderer.write('\x1b[31mHello world\x1b[0m');
...
...
@@ -1216,8 +1228,6 @@ declare module 'vscode' {
* ```typescript
* terminalRenderer.write('\x1b[10;20H*');
* ```
*
* @param text The text to write.
*/
write
(
text
:
string
):
void
;
...
...
@@ -1226,6 +1236,8 @@ declare module 'vscode' {
* [Terminal.sendText](#Terminal.sendText). Keystrokes are converted into their
* corresponding VT sequence representation.
*
* @deprecated Use [virtual processes](#TerminalVirtualProcess) instead.
*
* **Example:** Simulate interaction with the terminal from an outside extension or a
* workbench command such as `workbench.action.terminal.runSelectedText`
* ```typescript
...
...
@@ -1241,6 +1253,8 @@ declare module 'vscode' {
/**
* An event which fires when the [maximum dimensions](#TerminalRenderer.maximumDimensions) of
* the terminal renderer change.
*
* @deprecated Use [virtual processes](#TerminalVirtualProcess) instead.
*/
readonly
onDidChangeMaximumDimensions
:
Event
<
TerminalDimensions
>
;
}
...
...
@@ -1250,12 +1264,135 @@ declare module 'vscode' {
* Create a [TerminalRenderer](#TerminalRenderer).
*
* @param name The name of the terminal renderer, this shows up in the terminal selector.
* @deprecated Use [virtual processes](#TerminalVirtualProcess) instead.
*/
export
function
createTerminalRenderer
(
name
:
string
):
TerminalRenderer
;
}
//#endregion
//#region Terminal virtual process
export
namespace
window
{
/**
* Creates a [Terminal](#Terminal) where an extension acts as the process.
*
* @param options A [TerminalVirtualProcessOptions](#TerminalVirtualProcessOptions) object describing the
* characteristics of the new terminal.
* @return A new Terminal.
*/
export
function
createTerminal
(
options
:
TerminalVirtualProcessOptions
):
Terminal
;
}
/**
* Value-object describing what options a virtual process terminal should use.
*/
export
interface
TerminalVirtualProcessOptions
{
/**
* A human-readable string which will be used to represent the terminal in the UI.
*/
name
:
string
;
/**
* An implementation of [TerminalVirtualProcess](#TerminalVirtualProcess) that allows an
* extension to act as a terminal's backing process.
*/
virtualProcess
:
TerminalVirtualProcess
;
}
/**
* Defines the interface of a terminal virtual process, enabling extensions to act as a process
* in the terminal.
*/
interface
TerminalVirtualProcess
{
/**
* An event that when fired will write data to the terminal. Unlike
* [Terminal.sendText](#Terminal.sendText) which sends text to the underlying _process_,
* this will write the text to the terminal itself.
*
* **Example:** Write red text to the terminal
* ```typescript
* const writeEmitter = new vscode.EventEmitter<string>();
* const virtualProcess: TerminalVirtualProcess = {
* write: writeEmitter.event
* };
* vscode.window.createTerminal({ name: 'My terminal', virtualProcess });
* writeEmitter.fire('\x1b[31mHello world\x1b[0m');
* ```
*
* **Example:** Move the cursor to the 10th row and 20th column and write an asterisk
* ```typescript
* writeEmitter.fire('\x1b[10;20H*');
* ```
*/
write
:
Event
<
string
>
;
/**
* An event that when fired allows overriding the [dimensions](#Terminal.dimensions) of the
* terminal. Note that when set the overridden dimensions will only take effect when they
* are lower than the actual dimensions of the terminal (ie. there will never be a scroll
* bar). Set to `undefined` for the terminal to go back to the regular dimensions.
*
* **Example:** Override the dimensions of a terminal to 20 columns and 10 rows
* ```typescript
* const dimensionsEmitter = new vscode.EventEmitter<string>();
* const virtualProcess: TerminalVirtualProcess = {
* write: writeEmitter.event,
* overrideDimensions: dimensionsEmitter.event
* };
* vscode.window.createTerminal({ name: 'My terminal', virtualProcess });
* dimensionsEmitter.fire({
* columns: 20,
* rows: 10
* });
* ```
*/
overrideDimensions
?:
Event
<
TerminalDimensions
|
undefined
>
;
/**
* An event that when fired will exit the process with an exit code, this will behave the
* same for a virtual process as when a regular process exits with an exit code.
*/
exit
?:
Event
<
number
>
;
/**
* Implement to handle keystrokes in the terminal or when an extension calls
* [Terminal.sendText](#Terminal.sendText). Keystrokes are converted into their
* corresponding VT sequence representation.
*
* @param data The sent data.
*
* **Example:** Echo input in the terminal. The sequence for enter (`\r`) is translated to
* CRLF to go to a new line and move the cursor to the start of the line.
* ```typescript
* const writeEmitter = new vscode.EventEmitter<string>();
* const virtualProcess: TerminalVirtualProcess = {
* write: writeEmitter.event,
* onDidAcceptInput: data => writeEmitter.fire(data === '\r' ? '\r\n' : data);
* };
* vscode.window.createTerminal({ name: 'Local echo', virtualProcess });
* ```
*/
onDidAcceptInput
?(
data
:
string
):
void
;
/**
* Implement to handle when the number of rows and columns that fit into the terminal panel
* changes, for example when font size changes or when the panel is resized. The initial
* state of a terminal's dimensions should be treated as `undefined` until this is triggered
* as the size of a terminal isn't know until it shows up in the user interface.
*
* @param dimensions The new dimensions.
*/
onDidChangeDimensions
?(
dimensions
:
TerminalDimensions
):
void
;
/**
* Implement to handle when the terminal shuts down by an act of the user.
*/
onDidShutdownTerminal
?():
void
;
}
//#endregion
//#region Joh -> exclusive document filters
export
interface
DocumentFilter
{
...
...
src/vs/workbench/api/browser/mainThreadTerminalService.ts
浏览文件 @
8237428f
...
...
@@ -5,9 +5,9 @@
import
{
IDisposable
,
DisposableStore
}
from
'
vs/base/common/lifecycle
'
;
import
{
ITerminalService
,
ITerminalInstance
,
IShellLaunchConfig
,
ITerminalProcessExtHostProxy
,
ITerminalProcessExtHostRequest
,
ITerminalDimensions
,
EXT_HOST_CREATION_DELAY
,
IAvailableShellsRequest
,
IDefaultShellAndArgsRequest
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
ExtHostContext
,
ExtHostTerminalServiceShape
,
MainThreadTerminalServiceShape
,
MainContext
,
IExtHostContext
,
ShellLaunchConfigDto
}
from
'
vs/workbench/api/common/extHost.protocol
'
;
import
{
ExtHostContext
,
ExtHostTerminalServiceShape
,
MainThreadTerminalServiceShape
,
MainContext
,
IExtHostContext
,
ShellLaunchConfigDto
,
TerminalLaunchConfig
}
from
'
vs/workbench/api/common/extHost.protocol
'
;
import
{
extHostNamedCustomer
}
from
'
vs/workbench/api/common/extHostCustomers
'
;
import
{
U
riComponents
,
U
RI
}
from
'
vs/base/common/uri
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
StopWatch
}
from
'
vs/base/common/stopwatch
'
;
import
{
ITerminalInstanceService
}
from
'
vs/workbench/contrib/terminal/browser/terminal
'
;
import
{
IRemoteAgentService
}
from
'
vs/workbench/services/remote/common/remoteAgentService
'
;
...
...
@@ -18,7 +18,8 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
private
_proxy
:
ExtHostTerminalServiceShape
;
private
_remoteAuthority
:
string
|
null
;
private
readonly
_toDispose
=
new
DisposableStore
();
private
_terminalProcesses
:
{
[
id
:
number
]:
ITerminalProcessExtHostProxy
}
=
{};
private
_terminalProcesses
:
{
[
id
:
number
]:
Promise
<
ITerminalProcessExtHostProxy
>
}
=
{};
private
_terminalProcessesReady
:
{
[
id
:
number
]:
(
proxy
:
ITerminalProcessExtHostProxy
)
=>
void
}
=
{};
private
_terminalOnDidWriteDataListeners
:
{
[
id
:
number
]:
IDisposable
}
=
{};
private
_terminalOnDidAcceptInputListeners
:
{
[
id
:
number
]:
IDisposable
}
=
{};
...
...
@@ -41,11 +42,13 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this
.
_onInstanceDimensionsChanged
(
instance
);
},
EXT_HOST_CREATION_DELAY
);
}));
this
.
_toDispose
.
add
(
_terminalService
.
onInstanceDisposed
(
instance
=>
this
.
_onTerminalDisposed
(
instance
)));
this
.
_toDispose
.
add
(
_terminalService
.
onInstanceProcessIdReady
(
instance
=>
this
.
_onTerminalProcessIdReady
(
instance
)));
this
.
_toDispose
.
add
(
_terminalService
.
onInstanceDimensionsChanged
(
instance
=>
this
.
_onInstanceDimensionsChanged
(
instance
)));
this
.
_toDispose
.
add
(
_terminalService
.
onInstanceMaximumDimensionsChanged
(
instance
=>
this
.
_onInstanceMaximumDimensionsChanged
(
instance
)));
this
.
_toDispose
.
add
(
_terminalService
.
onInstanceRequestExtHostProcess
(
request
=>
this
.
_onTerminalRequestExtHostProcess
(
request
)));
this
.
_toDispose
.
add
(
_terminalService
.
onInstanceRequestVirtualProcess
(
proxy
=>
this
.
_onTerminalRequestVirtualProcess
(
proxy
)));
this
.
_toDispose
.
add
(
_terminalService
.
onActiveInstanceChanged
(
instance
=>
this
.
_onActiveTerminalChanged
(
instance
?
instance
.
id
:
null
)));
this
.
_toDispose
.
add
(
_terminalService
.
onInstanceTitleChanged
(
instance
=>
this
.
_onTitleChanged
(
instance
.
id
,
instance
.
title
)));
this
.
_toDispose
.
add
(
_terminalService
.
configHelper
.
onWorkspacePermissionsChanged
(
isAllowed
=>
this
.
_onWorkspacePermissionsChanged
(
isAllowed
)));
...
...
@@ -76,19 +79,21 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
// when the extension host process goes down ?
}
public
$createTerminal
(
name
?:
string
,
shellPath
?:
string
,
shellArgs
?:
string
[]
|
string
,
cwd
?:
string
|
UriComponents
,
env
?:
{
[
key
:
string
]:
string
},
waitOnExit
?:
boolean
,
strictEnv
?:
boolean
,
hideFromUser
?:
boolean
):
Promise
<
{
id
:
number
,
name
:
string
}
>
{
public
$createTerminal
(
launchConfig
:
TerminalLaunchConfig
):
Promise
<
{
id
:
number
,
name
:
string
}
>
{
const
shellLaunchConfig
:
IShellLaunchConfig
=
{
name
,
executable
:
shellPath
,
args
:
shellArgs
,
cwd
:
typeof
cwd
===
'
string
'
?
cwd
:
URI
.
revive
(
cwd
),
waitOnExit
,
name
:
launchConfig
.
name
,
executable
:
launchConfig
.
shellPath
,
args
:
launchConfig
.
shellArgs
,
cwd
:
typeof
launchConfig
.
cwd
===
'
string
'
?
launchConfig
.
cwd
:
URI
.
revive
(
launchConfig
.
cwd
),
waitOnExit
:
launchConfig
.
waitOnExit
,
ignoreConfigurationCwd
:
true
,
env
,
strictEnv
,
hideFromUser
env
:
launchConfig
.
env
,
strictEnv
:
launchConfig
.
strictEnv
,
hideFromUser
:
launchConfig
.
hideFromUser
,
isVirtualProcess
:
launchConfig
.
isVirtualProcess
};
const
terminal
=
this
.
_terminalService
.
createTerminal
(
shellLaunchConfig
);
this
.
_terminalProcesses
[
terminal
.
id
]
=
new
Promise
<
ITerminalProcessExtHostProxy
>
(
r
=>
this
.
_terminalProcessesReady
[
terminal
.
id
]
=
r
);
return
Promise
.
resolve
({
id
:
terminal
.
id
,
name
:
terminal
.
title
...
...
@@ -239,7 +244,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
return
;
}
this
.
_terminalProcesses
[
request
.
proxy
.
terminalId
]
=
request
.
proxy
;
this
.
_terminalProcesses
Ready
[
request
.
proxy
.
terminalId
](
request
.
proxy
)
;
const
shellLaunchConfigDto
:
ShellLaunchConfigDto
=
{
name
:
request
.
shellLaunchConfig
.
name
,
executable
:
request
.
shellLaunchConfig
.
executable
,
...
...
@@ -256,29 +261,46 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
request
.
proxy
.
onRequestLatency
(()
=>
this
.
_onRequestLatency
(
request
.
proxy
.
terminalId
));
}
private
_onTerminalRequestVirtualProcess
(
proxy
:
ITerminalProcessExtHostProxy
):
void
{
this
.
_terminalProcessesReady
[
proxy
.
terminalId
](
proxy
);
delete
this
.
_terminalProcessesReady
[
proxy
.
terminalId
];
// Note that onReisze is not being listened to here as it needs to fire when max dimensions
// change, excluding the dimension override
proxy
.
onInput
(
data
=>
this
.
_proxy
.
$acceptProcessInput
(
proxy
.
terminalId
,
data
));
proxy
.
onShutdown
(
immediate
=>
this
.
_proxy
.
$acceptProcessShutdown
(
proxy
.
terminalId
,
immediate
));
proxy
.
onRequestCwd
(()
=>
this
.
_proxy
.
$acceptProcessRequestCwd
(
proxy
.
terminalId
));
proxy
.
onRequestInitialCwd
(()
=>
this
.
_proxy
.
$acceptProcessRequestInitialCwd
(
proxy
.
terminalId
));
proxy
.
onRequestLatency
(()
=>
this
.
_onRequestLatency
(
proxy
.
terminalId
));
}
public
$sendProcessTitle
(
terminalId
:
number
,
title
:
string
):
void
{
this
.
_terminalProcesses
[
terminalId
].
emitTitle
(
title
);
this
.
_terminalProcesses
[
terminalId
].
then
(
e
=>
e
.
emitTitle
(
title
)
);
}
public
$sendProcessData
(
terminalId
:
number
,
data
:
string
):
void
{
this
.
_terminalProcesses
[
terminalId
].
emitData
(
data
);
this
.
_terminalProcesses
[
terminalId
].
then
(
e
=>
e
.
emitData
(
data
)
);
}
public
$sendProcessReady
(
terminalId
:
number
,
pid
:
number
,
cwd
:
string
):
void
{
this
.
_terminalProcesses
[
terminalId
].
emitReady
(
pid
,
cwd
);
this
.
_terminalProcesses
[
terminalId
].
then
(
e
=>
e
.
emitReady
(
pid
,
cwd
)
);
}
public
$sendProcessExit
(
terminalId
:
number
,
exitCode
:
number
):
void
{
this
.
_terminalProcesses
[
terminalId
].
emitExit
(
exitCode
);
this
.
_terminalProcesses
[
terminalId
].
then
(
e
=>
e
.
emitExit
(
exitCode
)
);
delete
this
.
_terminalProcesses
[
terminalId
];
}
public
$sendOverrideDimensions
(
terminalId
:
number
,
dimensions
:
ITerminalDimensions
|
undefined
):
void
{
this
.
_terminalProcesses
[
terminalId
].
then
(
e
=>
e
.
emitOverrideDimensions
(
dimensions
));
}
public
$sendProcessInitialCwd
(
terminalId
:
number
,
initialCwd
:
string
):
void
{
this
.
_terminalProcesses
[
terminalId
].
emitInitialCwd
(
initialCwd
);
this
.
_terminalProcesses
[
terminalId
].
then
(
e
=>
e
.
emitInitialCwd
(
initialCwd
)
);
}
public
$sendProcessCwd
(
terminalId
:
number
,
cwd
:
string
):
void
{
this
.
_terminalProcesses
[
terminalId
].
emitCwd
(
cwd
);
this
.
_terminalProcesses
[
terminalId
].
then
(
e
=>
e
.
emitCwd
(
cwd
)
);
}
private
async
_onRequestLatency
(
terminalId
:
number
):
Promise
<
void
>
{
...
...
@@ -290,7 +312,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
sw
.
stop
();
sum
+=
sw
.
elapsed
();
}
this
.
_terminalProcesses
[
terminalId
].
emitLatency
(
sum
/
COUNT
);
this
.
_terminalProcesses
[
terminalId
].
then
(
e
=>
e
.
emitLatency
(
sum
/
COUNT
)
);
}
private
_isPrimaryExtHost
():
boolean
{
...
...
src/vs/workbench/api/common/extHost.protocol.ts
浏览文件 @
8237428f
...
...
@@ -389,8 +389,20 @@ export interface MainThreadProgressShape extends IDisposable {
$progressEnd
(
handle
:
number
):
void
;
}
export
interface
TerminalLaunchConfig
{
name
?:
string
;
shellPath
?:
string
;
shellArgs
?:
string
[]
|
string
;
cwd
?:
string
|
UriComponents
;
env
?:
{
[
key
:
string
]:
string
|
null
};
waitOnExit
?:
boolean
;
strictEnv
?:
boolean
;
hideFromUser
?:
boolean
;
isVirtualProcess
?:
boolean
;
}
export
interface
MainThreadTerminalServiceShape
extends
IDisposable
{
$createTerminal
(
name
?:
string
,
shellPath
?:
string
,
shellArgs
?:
string
[]
|
string
,
cwd
?:
string
|
UriComponents
,
env
?:
{
[
key
:
string
]:
string
|
null
},
waitOnExit
?:
boolean
,
strictEnv
?:
boolean
,
hideFromUser
?:
boolean
):
Promise
<
{
id
:
number
,
name
:
string
}
>
;
$createTerminal
(
config
:
TerminalLaunchConfig
):
Promise
<
{
id
:
number
,
name
:
string
}
>
;
$createTerminalRenderer
(
name
:
string
):
Promise
<
number
>
;
$dispose
(
terminalId
:
number
):
void
;
$hide
(
terminalId
:
number
):
void
;
...
...
@@ -403,6 +415,7 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
$sendProcessData
(
terminalId
:
number
,
data
:
string
):
void
;
$sendProcessReady
(
terminalId
:
number
,
pid
:
number
,
cwd
:
string
):
void
;
$sendProcessExit
(
terminalId
:
number
,
exitCode
:
number
):
void
;
$sendOverrideDimensions
(
terminalId
:
number
,
dimensions
:
ITerminalDimensions
|
undefined
):
void
;
$sendProcessInitialCwd
(
terminalId
:
number
,
cwd
:
string
):
void
;
$sendProcessCwd
(
terminalId
:
number
,
initialCwd
:
string
):
void
;
...
...
src/vs/workbench/api/node/extHost.api.impl.ts
浏览文件 @
8237428f
...
...
@@ -524,10 +524,14 @@ export function createApiFactory(
checkProposedApiEnabled
(
extension
);
return
extHostEditorInsets
.
createWebviewEditorInset
(
editor
,
line
,
height
,
options
,
extension
);
},
createTerminal
(
nameOrOptions
?:
vscode
.
TerminalOptions
|
string
,
shellPath
?:
string
,
shellArgs
?:
string
[]
|
string
):
vscode
.
Terminal
{
createTerminal
(
nameOrOptions
?:
vscode
.
TerminalOptions
|
vscode
.
TerminalVirtualProcessOptions
|
string
,
shellPath
?:
string
,
shellArgs
?:
string
[]
|
string
):
vscode
.
Terminal
{
if
(
typeof
nameOrOptions
===
'
object
'
)
{
nameOrOptions
.
hideFromUser
=
nameOrOptions
.
hideFromUser
||
(
nameOrOptions
.
runInBackground
&&
extension
.
enableProposedApi
);
return
extHostTerminalService
.
createTerminalFromOptions
(
nameOrOptions
);
if
(
'
virtualProcess
'
in
nameOrOptions
)
{
return
extHostTerminalService
.
createVirtualProcessTerminal
(
nameOrOptions
);
}
else
{
nameOrOptions
.
hideFromUser
=
nameOrOptions
.
hideFromUser
||
(
nameOrOptions
.
runInBackground
&&
extension
.
enableProposedApi
);
return
extHostTerminalService
.
createTerminalFromOptions
(
nameOrOptions
);
}
}
return
extHostTerminalService
.
createTerminal
(
<
string
>
nameOrOptions
,
shellPath
,
shellArgs
);
},
...
...
src/vs/workbench/api/node/extHostTerminalService.ts
浏览文件 @
8237428f
...
...
@@ -13,7 +13,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import
{
ExtHostTerminalServiceShape
,
MainContext
,
MainThreadTerminalServiceShape
,
IMainContext
,
ShellLaunchConfigDto
,
IShellDefinitionDto
,
IShellAndArgsDto
}
from
'
vs/workbench/api/common/extHost.protocol
'
;
import
{
ExtHostConfiguration
,
ExtHostConfigProvider
}
from
'
vs/workbench/api/common/extHostConfiguration
'
;
import
{
ILogService
}
from
'
vs/platform/log/common/log
'
;
import
{
EXT_HOST_CREATION_DELAY
,
IShellLaunchConfig
,
ITerminalEnvironment
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
EXT_HOST_CREATION_DELAY
,
IShellLaunchConfig
,
ITerminalEnvironment
,
ITerminalChildProcess
,
ITerminalDimensions
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
TerminalProcess
}
from
'
vs/workbench/contrib/terminal/node/terminalProcess
'
;
import
{
timeout
}
from
'
vs/base/common/async
'
;
import
{
ExtHostWorkspace
}
from
'
vs/workbench/api/common/extHostWorkspace
'
;
...
...
@@ -22,6 +22,7 @@ import { ExtHostVariableResolverService } from 'vs/workbench/api/node/extHostDeb
import
{
ExtHostDocumentsAndEditors
}
from
'
vs/workbench/api/common/extHostDocumentsAndEditors
'
;
import
{
getSystemShell
,
detectAvailableShells
}
from
'
vs/workbench/contrib/terminal/node/terminal
'
;
import
{
getMainProcessParentEnv
}
from
'
vs/workbench/contrib/terminal/node/terminalEnvironment
'
;
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
const
RENDERER_NO_PROCESS_ID
=
-
1
;
...
...
@@ -118,7 +119,14 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
strictEnv
?:
boolean
,
hideFromUser
?:
boolean
):
void
{
this
.
_proxy
.
$createTerminal
(
this
.
_name
,
shellPath
,
shellArgs
,
cwd
,
env
,
waitOnExit
,
strictEnv
,
hideFromUser
).
then
(
terminal
=>
{
this
.
_proxy
.
$createTerminal
({
name
:
this
.
_name
,
shellPath
,
shellArgs
,
cwd
,
env
,
waitOnExit
,
strictEnv
,
hideFromUser
}).
then
(
terminal
=>
{
this
.
_name
=
terminal
.
name
;
this
.
_runQueuedRequests
(
terminal
.
id
);
});
}
public
createVirtualProcess
():
Promise
<
void
>
{
return
this
.
_proxy
.
$createTerminal
({
name
:
this
.
_name
,
isVirtualProcess
:
true
}).
then
(
terminal
=>
{
this
.
_name
=
terminal
.
name
;
this
.
_runQueuedRequests
(
terminal
.
id
);
});
...
...
@@ -275,7 +283,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
private
_proxy
:
MainThreadTerminalServiceShape
;
private
_activeTerminal
:
ExtHostTerminal
|
undefined
;
private
_terminals
:
ExtHostTerminal
[]
=
[];
private
_terminalProcesses
:
{
[
id
:
number
]:
Terminal
Process
}
=
{};
private
_terminalProcesses
:
{
[
id
:
number
]:
ITerminalChild
Process
}
=
{};
private
_terminalRenderers
:
ExtHostTerminalRenderer
[]
=
[];
private
_getTerminalPromises
:
{
[
id
:
number
]:
Promise
<
ExtHostTerminal
>
}
=
{};
...
...
@@ -318,6 +326,17 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
return
terminal
;
}
public
createVirtualProcessTerminal
(
options
:
vscode
.
TerminalVirtualProcessOptions
):
vscode
.
Terminal
{
const
terminal
=
new
ExtHostTerminal
(
this
.
_proxy
,
options
.
name
);
const
p
=
new
ExtHostVirtualProcess
(
options
.
virtualProcess
);
terminal
.
createVirtualProcess
().
then
(()
=>
{
this
.
_setupExtHostProcessListeners
(
terminal
.
_id
,
p
);
p
.
startSendingEvents
();
});
this
.
_terminals
.
push
(
terminal
);
return
terminal
;
}
public
createTerminalRenderer
(
name
:
string
):
vscode
.
TerminalRenderer
{
const
terminal
=
new
ExtHostTerminal
(
this
.
_proxy
,
name
);
terminal
.
_setProcessId
(
undefined
);
...
...
@@ -414,13 +433,20 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
}
public
$acceptTerminalMaximumDimensions
(
id
:
number
,
cols
:
number
,
rows
:
number
):
void
{
this
.
_getTerminalByIdEventually
(
id
).
then
(()
=>
{
// When a terminal's dimensions change, a renderer's _maximum_ dimensions change
const
renderer
=
this
.
_getTerminalRendererById
(
id
);
if
(
renderer
)
{
renderer
.
_setMaximumDimensions
(
cols
,
rows
);
}
});
if
(
this
.
_terminalProcesses
[
id
])
{
// Virtual processes only - when virtual process resize fires it means that the
// terminal's maximum dimensions changed
this
.
_terminalProcesses
[
id
].
resize
(
cols
,
rows
);
}
else
{
// Terminal renderer
this
.
_getTerminalByIdEventually
(
id
).
then
(()
=>
{
// When a terminal's dimensions change, a renderer's _maximum_ dimensions change
const
renderer
=
this
.
_getTerminalRendererById
(
id
);
if
(
renderer
)
{
renderer
.
_setMaximumDimensions
(
cols
,
rows
);
}
});
}
}
public
$acceptTerminalRendererInput
(
id
:
number
,
data
:
string
):
void
{
...
...
@@ -546,11 +572,17 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
// TODO: Support conpty on remote, it doesn't seem to work for some reason?
// TODO: When conpty is enabled, only enable it when accessibilityMode is off
const
enableConpty
=
false
;
//terminalConfig.get('windowsEnableConpty') as boolean;
const
p
=
new
TerminalProcess
(
shellLaunchConfig
,
initialCwd
,
cols
,
rows
,
env
,
enableConpty
,
this
.
_logService
);
this
.
_setupExtHostProcessListeners
(
id
,
new
TerminalProcess
(
shellLaunchConfig
,
initialCwd
,
cols
,
rows
,
env
,
enableConpty
,
this
.
_logService
));
}
private
_setupExtHostProcessListeners
(
id
:
number
,
p
:
ITerminalChildProcess
):
void
{
p
.
onProcessReady
((
e
:
{
pid
:
number
,
cwd
:
string
})
=>
this
.
_proxy
.
$sendProcessReady
(
id
,
e
.
pid
,
e
.
cwd
));
p
.
onProcessTitleChanged
(
title
=>
this
.
_proxy
.
$sendProcessTitle
(
id
,
title
));
p
.
onProcessData
(
data
=>
this
.
_proxy
.
$sendProcessData
(
id
,
data
));
p
.
onProcessExit
(
exitCode
=>
this
.
_onProcessExit
(
id
,
exitCode
));
if
(
p
.
onProcessOverrideDimensions
)
{
p
.
onProcessOverrideDimensions
(
e
=>
this
.
_proxy
.
$sendOverrideDimensions
(
id
,
e
));
}
this
.
_terminalProcesses
[
id
]
=
p
;
}
...
...
@@ -598,9 +630,6 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
}
private
_onProcessExit
(
id
:
number
,
exitCode
:
number
):
void
{
// Remove listeners
this
.
_terminalProcesses
[
id
].
dispose
();
// Remove process reference
delete
this
.
_terminalProcesses
[
id
];
...
...
@@ -681,3 +710,83 @@ class ApiRequest {
this
.
_callback
.
apply
(
proxy
,
[
id
].
concat
(
this
.
_args
));
}
}
class
ExtHostVirtualProcess
implements
ITerminalChildProcess
{
private
_queuedEvents
:
(
IQueuedEvent
<
string
>
|
IQueuedEvent
<
number
>
|
IQueuedEvent
<
{
pid
:
number
,
cwd
:
string
}
>
|
IQueuedEvent
<
ITerminalDimensions
|
undefined
>
)[]
=
[];
private
_queueDisposables
:
IDisposable
[]
|
undefined
;
private
readonly
_onProcessData
=
new
Emitter
<
string
>
();
public
get
onProcessData
():
Event
<
string
>
{
return
this
.
_onProcessData
.
event
;
}
private
readonly
_onProcessExit
=
new
Emitter
<
number
>
();
public
get
onProcessExit
():
Event
<
number
>
{
return
this
.
_onProcessExit
.
event
;
}
private
readonly
_onProcessReady
=
new
Emitter
<
{
pid
:
number
,
cwd
:
string
}
>
();
public
get
onProcessReady
():
Event
<
{
pid
:
number
,
cwd
:
string
}
>
{
return
this
.
_onProcessReady
.
event
;
}
private
readonly
_onProcessTitleChanged
=
new
Emitter
<
string
>
();
public
get
onProcessTitleChanged
():
Event
<
string
>
{
return
this
.
_onProcessTitleChanged
.
event
;
}
private
readonly
_onProcessOverrideDimensions
=
new
Emitter
<
ITerminalDimensions
|
undefined
>
();
public
get
onProcessOverrideDimensions
():
Event
<
ITerminalDimensions
|
undefined
>
{
return
this
.
_onProcessOverrideDimensions
.
event
;
}
constructor
(
private
readonly
_virtualProcess
:
vscode
.
TerminalVirtualProcess
)
{
this
.
_queueDisposables
=
[];
this
.
_queueDisposables
.
push
(
this
.
_virtualProcess
.
write
(
e
=>
this
.
_queuedEvents
.
push
({
emitter
:
this
.
_onProcessData
,
data
:
e
})));
if
(
this
.
_virtualProcess
.
exit
)
{
this
.
_queueDisposables
.
push
(
this
.
_virtualProcess
.
exit
(
e
=>
this
.
_queuedEvents
.
push
({
emitter
:
this
.
_onProcessExit
,
data
:
e
})));
}
if
(
this
.
_virtualProcess
.
overrideDimensions
)
{
this
.
_queueDisposables
.
push
(
this
.
_virtualProcess
.
overrideDimensions
(
e
=>
this
.
_queuedEvents
.
push
({
emitter
:
this
.
_onProcessOverrideDimensions
,
data
:
e
?
{
cols
:
e
.
columns
,
rows
:
e
.
rows
}
:
undefined
})));
}
}
shutdown
():
void
{
if
(
this
.
_virtualProcess
.
onDidShutdownTerminal
)
{
this
.
_virtualProcess
.
onDidShutdownTerminal
();
}
}
input
(
data
:
string
):
void
{
if
(
this
.
_virtualProcess
.
onDidAcceptInput
)
{
this
.
_virtualProcess
.
onDidAcceptInput
(
data
);
}
}
resize
(
cols
:
number
,
rows
:
number
):
void
{
if
(
this
.
_virtualProcess
.
onDidChangeDimensions
)
{
this
.
_virtualProcess
.
onDidChangeDimensions
({
columns
:
cols
,
rows
});
}
}
getInitialCwd
():
Promise
<
string
>
{
return
Promise
.
resolve
(
''
);
}
getCwd
():
Promise
<
string
>
{
return
Promise
.
resolve
(
''
);
}
getLatency
():
Promise
<
number
>
{
return
Promise
.
resolve
(
0
);
}
startSendingEvents
():
void
{
// Flush all buffered events
this
.
_queuedEvents
.
forEach
(
e
=>
(
<
any
>
e
.
emitter
.
fire
)(
e
.
data
));
this
.
_queuedEvents
=
[];
this
.
_queueDisposables
=
undefined
;
// Attach the real listeners
this
.
_virtualProcess
.
write
(
e
=>
this
.
_onProcessData
.
fire
(
e
));
if
(
this
.
_virtualProcess
.
exit
)
{
this
.
_virtualProcess
.
exit
(
e
=>
this
.
_onProcessExit
.
fire
(
e
));
}
if
(
this
.
_virtualProcess
.
overrideDimensions
)
{
this
.
_virtualProcess
.
overrideDimensions
(
e
=>
this
.
_onProcessOverrideDimensions
.
fire
(
e
?
{
cols
:
e
.
columns
,
rows
:
e
.
rows
}
:
e
));
}
}
}
interface
IQueuedEvent
<
T
>
{
emitter
:
Emitter
<
T
>
;
data
:
T
;
}
src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
浏览文件 @
8237428f
...
...
@@ -174,7 +174,7 @@ export class TerminalInstance implements ITerminalInstance {
private
_terminalHasTextContextKey
:
IContextKey
<
boolean
>
;
private
_cols
:
number
;
private
_rows
:
number
;
private
_dimensionsOverride
:
ITerminalDimensions
;
private
_dimensionsOverride
:
ITerminalDimensions
|
undefined
;
private
_windowsShellHelper
:
IWindowsShellHelper
|
undefined
;
private
_xtermReadyPromise
:
Promise
<
void
>
;
private
_titleReadyPromise
:
Promise
<
string
>
;
...
...
@@ -363,14 +363,17 @@ export class TerminalInstance implements ITerminalInstance {
if
(
this
.
_cols
!==
newCols
||
this
.
_rows
!==
newRows
)
{
this
.
_cols
=
newCols
;
this
.
_rows
=
newRows
;
if
(
this
.
shellLaunchConfig
.
isRendererOnly
)
{
this
.
_onMaximumDimensionsChanged
.
fire
();
}
this
.
_fireMaximumDimensionsChanged
();
}
return
dimension
.
width
;
}
@
debounce
(
50
)
private
_fireMaximumDimensionsChanged
():
void
{
this
.
_onMaximumDimensionsChanged
.
fire
();
}
private
_getDimension
(
width
:
number
,
height
:
number
):
dom
.
Dimension
|
null
{
// The font needs to have been initialized
const
font
=
this
.
_configHelper
.
getFont
(
this
.
_xterm
);
...
...
@@ -945,6 +948,7 @@ export class TerminalInstance implements ITerminalInstance {
this
.
_processManager
.
onProcessReady
(()
=>
this
.
_onProcessIdReady
.
fire
(
this
));
this
.
_processManager
.
onProcessExit
(
exitCode
=>
this
.
_onProcessExit
(
exitCode
));
this
.
_processManager
.
onProcessData
(
data
=>
this
.
_onData
.
fire
(
data
));
this
.
_processManager
.
onProcessOverrideDimensions
(
e
=>
this
.
setDimensions
(
e
));
if
(
this
.
_shellLaunchConfig
.
name
)
{
this
.
setTitle
(
this
.
_shellLaunchConfig
.
name
,
false
);
...
...
@@ -1343,7 +1347,7 @@ export class TerminalInstance implements ITerminalInstance {
return
this
.
_titleReadyPromise
;
}
public
setDimensions
(
dimensions
:
ITerminalDimensions
):
void
{
public
setDimensions
(
dimensions
:
ITerminalDimensions
|
undefined
):
void
{
this
.
_dimensionsOverride
=
dimensions
;
this
.
_resize
();
}
...
...
src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts
浏览文件 @
8237428f
...
...
@@ -5,7 +5,7 @@
import
*
as
platform
from
'
vs/base/common/platform
'
;
import
*
as
terminalEnvironment
from
'
vs/workbench/contrib/terminal/common/terminalEnvironment
'
;
import
{
ProcessState
,
ITerminalProcessManager
,
IShellLaunchConfig
,
ITerminalConfigHelper
,
ITerminalChildProcess
,
IBeforeProcessDataEvent
,
ITerminalEnvironment
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
ProcessState
,
ITerminalProcessManager
,
IShellLaunchConfig
,
ITerminalConfigHelper
,
ITerminalChildProcess
,
IBeforeProcessDataEvent
,
ITerminalEnvironment
,
ITerminalDimensions
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
ILogService
}
from
'
vs/platform/log/common/log
'
;
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
IHistoryService
}
from
'
vs/workbench/services/history/common/history
'
;
...
...
@@ -29,6 +29,11 @@ const LAUNCHING_DURATION = 500;
*/
const
LATENCY_MEASURING_INTERVAL
=
1000
;
enum
ProcessType
{
Process
,
VirtualProcess
}
/**
* Holds all state related to the creation and management of terminal processes.
*
...
...
@@ -46,6 +51,7 @@ export class TerminalProcessManager implements ITerminalProcessManager {
public
userHome
:
string
|
undefined
;
private
_process
:
ITerminalChildProcess
|
null
=
null
;
private
_processType
:
ProcessType
=
ProcessType
.
Process
;
private
_preLaunchInputQueue
:
string
[]
=
[];
private
_latency
:
number
=
-
1
;
private
_latencyRequest
:
Promise
<
number
>
;
...
...
@@ -62,6 +68,8 @@ export class TerminalProcessManager implements ITerminalProcessManager {
public
get
onProcessTitle
():
Event
<
string
>
{
return
this
.
_onProcessTitle
.
event
;
}
private
readonly
_onProcessExit
=
new
Emitter
<
number
>
();
public
get
onProcessExit
():
Event
<
number
>
{
return
this
.
_onProcessExit
.
event
;
}
private
readonly
_onProcessOverrideDimensions
=
new
Emitter
<
ITerminalDimensions
|
undefined
>
();
public
get
onProcessOverrideDimensions
():
Event
<
ITerminalDimensions
|
undefined
>
{
return
this
.
_onProcessOverrideDimensions
.
event
;
}
constructor
(
private
readonly
_terminalId
:
number
,
...
...
@@ -103,32 +111,37 @@ export class TerminalProcessManager implements ITerminalProcessManager {
rows
:
number
,
isScreenReaderModeEnabled
:
boolean
):
Promise
<
void
>
{
const
forceExtHostProcess
=
(
this
.
_configHelper
.
config
as
any
).
extHostProcess
;
if
(
shellLaunchConfig
.
cwd
&&
typeof
shellLaunchConfig
.
cwd
===
'
object
'
)
{
this
.
remoteAuthority
=
getRemoteAuthority
(
shellLaunchConfig
.
cwd
);
if
(
shellLaunchConfig
.
isVirtualProcess
)
{
this
.
_processType
=
ProcessType
.
VirtualProcess
;
this
.
_process
=
this
.
_instantiationService
.
createInstance
(
TerminalProcessExtHostProxy
,
this
.
_terminalId
,
shellLaunchConfig
,
undefined
,
cols
,
rows
,
this
.
_configHelper
);
}
else
{
this
.
remoteAuthority
=
this
.
_environmentService
.
configuration
.
remoteAuthority
;
}
const
hasRemoteAuthority
=
!!
this
.
remoteAuthority
;
let
launchRemotely
=
hasRemoteAuthority
||
forceExtHostProcess
;
this
.
userHome
=
this
.
_environmentService
.
userHome
;
this
.
os
=
platform
.
OS
;
if
(
launchRemotely
)
{
if
(
hasRemoteAuthority
)
{
this
.
_remoteAgentService
.
getEnvironment
().
then
(
env
=>
{
if
(
!
env
)
{
return
;
}
this
.
userHome
=
env
.
userHome
.
path
;
this
.
os
=
env
.
os
;
});
const
forceExtHostProcess
=
(
this
.
_configHelper
.
config
as
any
).
extHostProcess
;
if
(
shellLaunchConfig
.
cwd
&&
typeof
shellLaunchConfig
.
cwd
===
'
object
'
)
{
this
.
remoteAuthority
=
getRemoteAuthority
(
shellLaunchConfig
.
cwd
);
}
else
{
this
.
remoteAuthority
=
this
.
_environmentService
.
configuration
.
remoteAuthority
;
}
const
hasRemoteAuthority
=
!!
this
.
remoteAuthority
;
let
launchRemotely
=
hasRemoteAuthority
||
forceExtHostProcess
;
const
activeWorkspaceRootUri
=
this
.
_historyService
.
getLastActiveWorkspaceRoot
();
this
.
_process
=
this
.
_instantiationService
.
createInstance
(
TerminalProcessExtHostProxy
,
this
.
_terminalId
,
shellLaunchConfig
,
activeWorkspaceRootUri
,
cols
,
rows
,
this
.
_configHelper
);
}
else
{
this
.
_process
=
await
this
.
_launchProcess
(
shellLaunchConfig
,
cols
,
rows
,
isScreenReaderModeEnabled
);
this
.
userHome
=
this
.
_environmentService
.
userHome
;
this
.
os
=
platform
.
OS
;
if
(
launchRemotely
)
{
if
(
hasRemoteAuthority
)
{
this
.
_remoteAgentService
.
getEnvironment
().
then
(
env
=>
{
if
(
!
env
)
{
return
;
}
this
.
userHome
=
env
.
userHome
.
path
;
this
.
os
=
env
.
os
;
});
}
const
activeWorkspaceRootUri
=
this
.
_historyService
.
getLastActiveWorkspaceRoot
();
this
.
_process
=
this
.
_instantiationService
.
createInstance
(
TerminalProcessExtHostProxy
,
this
.
_terminalId
,
shellLaunchConfig
,
activeWorkspaceRootUri
,
cols
,
rows
,
this
.
_configHelper
);
}
else
{
this
.
_process
=
await
this
.
_launchProcess
(
shellLaunchConfig
,
cols
,
rows
,
isScreenReaderModeEnabled
);
}
}
this
.
processState
=
ProcessState
.
LAUNCHING
;
...
...
@@ -154,6 +167,9 @@ export class TerminalProcessManager implements ITerminalProcessManager {
this
.
_process
.
onProcessTitleChanged
(
title
=>
this
.
_onProcessTitle
.
fire
(
title
));
this
.
_process
.
onProcessExit
(
exitCode
=>
this
.
_onExit
(
exitCode
));
if
(
this
.
_process
.
onProcessOverrideDimensions
)
{
this
.
_process
.
onProcessOverrideDimensions
(
e
=>
this
.
_onProcessOverrideDimensions
.
fire
(
e
));
}
setTimeout
(()
=>
{
if
(
this
.
processState
===
ProcessState
.
LAUNCHING
)
{
...
...
@@ -205,7 +221,7 @@ export class TerminalProcessManager implements ITerminalProcessManager {
}
public
write
(
data
:
string
):
void
{
if
(
this
.
shellProcessId
)
{
if
(
this
.
shellProcessId
||
this
.
_processType
===
ProcessType
.
VirtualProcess
)
{
if
(
this
.
_process
)
{
// Send data if the pty is ready
this
.
_process
.
input
(
data
);
...
...
src/vs/workbench/contrib/terminal/common/terminal.ts
浏览文件 @
8237428f
...
...
@@ -184,11 +184,15 @@ export interface IShellLaunchConfig {
initialText
?:
string
;
/**
* When true the terminal will be created with no process. This is primarily used to give
* extensions full control over the terminal.
* @deprecated use `isVirtualProcess`
*/
isRendererOnly
?:
boolean
;
/**
* When true an extension is acting as the terminal's process.
*/
isVirtualProcess
?:
boolean
;
/**
* Whether the terminal process environment should be exactly as provided in
* `TerminalOptions.env`. When this is false (default), the environment will be based on the
...
...
@@ -224,6 +228,7 @@ export interface ITerminalService {
onInstanceDimensionsChanged
:
Event
<
ITerminalInstance
>
;
onInstanceMaximumDimensionsChanged
:
Event
<
ITerminalInstance
>
;
onInstanceRequestExtHostProcess
:
Event
<
ITerminalProcessExtHostRequest
>
;
onInstanceRequestVirtualProcess
:
Event
<
ITerminalProcessExtHostProxy
>
;
onInstancesChanged
:
Event
<
void
>
;
onInstanceTitleChanged
:
Event
<
ITerminalInstance
>
;
onActiveInstanceChanged
:
Event
<
ITerminalInstance
|
undefined
>
;
...
...
@@ -291,6 +296,7 @@ export interface ITerminalService {
extHostReady
(
remoteAuthority
:
string
):
void
;
requestExtHostProcess
(
proxy
:
ITerminalProcessExtHostProxy
,
shellLaunchConfig
:
IShellLaunchConfig
,
activeWorkspaceRootUri
:
URI
,
cols
:
number
,
rows
:
number
,
isWorkspaceShellAllowed
:
boolean
):
void
;
requestVirtualProcess
(
proxy
:
ITerminalProcessExtHostProxy
):
void
;
}
/**
...
...
@@ -700,6 +706,7 @@ export interface ITerminalProcessManager extends IDisposable {
readonly
onProcessData
:
Event
<
string
>
;
readonly
onProcessTitle
:
Event
<
string
>
;
readonly
onProcessExit
:
Event
<
number
>
;
readonly
onProcessOverrideDimensions
:
Event
<
ITerminalDimensions
|
undefined
>
;
dispose
(
immediate
?:
boolean
):
void
;
createProcess
(
shellLaunchConfig
:
IShellLaunchConfig
,
cols
:
number
,
rows
:
number
,
isScreenReaderModeEnabled
:
boolean
):
Promise
<
void
>
;
...
...
@@ -737,6 +744,7 @@ export interface ITerminalProcessExtHostProxy extends IDisposable {
emitTitle
(
title
:
string
):
void
;
emitReady
(
pid
:
number
,
cwd
:
string
):
void
;
emitExit
(
exitCode
:
number
):
void
;
emitOverrideDimensions
(
dimensions
:
ITerminalDimensions
|
undefined
):
void
;
emitInitialCwd
(
initialCwd
:
string
):
void
;
emitCwd
(
cwd
:
string
):
void
;
emitLatency
(
latency
:
number
):
void
;
...
...
@@ -785,6 +793,7 @@ export interface ITerminalChildProcess {
onProcessExit
:
Event
<
number
>
;
onProcessReady
:
Event
<
{
pid
:
number
,
cwd
:
string
}
>
;
onProcessTitleChanged
:
Event
<
string
>
;
onProcessOverrideDimensions
?:
Event
<
ITerminalDimensions
|
undefined
>
;
/**
* Shutdown the terminal process.
...
...
src/vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy.ts
浏览文件 @
8237428f
...
...
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import
{
Event
,
Emitter
}
from
'
vs/base/common/event
'
;
import
{
ITerminalService
,
ITerminalProcessExtHostProxy
,
IShellLaunchConfig
,
ITerminalChildProcess
,
ITerminalConfigHelper
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
ITerminalService
,
ITerminalProcessExtHostProxy
,
IShellLaunchConfig
,
ITerminalChildProcess
,
ITerminalConfigHelper
,
ITerminalDimensions
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
Disposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
IRemoteAgentService
}
from
'
vs/workbench/services/remote/common/remoteAgentService
'
;
...
...
@@ -22,6 +22,8 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
public
get
onProcessReady
():
Event
<
{
pid
:
number
,
cwd
:
string
}
>
{
return
this
.
_onProcessReady
.
event
;
}
private
readonly
_onProcessTitleChanged
=
this
.
_register
(
new
Emitter
<
string
>
());
public
readonly
onProcessTitleChanged
:
Event
<
string
>
=
this
.
_onProcessTitleChanged
.
event
;
private
readonly
_onProcessOverrideDimensions
=
new
Emitter
<
ITerminalDimensions
|
undefined
>
();
public
get
onProcessOverrideDimensions
():
Event
<
ITerminalDimensions
|
undefined
>
{
return
this
.
_onProcessOverrideDimensions
.
event
;
}
private
readonly
_onInput
=
this
.
_register
(
new
Emitter
<
string
>
());
public
readonly
onInput
:
Event
<
string
>
=
this
.
_onInput
.
event
;
...
...
@@ -51,14 +53,21 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
@
IRemoteAgentService
readonly
remoteAgentService
:
IRemoteAgentService
)
{
super
();
remoteAgentService
.
getEnvironment
().
then
(
env
=>
{
if
(
!
env
)
{
throw
new
Error
(
'
Could not fetch environment
'
);
// Request a process if needed, if this is a virtual process this step can be skipped as
// there is no real "process" and we know it's ready on the ext host already.
if
(
shellLaunchConfig
.
isVirtualProcess
)
{
this
.
_terminalService
.
requestVirtualProcess
(
this
);
}
else
{
remoteAgentService
.
getEnvironment
().
then
(
env
=>
{
if
(
!
env
)
{
throw
new
Error
(
'
Could not fetch environment
'
);
}
this
.
_terminalService
.
requestExtHostProcess
(
this
,
shellLaunchConfig
,
activeWorkspaceRootUri
,
cols
,
rows
,
configHelper
.
checkWorkspaceShellPermissions
(
env
.
os
));
});
if
(
!
hasReceivedResponse
)
{
setTimeout
(()
=>
this
.
_onProcessTitleChanged
.
fire
(
nls
.
localize
(
'
terminal.integrated.starting
'
,
"
Starting...
"
)),
0
);
}
this
.
_terminalService
.
requestExtHostProcess
(
this
,
shellLaunchConfig
,
activeWorkspaceRootUri
,
cols
,
rows
,
configHelper
.
checkWorkspaceShellPermissions
(
env
.
os
));
});
if
(
!
hasReceivedResponse
)
{
setTimeout
(()
=>
this
.
_onProcessTitleChanged
.
fire
(
nls
.
localize
(
'
terminal.integrated.starting
'
,
"
Starting...
"
)),
0
);
}
}
...
...
@@ -80,6 +89,10 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
this
.
dispose
();
}
public
emitOverrideDimensions
(
dimensions
:
ITerminalDimensions
|
undefined
):
void
{
this
.
_onProcessOverrideDimensions
.
fire
(
dimensions
);
}
public
emitInitialCwd
(
initialCwd
:
string
):
void
{
while
(
this
.
_pendingInitialCwdRequests
.
length
>
0
)
{
this
.
_pendingInitialCwdRequests
.
pop
()
!
(
initialCwd
);
...
...
src/vs/workbench/contrib/terminal/common/terminalService.ts
浏览文件 @
8237428f
...
...
@@ -55,6 +55,8 @@ export abstract class TerminalService implements ITerminalService {
public
get
onInstanceProcessIdReady
():
Event
<
ITerminalInstance
>
{
return
this
.
_onInstanceProcessIdReady
.
event
;
}
protected
readonly
_onInstanceRequestExtHostProcess
=
new
Emitter
<
ITerminalProcessExtHostRequest
>
();
public
get
onInstanceRequestExtHostProcess
():
Event
<
ITerminalProcessExtHostRequest
>
{
return
this
.
_onInstanceRequestExtHostProcess
.
event
;
}
protected
readonly
_onInstanceRequestVirtualProcess
=
new
Emitter
<
ITerminalProcessExtHostProxy
>
();
public
get
onInstanceRequestVirtualProcess
():
Event
<
ITerminalProcessExtHostProxy
>
{
return
this
.
_onInstanceRequestVirtualProcess
.
event
;
}
protected
readonly
_onInstanceDimensionsChanged
=
new
Emitter
<
ITerminalInstance
>
();
public
get
onInstanceDimensionsChanged
():
Event
<
ITerminalInstance
>
{
return
this
.
_onInstanceDimensionsChanged
.
event
;
}
protected
readonly
_onInstanceMaximumDimensionsChanged
=
new
Emitter
<
ITerminalInstance
>
();
...
...
@@ -142,6 +144,11 @@ export abstract class TerminalService implements ITerminalService {
});
}
public
requestVirtualProcess
(
proxy
:
ITerminalProcessExtHostProxy
):
void
{
// Don't need to wait on extensions here as this can only be triggered by an extension
this
.
_onInstanceRequestVirtualProcess
.
fire
(
proxy
);
}
public
extHostReady
(
remoteAuthority
:
string
):
void
{
this
.
_extHostsReady
[
remoteAuthority
]
=
true
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录