Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
036a087a
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,发现更多精彩内容 >>
提交
036a087a
编写于
4月 16, 2018
作者:
D
Daniel Imms
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Move environment helper functions into own module
上级
0b1b44d3
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
166 addition
and
152 deletion
+166
-152
src/vs/workbench/parts/terminal/common/terminal.ts
src/vs/workbench/parts/terminal/common/terminal.ts
+0
-1
src/vs/workbench/parts/terminal/electron-browser/terminalEnvironment.ts
...ch/parts/terminal/electron-browser/terminalEnvironment.ts
+159
-0
src/vs/workbench/parts/terminal/electron-browser/terminalProcessManager.ts
...parts/terminal/electron-browser/terminalProcessManager.ts
+7
-151
未找到文件。
src/vs/workbench/parts/terminal/common/terminal.ts
浏览文件 @
036a087a
...
...
@@ -459,7 +459,6 @@ export interface ITerminalCommandTracker {
export
interface
ITerminalProcessMessage
{
type
:
'
pid
'
|
'
data
'
|
'
title
'
;
// TODO: Use conditional type so type is narrowed
content
:
number
|
string
;
}
...
...
src/vs/workbench/parts/terminal/electron-browser/terminalEnvironment.ts
0 → 100644
浏览文件 @
036a087a
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
*
as
os
from
'
os
'
;
import
*
as
path
from
'
path
'
;
import
*
as
platform
from
'
vs/base/common/platform
'
;
import
pkg
from
'
vs/platform/node/package
'
;
import
Uri
from
'
vs/base/common/uri
'
;
import
{
IStringDictionary
}
from
'
vs/base/common/collections
'
;
import
{
IWorkspaceFolder
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
IShellLaunchConfig
,
ITerminalConfigHelper
}
from
'
vs/workbench/parts/terminal/common/terminal
'
;
import
{
IConfigurationResolverService
}
from
'
vs/workbench/services/configurationResolver/common/configurationResolver
'
;
/**
* This module contains utility functions related to the environment, cwd and paths.
*/
export
function
mergeEnvironments
(
parent
:
IStringDictionary
<
string
>
,
other
:
IStringDictionary
<
string
>
)
{
if
(
!
other
)
{
return
;
}
// On Windows apply the new values ignoring case, while still retaining
// the case of the original key.
if
(
platform
.
isWindows
)
{
for
(
let
configKey
in
other
)
{
let
actualKey
=
configKey
;
for
(
let
envKey
in
parent
)
{
if
(
configKey
.
toLowerCase
()
===
envKey
.
toLowerCase
())
{
actualKey
=
envKey
;
break
;
}
}
const
value
=
other
[
configKey
];
_mergeEnvironmentValue
(
parent
,
actualKey
,
value
);
}
}
else
{
Object
.
keys
(
other
).
forEach
((
key
)
=>
{
const
value
=
other
[
key
];
_mergeEnvironmentValue
(
parent
,
key
,
value
);
});
}
}
function
_mergeEnvironmentValue
(
env
:
IStringDictionary
<
string
>
,
key
:
string
,
value
:
string
|
null
)
{
if
(
typeof
value
===
'
string
'
)
{
env
[
key
]
=
value
;
}
else
{
delete
env
[
key
];
}
}
export
function
createTerminalEnv
(
parentEnv
:
IStringDictionary
<
string
>
,
shell
:
IShellLaunchConfig
,
cwd
:
string
,
locale
:
string
,
cols
?:
number
,
rows
?:
number
):
IStringDictionary
<
string
>
{
const
env
=
{
...
parentEnv
};
if
(
shell
.
env
)
{
mergeEnvironments
(
env
,
shell
.
env
);
}
env
[
'
PTYPID
'
]
=
process
.
pid
.
toString
();
env
[
'
PTYSHELL
'
]
=
shell
.
executable
;
env
[
'
TERM_PROGRAM
'
]
=
'
vscode
'
;
env
[
'
TERM_PROGRAM_VERSION
'
]
=
pkg
.
version
;
if
(
shell
.
args
)
{
if
(
typeof
shell
.
args
===
'
string
'
)
{
env
[
`PTYSHELLCMDLINE`
]
=
shell
.
args
;
}
else
{
shell
.
args
.
forEach
((
arg
,
i
)
=>
env
[
`PTYSHELLARG
${
i
}
`
]
=
arg
);
}
}
env
[
'
PTYCWD
'
]
=
cwd
;
env
[
'
LANG
'
]
=
_getLangEnvVariable
(
locale
);
if
(
cols
&&
rows
)
{
env
[
'
PTYCOLS
'
]
=
cols
.
toString
();
env
[
'
PTYROWS
'
]
=
rows
.
toString
();
}
env
[
'
AMD_ENTRYPOINT
'
]
=
'
vs/workbench/parts/terminal/node/terminalProcess
'
;
return
env
;
}
// TODO:should be protected/non-static
export
function
resolveConfigurationVariables
(
configurationResolverService
:
IConfigurationResolverService
,
env
:
IStringDictionary
<
string
>
,
lastActiveWorkspaceRoot
:
IWorkspaceFolder
):
IStringDictionary
<
string
>
{
Object
.
keys
(
env
).
forEach
((
key
)
=>
{
if
(
typeof
env
[
key
]
===
'
string
'
)
{
env
[
key
]
=
configurationResolverService
.
resolve
(
lastActiveWorkspaceRoot
,
env
[
key
]);
}
});
return
env
;
}
function
_getLangEnvVariable
(
locale
?:
string
)
{
const
parts
=
locale
?
locale
.
split
(
'
-
'
)
:
[];
const
n
=
parts
.
length
;
if
(
n
===
0
)
{
// Fallback to en_US to prevent possible encoding issues.
return
'
en_US.UTF-8
'
;
}
if
(
n
===
1
)
{
// app.getLocale can return just a language without a variant, fill in the variant for
// supported languages as many shells expect a 2-part locale.
const
languageVariants
=
{
de
:
'
DE
'
,
en
:
'
US
'
,
es
:
'
ES
'
,
fi
:
'
FI
'
,
fr
:
'
FR
'
,
it
:
'
IT
'
,
ja
:
'
JP
'
,
ko
:
'
KR
'
,
pl
:
'
PL
'
,
ru
:
'
RU
'
,
zh
:
'
CN
'
};
if
(
parts
[
0
]
in
languageVariants
)
{
parts
.
push
(
languageVariants
[
parts
[
0
]]);
}
}
else
{
// Ensure the variant is uppercase
parts
[
1
]
=
parts
[
1
].
toUpperCase
();
}
return
parts
.
join
(
'
_
'
)
+
'
.UTF-8
'
;
}
export
function
getCwd
(
shell
:
IShellLaunchConfig
,
root
:
Uri
,
configHelper
:
ITerminalConfigHelper
):
string
{
if
(
shell
.
cwd
)
{
return
shell
.
cwd
;
}
let
cwd
:
string
;
// TODO: Handle non-existent customCwd
if
(
!
shell
.
ignoreConfigurationCwd
)
{
// Evaluate custom cwd first
const
customCwd
=
configHelper
.
config
.
cwd
;
if
(
customCwd
)
{
if
(
path
.
isAbsolute
(
customCwd
))
{
cwd
=
customCwd
;
}
else
if
(
root
)
{
cwd
=
path
.
normalize
(
path
.
join
(
root
.
fsPath
,
customCwd
));
}
}
}
// If there was no custom cwd or it was relative with no workspace
if
(
!
cwd
)
{
cwd
=
root
?
root
.
fsPath
:
os
.
homedir
();
}
return
_sanitizeCwd
(
cwd
);
}
function
_sanitizeCwd
(
cwd
:
string
):
string
{
// Make the drive letter uppercase on Windows (see #9448)
if
(
platform
.
platform
===
platform
.
Platform
.
Windows
&&
cwd
&&
cwd
[
1
]
===
'
:
'
)
{
return
cwd
[
0
].
toUpperCase
()
+
cwd
.
substr
(
1
);
}
return
cwd
;
}
src/vs/workbench/parts/terminal/electron-browser/terminalProcessManager.ts
浏览文件 @
036a087a
...
...
@@ -4,19 +4,17 @@
*--------------------------------------------------------------------------------------------*/
import
*
as
cp
from
'
child_process
'
;
import
*
as
os
from
'
os
'
;
import
*
as
path
from
'
path
'
;
import
*
as
platform
from
'
vs/base/common/platform
'
;
import
*
as
terminalEnvironment
from
'
vs/workbench/parts/terminal/electron-browser/terminalEnvironment
'
;
import
Uri
from
'
vs/base/common/uri
'
;
import
pkg
from
'
vs/platform/node/package
'
;
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
ProcessState
,
ITerminalProcessManager
,
ITerminalProcessMessage
,
IShellLaunchConfig
,
ITerminalConfigHelper
}
from
'
vs/workbench/parts/terminal/common/terminal
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
ILogService
}
from
'
vs/platform/log/common/log
'
;
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
IStringDictionary
}
from
'
vs/base/common/collections
'
;
import
{
IConfigurationResolverService
}
from
'
vs/workbench/services/configurationResolver/common/configurationResolver
'
;
import
{
IWorkspace
Folder
,
IWorkspace
ContextService
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
IWorkspaceContextService
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
IHistoryService
}
from
'
vs/workbench/services/history/common/history
'
;
/** The amount of time to consider terminal errors to be related to the launch */
...
...
@@ -95,22 +93,22 @@ export class TerminalProcessManager implements ITerminalProcessManager {
}
const
lastActiveWorkspaceRootUri
=
this
.
_historyService
.
getLastActiveWorkspaceRoot
(
'
file
'
);
this
.
initialCwd
=
t
his
.
_getCwd
(
shellLaunchConfig
,
lastActiveWorkspaceRootUri
);
this
.
initialCwd
=
t
erminalEnvironment
.
getCwd
(
shellLaunchConfig
,
lastActiveWorkspaceRootUri
,
this
.
_configHelper
);
// Resolve env vars from config and shell
const
lastActiveWorkspaceRoot
=
this
.
_workspaceContextService
.
getWorkspaceFolder
(
lastActiveWorkspaceRootUri
);
const
platformKey
=
platform
.
isWindows
?
'
windows
'
:
(
platform
.
isMacintosh
?
'
osx
'
:
'
linux
'
);
const
envFromConfig
=
TerminalProcessManager
.
resolveConfigurationVariables
(
this
.
_configurationResolverService
,
{
...
this
.
_configHelper
.
config
.
env
[
platformKey
]
},
lastActiveWorkspaceRoot
);
const
envFromShell
=
TerminalProcessManager
.
resolveConfigurationVariables
(
this
.
_configurationResolverService
,
{
...
shellLaunchConfig
.
env
},
lastActiveWorkspaceRoot
);
const
envFromConfig
=
terminalEnvironment
.
resolveConfigurationVariables
(
this
.
_configurationResolverService
,
{
...
this
.
_configHelper
.
config
.
env
[
platformKey
]
},
lastActiveWorkspaceRoot
);
const
envFromShell
=
terminalEnvironment
.
resolveConfigurationVariables
(
this
.
_configurationResolverService
,
{
...
shellLaunchConfig
.
env
},
lastActiveWorkspaceRoot
);
shellLaunchConfig
.
env
=
envFromShell
;
// Merge process env with the env from config
const
parentEnv
=
{
...
process
.
env
};
TerminalProcessManager
.
mergeEnvironments
(
parentEnv
,
envFromConfig
);
terminalEnvironment
.
mergeEnvironments
(
parentEnv
,
envFromConfig
);
// Continue env initialization, merging in the env from the launch
// config and adding keys that are needed to create the process
const
env
=
TerminalProcessManager
.
createTerminalEnv
(
parentEnv
,
shellLaunchConfig
,
this
.
initialCwd
,
locale
,
cols
,
rows
);
const
env
=
terminalEnvironment
.
createTerminalEnv
(
parentEnv
,
shellLaunchConfig
,
this
.
initialCwd
,
locale
,
cols
,
rows
);
const
cwd
=
Uri
.
parse
(
path
.
dirname
(
require
.
toUrl
(
'
../node/terminalProcess
'
))).
fsPath
;
const
options
=
{
env
,
cwd
};
this
.
_logService
.
debug
(
`Terminal process launching`
,
options
);
...
...
@@ -141,34 +139,6 @@ export class TerminalProcessManager implements ITerminalProcessManager {
}
}
protected
_getCwd
(
shell
:
IShellLaunchConfig
,
root
:
Uri
):
string
{
if
(
shell
.
cwd
)
{
return
shell
.
cwd
;
}
let
cwd
:
string
;
// TODO: Handle non-existent customCwd
if
(
!
shell
.
ignoreConfigurationCwd
)
{
// Evaluate custom cwd first
const
customCwd
=
this
.
_configHelper
.
config
.
cwd
;
if
(
customCwd
)
{
if
(
path
.
isAbsolute
(
customCwd
))
{
cwd
=
customCwd
;
}
else
if
(
root
)
{
cwd
=
path
.
normalize
(
path
.
join
(
root
.
fsPath
,
customCwd
));
}
}
}
// If there was no custom cwd or it was relative with no workspace
if
(
!
cwd
)
{
cwd
=
root
?
root
.
fsPath
:
os
.
homedir
();
}
return
TerminalProcessManager
.
_sanitizeCwd
(
cwd
);
}
public
write
(
data
:
string
):
void
{
if
(
this
.
shellProcessId
)
{
// Send data if the pty is ready
...
...
@@ -225,118 +195,4 @@ export class TerminalProcessManager implements ITerminalProcessManager {
this
.
_onProcessExit
.
fire
(
exitCode
);
}
public
static
mergeEnvironments
(
parent
:
IStringDictionary
<
string
>
,
other
:
IStringDictionary
<
string
>
)
{
if
(
!
other
)
{
return
;
}
// On Windows apply the new values ignoring case, while still retaining
// the case of the original key.
if
(
platform
.
isWindows
)
{
for
(
let
configKey
in
other
)
{
let
actualKey
=
configKey
;
for
(
let
envKey
in
parent
)
{
if
(
configKey
.
toLowerCase
()
===
envKey
.
toLowerCase
())
{
actualKey
=
envKey
;
break
;
}
}
const
value
=
other
[
configKey
];
TerminalProcessManager
.
_mergeEnvironmentValue
(
parent
,
actualKey
,
value
);
}
}
else
{
Object
.
keys
(
other
).
forEach
((
key
)
=>
{
const
value
=
other
[
key
];
TerminalProcessManager
.
_mergeEnvironmentValue
(
parent
,
key
,
value
);
});
}
}
private
static
_mergeEnvironmentValue
(
env
:
IStringDictionary
<
string
>
,
key
:
string
,
value
:
string
|
null
)
{
if
(
typeof
value
===
'
string
'
)
{
env
[
key
]
=
value
;
}
else
{
delete
env
[
key
];
}
}
// TODO: This should be private/protected
public
static
createTerminalEnv
(
parentEnv
:
IStringDictionary
<
string
>
,
shell
:
IShellLaunchConfig
,
cwd
:
string
,
locale
:
string
,
cols
?:
number
,
rows
?:
number
):
IStringDictionary
<
string
>
{
const
env
=
{
...
parentEnv
};
if
(
shell
.
env
)
{
TerminalProcessManager
.
mergeEnvironments
(
env
,
shell
.
env
);
}
env
[
'
PTYPID
'
]
=
process
.
pid
.
toString
();
env
[
'
PTYSHELL
'
]
=
shell
.
executable
;
env
[
'
TERM_PROGRAM
'
]
=
'
vscode
'
;
env
[
'
TERM_PROGRAM_VERSION
'
]
=
pkg
.
version
;
if
(
shell
.
args
)
{
if
(
typeof
shell
.
args
===
'
string
'
)
{
env
[
`PTYSHELLCMDLINE`
]
=
shell
.
args
;
}
else
{
shell
.
args
.
forEach
((
arg
,
i
)
=>
env
[
`PTYSHELLARG
${
i
}
`
]
=
arg
);
}
}
env
[
'
PTYCWD
'
]
=
cwd
;
env
[
'
LANG
'
]
=
TerminalProcessManager
.
_getLangEnvVariable
(
locale
);
if
(
cols
&&
rows
)
{
env
[
'
PTYCOLS
'
]
=
cols
.
toString
();
env
[
'
PTYROWS
'
]
=
rows
.
toString
();
}
env
[
'
AMD_ENTRYPOINT
'
]
=
'
vs/workbench/parts/terminal/node/terminalProcess
'
;
return
env
;
}
// TODO:should be protected/non-static
private
static
resolveConfigurationVariables
(
configurationResolverService
:
IConfigurationResolverService
,
env
:
IStringDictionary
<
string
>
,
lastActiveWorkspaceRoot
:
IWorkspaceFolder
):
IStringDictionary
<
string
>
{
Object
.
keys
(
env
).
forEach
((
key
)
=>
{
if
(
typeof
env
[
key
]
===
'
string
'
)
{
env
[
key
]
=
configurationResolverService
.
resolve
(
lastActiveWorkspaceRoot
,
env
[
key
]);
}
});
return
env
;
}
private
static
_sanitizeCwd
(
cwd
:
string
)
{
// Make the drive letter uppercase on Windows (see #9448)
if
(
platform
.
platform
===
platform
.
Platform
.
Windows
&&
cwd
&&
cwd
[
1
]
===
'
:
'
)
{
return
cwd
[
0
].
toUpperCase
()
+
cwd
.
substr
(
1
);
}
return
cwd
;
}
private
static
_getLangEnvVariable
(
locale
?:
string
)
{
const
parts
=
locale
?
locale
.
split
(
'
-
'
)
:
[];
const
n
=
parts
.
length
;
if
(
n
===
0
)
{
// Fallback to en_US to prevent possible encoding issues.
return
'
en_US.UTF-8
'
;
}
if
(
n
===
1
)
{
// app.getLocale can return just a language without a variant, fill in the variant for
// supported languages as many shells expect a 2-part locale.
const
languageVariants
=
{
de
:
'
DE
'
,
en
:
'
US
'
,
es
:
'
ES
'
,
fi
:
'
FI
'
,
fr
:
'
FR
'
,
it
:
'
IT
'
,
ja
:
'
JP
'
,
ko
:
'
KR
'
,
pl
:
'
PL
'
,
ru
:
'
RU
'
,
zh
:
'
CN
'
};
if
(
parts
[
0
]
in
languageVariants
)
{
parts
.
push
(
languageVariants
[
parts
[
0
]]);
}
}
else
{
// Ensure the variant is uppercase
parts
[
1
]
=
parts
[
1
].
toUpperCase
();
}
return
parts
.
join
(
'
_
'
)
+
'
.UTF-8
'
;
}
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录