Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
7d4e15a3
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,发现更多精彩内容 >>
提交
7d4e15a3
编写于
7月 19, 2017
作者:
D
Daniel Imms
提交者:
GitHub
7月 19, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #30732 from Microsoft/amqi/update-window-shellname
Rename terminal instance on enter in Windows
上级
224467ef
b9f99bc7
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
133 addition
and
16 deletion
+133
-16
src/vs/workbench/parts/terminal/common/terminal.ts
src/vs/workbench/parts/terminal/common/terminal.ts
+1
-1
src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts
...kbench/parts/terminal/electron-browser/terminalActions.ts
+1
-1
src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts
...bench/parts/terminal/electron-browser/terminalInstance.ts
+35
-14
src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts
...orkbench/parts/terminal/electron-browser/terminalPanel.ts
+2
-0
src/vs/workbench/parts/terminal/electron-browser/windowsShellHelper.ts
...nch/parts/terminal/electron-browser/windowsShellHelper.ts
+94
-0
未找到文件。
src/vs/workbench/parts/terminal/common/terminal.ts
浏览文件 @
7d4e15a3
...
...
@@ -361,5 +361,5 @@ export interface ITerminalInstance {
/**
* Sets the title of the terminal instance.
*/
setTitle
(
title
:
string
):
void
;
setTitle
(
title
:
string
,
eventFromProcess
:
boolean
):
void
;
}
src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts
浏览文件 @
7d4e15a3
...
...
@@ -622,7 +622,7 @@ export class RenameTerminalAction extends Action {
prompt
:
nls
.
localize
(
'
workbench.action.terminal.rename.prompt
'
,
"
Enter terminal name
"
),
}).
then
(
name
=>
{
if
(
name
)
{
terminalInstance
.
setTitle
(
name
);
terminalInstance
.
setTitle
(
name
,
false
);
}
});
}
...
...
src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts
浏览文件 @
7d4e15a3
...
...
@@ -12,6 +12,7 @@ import * as platform from 'vs/base/common/platform';
import
*
as
dom
from
'
vs/base/browser/dom
'
;
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
Uri
from
'
vs/base/common/uri
'
;
import
{
WindowsShellHelper
}
from
'
vs/workbench/parts/terminal/electron-browser/windowsShellHelper
'
;
import
XTermTerminal
=
require
(
'
xterm
'
);
import
{
Dimension
}
from
'
vs/base/browser/builder
'
;
import
{
IContextKeyService
,
IContextKey
}
from
'
vs/platform/contextkey/common/contextkey
'
;
...
...
@@ -84,6 +85,7 @@ export class TerminalInstance implements ITerminalInstance {
private
_messageTitleListener
:
(
message
:
{
type
:
string
,
content
:
string
})
=>
void
;
private
_preLaunchInputQueue
:
string
;
private
_initialCwd
:
string
;
private
_windowsShellHelper
:
WindowsShellHelper
;
private
_widgetManager
:
TerminalWidgetManager
;
private
_linkHandler
:
TerminalLinkHandler
;
...
...
@@ -138,6 +140,12 @@ export class TerminalInstance implements ITerminalInstance {
this
.
_createProcess
(
this
.
_shellLaunchConfig
);
this
.
_createXterm
();
if
(
platform
.
isWindows
)
{
this
.
_processReady
.
then
(()
=>
{
this
.
_windowsShellHelper
=
new
WindowsShellHelper
(
this
.
_processId
,
this
.
_shellLaunchConfig
.
executable
);
});
}
// Only attach xterm.js to the DOM if the terminal panel has been opened before.
if
(
_container
)
{
this
.
attachToElement
(
_container
);
...
...
@@ -264,6 +272,13 @@ export class TerminalInstance implements ITerminalInstance {
if
(
TabFocus
.
getTabFocusMode
()
&&
event
.
keyCode
===
9
)
{
return
false
;
}
// Windows does not get a process title event from terminalProcess so we check the name on enter
// messageTitleListener is falsy when the API/user renames the terminal so we don't override it
if
(
platform
.
isWindows
&&
event
.
keyCode
===
13
/* ENTER */
&&
this
.
_messageTitleListener
)
{
this
.
_windowsShellHelper
.
getShellName
().
then
(
title
=>
this
.
setTitle
(
title
,
true
));
}
return
undefined
;
});
this
.
_instanceDisposables
.
push
(
dom
.
addDisposableListener
(
this
.
_xterm
.
element
,
'
mouseup
'
,
(
event
:
KeyboardEvent
)
=>
{
...
...
@@ -519,17 +534,17 @@ export class TerminalInstance implements ITerminalInstance {
const
platformKey
=
platform
.
isWindows
?
'
windows
'
:
platform
.
isMacintosh
?
'
osx
'
:
'
linux
'
;
const
envFromConfig
=
{
...
process
.
env
,
...
this
.
_configHelper
.
config
.
env
[
platformKey
]
};
const
env
=
TerminalInstance
.
createTerminalEnv
(
envFromConfig
,
shell
,
this
.
_initialCwd
,
locale
,
this
.
_cols
,
this
.
_rows
);
this
.
_title
=
shell
.
name
||
''
;
this
.
_process
=
cp
.
fork
(
Uri
.
parse
(
require
.
toUrl
(
'
bootstrap
'
)).
fsPath
,
[
'
--type=terminal
'
],
{
env
,
cwd
:
Uri
.
parse
(
path
.
dirname
(
require
.
toUrl
(
'
../node/terminalProcess
'
))).
fsPath
});
if
(
!
shell
.
name
)
{
if
(
shell
.
name
)
{
this
.
setTitle
(
shell
.
name
,
false
);
}
else
{
// Only listen for process title changes when a name is not provided
this
.
_messageTitleListener
=
(
message
)
=>
{
if
(
message
.
type
===
'
title
'
)
{
this
.
_title
=
message
.
content
?
message
.
content
:
''
;
this
.
_onTitleChanged
.
fire
(
this
.
_title
);
this
.
setTitle
(
message
.
content
?
message
.
content
:
''
,
true
);
}
};
this
.
_process
.
on
(
'
message
'
,
this
.
_messageTitleListener
);
...
...
@@ -652,7 +667,7 @@ export class TerminalInstance implements ITerminalInstance {
const
oldTitle
=
this
.
_title
;
this
.
_createProcess
(
shell
);
if
(
oldTitle
!==
this
.
_title
)
{
this
.
_onTitleChanged
.
fire
(
this
.
_titl
e
);
this
.
setTitle
(
this
.
_title
,
tru
e
);
}
this
.
_process
.
on
(
'
message
'
,
(
message
)
=>
this
.
_sendPtyDataToXterm
(
message
));
...
...
@@ -829,19 +844,25 @@ export class TerminalInstance implements ITerminalInstance {
this
.
_terminalProcessFactory
=
factory
;
}
public
setTitle
(
title
:
string
):
void
{
public
setTitle
(
title
:
string
,
eventFromProcess
:
boolean
):
void
{
if
(
eventFromProcess
)
{
if
(
platform
.
isWindows
)
{
// Remove the .exe extension
title
=
path
.
basename
(
title
.
split
(
'
.exe
'
)[
0
]);
}
}
else
{
// If the title has not been set by the API or the rename command, unregister the handler that
// automatically updates the terminal name
if
(
this
.
_process
&&
this
.
_messageTitleListener
)
{
this
.
_process
.
removeListener
(
'
message
'
,
this
.
_messageTitleListener
);
this
.
_messageTitleListener
=
null
;
}
}
const
didTitleChange
=
title
!==
this
.
_title
;
this
.
_title
=
title
;
if
(
didTitleChange
)
{
this
.
_onTitleChanged
.
fire
(
title
);
}
// If the title was not set by the API, unregister the handler that
// automatically updates the terminal name
if
(
this
.
_process
&&
this
.
_messageTitleListener
)
{
this
.
_process
.
removeListener
(
'
message
'
,
this
.
_messageTitleListener
);
this
.
_messageTitleListener
=
null
;
}
}
}
...
...
@@ -866,4 +887,4 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
if
(
scrollbarSliderActiveBackgroundColor
)
{
collector
.
addRule
(
`.monaco-workbench .panel.integrated-terminal .xterm .xterm-viewport::-webkit-scrollbar-thumb:active { background-color:
${
scrollbarSliderActiveBackgroundColor
}
; }`
);
}
});
\ No newline at end of file
});
src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts
浏览文件 @
7d4e15a3
...
...
@@ -3,6 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
*
as
dom
from
'
vs/base/browser/dom
'
;
import
*
as
nls
from
'
vs/nls
'
;
import
*
as
platform
from
'
vs/base/common/platform
'
;
...
...
src/vs/workbench/parts/terminal/electron-browser/windowsShellHelper.ts
0 → 100644
浏览文件 @
7d4e15a3
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
*
as
cp
from
'
child_process
'
;
import
*
as
platform
from
'
vs/base/common/platform
'
;
import
*
as
path
from
'
path
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
Emitter
,
debounceEvent
}
from
'
vs/base/common/event
'
;
const
SHELL_EXECUTABLES
=
[
'
cmd.exe
'
,
'
powershell.exe
'
,
'
bash.exe
'
];
export
class
WindowsShellHelper
{
private
_childProcessIdStack
:
number
[];
private
_onCheckWindowsShell
:
Emitter
<
string
>
;
private
_rootShellExecutable
:
string
;
private
_rootProcessId
:
number
;
public
constructor
(
rootProcessId
:
number
,
rootShellExecutable
:
string
)
{
this
.
_childProcessIdStack
=
[];
this
.
_rootShellExecutable
=
rootShellExecutable
;
this
.
_rootProcessId
=
rootProcessId
;
if
(
!
platform
.
isWindows
)
{
throw
new
Error
(
`WindowsShellHelper cannot be instantiated on
${
platform
.
platform
}
`
);
}
this
.
_onCheckWindowsShell
=
new
Emitter
<
string
>
();
debounceEvent
(
this
.
_onCheckWindowsShell
.
event
,
(
l
,
e
)
=>
e
,
100
,
true
)(()
=>
{
this
.
getShellName
();
});
}
private
getChildProcessDetails
(
pid
:
number
):
TPromise
<
{
executable
:
string
,
pid
:
number
}[]
>
{
return
new
TPromise
((
resolve
,
reject
)
=>
{
cp
.
execFile
(
'
wmic.exe
'
,
[
'
process
'
,
'
where
'
,
`parentProcessId=
${
pid
}
`
,
'
get
'
,
'
ExecutablePath,ProcessId
'
],
(
err
,
stdout
,
stderr
)
=>
{
if
(
err
)
{
reject
(
err
);
}
else
if
(
stderr
.
length
>
0
)
{
resolve
([]);
// No processes found
}
else
{
const
childProcessLines
=
stdout
.
split
(
'
\n
'
).
slice
(
1
).
filter
(
str
=>
!
/^
\s
*$/
.
test
(
str
));
const
childProcessDetails
=
childProcessLines
.
map
(
str
=>
{
const
s
=
str
.
split
(
'
'
);
return
{
executable
:
s
[
0
],
pid
:
Number
(
s
[
1
])
};
});
resolve
(
childProcessDetails
);
}
});
});
}
private
refreshShellProcessTree
(
pid
:
number
,
parent
:
string
):
TPromise
<
string
>
{
return
this
.
getChildProcessDetails
(
pid
).
then
(
result
=>
{
// When we didn't find any child processes of the process
if
(
result
.
length
===
0
)
{
// Case where we found a child process already and are checking further down the pid tree
// We have reached the end here so we know that parent is the deepest first child of the tree
if
(
parent
)
{
return
TPromise
.
as
(
parent
);
}
// Case where we haven't found a child and only the root shell is left
if
(
this
.
_childProcessIdStack
.
length
===
1
)
{
return
TPromise
.
as
(
this
.
_rootShellExecutable
);
}
// Otherwise, we go up the tree to find the next valid deepest child of the root
this
.
_childProcessIdStack
.
pop
();
return
this
.
refreshShellProcessTree
(
this
.
_childProcessIdStack
[
this
.
_childProcessIdStack
.
length
-
1
],
null
);
}
// We only go one level deep when checking for children of processes other then shells
if
(
SHELL_EXECUTABLES
.
indexOf
(
path
.
basename
(
result
[
0
].
executable
))
===
-
1
)
{
return
TPromise
.
as
(
result
[
0
].
executable
);
}
// Save the pid in the stack and keep looking for children of that child
this
.
_childProcessIdStack
.
push
(
result
[
0
].
pid
);
return
this
.
refreshShellProcessTree
(
result
[
0
].
pid
,
result
[
0
].
executable
);
},
error
=>
{
return
error
;
});
}
/**
* Returns the innermost shell executable running in the terminal
*/
public
getShellName
():
TPromise
<
string
>
{
if
(
this
.
_childProcessIdStack
.
length
===
0
)
{
this
.
_childProcessIdStack
.
push
(
this
.
_rootProcessId
);
}
return
new
TPromise
<
string
>
((
resolve
)
=>
{
this
.
refreshShellProcessTree
(
this
.
_childProcessIdStack
[
this
.
_childProcessIdStack
.
length
-
1
],
null
).
then
(
result
=>
{
resolve
(
result
);
},
error
=>
{
return
error
;
});
});
}
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录