Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
1f110359
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
1f110359
编写于
1月 04, 2022
作者:
M
meganrogge
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
start work
上级
18ab7aca
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
230 addition
and
14 deletion
+230
-14
src/vs/platform/terminal/common/terminal.ts
src/vs/platform/terminal/common/terminal.ts
+2
-1
src/vs/platform/terminal/node/terminalProcess.ts
src/vs/platform/terminal/node/terminalProcess.ts
+3
-0
src/vs/workbench/contrib/terminal/browser/terminal.ts
src/vs/workbench/contrib/terminal/browser/terminal.ts
+28
-0
src/vs/workbench/contrib/terminal/browser/terminalActions.ts
src/vs/workbench/contrib/terminal/browser/terminalActions.ts
+28
-0
src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
...vs/workbench/contrib/terminal/browser/terminalInstance.ts
+53
-1
src/vs/workbench/contrib/terminal/browser/xterm/commandTrackerAddon.ts
...nch/contrib/terminal/browser/xterm/commandTrackerAddon.ts
+100
-10
src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts
...workbench/contrib/terminal/browser/xterm/xtermTerminal.ts
+7
-2
src/vs/workbench/contrib/terminal/common/terminal.ts
src/vs/workbench/contrib/terminal/common/terminal.ts
+9
-0
未找到文件。
src/vs/platform/terminal/common/terminal.ts
浏览文件 @
1f110359
...
...
@@ -548,7 +548,8 @@ export interface IProcessReadyEvent {
}
export
const
enum
ProcessCapability
{
CwdDetection
=
'
cwdDetection
'
CwdDetection
=
'
cwdDetection
'
,
ShellIntegration
=
'
shellIntegration
'
}
/**
...
...
src/vs/platform/terminal/node/terminalProcess.ts
浏览文件 @
1f110359
...
...
@@ -182,6 +182,9 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
if
(
isLinux
||
isMacintosh
)
{
this
.
capabilities
.
push
(
ProcessCapability
.
CwdDetection
);
}
if
(
shellLaunchConfig
.
executable
===
'
zsh
'
)
{
this
.
capabilities
.
push
(
ProcessCapability
.
ShellIntegration
);
}
}
async
start
():
Promise
<
ITerminalLaunchError
|
undefined
>
{
...
...
src/vs/workbench/contrib/terminal/browser/terminal.ts
浏览文件 @
1f110359
...
...
@@ -792,6 +792,12 @@ export interface ITerminalInstance {
* Triggers a quick pick that displays links from the viewport of the active terminal.
*/
showLinkQuickpick
(
type
:
TerminalLinkProviderType
):
Promise
<
void
>
;
/**
* Triggers a quick pick that displays recent commands or cwds. Selecting one will
* re-run it in the active terminal.
*/
runRecent
(
type
:
'
command
'
|
'
cwd
'
):
Promise
<
void
>
;
}
export
interface
IXtermTerminal
{
...
...
@@ -850,3 +856,25 @@ export const enum LinuxDistro {
Fedora
=
2
,
Ubuntu
=
3
,
}
export
enum
ShellIntegrationInteraction
{
PromptStart
=
'
PROMPT_START
'
,
CommandStart
=
'
COMMAND_START
'
,
CommandExecuted
=
'
COMMAND_EXECUTED
'
,
CommandFinished
=
'
COMMAND_FINISHED
'
}
export
interface
TerminalCommand
{
command
:
string
;
timestamp
:
string
;
cwd
?:
string
;
exitCode
?:
number
;
}
export
enum
ShellIntegrationInfo
{
RemoteHost
=
'
RemoteHost
'
,
CurrentDir
=
'
CurrentDir
'
,
}
export
interface
IShellChangeEvent
{
type
:
ShellIntegrationInfo
|
ShellIntegrationInteraction
,
value
:
string
}
src/vs/workbench/contrib/terminal/browser/terminalActions.ts
浏览文件 @
1f110359
...
...
@@ -538,6 +538,34 @@ export function registerTerminalActions() {
return
terminalGroupService
.
showPanel
();
}
});
registerAction2
(
class
extends
Action2
{
constructor
()
{
super
({
id
:
TerminalCommandId
.
RerunCommand
,
title
:
{
value
:
localize
(
'
workbench.action.terminal.rerunCommand
'
,
"
Re-run Command
"
),
original
:
'
Re-run Command
'
},
f1
:
true
,
category
,
precondition
:
ContextKeyExpr
.
or
(
TerminalContextKeys
.
processSupported
,
TerminalContextKeys
.
terminalHasBeenCreated
)
});
}
async
run
(
accessor
:
ServicesAccessor
):
Promise
<
void
>
{
await
accessor
.
get
(
ITerminalService
).
activeInstance
?.
runRecent
(
'
command
'
);
}
});
registerAction2
(
class
extends
Action2
{
constructor
()
{
super
({
id
:
TerminalCommandId
.
GoToRecentDirectory
,
title
:
{
value
:
localize
(
'
workbench.action.terminal.goToRecentDirectory
'
,
"
Go to Recent Directory
"
),
original
:
'
Go to Recent Directory
'
},
f1
:
true
,
category
,
precondition
:
ContextKeyExpr
.
or
(
TerminalContextKeys
.
processSupported
,
TerminalContextKeys
.
terminalHasBeenCreated
)
});
}
async
run
(
accessor
:
ServicesAccessor
):
Promise
<
void
>
{
await
accessor
.
get
(
ITerminalService
).
activeInstance
?.
runRecent
(
'
cwd
'
);
}
});
registerAction2
(
class
extends
Action2
{
constructor
()
{
super
({
...
...
src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
浏览文件 @
1f110359
...
...
@@ -597,7 +597,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
xterm
.
raw
.
onKey
(
e
=>
this
.
_onKey
(
e
.
key
,
e
.
domEvent
));
xterm
.
raw
.
onSelectionChange
(
async
()
=>
this
.
_onSelectionChange
());
xterm
.
raw
.
buffer
.
onBufferChange
(()
=>
this
.
_refreshAltBufferContextKey
());
this
.
_processManager
.
onProcessData
(
e
=>
this
.
_onProcessData
(
e
));
xterm
.
raw
.
onData
(
async
data
=>
{
await
this
.
_processManager
.
write
(
data
);
...
...
@@ -639,6 +638,10 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this
.
_pathService
.
userHome
().
then
(
userHome
=>
{
this
.
_userHome
=
userHome
.
fsPath
;
});
if
(
this
.
capabilities
.
includes
(
ProcessCapability
.
ShellIntegration
))
{
//TODO: turn off polling for this case
xterm
.
commandTracker
.
onCwdChanged
(
cwd
=>
this
.
_cwd
=
cwd
);
}
return
xterm
;
}
...
...
@@ -858,6 +861,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this
.
_processManager
.
onProcessReady
((
e
)
=>
{
this
.
_linkManager
?.
setWidgetManager
(
this
.
_widgetManager
);
this
.
_capabilities
=
e
.
capabilities
;
this
.
xterm
?.
setCapabilites
(
this
.
_capabilities
);
this
.
_workspaceFolder
=
path
.
basename
(
e
.
cwd
.
toString
());
});
...
...
@@ -916,6 +920,54 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this
.
xterm
?.
raw
.
selectAll
();
}
async
runRecent
(
type
:
'
command
'
|
'
cwd
'
):
Promise
<
void
>
{
const
commands
=
this
.
xterm
?.
commandTracker
.
getCommands
();
if
(
!
commands
||
!
this
.
xterm
)
{
return
;
}
type
Item
=
IQuickPickItem
;
const
items
:
Item
[]
=
[];
if
(
type
===
'
command
'
)
{
for
(
const
{
command
,
timestamp
,
cwd
,
exitCode
}
of
commands
)
{
// trim off /r
const
label
=
command
.
substring
(
0
,
command
.
length
-
1
);
if
(
label
.
length
===
0
)
{
continue
;
}
const
cwdDescription
=
cwd
?
`cwd:
${
cwd
}
`
:
''
;
const
exitCodeDescription
=
exitCode
?
`exitCode:
${
exitCode
}
`
:
''
;
items
.
push
({
label
,
description
:
exitCodeDescription
+
cwdDescription
,
detail
:
timestamp
,
id
:
timestamp
});
}
}
else
{
const
cwds
=
this
.
xterm
.
commandTracker
.
getCommands
().
map
(
c
=>
c
.
cwd
).
filter
(
c
=>
c
!==
undefined
);
const
map
=
new
Map
<
string
,
number
>
();
if
(
!
cwds
)
{
return
;
}
for
(
const
cwd
of
cwds
)
{
const
entry
=
map
.
get
(
cwd
!
);
if
(
entry
)
{
map
.
set
(
cwd
!
,
entry
+
1
);
}
else
{
map
.
set
(
cwd
!
,
1
);
}
}
const
sorted
=
[...
map
.
entries
()].
sort
((
a
,
b
)
=>
b
[
1
]
-
a
[
1
]);
for
(
const
entry
of
sorted
)
{
items
.
push
({
label
:
entry
[
0
]
});
}
}
const
result
=
await
this
.
_quickInputService
.
pick
(
items
.
reverse
(),
{});
if
(
result
)
{
this
.
sendText
(
type
===
'
cwd
'
?
`cd
${
result
.
label
}
`
:
result
.
label
,
true
);
}
}
notifyFindWidgetFocusChanged
(
isFocused
:
boolean
):
void
{
if
(
!
this
.
xterm
)
{
return
;
...
...
src/vs/workbench/contrib/terminal/browser/xterm/commandTrackerAddon.ts
浏览文件 @
1f110359
...
...
@@ -5,12 +5,14 @@
import
type
{
Terminal
,
IMarker
,
ITerminalAddon
}
from
'
xterm
'
;
import
{
ICommandTracker
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
ShellIntegrationInfo
,
ShellIntegrationInteraction
,
TerminalCommand
}
from
'
vs/workbench/contrib/terminal/browser/terminal
'
;
import
{
ProcessCapability
}
from
'
vs/platform/terminal/common/terminal
'
;
import
{
Emitter
}
from
'
vs/base/common/event
'
;
import
{
Disposable
}
from
'
vs/base/common/lifecycle
'
;
/**
* The minimum size of the prompt in which to assume the line is a command.
*/
const
MINIMUM_PROMPT_LENGTH
=
2
;
enum
Boundary
{
Top
,
Bottom
...
...
@@ -21,29 +23,104 @@ export const enum ScrollPosition {
Middle
}
export
class
CommandTrackerAddon
implements
ICommandTracker
,
ITerminalAddon
{
export
class
CommandTrackerAddon
extends
Disposable
implements
ICommandTracker
,
ITerminalAddon
{
private
_currentMarker
:
IMarker
|
Boundary
=
Boundary
.
Bottom
;
private
_selectionStart
:
IMarker
|
Boundary
|
null
=
null
;
private
_isDisposable
:
boolean
=
false
;
private
_terminal
:
Terminal
|
undefined
;
private
_capabilities
:
ProcessCapability
[]
|
undefined
=
undefined
;
private
_dataIsCommand
=
false
;
private
_commands
:
TerminalCommand
[]
=
[];
private
_exitCode
:
number
|
undefined
;
private
_cwd
:
string
|
undefined
;
private
_currentCommand
=
''
;
private
readonly
_onCwdChanged
=
this
.
_register
(
new
Emitter
<
string
>
());
readonly
onCwdChanged
=
this
.
_onCwdChanged
.
event
;
activate
(
terminal
:
Terminal
):
void
{
this
.
_terminal
=
terminal
;
terminal
.
onKey
(
e
=>
this
.
_onKey
(
e
.
key
));
terminal
.
onIntegratedShellChange
(
e
=>
{
if
(
!
this
.
_terminal
)
{
return
;
}
if
(
this
.
_terminal
.
buffer
.
active
.
cursorX
>=
MINIMUM_PROMPT_LENGTH
)
{
if
(
!
this
.
_shellIntegrationEnabled
())
{
terminal
.
onKey
(
e
=>
this
.
_onKey
(
e
.
key
));
}
else
if
(
e
.
type
===
ShellIntegrationInteraction
.
CommandFinished
)
{
this
.
_terminal
?.
registerMarker
(
0
);
this
.
clearMarker
();
}
}
this
.
_handleIntegratedShellChange
(
e
);
});
terminal
.
onData
(
data
=>
{
if
(
this
.
_shellIntegrationEnabled
()
&&
this
.
_dataIsCommand
)
{
this
.
_currentCommand
+=
data
;
}
});
}
private
_shellIntegrationEnabled
():
boolean
{
return
this
.
_capabilities
?.
includes
(
ProcessCapability
.
ShellIntegration
)
||
false
;
}
private
_handleIntegratedShellChange
(
event
:
{
type
:
string
,
value
:
string
}):
void
{
if
(
!
this
.
_shellIntegrationEnabled
())
{
return
;
}
switch
(
event
.
type
)
{
case
ShellIntegrationInfo
.
CurrentDir
:
this
.
_cwd
=
event
.
value
;
this
.
_onCwdChanged
.
fire
(
this
.
_cwd
);
break
;
case
ShellIntegrationInfo
.
RemoteHost
:
break
;
case
ShellIntegrationInteraction
.
PromptStart
:
break
;
case
ShellIntegrationInteraction
.
CommandStart
:
this
.
_dataIsCommand
=
true
;
break
;
case
ShellIntegrationInteraction
.
CommandExecuted
:
break
;
case
ShellIntegrationInteraction
.
CommandFinished
:
this
.
_exitCode
=
Number
.
parseInt
(
event
.
value
);
if
(
!
this
.
_currentCommand
.
startsWith
(
'
\\
'
)
&&
this
.
_currentCommand
!==
''
)
{
this
.
_commands
.
push
(
{
command
:
this
.
_currentCommand
,
timestamp
:
this
.
_getCurrentTimestamp
(),
cwd
:
this
.
_cwd
,
exitCode
:
this
.
_exitCode
});
}
this
.
_currentCommand
=
''
;
break
;
default
:
return
;
}
}
private
_getCurrentTimestamp
():
string
{
const
toTwoDigits
=
(
v
:
number
)
=>
v
<
10
?
`0
${
v
}
`
:
v
;
const
toThreeDigits
=
(
v
:
number
)
=>
v
<
10
?
`00
${
v
}
`
:
v
<
100
?
`0
${
v
}
`
:
v
;
const
currentTime
=
new
Date
();
return
`
${
currentTime
.
getFullYear
()}
-
${
toTwoDigits
(
currentTime
.
getMonth
()
+
1
)}
-
${
toTwoDigits
(
currentTime
.
getDate
())}
${
toTwoDigits
(
currentTime
.
getHours
())}
:
${
toTwoDigits
(
currentTime
.
getMinutes
())}
:
${
toTwoDigits
(
currentTime
.
getSeconds
())}
.
${
toThreeDigits
(
currentTime
.
getMilliseconds
())}
`
;
}
dispose
():
void
{
getCommands
():
TerminalCommand
[]
{
return
this
.
_commands
;
}
override
dispose
():
void
{
}
private
_onKey
(
key
:
string
):
void
{
if
(
key
===
'
\
x0d
'
)
{
this
.
_onEnter
();
}
// Clear the current marker so successive focus/selection actions are performed from the
// bottom of the buffer
this
.
_currentMarker
=
Boundary
.
Bottom
;
this
.
_selectionStart
=
null
;
this
.
clearMarker
();
}
private
_onEnter
():
void
{
...
...
@@ -55,6 +132,19 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon {
}
}
clearMarker
():
void
{
// Clear the current marker so successive focus/selection actions are performed from the
// bottom of the buffer
this
.
_currentMarker
=
Boundary
.
Bottom
;
this
.
_selectionStart
=
null
;
}
setCapabilites
(
capabilties
:
ProcessCapability
[]):
void
{
// this is created before the onProcessReady event
// gets fired, which has the capabilities
this
.
_capabilities
=
capabilties
;
}
scrollToPreviousCommand
(
scrollPosition
:
ScrollPosition
=
ScrollPosition
.
Top
,
retainSelection
:
boolean
=
false
):
void
{
if
(
!
this
.
_terminal
)
{
return
;
...
...
src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts
浏览文件 @
1f110359
...
...
@@ -12,7 +12,7 @@ import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configur
import
{
TerminalConfigHelper
}
from
'
vs/workbench/contrib/terminal/browser/terminalConfigHelper
'
;
import
{
DisposableStore
}
from
'
vs/base/common/lifecycle
'
;
import
{
IEditorOptions
}
from
'
vs/editor/common/config/editorOptions
'
;
import
{
TerminalLocation
,
TerminalSettingId
}
from
'
vs/platform/terminal/common/terminal
'
;
import
{
ProcessCapability
,
TerminalLocation
,
TerminalSettingId
}
from
'
vs/platform/terminal/common/terminal
'
;
import
{
ICommandTracker
,
ITerminalFont
,
TERMINAL_VIEW_ID
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
isSafari
}
from
'
vs/base/browser/browser
'
;
import
{
IXtermTerminal
}
from
'
vs/workbench/contrib/terminal/browser/terminal
'
;
...
...
@@ -139,11 +139,16 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal {
// Load addons
this
.
_updateUnicodeVersion
();
this
.
_commandTrackerAddon
=
new
CommandTrackerAddon
();
this
.
raw
.
loadAddon
(
this
.
_commandTrackerAddon
);
}
setCapabilites
(
capabilties
:
ProcessCapability
[]):
void
{
// this is created before the onProcessReady event
// gets fired, which has the capabilities
this
.
_commandTrackerAddon
.
setCapabilites
(
capabilties
);
}
attachToElement
(
container
:
HTMLElement
)
{
// Update the theme when attaching as the terminal location could have changed
this
.
_updateTheme
();
...
...
src/vs/workbench/contrib/terminal/common/terminal.ts
浏览文件 @
1f110359
...
...
@@ -326,6 +326,13 @@ export interface ICommandTracker {
selectToNextCommand
():
void
;
selectToPreviousLine
():
void
;
selectToNextLine
():
void
;
clearMarker
():
void
;
getCommands
():
{
command
:
string
,
timestamp
:
string
,
cwd
?:
string
,
exitCode
?:
number
}[];
/**
* Fired when shell integration is enabled
* and the command tracker receives an updated cwd
*/
onCwdChanged
:
Event
<
string
>
;
}
export
interface
INavigationMode
{
...
...
@@ -497,6 +504,8 @@ export const enum TerminalCommandId {
SelectDefaultProfile
=
'
workbench.action.terminal.selectDefaultShell
'
,
RunSelectedText
=
'
workbench.action.terminal.runSelectedText
'
,
RunActiveFile
=
'
workbench.action.terminal.runActiveFile
'
,
RerunCommand
=
'
workbench.action.terminal.rerunCommand
'
,
GoToRecentDirectory
=
'
workbench.action.terminal.goToRecentDirectory
'
,
SwitchTerminal
=
'
workbench.action.terminal.switchTerminal
'
,
ScrollDownLine
=
'
workbench.action.terminal.scrollDown
'
,
ScrollDownPage
=
'
workbench.action.terminal.scrollDownPage
'
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录