Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
c3378834
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,体验更适合开发者的 AI 搜索 >>
提交
c3378834
编写于
3月 14, 2019
作者:
D
Daniel Imms
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Refactor for terminal links in live share
上级
daccb87f
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
161 addition
and
82 deletion
+161
-82
src/vs/workbench/contrib/terminal/browser/terminal.ts
src/vs/workbench/contrib/terminal/browser/terminal.ts
+4
-1
src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
...vs/workbench/contrib/terminal/browser/terminalInstance.ts
+1
-1
src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts
...workbench/contrib/terminal/browser/terminalLinkHandler.ts
+61
-41
src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts
...kbench/contrib/terminal/browser/terminalProcessManager.ts
+16
-6
src/vs/workbench/contrib/terminal/common/terminal.ts
src/vs/workbench/contrib/terminal/common/terminal.ts
+3
-0
src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts
...trib/terminal/electron-browser/terminalInstanceService.ts
+34
-1
src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts
...erminal/test/electron-browser/terminalLinkHandler.test.ts
+42
-32
未找到文件。
src/vs/workbench/contrib/terminal/browser/terminal.ts
浏览文件 @
c3378834
...
...
@@ -6,7 +6,8 @@
import
{
Terminal
as
XTermTerminal
}
from
'
vscode-xterm
'
;
import
{
ITerminalInstance
,
IWindowsShellHelper
,
ITerminalProcessManager
,
ITerminalConfigHelper
,
ITerminalChildProcess
,
IShellLaunchConfig
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
createDecorator
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IProcessEnvironment
}
from
'
vs/base/common/platform
'
;
import
{
IProcessEnvironment
,
OperatingSystem
}
from
'
vs/base/common/platform
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
export
const
ITerminalInstanceService
=
createDecorator
<
ITerminalInstanceService
>
(
'
terminalInstanceService
'
);
...
...
@@ -17,6 +18,8 @@ export interface ITerminalInstanceService {
createWindowsShellHelper
(
shellProcessId
:
number
,
instance
:
ITerminalInstance
,
xterm
:
XTermTerminal
):
IWindowsShellHelper
;
createTerminalProcessManager
(
id
:
number
,
configHelper
:
ITerminalConfigHelper
):
ITerminalProcessManager
;
createTerminalProcess
(
shellLaunchConfig
:
IShellLaunchConfig
,
cwd
:
string
,
cols
:
number
,
rows
:
number
,
env
:
IProcessEnvironment
,
windowsEnableConpty
:
boolean
):
ITerminalChildProcess
;
getRemoteOperatingSystem
():
Promise
<
OperatingSystem
|
undefined
>
;
getRemoteUserHome
():
Promise
<
URI
|
undefined
>
;
}
export
interface
IBrowserTerminalConfigHelper
extends
ITerminalConfigHelper
{
...
...
src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
浏览文件 @
c3378834
...
...
@@ -430,7 +430,7 @@ export class TerminalInstance implements ITerminalInstance {
this
.
_processManager
.
onProcessData
(
data
=>
this
.
_onProcessData
(
data
));
this
.
_xterm
.
on
(
'
data
'
,
data
=>
this
.
_processManager
!
.
write
(
data
));
// TODO: How does the cwd work on detached processes?
this
.
_linkHandler
=
this
.
_instantiationService
.
createInstance
(
TerminalLinkHandler
,
this
.
_xterm
,
platform
.
platform
);
this
.
_linkHandler
=
this
.
_instantiationService
.
createInstance
(
TerminalLinkHandler
,
this
.
_xterm
,
platform
.
platform
,
this
.
_processManager
);
this
.
processReady
.
then
(
async
()
=>
{
this
.
_linkHandler
.
processCwd
=
await
this
.
_processManager
!
.
getInitialCwd
();
});
...
...
src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts
浏览文件 @
c3378834
...
...
@@ -4,18 +4,19 @@
*--------------------------------------------------------------------------------------------*/
import
*
as
nls
from
'
vs/nls
'
;
import
*
as
path
from
'
vs/base/common/path
'
;
import
*
as
platform
from
'
vs/base/common/platform
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
dispose
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
IOpenerService
}
from
'
vs/platform/opener/common/opener
'
;
import
{
TerminalWidgetManager
}
from
'
vs/workbench/contrib/terminal/browser/terminalWidgetManager
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
ITerminalService
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
ITerminalService
,
ITerminalProcessManager
}
from
'
vs/workbench/contrib/terminal/common/terminal
'
;
import
{
ITextEditorSelection
}
from
'
vs/platform/editor/common/editor
'
;
import
{
IEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
ILinkMatcherOptions
}
from
'
vscode-xterm
'
;
import
{
REMOTE_HOST_SCHEME
}
from
'
vs/platform/remote/common/remoteHosts
'
;
import
{
posix
,
win32
}
from
'
vs/base/common/path
'
;
const
pathPrefix
=
'
(
\\
.
\\
.?|
\\
~)
'
;
const
pathSeparatorClause
=
'
\\
/
'
;
...
...
@@ -57,12 +58,16 @@ const LOCAL_LINK_PRIORITY = -2;
export
type
XtermLinkMatcherHandler
=
(
event
:
MouseEvent
,
uri
:
string
)
=>
boolean
|
void
;
export
type
XtermLinkMatcherValidationCallback
=
(
uri
:
string
,
callback
:
(
isValid
:
boolean
)
=>
void
)
=>
void
;
interface
IPath
{
join
(...
paths
:
string
[]):
string
;
normalize
(
path
:
string
):
string
;
}
export
class
TerminalLinkHandler
{
private
_hoverDisposables
:
IDisposable
[]
=
[];
private
_mouseMoveDisposable
:
IDisposable
;
private
_widgetManager
:
TerminalWidgetManager
;
private
_processCwd
:
string
;
private
_localLinkPattern
:
RegExp
;
private
_gitDiffPreImagePattern
:
RegExp
;
private
_gitDiffPostImagePattern
:
RegExp
;
private
readonly
_tooltipCallback
:
(
event
:
MouseEvent
,
uri
:
string
)
=>
boolean
|
void
;
...
...
@@ -70,15 +75,13 @@ export class TerminalLinkHandler {
constructor
(
private
_xterm
:
any
,
private
_platform
:
platform
.
Platform
,
private
readonly
_processManager
:
ITerminalProcessManager
,
@
IOpenerService
private
readonly
_openerService
:
IOpenerService
,
@
IEditorService
private
readonly
_editorService
:
IEditorService
,
@
IConfigurationService
private
readonly
_configurationService
:
IConfigurationService
,
@
ITerminalService
private
readonly
_terminalService
:
ITerminalService
,
@
IFileService
private
readonly
_fileService
:
IFileService
)
{
const
baseLocalLinkClause
=
_platform
===
platform
.
Platform
.
Windows
?
winLocalLinkClause
:
unixLocalLinkClause
;
// Append line and column number regex
this
.
_localLinkPattern
=
new
RegExp
(
`
${
baseLocalLinkClause
}
(
${
lineAndColumnClause
}
)`
);
// Matches '--- a/src/file1', capturing 'src/file1' in group 1
this
.
_gitDiffPreImagePattern
=
/^--- a
\/(\S
*
)
/
;
// Matches '+++ b/src/file1', capturing 'src/file1' in group 1
...
...
@@ -183,7 +186,9 @@ export class TerminalLinkHandler {
}
protected
get
_localLinkRegex
():
RegExp
{
return
this
.
_localLinkPattern
;
const
baseLocalLinkClause
=
this
.
_processManager
.
os
===
platform
.
OperatingSystem
.
Windows
?
winLocalLinkClause
:
unixLocalLinkClause
;
// Append line and column number regex
return
new
RegExp
(
`
${
baseLocalLinkClause
}
(
${
lineAndColumnClause
}
)`
);
}
protected
get
_gitDiffPreImageRegex
():
RegExp
{
...
...
@@ -199,19 +204,12 @@ export class TerminalLinkHandler {
if
(
!
resolvedLink
)
{
return
Promise
.
resolve
(
null
);
}
const
normalizedPath
=
path
.
normalize
(
path
.
resolve
(
resolvedLink
));
const
normalizedUrl
=
this
.
extractLinkUrl
(
normalizedPath
);
if
(
!
normalizedUrl
)
{
return
Promise
.
resolve
(
null
);
}
const
resource
=
URI
.
file
(
normalizedUrl
);
const
lineColumnInfo
:
LineColumnInfo
=
this
.
extractLineColumnInfo
(
link
);
const
selection
:
ITextEditorSelection
=
{
startLineNumber
:
lineColumnInfo
.
lineNumber
,
startColumn
:
lineColumnInfo
.
columnNumber
};
return
this
.
_editorService
.
openEditor
({
resource
,
options
:
{
pinned
:
true
,
selection
}
});
return
this
.
_editorService
.
openEditor
({
resource
:
resolvedLink
,
options
:
{
pinned
:
true
,
selection
}
});
});
}
...
...
@@ -247,37 +245,41 @@ export class TerminalLinkHandler {
return
nls
.
localize
(
'
terminalLinkHandler.followLinkCtrl
'
,
'
Ctrl + click to follow link
'
);
}
private
get
osPath
():
IPath
{
if
(
this
.
_processManager
.
os
===
platform
.
OperatingSystem
.
Windows
)
{
return
win32
;
}
return
posix
;
}
protected
_preprocessPath
(
link
:
string
):
string
|
null
{
if
(
this
.
_platform
===
platform
.
Platform
.
Windows
)
{
// Resolve ~ -> %HOMEDRIVE%\%HOMEPATH%
if
(
link
.
charAt
(
0
)
===
'
~
'
)
{
if
(
!
process
.
env
.
HOMEDRIVE
||
!
process
.
env
.
HOMEPATH
)
{
return
null
;
if
(
link
.
charAt
(
0
)
===
'
~
'
)
{
// Resolve ~ -> userHome
link
=
this
.
osPath
.
join
(
this
.
_processManager
.
userHome
,
link
.
substring
(
1
));
}
else
if
(
link
.
charAt
(
0
)
!==
'
/
'
&&
link
.
charAt
(
0
)
!==
'
~
'
)
{
// Resolve workspace path . | .. | <relative_path> -> <path>/. | <path>/.. | <path>/<relative_path>
if
(
this
.
_processManager
.
os
===
platform
.
OperatingSystem
.
Windows
)
{
if
(
!
link
.
match
(
'
^
'
+
winDrivePrefix
))
{
if
(
!
this
.
_processCwd
)
{
// Abort if no workspace is open
return
null
;
}
link
=
this
.
osPath
.
join
(
this
.
_processCwd
,
link
);
}
link
=
`
${
process
.
env
.
HOMEDRIVE
}
\
\$
{process.env.HOMEPATH + link.substring(1)}`
;
}
// Resolve relative paths (.\a, ..\a, ~\a, a\b)
if
(
!
link
.
match
(
'
^
'
+
winDrivePrefix
))
{
}
else
{
if
(
!
this
.
_processCwd
)
{
// Abort if no workspace is open
return
null
;
}
link
=
p
ath
.
join
(
this
.
_processCwd
,
link
);
link
=
this
.
osP
ath
.
join
(
this
.
_processCwd
,
link
);
}
}
// Resolve workspace path . | .. | <relative_path> -> <path>/. | <path>/.. | <path>/<relative_path>
else
if
(
link
.
charAt
(
0
)
!==
'
/
'
&&
link
.
charAt
(
0
)
!==
'
~
'
)
{
if
(
!
this
.
_processCwd
)
{
// Abort if no workspace is open
return
null
;
}
link
=
path
.
join
(
this
.
_processCwd
,
link
);
}
link
=
this
.
osPath
.
normalize
(
link
);
return
link
;
}
private
_resolvePath
(
link
:
string
):
PromiseLike
<
string
|
null
>
{
private
_resolvePath
(
link
:
string
):
PromiseLike
<
URI
|
null
>
{
const
preprocessedLink
=
this
.
_preprocessPath
(
link
);
if
(
!
preprocessedLink
)
{
return
Promise
.
resolve
(
null
);
...
...
@@ -288,13 +290,31 @@ export class TerminalLinkHandler {
return
Promise
.
resolve
(
null
);
}
// Ensure the file exists on disk, so an editor can be opened after clicking it
return
this
.
_fileService
.
resolveFile
(
URI
.
file
(
linkUrl
)).
then
(
stat
=>
{
if
(
stat
.
isDirectory
)
{
return
null
;
try
{
let
uri
:
URI
;
if
(
this
.
_processManager
.
remoteAuthority
)
{
uri
=
URI
.
from
({
scheme
:
REMOTE_HOST_SCHEME
,
authority
:
this
.
_processManager
.
remoteAuthority
,
path
:
linkUrl
});
}
else
{
uri
=
URI
.
file
(
linkUrl
);
}
return
preprocessedLink
;
});
return
this
.
_fileService
.
resolveFile
(
uri
).
then
(
stat
=>
{
if
(
stat
.
isDirectory
)
{
return
null
;
}
return
uri
;
}).
catch
(()
=>
{
// Does not exist
return
null
;
});
}
catch
{
// Errors in parsing the path
return
Promise
.
resolve
(
null
);
}
}
/**
...
...
src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts
浏览文件 @
c3378834
...
...
@@ -38,6 +38,9 @@ export class TerminalProcessManager implements ITerminalProcessManager {
public
processState
:
ProcessState
=
ProcessState
.
UNINITIALIZED
;
public
ptyProcessReady
:
Promise
<
void
>
;
public
shellProcessId
:
number
;
public
remoteAuthority
:
string
|
undefined
;
public
os
:
platform
.
OperatingSystem
;
public
userHome
:
string
;
private
_process
:
ITerminalChildProcess
|
null
=
null
;
private
_preLaunchInputQueue
:
string
[]
=
[];
...
...
@@ -96,17 +99,24 @@ export class TerminalProcessManager implements ITerminalProcessManager {
cols
:
number
,
rows
:
number
):
void
{
let
launchRemotely
=
false
;
const
forceExtHostProcess
=
(
this
.
_configHelper
.
config
as
any
).
extHostProcess
;
if
(
shellLaunchConfig
.
cwd
&&
typeof
shellLaunchConfig
.
cwd
===
'
object
'
)
{
launchRemotely
=
!!
getRemoteAuthority
(
shellLaunchConfig
.
cwd
);
this
.
remoteAuthority
=
getRemoteAuthority
(
shellLaunchConfig
.
cwd
);
}
else
{
launchRemotely
=
!!
this
.
_windowService
.
getConfiguration
().
remoteAuthority
;
this
.
remoteAuthority
=
this
.
_windowService
.
getConfiguration
().
remoteAuthority
;
}
const
hasRemoteAuthority
=
!!
this
.
remoteAuthority
;
let
launchRemotely
=
hasRemoteAuthority
||
forceExtHostProcess
;
this
.
userHome
=
this
.
_environmentService
.
userHome
;
this
.
os
=
platform
.
OS
;
if
(
launchRemotely
)
{
if
(
hasRemoteAuthority
)
{
this
.
_terminalInstanceService
.
getRemoteUserHome
().
then
(
userHome
=>
this
.
userHome
=
userHome
.
path
);
this
.
_terminalInstanceService
.
getRemoteOperatingSystem
().
then
(
os
=>
this
.
os
=
os
);
}
if
(
launchRemotely
||
forceExtHostProcess
)
{
const
activeWorkspaceRootUri
=
this
.
_historyService
.
getLastActiveWorkspaceRoot
(
forceExtHostProcess
?
undefined
:
REMOTE_HOST_SCHEME
);
const
activeWorkspaceRootUri
=
this
.
_historyService
.
getLastActiveWorkspaceRoot
(
hasRemoteAuthority
?
REMOTE_HOST_SCHEME
:
undefined
);
this
.
_process
=
this
.
_instantiationService
.
createInstance
(
TerminalProcessExtHostProxy
,
this
.
_terminalId
,
shellLaunchConfig
,
activeWorkspaceRootUri
,
cols
,
rows
);
}
else
{
if
(
!
shellLaunchConfig
.
executable
)
{
...
...
src/vs/workbench/contrib/terminal/common/terminal.ts
浏览文件 @
c3378834
...
...
@@ -637,6 +637,9 @@ export interface ITerminalProcessManager extends IDisposable {
readonly
processState
:
ProcessState
;
readonly
ptyProcessReady
:
Promise
<
void
>
;
readonly
shellProcessId
:
number
;
readonly
remoteAuthority
:
string
|
undefined
;
readonly
os
:
platform
.
OperatingSystem
;
readonly
userHome
:
string
;
readonly
onProcessReady
:
Event
<
void
>
;
readonly
onProcessData
:
Event
<
string
>
;
...
...
src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts
浏览文件 @
c3378834
...
...
@@ -10,8 +10,10 @@ import { ITerminalInstance, IWindowsShellHelper, ITerminalConfigHelper, ITermina
import
{
WindowsShellHelper
}
from
'
vs/workbench/contrib/terminal/node/windowsShellHelper
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
TerminalProcessManager
}
from
'
vs/workbench/contrib/terminal/browser/terminalProcessManager
'
;
import
{
IProcessEnvironment
}
from
'
vs/base/common/platform
'
;
import
{
IProcessEnvironment
,
OperatingSystem
}
from
'
vs/base/common/platform
'
;
import
{
TerminalProcess
}
from
'
vs/workbench/contrib/terminal/node/terminalProcess
'
;
import
{
IRemoteAgentService
,
IRemoteAgentEnvironment
}
from
'
vs/workbench/services/remote/node/remoteAgentService
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
let
Terminal
:
typeof
XTermTerminal
;
...
...
@@ -23,8 +25,11 @@ let Terminal: typeof XTermTerminal;
export
class
TerminalInstanceService
implements
ITerminalInstanceService
{
public
_serviceBrand
:
any
;
private
_remoteAgentEnvironment
:
IRemoteAgentEnvironment
|
undefined
|
null
;
constructor
(
@
IInstantiationService
private
readonly
_instantiationService
:
IInstantiationService
,
@
IRemoteAgentService
private
readonly
_remoteAgentService
:
IRemoteAgentService
)
{
}
...
...
@@ -54,4 +59,32 @@ export class TerminalInstanceService implements ITerminalInstanceService {
public
createTerminalProcess
(
shellLaunchConfig
:
IShellLaunchConfig
,
cwd
:
string
,
cols
:
number
,
rows
:
number
,
env
:
IProcessEnvironment
,
windowsEnableConpty
:
boolean
):
ITerminalChildProcess
{
return
new
TerminalProcess
(
shellLaunchConfig
,
cwd
,
cols
,
rows
,
env
,
windowsEnableConpty
);
}
private
async
_fetchRemoteAgentEnvironment
():
Promise
<
IRemoteAgentEnvironment
|
null
>
{
if
(
this
.
_remoteAgentEnvironment
===
undefined
)
{
const
connection
=
await
this
.
_remoteAgentService
.
getConnection
();
if
(
!
connection
)
{
this
.
_remoteAgentEnvironment
=
null
;
return
this
.
_remoteAgentEnvironment
;
}
this
.
_remoteAgentEnvironment
=
await
connection
.
getEnvironment
();
}
return
this
.
_remoteAgentEnvironment
;
}
public
async
getRemoteUserHome
():
Promise
<
URI
|
undefined
>
{
const
env
=
await
this
.
_fetchRemoteAgentEnvironment
();
if
(
env
===
null
)
{
return
undefined
;
}
return
env
.
userHome
;
}
public
async
getRemoteOperatingSystem
():
Promise
<
OperatingSystem
|
undefined
>
{
const
env
=
await
this
.
_fetchRemoteAgentEnvironment
();
if
(
env
===
null
)
{
return
undefined
;
}
return
env
.
os
;
}
}
\ No newline at end of file
src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts
浏览文件 @
c3378834
...
...
@@ -4,11 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import
*
as
assert
from
'
assert
'
;
import
{
Platform
}
from
'
vs/base/common/platform
'
;
import
{
Platform
,
OperatingSystem
}
from
'
vs/base/common/platform
'
;
import
{
TerminalLinkHandler
,
LineColumnInfo
}
from
'
vs/workbench/contrib/terminal/browser/terminalLinkHandler
'
;
import
*
as
strings
from
'
vs/base/common/strings
'
;
import
*
as
path
from
'
vs/base/common/path
'
;
import
*
as
sinon
from
'
sinon
'
;
class
TestTerminalLinkHandler
extends
TerminalLinkHandler
{
public
get
localLinkRegex
():
RegExp
{
...
...
@@ -39,7 +37,10 @@ interface LinkFormatInfo {
suite
(
'
Workbench - TerminalLinkHandler
'
,
()
=>
{
suite
(
'
localLinkRegex
'
,
()
=>
{
test
(
'
Windows
'
,
()
=>
{
const
terminalLinkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Windows
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
const
terminalLinkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Windows
,
{
os
:
OperatingSystem
.
Windows
,
userHome
:
''
}
as
any
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
function
testLink
(
link
:
string
,
linkUrl
:
string
,
lineNo
?:
string
,
columnNo
?:
string
)
{
assert
.
equal
(
terminalLinkHandler
.
extractLinkUrl
(
link
),
linkUrl
);
assert
.
equal
(
terminalLinkHandler
.
extractLinkUrl
(
`:
${
link
}
:`
),
linkUrl
);
...
...
@@ -111,7 +112,10 @@ suite('Workbench - TerminalLinkHandler', () => {
});
test
(
'
Linux
'
,
()
=>
{
const
terminalLinkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Linux
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
const
terminalLinkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Linux
,
{
os
:
OperatingSystem
.
Linux
,
userHome
:
''
}
as
any
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
function
testLink
(
link
:
string
,
linkUrl
:
string
,
lineNo
?:
string
,
columnNo
?:
string
)
{
assert
.
equal
(
terminalLinkHandler
.
extractLinkUrl
(
link
),
linkUrl
);
assert
.
equal
(
terminalLinkHandler
.
extractLinkUrl
(
`:
${
link
}
:`
),
linkUrl
);
...
...
@@ -175,58 +179,64 @@ suite('Workbench - TerminalLinkHandler', () => {
suite
(
'
preprocessPath
'
,
()
=>
{
test
(
'
Windows
'
,
()
=>
{
const
linkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Windows
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
const
linkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Windows
,
{
os
:
OperatingSystem
.
Windows
,
userHome
:
'
C:
\\
Users
\\
Me
'
}
as
any
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
linkHandler
.
processCwd
=
'
C:
\\
base
'
;
let
stub
=
sinon
.
stub
(
path
,
'
join
'
,
function
(
arg1
:
string
,
arg2
:
string
)
{
return
arg1
+
'
\\
'
+
arg2
;
});
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
./src/file1
'
),
'
C:
\\
base
\\
./src/file1
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
./src/file1
'
),
'
C:
\\
base
\\
src
\\
file1
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
src
\\
file2
'
),
'
C:
\\
base
\\
src
\\
file2
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
C:
\\
absolute
\\
path
\\
file3
'
),
'
C:
\\
absolute
\\
path
\\
file3
'
);
stub
.
restore
(
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
~/src/file3
'
),
'
C:
\\
Users
\\
Me
\\
src
\\
file3
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
~
\\
src
\\
file4
'
),
'
C:
\\
Users
\\
Me
\\
src
\\
file4
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
C:
\\
absolute
\\
path
\\
file5
'
),
'
C:
\\
absolute
\\
path
\\
file5
'
);
});
test
(
'
Windows - spaces
'
,
()
=>
{
const
linkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Windows
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
const
linkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Windows
,
{
os
:
OperatingSystem
.
Windows
,
userHome
:
'
C:
\\
Users
\\
M e
'
}
as
any
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
linkHandler
.
processCwd
=
'
C:
\\
base dir
'
;
let
stub
=
sinon
.
stub
(
path
,
'
join
'
,
function
(
arg1
:
string
,
arg2
:
string
)
{
return
arg1
+
'
\\
'
+
arg2
;
});
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
./src/file1
'
),
'
C:
\\
base dir
\\
./src/file1
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
./src/file1
'
),
'
C:
\\
base dir
\\
src
\\
file1
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
src
\\
file2
'
),
'
C:
\\
base dir
\\
src
\\
file2
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
C:
\\
absolute
\\
path
\\
file3
'
),
'
C:
\\
absolute
\\
path
\\
file3
'
);
stub
.
restore
(
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
~/src/file3
'
),
'
C:
\\
Users
\\
M e
\\
src
\\
file3
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
~
\\
src
\\
file4
'
),
'
C:
\\
Users
\\
M e
\\
src
\\
file4
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
C:
\\
abso lute
\\
path
\\
file5
'
),
'
C:
\\
abso lute
\\
path
\\
file5
'
);
});
test
(
'
Linux
'
,
()
=>
{
const
linkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Linux
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
const
linkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Linux
,
{
os
:
OperatingSystem
.
Linux
,
userHome
:
'
/home/me
'
}
as
any
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
linkHandler
.
processCwd
=
'
/base
'
;
let
stub
=
sinon
.
stub
(
path
,
'
join
'
,
function
(
arg1
:
string
,
arg2
:
string
)
{
return
arg1
+
'
/
'
+
arg2
;
});
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
./src/file1
'
),
'
/base/./src/file1
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
./src/file1
'
),
'
/base/src/file1
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
src/file2
'
),
'
/base/src/file2
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
/absolute/path/file3
'
),
'
/absolute/path
/file3
'
);
stub
.
restore
(
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
~/src/file3
'
),
'
/home/me/src
/file3
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
/absolute/path/file4
'
),
'
/absolute/path/file4
'
);
});
test
(
'
No Workspace
'
,
()
=>
{
const
linkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Linux
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
const
linkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Linux
,
{
os
:
OperatingSystem
.
Linux
,
userHome
:
'
/home/me
'
}
as
any
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
./src/file1
'
),
null
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
src/file2
'
),
null
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
/absolute/path/file3
'
),
'
/absolute/path/file3
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
~/src/file3
'
),
'
/home/me/src/file3
'
);
assert
.
equal
(
linkHandler
.
preprocessPath
(
'
/absolute/path/file4
'
),
'
/absolute/path/file4
'
);
});
});
test
(
'
gitDiffLinkRegex
'
,
()
=>
{
// The platform is irrelevant because the links generated by Git are the same format regardless of platform
const
linkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Linux
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
const
linkHandler
=
new
TestTerminalLinkHandler
(
new
TestXterm
(),
Platform
.
Linux
,
{
os
:
OperatingSystem
.
Linux
,
userHome
:
''
}
as
any
,
null
!
,
null
!
,
null
!
,
null
!
,
null
!
);
function
assertAreGoodMatches
(
matches
:
RegExpMatchArray
|
null
)
{
if
(
matches
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录