Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
fedfbacf
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,发现更多精彩内容 >>
未验证
提交
fedfbacf
编写于
11月 05, 2019
作者:
D
Daniel Imms
提交者:
GitHub
11月 05, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #84000 from microsoft/tyriar/exitCode
Support Terminal.exitStatus API
上级
5d3c599e
7215e5e9
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
173 addition
and
21 deletion
+173
-21
extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts
.../vscode-api-tests/src/singlefolder-tests/terminal.test.ts
+112
-3
src/vs/vscode.proposed.d.ts
src/vs/vscode.proposed.d.ts
+26
-0
src/vs/workbench/api/browser/mainThreadTerminalService.ts
src/vs/workbench/api/browser/mainThreadTerminalService.ts
+2
-2
src/vs/workbench/api/common/extHost.protocol.ts
src/vs/workbench/api/common/extHost.protocol.ts
+2
-2
src/vs/workbench/api/common/extHostTerminalService.ts
src/vs/workbench/api/common/extHostTerminalService.ts
+17
-5
src/vs/workbench/contrib/terminal/browser/terminal.ts
src/vs/workbench/contrib/terminal/browser/terminal.ts
+2
-0
src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
...vs/workbench/contrib/terminal/browser/terminalInstance.ts
+3
-0
src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts
...h/contrib/terminal/browser/terminalProcessExtHostProxy.ts
+3
-3
src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts
...kbench/contrib/terminal/browser/terminalProcessManager.ts
+3
-3
src/vs/workbench/contrib/terminal/common/terminal.ts
src/vs/workbench/contrib/terminal/common/terminal.ts
+3
-3
未找到文件。
extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts
浏览文件 @
fedfbacf
...
...
@@ -97,6 +97,27 @@ suite('window namespace tests', () => {
const
terminal
=
window
.
createTerminal
(
'
b
'
);
});
test
(
'
exitStatus.code should be set to undefined after a terminal is disposed
'
,
(
done
)
=>
{
disposables
.
push
(
window
.
onDidOpenTerminal
(
term
=>
{
try
{
equal
(
term
,
terminal
);
}
catch
(
e
)
{
done
(
e
);
}
disposables
.
push
(
window
.
onDidCloseTerminal
(
t
=>
{
try
{
deepEqual
(
t
.
exitStatus
,
{
code
:
undefined
});
}
catch
(
e
)
{
done
(
e
);
return
;
}
done
();
}));
terminal
.
dispose
();
}));
const
terminal
=
window
.
createTerminal
();
});
// test('onDidChangeActiveTerminal should fire when new terminals are created', (done) => {
// const reg1 = window.onDidChangeActiveTerminal((active: Terminal | undefined) => {
// equal(active, terminal);
...
...
@@ -362,9 +383,97 @@ suite('window namespace tests', () => {
const
pty
:
Pseudoterminal
=
{
onDidWrite
:
writeEmitter
.
event
,
onDidOverrideDimensions
:
overrideDimensionsEmitter
.
event
,
open
:
()
=>
{
overrideDimensionsEmitter
.
fire
({
columns
:
10
,
rows
:
5
});
},
open
:
()
=>
overrideDimensionsEmitter
.
fire
({
columns
:
10
,
rows
:
5
}),
close
:
()
=>
{
}
};
const
terminal
=
window
.
createTerminal
({
name
:
'
foo
'
,
pty
});
});
test
(
'
exitStatus.code should be set to the exit code (undefined)
'
,
(
done
)
=>
{
disposables
.
push
(
window
.
onDidOpenTerminal
(
term
=>
{
try
{
equal
(
terminal
,
term
);
equal
(
terminal
.
exitStatus
,
undefined
);
}
catch
(
e
)
{
done
(
e
);
}
disposables
.
push
(
window
.
onDidCloseTerminal
(
t
=>
{
try
{
equal
(
terminal
,
t
);
deepEqual
(
terminal
.
exitStatus
,
{
code
:
undefined
});
}
catch
(
e
)
{
done
(
e
);
return
;
}
done
();
}));
}));
const
writeEmitter
=
new
EventEmitter
<
string
>
();
const
closeEmitter
=
new
EventEmitter
<
number
|
undefined
>
();
const
pty
:
Pseudoterminal
=
{
onDidWrite
:
writeEmitter
.
event
,
onDidClose
:
closeEmitter
.
event
,
open
:
()
=>
closeEmitter
.
fire
(),
close
:
()
=>
{
}
};
const
terminal
=
window
.
createTerminal
({
name
:
'
foo
'
,
pty
});
});
test
(
'
exitStatus.code should be set to the exit code (zero)
'
,
(
done
)
=>
{
disposables
.
push
(
window
.
onDidOpenTerminal
(
term
=>
{
try
{
equal
(
terminal
,
term
);
equal
(
terminal
.
exitStatus
,
undefined
);
}
catch
(
e
)
{
done
(
e
);
}
disposables
.
push
(
window
.
onDidCloseTerminal
(
t
=>
{
try
{
equal
(
terminal
,
t
);
deepEqual
(
terminal
.
exitStatus
,
{
code
:
0
});
}
catch
(
e
)
{
done
(
e
);
return
;
}
done
();
}));
}));
const
writeEmitter
=
new
EventEmitter
<
string
>
();
const
closeEmitter
=
new
EventEmitter
<
number
|
undefined
>
();
const
pty
:
Pseudoterminal
=
{
onDidWrite
:
writeEmitter
.
event
,
onDidClose
:
closeEmitter
.
event
,
open
:
()
=>
closeEmitter
.
fire
(
0
),
close
:
()
=>
{
}
};
const
terminal
=
window
.
createTerminal
({
name
:
'
foo
'
,
pty
});
});
test
(
'
exitStatus.code should be set to the exit code (non-zero)
'
,
(
done
)
=>
{
disposables
.
push
(
window
.
onDidOpenTerminal
(
term
=>
{
try
{
equal
(
terminal
,
term
);
equal
(
terminal
.
exitStatus
,
undefined
);
}
catch
(
e
)
{
done
(
e
);
}
disposables
.
push
(
window
.
onDidCloseTerminal
(
t
=>
{
try
{
equal
(
terminal
,
t
);
deepEqual
(
terminal
.
exitStatus
,
{
code
:
22
});
}
catch
(
e
)
{
done
(
e
);
return
;
}
done
();
}));
}));
const
writeEmitter
=
new
EventEmitter
<
string
>
();
const
closeEmitter
=
new
EventEmitter
<
number
|
undefined
>
();
const
pty
:
Pseudoterminal
=
{
onDidWrite
:
writeEmitter
.
event
,
onDidClose
:
closeEmitter
.
event
,
open
:
()
=>
closeEmitter
.
fire
(
22
),
close
:
()
=>
{
}
};
const
terminal
=
window
.
createTerminal
({
name
:
'
foo
'
,
pty
});
...
...
src/vs/vscode.proposed.d.ts
浏览文件 @
fedfbacf
...
...
@@ -674,6 +674,17 @@ declare module 'vscode' {
readonly
data
:
string
;
}
export
interface
TerminalExitStatus
{
/**
* The exit code that a terminal exited with, it can have the following values:
* - Zero: the terminal process or custom execution succeeded.
* - Non-zero: the terminal process or custom execution failed.
* - `undefined`: the user forcefully closed the terminal or a custom execution exited
* without providing an exit code.
*/
readonly
code
:
number
|
undefined
;
}
namespace
window
{
/**
* An event which fires when the [dimensions](#Terminal.dimensions) of the terminal change.
...
...
@@ -695,6 +706,21 @@ declare module 'vscode' {
* created.
*/
readonly
dimensions
:
TerminalDimensions
|
undefined
;
/**
* The exit status of the terminal, this will be undefined while the terminal is active.
*
* **Example:** Show a notification with the exit code when the terminal exits with a
* non-zero exit code.
* ```typescript
* window.onDidCloseTerminal(t => {
* if (t.exitStatus && t.exitStatus.code) {
* vscode.window.showInformationMessage(`Exit code: ${t.exitStatus.code}`);
* }
* });
* ```
*/
readonly
exitStatus
:
TerminalExitStatus
|
undefined
;
}
//#endregion
...
...
src/vs/workbench/api/browser/mainThreadTerminalService.ts
浏览文件 @
fedfbacf
...
...
@@ -163,7 +163,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
}
private
_onTerminalDisposed
(
terminalInstance
:
ITerminalInstance
):
void
{
this
.
_proxy
.
$acceptTerminalClosed
(
terminalInstance
.
id
);
this
.
_proxy
.
$acceptTerminalClosed
(
terminalInstance
.
id
,
terminalInstance
.
exitCode
);
}
private
_onTerminalOpened
(
terminalInstance
:
ITerminalInstance
):
void
{
...
...
@@ -257,7 +257,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this
.
_getTerminalProcess
(
terminalId
).
then
(
e
=>
e
.
emitReady
(
pid
,
cwd
));
}
public
$sendProcessExit
(
terminalId
:
number
,
exitCode
:
number
):
void
{
public
$sendProcessExit
(
terminalId
:
number
,
exitCode
:
number
|
undefined
):
void
{
this
.
_getTerminalProcess
(
terminalId
).
then
(
e
=>
e
.
emitExit
(
exitCode
));
this
.
_terminalProcesses
.
delete
(
terminalId
);
}
...
...
src/vs/workbench/api/common/extHost.protocol.ts
浏览文件 @
fedfbacf
...
...
@@ -420,7 +420,7 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
$sendProcessTitle
(
terminalId
:
number
,
title
:
string
):
void
;
$sendProcessData
(
terminalId
:
number
,
data
:
string
):
void
;
$sendProcessReady
(
terminalId
:
number
,
pid
:
number
,
cwd
:
string
):
void
;
$sendProcessExit
(
terminalId
:
number
,
exitCode
:
number
):
void
;
$sendProcessExit
(
terminalId
:
number
,
exitCode
:
number
|
undefined
):
void
;
$sendProcessInitialCwd
(
terminalId
:
number
,
cwd
:
string
):
void
;
$sendProcessCwd
(
terminalId
:
number
,
initialCwd
:
string
):
void
;
$sendOverrideDimensions
(
terminalId
:
number
,
dimensions
:
ITerminalDimensions
|
undefined
):
void
;
...
...
@@ -1196,7 +1196,7 @@ export interface ITerminalDimensionsDto {
}
export
interface
ExtHostTerminalServiceShape
{
$acceptTerminalClosed
(
id
:
number
):
void
;
$acceptTerminalClosed
(
id
:
number
,
exitCode
:
number
|
undefined
):
void
;
$acceptTerminalOpened
(
id
:
number
,
name
:
string
):
void
;
$acceptActiveTerminalChanged
(
id
:
number
|
null
):
void
;
$acceptTerminalProcessId
(
id
:
number
,
processId
:
number
):
void
;
...
...
src/vs/workbench/api/common/extHostTerminalService.ts
浏览文件 @
fedfbacf
...
...
@@ -97,6 +97,7 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
private
_cols
:
number
|
undefined
;
private
_pidPromiseComplete
:
((
value
:
number
|
undefined
)
=>
any
)
|
undefined
;
private
_rows
:
number
|
undefined
;
private
_exitStatus
:
vscode
.
TerminalExitStatus
|
undefined
;
public
isOpen
:
boolean
=
false
;
...
...
@@ -138,6 +139,10 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
this
.
_name
=
name
;
}
public
get
exitStatus
():
vscode
.
TerminalExitStatus
|
undefined
{
return
this
.
_exitStatus
;
}
public
get
dimensions
():
vscode
.
TerminalDimensions
|
undefined
{
if
(
this
.
_cols
===
undefined
||
this
.
_rows
===
undefined
)
{
return
undefined
;
...
...
@@ -148,6 +153,10 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
};
}
public
setExitCode
(
code
:
number
|
undefined
)
{
this
.
_exitStatus
=
Object
.
freeze
({
code
});
}
public
setDimensions
(
cols
:
number
,
rows
:
number
):
boolean
{
if
(
cols
===
this
.
_cols
&&
rows
===
this
.
_rows
)
{
// Nothing changed
...
...
@@ -210,8 +219,8 @@ class ApiRequest {
export
class
ExtHostPseudoterminal
implements
ITerminalChildProcess
{
private
readonly
_onProcessData
=
new
Emitter
<
string
>
();
public
readonly
onProcessData
:
Event
<
string
>
=
this
.
_onProcessData
.
event
;
private
readonly
_onProcessExit
=
new
Emitter
<
number
>
();
public
readonly
onProcessExit
:
Event
<
number
>
=
this
.
_onProcessExit
.
event
;
private
readonly
_onProcessExit
=
new
Emitter
<
number
|
undefined
>
();
public
readonly
onProcessExit
:
Event
<
number
|
undefined
>
=
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
>
();
...
...
@@ -253,7 +262,9 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
// Attach the listeners
this
.
_pty
.
onDidWrite
(
e
=>
this
.
_onProcessData
.
fire
(
e
));
if
(
this
.
_pty
.
onDidClose
)
{
this
.
_pty
.
onDidClose
(
e
=>
this
.
_onProcessExit
.
fire
(
e
||
0
));
this
.
_pty
.
onDidClose
((
e
:
number
|
undefined
=
undefined
)
=>
{
this
.
_onProcessExit
.
fire
(
e
);
});
}
if
(
this
.
_pty
.
onDidOverrideDimensions
)
{
this
.
_pty
.
onDidOverrideDimensions
(
e
=>
this
.
_onProcessOverrideDimensions
.
fire
(
e
?
{
cols
:
e
.
columns
,
rows
:
e
.
rows
}
:
e
));
...
...
@@ -381,11 +392,12 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
}
}
public
async
$acceptTerminalClosed
(
id
:
number
):
Promise
<
void
>
{
public
async
$acceptTerminalClosed
(
id
:
number
,
exitCode
:
number
|
undefined
):
Promise
<
void
>
{
await
this
.
_getTerminalByIdEventually
(
id
);
const
index
=
this
.
_getTerminalObjectIndexById
(
this
.
terminals
,
id
);
if
(
index
!==
null
)
{
const
terminal
=
this
.
_terminals
.
splice
(
index
,
1
)[
0
];
terminal
.
setExitCode
(
exitCode
);
this
.
_onDidCloseTerminal
.
fire
(
terminal
);
}
}
...
...
@@ -511,7 +523,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
return
id
;
}
private
_onProcessExit
(
id
:
number
,
exitCode
:
number
):
void
{
private
_onProcessExit
(
id
:
number
,
exitCode
:
number
|
undefined
):
void
{
this
.
_bufferer
.
stopBuffering
(
id
);
// Remove process reference
...
...
src/vs/workbench/contrib/terminal/browser/terminal.ts
浏览文件 @
fedfbacf
...
...
@@ -236,6 +236,8 @@ export interface ITerminalInstance {
*/
onExit
:
Event
<
number
|
undefined
>
;
readonly
exitCode
:
number
|
undefined
;
processReady
:
Promise
<
void
>
;
/**
...
...
src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
浏览文件 @
fedfbacf
...
...
@@ -181,6 +181,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
private
_hadFocusOnExit
:
boolean
;
private
_isVisible
:
boolean
;
private
_isDisposed
:
boolean
;
private
_exitCode
:
number
|
undefined
;
private
_skipTerminalCommands
:
string
[];
private
_shellType
:
TerminalShellType
;
private
_title
:
string
=
''
;
...
...
@@ -227,6 +228,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
// TODO: How does this work with detached processes?
// TODO: Should this be an event as it can fire twice?
public
get
processReady
():
Promise
<
void
>
{
return
this
.
_processManager
.
ptyProcessReady
;
}
public
get
exitCode
():
number
|
undefined
{
return
this
.
_exitCode
;
}
public
get
title
():
string
{
return
this
.
_title
;
}
public
get
hadFocusOnExit
():
boolean
{
return
this
.
_hadFocusOnExit
;
}
public
get
isTitleSetByProcess
():
boolean
{
return
!!
this
.
_messageTitleDisposable
;
}
...
...
@@ -1011,6 +1013,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this
.
_logService
.
debug
(
`Terminal process exit (id:
${
this
.
id
}
) with code
${
exitCode
}
`
);
this
.
_exitCode
=
exitCode
;
this
.
_isExiting
=
true
;
let
exitCodeMessage
:
string
|
undefined
;
...
...
src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts
浏览文件 @
fedfbacf
...
...
@@ -17,8 +17,8 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
private
readonly
_onProcessData
=
this
.
_register
(
new
Emitter
<
string
>
());
public
readonly
onProcessData
:
Event
<
string
>
=
this
.
_onProcessData
.
event
;
private
readonly
_onProcessExit
=
this
.
_register
(
new
Emitter
<
number
>
());
public
readonly
onProcessExit
:
Event
<
number
>
=
this
.
_onProcessExit
.
event
;
private
readonly
_onProcessExit
=
this
.
_register
(
new
Emitter
<
number
|
undefined
>
());
public
readonly
onProcessExit
:
Event
<
number
|
undefined
>
=
this
.
_onProcessExit
.
event
;
private
readonly
_onProcessReady
=
this
.
_register
(
new
Emitter
<
{
pid
:
number
,
cwd
:
string
}
>
());
public
get
onProcessReady
():
Event
<
{
pid
:
number
,
cwd
:
string
}
>
{
return
this
.
_onProcessReady
.
event
;
}
private
readonly
_onProcessTitleChanged
=
this
.
_register
(
new
Emitter
<
string
>
());
...
...
@@ -87,7 +87,7 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
this
.
_onProcessReady
.
fire
({
pid
,
cwd
});
}
public
emitExit
(
exitCode
:
number
):
void
{
public
emitExit
(
exitCode
:
number
|
undefined
):
void
{
this
.
_onProcessExit
.
fire
(
exitCode
);
this
.
dispose
();
}
...
...
src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts
浏览文件 @
fedfbacf
...
...
@@ -67,8 +67,8 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
public
get
onProcessData
():
Event
<
string
>
{
return
this
.
_onProcessData
.
event
;
}
private
readonly
_onProcessTitle
=
this
.
_register
(
new
Emitter
<
string
>
());
public
get
onProcessTitle
():
Event
<
string
>
{
return
this
.
_onProcessTitle
.
event
;
}
private
readonly
_onProcessExit
=
this
.
_register
(
new
Emitter
<
number
>
());
public
get
onProcessExit
():
Event
<
number
>
{
return
this
.
_onProcessExit
.
event
;
}
private
readonly
_onProcessExit
=
this
.
_register
(
new
Emitter
<
number
|
undefined
>
());
public
get
onProcessExit
():
Event
<
number
|
undefined
>
{
return
this
.
_onProcessExit
.
event
;
}
private
readonly
_onProcessOverrideDimensions
=
this
.
_register
(
new
Emitter
<
ITerminalDimensions
|
undefined
>
());
public
get
onProcessOverrideDimensions
():
Event
<
ITerminalDimensions
|
undefined
>
{
return
this
.
_onProcessOverrideDimensions
.
event
;
}
private
readonly
_onProcessOverrideShellLaunchConfig
=
this
.
_register
(
new
Emitter
<
IShellLaunchConfig
>
());
...
...
@@ -285,7 +285,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
return
Promise
.
resolve
(
this
.
_latency
);
}
private
_onExit
(
exitCode
:
number
):
void
{
private
_onExit
(
exitCode
:
number
|
undefined
):
void
{
this
.
_process
=
null
;
// If the process is marked as launching then mark the process as killed
...
...
src/vs/workbench/contrib/terminal/common/terminal.ts
浏览文件 @
fedfbacf
...
...
@@ -285,7 +285,7 @@ export interface ITerminalProcessManager extends IDisposable {
readonly
onBeforeProcessData
:
Event
<
IBeforeProcessDataEvent
>
;
readonly
onProcessData
:
Event
<
string
>
;
readonly
onProcessTitle
:
Event
<
string
>
;
readonly
onProcessExit
:
Event
<
number
>
;
readonly
onProcessExit
:
Event
<
number
|
undefined
>
;
readonly
onProcessOverrideDimensions
:
Event
<
ITerminalDimensions
|
undefined
>
;
readonly
onProcessResolvedShellLaunchConfig
:
Event
<
IShellLaunchConfig
>
;
...
...
@@ -324,7 +324,7 @@ export interface ITerminalProcessExtHostProxy extends IDisposable {
emitData
(
data
:
string
):
void
;
emitTitle
(
title
:
string
):
void
;
emitReady
(
pid
:
number
,
cwd
:
string
):
void
;
emitExit
(
exitCode
:
number
):
void
;
emitExit
(
exitCode
:
number
|
undefined
):
void
;
emitOverrideDimensions
(
dimensions
:
ITerminalDimensions
|
undefined
):
void
;
emitResolvedShellLaunchConfig
(
shellLaunchConfig
:
IShellLaunchConfig
):
void
;
emitInitialCwd
(
initialCwd
:
string
):
void
;
...
...
@@ -388,7 +388,7 @@ export interface IWindowsShellHelper extends IDisposable {
*/
export
interface
ITerminalChildProcess
{
onProcessData
:
Event
<
string
>
;
onProcessExit
:
Event
<
number
>
;
onProcessExit
:
Event
<
number
|
undefined
>
;
onProcessReady
:
Event
<
{
pid
:
number
,
cwd
:
string
}
>
;
onProcessTitleChanged
:
Event
<
string
>
;
onProcessOverrideDimensions
?:
Event
<
ITerminalDimensions
|
undefined
>
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录