Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
495c42c6
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,发现更多精彩内容 >>
提交
495c42c6
编写于
1月 23, 2017
作者:
D
Dirk Baeumer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add support to run multiple tasks
上级
f675d510
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
90 addition
and
24 deletion
+90
-24
src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts
...kbench/parts/tasks/electron-browser/terminalTaskSystem.ts
+72
-18
src/vs/workbench/parts/terminal/common/terminal.ts
src/vs/workbench/parts/terminal/common/terminal.ts
+3
-2
src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts
...bench/parts/terminal/electron-browser/terminalInstance.ts
+15
-4
未找到文件。
src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts
浏览文件 @
495c42c6
...
...
@@ -33,11 +33,6 @@ import { IOutputService, IOutputChannel } from 'vs/workbench/parts/output/common
import
{
StartStopProblemCollector
,
WatchingProblemCollector
,
ProblemCollectorEvents
}
from
'
vs/workbench/parts/tasks/common/problemCollectors
'
;
import
{
ITaskSystem
,
ITaskSummary
,
ITaskExecuteResult
,
TaskExecuteKind
,
TaskError
,
TaskErrors
,
TaskRunnerConfiguration
,
TaskDescription
,
ShowOutput
,
TelemetryEvent
,
Triggers
,
TaskSystemEvents
,
TaskEvent
,
TaskType
,
CommandOptions
}
from
'
vs/workbench/parts/tasks/common/taskSystem
'
;
interface
TerminalData
{
terminal
:
ITerminalInstance
;
promise
:
TPromise
<
ITaskSummary
>
;
}
class
TerminalDecoder
{
// See https://en.wikipedia.org/wiki/ANSI_escape_code & http://stackoverflow.com/questions/25189651/how-to-remove-ansi-control-chars-vt100-from-a-java-string &
// https://www.npmjs.com/package/strip-ansi
...
...
@@ -81,12 +76,31 @@ class TerminalDecoder {
return
this
.
remaining
;
}
}
interface
PrimaryTerminal
{
terminal
:
ITerminalInstance
;
busy
:
boolean
;
}
interface
TerminalData
{
terminal
:
ITerminalInstance
;
lastTask
:
string
;
}
interface
ActiveTerminalData
{
terminal
:
ITerminalInstance
;
promise
:
TPromise
<
ITaskSummary
>
;
}
export
class
TerminalTaskSystem
extends
EventEmitter
implements
ITaskSystem
{
public
static
TelemetryEventName
:
string
=
'
taskService
'
;
private
outputChannel
:
IOutputChannel
;
private
activeTasks
:
IStringDictionary
<
TerminalData
>
;
private
activeTasks
:
IStringDictionary
<
ActiveTerminalData
>
;
private
primaryTerminal
:
PrimaryTerminal
;
private
terminals
:
IStringDictionary
<
TerminalData
>
;
private
idleTaskTerminals
:
IStringDictionary
<
string
>
;
constructor
(
private
configuration
:
TaskRunnerConfiguration
,
private
terminalService
:
ITerminalService
,
private
outputService
:
IOutputService
,
private
markerService
:
IMarkerService
,
private
modelService
:
IModelService
,
private
configurationResolverService
:
IConfigurationResolverService
,
...
...
@@ -96,6 +110,8 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem {
this
.
outputChannel
=
this
.
outputService
.
getChannel
(
outputChannelId
);
this
.
clearOutput
();
this
.
activeTasks
=
Object
.
create
(
null
);
this
.
terminals
=
Object
.
create
(
null
);
this
.
idleTaskTerminals
=
Object
.
create
(
null
);
}
public
log
(
value
:
string
):
void
{
...
...
@@ -227,7 +243,7 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem {
let
delayer
:
Async
.
Delayer
<
any
>
=
null
;
let
decoder
=
new
TerminalDecoder
();
terminal
=
this
.
createTerminal
(
task
);
terminal
.
onData
((
data
:
string
)
=>
{
const
onData
=
terminal
.
onData
((
data
:
string
)
=>
{
decoder
.
write
(
data
).
forEach
(
line
=>
{
watchingProblemMatcher
.
processLine
(
line
);
if
(
delayer
===
null
)
{
...
...
@@ -239,8 +255,14 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem {
});
});
});
terminal
.
onExit
((
exitCode
)
=>
{
const
onExit
=
terminal
.
onExit
((
exitCode
)
=>
{
onData
.
dispose
();
onExit
.
dispose
();
delete
this
.
activeTasks
[
task
.
id
];
if
(
this
.
primaryTerminal
.
terminal
===
terminal
)
{
this
.
primaryTerminal
.
busy
=
false
;
}
this
.
idleTaskTerminals
[
task
.
id
]
=
terminal
.
id
.
toString
();
watchingProblemMatcher
.
dispose
();
toUnbind
=
dispose
(
toUnbind
);
toUnbind
=
null
;
...
...
@@ -261,23 +283,25 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem {
this
.
emit
(
TaskSystemEvents
.
Active
,
event
);
let
decoder
=
new
TerminalDecoder
();
let
startStopProblemMatcher
=
new
StartStopProblemCollector
(
this
.
resolveMatchers
(
task
.
problemMatchers
),
this
.
markerService
,
this
.
modelService
);
terminal
.
onData
((
data
:
string
)
=>
{
const
onData
=
terminal
.
onData
((
data
:
string
)
=>
{
decoder
.
write
(
data
).
forEach
((
line
)
=>
{
startStopProblemMatcher
.
processLine
(
line
);
});
});
terminal
.
onExit
((
exitCode
)
=>
{
const
onExit
=
terminal
.
onExit
((
exitCode
)
=>
{
onData
.
dispose
();
onExit
.
dispose
();
delete
this
.
activeTasks
[
task
.
id
];
if
(
this
.
primaryTerminal
.
terminal
===
terminal
)
{
this
.
primaryTerminal
.
busy
=
false
;
}
this
.
idleTaskTerminals
[
task
.
id
]
=
terminal
.
id
.
toString
();
startStopProblemMatcher
.
processLine
(
decoder
.
end
());
startStopProblemMatcher
.
done
();
startStopProblemMatcher
.
dispose
();
this
.
emit
(
TaskSystemEvents
.
Inactive
,
event
);
resolve
({
exitCode
});
});
this
.
terminalService
.
setActiveInstance
(
terminal
);
if
(
task
.
showOutput
===
ShowOutput
.
Always
)
{
this
.
terminalService
.
showPanel
(
false
);
}
});
}
this
.
terminalService
.
setActiveInstance
(
terminal
);
...
...
@@ -294,6 +318,7 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem {
let
{
command
,
args
}
=
this
.
resolveCommandAndArgs
(
task
);
let
terminalName
=
nls
.
localize
(
'
TerminalTaskSystem.terminalName
'
,
'
Task - {0}
'
,
task
.
name
);
let
waitOnExit
=
task
.
showOutput
!==
ShowOutput
.
Never
||
!
task
.
isBackground
;
let
shellLaunchConfig
:
IShellLaunchConfig
=
undefined
;
if
(
task
.
command
.
isShellCommand
)
{
if
(
Platform
.
isWindows
&&
((
options
.
cwd
&&
TPath
.
isUNC
(
options
.
cwd
))
||
(
!
options
.
cwd
&&
TPath
.
isUNC
(
process
.
cwd
()))))
{
throw
new
TaskError
(
Severity
.
Error
,
nls
.
localize
(
'
TerminalTaskSystem
'
,
'
Can
\'
t execute a shell command on an UNC drive.
'
),
TaskErrors
.
UnknownError
);
...
...
@@ -359,26 +384,55 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem {
}
});
shellArgs
.
push
(
commandLine
);
const
shellLaunchConfig
:
IS
hellLaunchConfig
=
{
s
hellLaunchConfig
=
{
name
:
terminalName
,
executable
:
shellConfig
.
executable
,
args
:
shellArgs
,
waitOnExit
};
return
this
.
terminalService
.
createInstance
(
shellLaunchConfig
);
}
else
{
let
cwd
=
options
&&
options
.
cwd
?
options
.
cwd
:
process
.
cwd
();
// On Windows executed process must be described absolute. Since we allowed command without an
// absolute path (e.g. "command": "node") we need to find the executable in the CWD or PATH.
let
executable
=
Platform
.
isWindows
&&
!
task
.
command
.
isShellCommand
?
this
.
findExecutable
(
command
,
cwd
)
:
command
;
const
shellLaunchConfig
:
IS
hellLaunchConfig
=
{
s
hellLaunchConfig
=
{
name
:
terminalName
,
executable
:
executable
,
args
,
waitOnExit
};
return
this
.
terminalService
.
createInstance
(
shellLaunchConfig
);
}
let
terminalId
=
this
.
idleTaskTerminals
[
task
.
id
];
if
(
terminalId
)
{
let
taskTerminal
=
this
.
terminals
[
terminalId
];
if
(
taskTerminal
)
{
delete
this
.
idleTaskTerminals
[
task
.
id
];
taskTerminal
.
terminal
.
reuseTerminal
(
shellLaunchConfig
);
return
taskTerminal
.
terminal
;
}
}
if
(
this
.
primaryTerminal
&&
!
this
.
primaryTerminal
.
busy
)
{
this
.
primaryTerminal
.
terminal
.
reuseTerminal
(
shellLaunchConfig
);
this
.
primaryTerminal
.
busy
=
true
;
return
this
.
primaryTerminal
.
terminal
;
}
const
result
=
this
.
terminalService
.
createInstance
(
shellLaunchConfig
);
const
key
=
result
.
id
.
toString
();
result
.
onDisposed
((
terminal
)
=>
{
let
terminalData
=
this
.
terminals
[
key
];
if
(
terminalData
)
{
delete
this
.
terminals
[
key
];
delete
this
.
idleTaskTerminals
[
terminalData
.
lastTask
];
}
if
(
terminal
===
this
.
primaryTerminal
.
terminal
)
{
this
.
primaryTerminal
=
undefined
;
}
});
this
.
terminals
[
key
]
=
{
terminal
:
result
,
lastTask
:
task
.
id
};
if
(
!
task
.
isBackground
&&
!
this
.
primaryTerminal
)
{
this
.
primaryTerminal
=
{
terminal
:
result
,
busy
:
true
};
}
return
result
;
}
private
resolveCommandAndArgs
(
task
:
TaskDescription
):
{
command
:
string
,
args
:
string
[]
}
{
...
...
src/vs/workbench/parts/terminal/common/terminal.ts
浏览文件 @
495c42c6
...
...
@@ -6,6 +6,7 @@
import
Event
from
'
vs/base/common/event
'
;
import
platform
=
require
(
'
vs/base/common/platform
'
);
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
RawContextKey
,
ContextKeyExpr
}
from
'
vs/platform/contextkey/common/contextkey
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
createDecorator
}
from
'
vs/platform/instantiation/common/instantiation
'
;
...
...
@@ -265,7 +266,7 @@ export interface ITerminalInstance {
* @param listener The listener function which takes the processes' data stream (including
* ANSI escape sequences).
*/
onData
(
listener
:
(
data
:
string
)
=>
void
):
void
;
onData
(
listener
:
(
data
:
string
)
=>
void
):
IDisposable
;
/**
* Attach a listener that fires when the terminal's pty process exits.
...
...
@@ -273,7 +274,7 @@ export interface ITerminalInstance {
* @param listener The listener function which takes the processes' exit code, an exit code of
* null means the process was killed as a result of the ITerminalInstance being disposed.
*/
onExit
(
listener
:
(
exitCode
:
number
)
=>
void
):
void
;
onExit
(
listener
:
(
exitCode
:
number
)
=>
void
):
IDisposable
;
/**
* Immediately kills the terminal's current pty process and launches a new one to replace it.
...
...
src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts
浏览文件 @
495c42c6
...
...
@@ -489,16 +489,27 @@ export class TerminalInstance implements ITerminalInstance {
return
env
;
}
public
onData
(
listener
:
(
data
:
string
)
=>
void
):
void
{
this
.
_process
.
on
(
'
message
'
,
(
message
)
=>
{
public
onData
(
listener
:
(
data
:
string
)
=>
void
):
lifecycle
.
IDisposable
{
let
callback
=
(
message
)
=>
{
if
(
message
.
type
===
'
data
'
)
{
listener
(
message
.
content
);
}
});
};
this
.
_process
.
on
(
'
message
'
,
callback
);
return
{
dispose
:
()
=>
{
this
.
_process
.
removeListener
(
'
message
'
,
callback
);
}
};
}
public
onExit
(
listener
:
(
exitCode
:
number
)
=>
void
):
void
{
public
onExit
(
listener
:
(
exitCode
:
number
)
=>
void
):
lifecycle
.
IDisposable
{
this
.
_process
.
on
(
'
exit
'
,
listener
);
return
{
dispose
:
()
=>
{
this
.
_process
.
removeListener
(
'
exit
'
,
listener
);
}
};
}
private
static
_sanitizeCwd
(
cwd
:
string
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录