Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
27c5f644
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,发现更多精彩内容 >>
提交
27c5f644
编写于
2月 14, 2017
作者:
D
Daniel Imms
提交者:
GitHub
2月 14, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #20582 from Microsoft/tyriar/7321
Terminal links
上级
62383be3
1a76f05c
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
166 addition
and
5 deletion
+166
-5
npm-shrinkwrap.json
npm-shrinkwrap.json
+2
-2
src/vs/workbench/parts/terminal/electron-browser/media/xterm.css
...workbench/parts/terminal/electron-browser/media/xterm.css
+10
-0
src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts
...bench/parts/terminal/electron-browser/terminalInstance.ts
+7
-2
src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.ts
...ch/parts/terminal/electron-browser/terminalLinkHandler.ts
+92
-0
src/vs/workbench/parts/terminal/electron-browser/terminalService.ts
...kbench/parts/terminal/electron-browser/terminalService.ts
+5
-1
src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts
...erminal/test/electron-browser/terminalLinkHandler.test.ts
+50
-0
未找到文件。
npm-shrinkwrap.json
浏览文件 @
27c5f644
...
...
@@ -425,9 +425,9 @@
"resolved"
:
"https://registry.npmjs.org/winreg/-/winreg-1.2.0.tgz"
},
"xterm"
:
{
"version"
:
"2.
2.3
"
,
"version"
:
"2.
3.0
"
,
"from"
:
"Tyriar/xterm.js#vscode-release/1.10"
,
"resolved"
:
"git+https://github.com/Tyriar/xterm.js.git#
90cd66bf353b86ad52d7b650760d8d879dd1c7b8
"
"resolved"
:
"git+https://github.com/Tyriar/xterm.js.git#
5513303451202b0135601a2f026602ed391b3906
"
},
"yauzl"
:
{
"version"
:
"2.3.1"
,
...
...
src/vs/workbench/parts/terminal/electron-browser/media/xterm.css
浏览文件 @
27c5f644
...
...
@@ -58,6 +58,16 @@
opacity
:
0
!important
;
}
.monaco-workbench
.panel.integrated-terminal
.xterm
a
{
color
:
inherit
;
text-decoration
:
none
;
}
.monaco-workbench
.panel.integrated-terminal
.xterm
a
:hover
{
cursor
:
pointer
;
text-decoration
:
underline
;
}
.monaco-workbench
.panel.integrated-terminal
.xterm
:not
(
.xterm-cursor-style-underline
)
:not
(
.xterm-cursor-style-bar
)
.focus
.reverse-video
,
.monaco-workbench
.panel.integrated-terminal
.xterm
:not
(
.xterm-cursor-style-underline
)
:not
(
.xterm-cursor-style-bar
)
:focus
.reverse-video
{
color
:
#CCC
;
}
.vs-dark
.monaco-workbench
.panel.integrated-terminal
.xterm
:not
(
.xterm-cursor-style-underline
)
:not
(
.xterm-cursor-style-bar
)
.focus
.reverse-video
,
...
...
src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts
浏览文件 @
27c5f644
...
...
@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
*
as
path
from
'
path
'
;
import
DOM
=
require
(
'
vs/base/browser/dom
'
);
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
URI
from
'
vs/base/common/uri
'
;
...
...
@@ -10,7 +11,6 @@ import cp = require('child_process');
import
lifecycle
=
require
(
'
vs/base/common/lifecycle
'
);
import
nls
=
require
(
'
vs/nls
'
);
import
os
=
require
(
'
os
'
);
import
path
=
require
(
'
path
'
);
import
platform
=
require
(
'
vs/base/common/platform
'
);
import
xterm
=
require
(
'
xterm
'
);
import
{
Dimension
}
from
'
vs/base/browser/builder
'
;
...
...
@@ -22,9 +22,11 @@ import { IStringDictionary } from 'vs/base/common/collections';
import
{
ITerminalInstance
,
KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED
,
TERMINAL_PANEL_ID
,
IShellLaunchConfig
}
from
'
vs/workbench/parts/terminal/common/terminal
'
;
import
{
ITerminalProcessFactory
}
from
'
vs/workbench/parts/terminal/electron-browser/terminal
'
;
import
{
IWorkspace
,
IWorkspaceContextService
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
StandardKeyboardEvent
}
from
'
vs/base/browser/keyboardEvent
'
;
import
{
TabFocus
}
from
'
vs/editor/common/config/commonEditorConfig
'
;
import
{
TerminalConfigHelper
}
from
'
vs/workbench/parts/terminal/electron-browser/terminalConfigHelper
'
;
import
{
TerminalLinkHandler
}
from
'
vs/workbench/parts/terminal/electron-browser/terminalLinkHandler
'
;
/** The amount of time to consider terminal errors to be related to the launch */
const
LAUNCHING_DURATION
=
500
;
...
...
@@ -74,13 +76,15 @@ export class TerminalInstance implements ITerminalInstance {
public
constructor
(
private
_terminalFocusContextKey
:
IContextKey
<
boolean
>
,
private
_configHelper
:
TerminalConfigHelper
,
private
_linkHandler
:
TerminalLinkHandler
,
private
_container
:
HTMLElement
,
private
_shellLaunchConfig
:
IShellLaunchConfig
,
@
IContextKeyService
private
_contextKeyService
:
IContextKeyService
,
@
IKeybindingService
private
_keybindingService
:
IKeybindingService
,
@
IMessageService
private
_messageService
:
IMessageService
,
@
IPanelService
private
_panelService
:
IPanelService
,
@
IWorkspaceContextService
private
_contextService
:
IWorkspaceContextService
@
IWorkspaceContextService
private
_contextService
:
IWorkspaceContextService
,
@
IWorkbenchEditorService
private
_editorService
:
IWorkbenchEditorService
)
{
this
.
_instanceDisposables
=
[];
this
.
_processDisposables
=
[];
...
...
@@ -139,6 +143,7 @@ export class TerminalInstance implements ITerminalInstance {
this
.
_xtermElement
=
document
.
createElement
(
'
div
'
);
this
.
_xterm
.
open
(
this
.
_xtermElement
);
this
.
_xterm
.
registerLinkMatcher
(
this
.
_linkHandler
.
localLinkRegex
,
(
url
)
=>
this
.
_linkHandler
.
handleLocalLink
(
url
),
1
);
this
.
_xterm
.
attachCustomKeydownHandler
((
event
:
KeyboardEvent
)
=>
{
// Disable all input if the terminal is exiting
if
(
this
.
_isExiting
)
{
...
...
src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.ts
0 → 100644
浏览文件 @
27c5f644
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
*
as
path
from
'
path
'
;
import
*
as
pfs
from
'
vs/base/node/pfs
'
;
import
Uri
from
'
vs/base/common/uri
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IWorkspaceContextService
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
Platform
}
from
'
vs/base/common/platform
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
const
pathPrefix
=
'
(
\\
.
\\
.?|
\\
~)
'
;
const
pathSeparatorClause
=
'
\\
/
'
;
const
excludedPathCharactersClause
=
'
[^
\\
0
\\
s!$`&*()+
\'
":;]
'
;
// '":; are allowed in paths but they are often separators so ignore them
const
escapedExcludedPathCharactersClause
=
'
(
\\\\
s|
\\\\
!|
\\\\
$|
\\\\
`|
\\\\
&|
\\\\
*|(|)|
\\
+)
'
;
/** A regex that matches paths in the form /path, ~/path, ./path, ../path */
const
UNIX_LIKE_LOCAL_LINK_REGEX
=
new
RegExp
(
'
(
'
+
pathPrefix
+
'
?(
'
+
pathSeparatorClause
+
'
(
'
+
excludedPathCharactersClause
+
'
|
'
+
escapedExcludedPathCharactersClause
+
'
)+)+)
'
);
const
winPathPrefix
=
'
([a-zA-Z]:|
\\
.
\\
.?|
\\
~)
'
;
const
winPathSeparatorClause
=
'
(
\\\\
|
\\
/)
'
;
const
winExcludedPathCharactersClause
=
'
[^
\\
0<>
\\
?
\\
|
\\
/
\\
s!$`&*()+
\'
":;]
'
;
/** A regex that matches paths in the form c:\path, ~\path, .\path */
const
WINDOWS_LOCAL_LINK_REGEX
=
new
RegExp
(
'
(
'
+
winPathPrefix
+
'
?(
'
+
winPathSeparatorClause
+
'
(
'
+
winExcludedPathCharactersClause
+
'
)+)+)
'
);
export
class
TerminalLinkHandler
{
constructor
(
private
_platform
:
Platform
,
@
IWorkbenchEditorService
private
_editorService
:
IWorkbenchEditorService
,
@
IWorkspaceContextService
private
_contextService
:
IWorkspaceContextService
)
{
}
public
get
localLinkRegex
():
RegExp
{
if
(
this
.
_platform
===
Platform
.
Windows
)
{
return
WINDOWS_LOCAL_LINK_REGEX
;
}
return
UNIX_LIKE_LOCAL_LINK_REGEX
;
}
public
handleLocalLink
(
link
:
string
):
TPromise
<
void
>
{
if
(
this
.
_platform
===
Platform
.
Windows
)
{
return
this
.
_handleWindowsLocalLink
(
link
);
}
return
this
.
_handleUnixLikeLocalLink
(
link
);
}
private
_handleUnixLikeLocalLink
(
link
:
string
):
TPromise
<
void
>
{
// Resolve ~ -> $HOME
if
(
link
.
charAt
(
0
)
===
'
~
'
)
{
if
(
!
process
.
env
.
HOME
)
{
return
TPromise
.
as
(
void
0
);
}
link
=
process
.
env
.
HOME
+
link
.
substring
(
1
);
}
return
this
.
_handleCommonLocalLink
(
link
);
}
private
_handleWindowsLocalLink
(
link
:
string
):
TPromise
<
void
>
{
// Resolve ~ -> %HOMEDRIVE%\%HOMEPATH%
if
(
link
.
charAt
(
0
)
===
'
~
'
)
{
if
(
!
process
.
env
.
HOMEDRIVE
||
!
process
.
env
.
HOMEPATH
)
{
return
TPromise
.
as
(
void
0
);
}
link
=
`
${
process
.
env
.
HOMEDRIVE
}
\
\$
{process.env.HOMEPATH + link.substring(1)}`
;
}
return
this
.
_handleCommonLocalLink
(
link
);
}
private
_handleCommonLocalLink
(
link
:
string
):
TPromise
<
void
>
{
// Resolve workspace path . / .. -> <path>/. / <path/..
if
(
link
.
charAt
(
0
)
===
'
.
'
)
{
if
(
!
this
.
_contextService
.
hasWorkspace
)
{
// Abort if no workspace is open
return
TPromise
.
as
(
void
0
);
}
link
=
path
.
join
(
this
.
_contextService
.
getWorkspace
().
resource
.
fsPath
,
link
);
}
// Clean up the path
const
resource
=
Uri
.
file
(
path
.
normalize
(
path
.
resolve
(
link
)));
// Open an editor if the path exists
return
pfs
.
fileExists
(
link
).
then
(
isFile
=>
{
if
(
!
isFile
)
{
return
void
0
;
}
return
this
.
_editorService
.
openEditor
({
resource
}).
then
(()
=>
void
0
);
});
}
}
src/vs/workbench/parts/terminal/electron-browser/terminalService.ts
浏览文件 @
27c5f644
...
...
@@ -15,12 +15,14 @@ import { ITerminalInstance, ITerminalService, IShellLaunchConfig, KEYBINDING_CON
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
TerminalConfigHelper
}
from
'
vs/workbench/parts/terminal/electron-browser/terminalConfigHelper
'
;
import
{
TerminalInstance
}
from
'
vs/workbench/parts/terminal/electron-browser/terminalInstance
'
;
import
{
TerminalLinkHandler
}
from
'
vs/workbench/parts/terminal/electron-browser/terminalLinkHandler
'
;
export
class
TerminalService
implements
ITerminalService
{
public
_serviceBrand
:
any
;
private
_activeTerminalInstanceIndex
:
number
;
private
_configHelper
:
TerminalConfigHelper
;
private
_linkHandler
:
TerminalLinkHandler
;
private
_onActiveInstanceChanged
:
Emitter
<
string
>
;
private
_onInstanceDisposed
:
Emitter
<
ITerminalInstance
>
;
private
_onInstanceProcessIdReady
:
Emitter
<
ITerminalInstance
>
;
...
...
@@ -57,7 +59,8 @@ export class TerminalService implements ITerminalService {
this
.
_configurationService
.
onDidUpdateConfiguration
(()
=>
this
.
updateConfig
());
this
.
_terminalFocusContextKey
=
KEYBINDING_CONTEXT_TERMINAL_FOCUS
.
bindTo
(
this
.
_contextKeyService
);
this
.
_configHelper
=
<
TerminalConfigHelper
>
this
.
_instantiationService
.
createInstance
(
TerminalConfigHelper
,
platform
.
platform
);
this
.
_configHelper
=
this
.
_instantiationService
.
createInstance
(
TerminalConfigHelper
,
platform
.
platform
);
this
.
_linkHandler
=
this
.
_instantiationService
.
createInstance
(
TerminalLinkHandler
,
platform
.
platform
);
this
.
onInstanceDisposed
((
terminalInstance
)
=>
{
this
.
_removeInstance
(
terminalInstance
);
});
}
...
...
@@ -65,6 +68,7 @@ export class TerminalService implements ITerminalService {
let
terminalInstance
=
this
.
_instantiationService
.
createInstance
(
TerminalInstance
,
this
.
_terminalFocusContextKey
,
this
.
_configHelper
,
this
.
_linkHandler
,
this
.
_terminalContainer
,
shell
);
terminalInstance
.
addDisposable
(
terminalInstance
.
onTitleChanged
(
this
.
_onInstanceTitleChanged
.
fire
,
this
.
_onInstanceTitleChanged
));
...
...
src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts
0 → 100644
浏览文件 @
27c5f644
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
{
Platform
}
from
'
vs/base/common/platform
'
;
import
{
TerminalLinkHandler
}
from
'
vs/workbench/parts/terminal/electron-browser/terminalLinkHandler
'
;
suite
(
'
Workbench - TerminalLinkHandler
'
,
()
=>
{
suite
(
'
localLinkRegex
'
,
()
=>
{
test
(
'
Windows
'
,
()
=>
{
const
regex
=
new
TerminalLinkHandler
(
Platform
.
Windows
,
null
,
null
).
localLinkRegex
;
function
testLink
(
link
:
string
)
{
assert
.
equal
(
`
${
link
}
`
.
match
(
regex
)[
1
],
link
);
assert
.
equal
(
`:
${
link
}
:`
.
match
(
regex
)[
1
],
link
);
assert
.
equal
(
`;
${
link
}
;`
.
match
(
regex
)[
1
],
link
);
assert
.
equal
(
`(
${
link
}
)`
.
match
(
regex
)[
1
],
link
);
}
testLink
(
'
c:
\\
foo
'
);
testLink
(
'
c:/foo
'
);
testLink
(
'
.
\\
foo
'
);
testLink
(
'
./foo
'
);
testLink
(
'
..
\\
foo
'
);
testLink
(
'
../foo
'
);
testLink
(
'
~
\\
foo
'
);
testLink
(
'
~/foo
'
);
testLink
(
'
c:/a/long/path
'
);
testLink
(
'
c:
\\
a
\\
long
\\
path
'
);
testLink
(
'
c:
\\
mixed/slash
\\
path
'
);
});
test
(
'
Linux
'
,
()
=>
{
const
regex
=
new
TerminalLinkHandler
(
Platform
.
Linux
,
null
,
null
).
localLinkRegex
;
function
testLink
(
link
:
string
)
{
assert
.
equal
(
`
${
link
}
`
.
match
(
regex
)[
1
],
link
);
assert
.
equal
(
`:
${
link
}
:`
.
match
(
regex
)[
1
],
link
);
assert
.
equal
(
`;
${
link
}
;`
.
match
(
regex
)[
1
],
link
);
assert
.
equal
(
`(
${
link
}
)`
.
match
(
regex
)[
1
],
link
);
}
testLink
(
'
/foo
'
);
testLink
(
'
~/foo
'
);
testLink
(
'
./foo
'
);
testLink
(
'
../foo
'
);
testLink
(
'
/a/long/path
'
);
});
});
});
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录