Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
徽霖
Vscode
提交
0f312a4c
V
Vscode
项目概览
徽霖
/
Vscode
通知
9
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,发现更多精彩内容 >>
提交
0f312a4c
编写于
9月 06, 2017
作者:
C
Christof Marti
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Explore using ripgrep for QuickOpen (#24074)
上级
30b21868
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
94 addition
and
20 deletion
+94
-20
src/vs/platform/telemetry/common/experiments.ts
src/vs/platform/telemetry/common/experiments.ts
+3
-1
src/vs/workbench/parts/search/browser/openFileHandler.ts
src/vs/workbench/parts/search/browser/openFileHandler.ts
+4
-1
src/vs/workbench/parts/search/common/queryBuilder.ts
src/vs/workbench/parts/search/common/queryBuilder.ts
+1
-1
src/vs/workbench/services/search/node/fileSearch.ts
src/vs/workbench/services/search/node/fileSearch.ts
+14
-7
src/vs/workbench/services/search/node/ripgrepFileSearch.ts
src/vs/workbench/services/search/node/ripgrepFileSearch.ts
+49
-0
src/vs/workbench/services/search/node/ripgrepTextSearch.ts
src/vs/workbench/services/search/node/ripgrepTextSearch.ts
+8
-10
src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts
...h/test/electron-browser/quickopen.perf.integrationTest.ts
+15
-0
未找到文件。
src/vs/platform/telemetry/common/experiments.ts
浏览文件 @
0f312a4c
...
...
@@ -9,6 +9,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
import
{
createDecorator
}
from
'
vs/platform/instantiation/common/instantiation
'
;
export
interface
IExperiments
{
ripgrepQuickSearch
:
boolean
;
deployToAzureQuickLink
:
boolean
;
}
...
...
@@ -57,11 +58,12 @@ function applyOverrides(experiments: IExperiments, configurationService: IConfig
function
splitExperimentsRandomness
(
storageService
:
IStorageService
):
IExperiments
{
const
random1
=
getExperimentsRandomness
(
storageService
);
const
[
random2
,
/* showTaskDocumentation */
]
=
splitRandom
(
random1
);
const
[
random2
,
ripgrepQuickSearch
]
=
splitRandom
(
random1
);
const
[
/* random3 */
,
deployToAzureQuickLink
]
=
splitRandom
(
random2
);
// const [random4, /* mergeQuickLinks */] = splitRandom(random3);
// const [random5, /* enableWelcomePage */] = splitRandom(random4);
return
{
ripgrepQuickSearch
,
deployToAzureQuickLink
};
}
...
...
src/vs/workbench/parts/search/browser/openFileHandler.ts
浏览文件 @
0f312a4c
...
...
@@ -32,6 +32,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IRange
}
from
'
vs/editor/common/core/range
'
;
import
{
getOutOfWorkspaceEditorResources
}
from
'
vs/workbench/parts/search/common/search
'
;
import
{
IExperimentService
}
from
'
vs/platform/telemetry/common/experiments
'
;
export
class
FileQuickOpenModel
extends
QuickOpenModel
{
...
...
@@ -122,6 +123,7 @@ export class OpenFileHandler extends QuickOpenHandler {
@
IWorkbenchThemeService
private
themeService
:
IWorkbenchThemeService
,
@
IWorkspaceContextService
private
contextService
:
IWorkspaceContextService
,
@
ISearchService
private
searchService
:
ISearchService
,
@
IExperimentService
private
experimentService
:
IExperimentService
,
@
IEnvironmentService
private
environmentService
:
IEnvironmentService
)
{
super
();
...
...
@@ -193,7 +195,8 @@ export class OpenFileHandler extends QuickOpenHandler {
filePattern
:
''
,
cacheKey
:
cacheKey
,
maxResults
:
0
,
sortByScore
:
true
sortByScore
:
true
,
useRipgrep
:
this
.
experimentService
.
getExperiments
().
ripgrepQuickSearch
};
const
folderResources
=
this
.
contextService
.
hasWorkspace
()
?
this
.
contextService
.
getWorkspace
().
roots
:
[];
...
...
src/vs/workbench/parts/search/common/queryBuilder.ts
浏览文件 @
0f312a4c
...
...
@@ -55,7 +55,7 @@ export class QueryBuilder {
}
}
const
useRipgrep
=
!
folderResources
||
folderResources
.
every
(
folder
=>
{
const
useRipgrep
=
type
===
QueryType
.
File
?
options
.
useRipgrep
:
!
folderResources
||
folderResources
.
every
(
folder
=>
{
const
folderConfig
=
this
.
configurationService
.
getConfiguration
<
ISearchConfiguration
>
(
undefined
,
{
resource
:
folder
});
return
folderConfig
.
search
.
useRipgrep
;
});
...
...
src/vs/workbench/services/search/node/fileSearch.ts
浏览文件 @
0f312a4c
...
...
@@ -26,12 +26,14 @@ import { IProgress, IUncachedSearchStats } from 'vs/platform/search/common/searc
import
extfs
=
require
(
'
vs/base/node/extfs
'
);
import
flow
=
require
(
'
vs/base/node/flow
'
);
import
{
IRawFileMatch
,
ISerializedSearchComplete
,
IRawSearch
,
ISearchEngine
,
IFolderSearch
}
from
'
./search
'
;
import
{
spawnRipgrepCmd
}
from
'
./ripgrepFileSearch
'
;
enum
Traversal
{
Node
=
1
,
MacFind
,
WindowsDir
,
LinuxFind
LinuxFind
,
Ripgrep
}
interface
IDirectoryEntry
{
...
...
@@ -151,16 +153,19 @@ export class FileWalker {
let
traverse
=
this
.
nodeJSTraversal
;
if
(
!
this
.
maxFilesize
)
{
if
(
platform
.
isMacintosh
)
{
if
(
this
.
config
.
useRipgrep
)
{
this
.
traversal
=
Traversal
.
Ripgrep
;
traverse
=
this
.
cmdTraversal
;
}
else
if
(
platform
.
isMacintosh
)
{
this
.
traversal
=
Traversal
.
MacFind
;
traverse
=
this
.
fin
dTraversal
;
traverse
=
this
.
cm
dTraversal
;
// Disable 'dir' for now (#11181, #11179, #11183, #11182).
}
/* else if (platform.isWindows) {
this.traversal = Traversal.WindowsDir;
traverse = this.windowsDirTraversal;
} */
else
if
(
platform
.
isLinux
)
{
this
.
traversal
=
Traversal
.
LinuxFind
;
traverse
=
this
.
fin
dTraversal
;
traverse
=
this
.
cm
dTraversal
;
}
}
...
...
@@ -200,7 +205,7 @@ export class FileWalker {
}
}
private
fin
dTraversal
(
folderQuery
:
IFolderSearch
,
onResult
:
(
result
:
IRawFileMatch
)
=>
void
,
cb
:
(
err
?:
Error
)
=>
void
):
void
{
private
cm
dTraversal
(
folderQuery
:
IFolderSearch
,
onResult
:
(
result
:
IRawFileMatch
)
=>
void
,
cb
:
(
err
?:
Error
)
=>
void
):
void
{
const
rootFolder
=
folderQuery
.
folder
;
const
isMac
=
platform
.
isMacintosh
;
let
done
=
(
err
?:
Error
)
=>
{
...
...
@@ -210,7 +215,8 @@ export class FileWalker {
let
leftover
=
''
;
let
first
=
true
;
const
tree
=
this
.
initDirectoryTree
();
const
cmd
=
this
.
spawnFindCmd
(
folderQuery
);
const
useRipgrep
=
this
.
config
.
useRipgrep
;
const
cmd
=
useRipgrep
?
spawnRipgrepCmd
(
folderQuery
,
this
.
config
.
includePattern
,
this
.
folderExcludePatterns
.
get
(
folderQuery
.
folder
)).
cmd
:
this
.
spawnFindCmd
(
folderQuery
);
this
.
collectStdout
(
cmd
,
'
utf8
'
,
(
err
:
Error
,
stdout
?:
string
,
last
?:
boolean
)
=>
{
if
(
err
)
{
done
(
err
);
...
...
@@ -219,7 +225,7 @@ export class FileWalker {
// Mac: uses NFD unicode form on disk, but we want NFC
const
normalized
=
leftover
+
(
isMac
?
strings
.
normalizeNFC
(
stdout
)
:
stdout
);
const
relativeFiles
=
normalized
.
split
(
'
\n
./
'
);
const
relativeFiles
=
normalized
.
split
(
useRipgrep
?
'
\n
'
:
'
\n
./
'
);
if
(
first
&&
normalized
.
length
>=
2
)
{
first
=
false
;
relativeFiles
[
0
]
=
relativeFiles
[
0
].
trim
().
substr
(
2
);
...
...
@@ -240,6 +246,7 @@ export class FileWalker {
return
;
}
// TODO: Optimize siblings clauses with ripgrep here.
this
.
addDirectoryEntries
(
tree
,
rootFolder
,
relativeFiles
,
onResult
);
if
(
last
)
{
...
...
src/vs/workbench/services/search/node/ripgrepFileSearch.ts
0 → 100644
浏览文件 @
0f312a4c
/*---------------------------------------------------------------------------------------------
* 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
{
rgPath
}
from
'
vscode-ripgrep
'
;
import
*
as
glob
from
'
vs/base/common/glob
'
;
import
{
IFolderSearch
}
from
'
./search
'
;
import
{
foldersToIncludeGlobs
,
foldersToRgExcludeGlobs
}
from
'
./ripgrepTextSearch
'
;
export
function
spawnRipgrepCmd
(
folderQuery
:
IFolderSearch
,
includePattern
:
glob
.
IExpression
,
excludePattern
:
glob
.
IExpression
)
{
const
rgArgs
=
getRgArgs
(
folderQuery
,
includePattern
,
excludePattern
);
return
{
cmd
:
cp
.
spawn
(
rgPath
,
rgArgs
.
globArgs
,
{
cwd
:
folderQuery
.
folder
}),
siblingClauses
:
rgArgs
.
siblingClauses
};
}
function
getRgArgs
(
folderQuery
:
IFolderSearch
,
includePattern
:
glob
.
IExpression
,
excludePattern
:
glob
.
IExpression
)
{
const
args
=
[
'
--files
'
,
'
--hidden
'
,
'
--case-sensitive
'
];
// includePattern can't have siblingClauses
foldersToIncludeGlobs
([
folderQuery
],
includePattern
,
false
).
forEach
(
globArg
=>
{
args
.
push
(
'
-g
'
,
globArg
);
});
let
siblingClauses
:
glob
.
IExpression
;
const
rgGlobs
=
foldersToRgExcludeGlobs
([
folderQuery
],
excludePattern
,
undefined
,
false
);
rgGlobs
.
globArgs
.
forEach
(
rgGlob
=>
args
.
push
(
'
-g
'
,
`!
${
rgGlob
}
`
));
siblingClauses
=
rgGlobs
.
siblingClauses
;
// Don't use .gitignore or .ignore
args
.
push
(
'
--no-ignore
'
);
// Follow symlinks
args
.
push
(
'
--follow
'
);
// Folder to search
args
.
push
(
'
--
'
);
args
.
push
(
'
.
'
);
return
{
globArgs
:
args
,
siblingClauses
};
}
src/vs/workbench/services/search/node/ripgrepTextSearch.ts
浏览文件 @
0f312a4c
...
...
@@ -363,17 +363,17 @@ export class LineMatch implements ILineMatch {
}
}
interface
IRgGlobResult
{
export
interface
IRgGlobResult
{
globArgs
:
string
[];
siblingClauses
:
glob
.
IExpression
;
}
function
foldersToRgExcludeGlobs
(
folderQueries
:
IFolderSearch
[],
globalExclude
:
glob
.
IExpression
,
excludesToSkip
:
Set
<
string
>
):
IRgGlobResult
{
export
function
foldersToRgExcludeGlobs
(
folderQueries
:
IFolderSearch
[],
globalExclude
:
glob
.
IExpression
,
excludesToSkip
?:
Set
<
string
>
,
absoluteGlobs
=
true
):
IRgGlobResult
{
const
globArgs
:
string
[]
=
[];
let
siblingClauses
:
glob
.
IExpression
=
{};
folderQueries
.
forEach
(
folderQuery
=>
{
const
totalExcludePattern
=
objects
.
assign
({},
folderQuery
.
excludePattern
||
{},
globalExclude
||
{});
const
result
=
globExprsToRgGlobs
(
totalExcludePattern
,
folderQuery
.
folder
,
excludesToSkip
);
const
result
=
globExprsToRgGlobs
(
totalExcludePattern
,
absoluteGlobs
&&
folderQuery
.
folder
,
excludesToSkip
);
globArgs
.
push
(...
result
.
globArgs
);
if
(
result
.
siblingClauses
)
{
siblingClauses
=
objects
.
assign
(
siblingClauses
,
result
.
siblingClauses
);
...
...
@@ -383,18 +383,18 @@ function foldersToRgExcludeGlobs(folderQueries: IFolderSearch[], globalExclude:
return
{
globArgs
,
siblingClauses
};
}
function
foldersToIncludeGlobs
(
folderQueries
:
IFolderSearch
[],
globalInclude
:
glob
.
IExpression
):
string
[]
{
export
function
foldersToIncludeGlobs
(
folderQueries
:
IFolderSearch
[],
globalInclude
:
glob
.
IExpression
,
absoluteGlobs
=
true
):
string
[]
{
const
globArgs
:
string
[]
=
[];
folderQueries
.
forEach
(
folderQuery
=>
{
const
totalIncludePattern
=
objects
.
assign
({},
globalInclude
||
{},
folderQuery
.
includePattern
||
{});
const
result
=
globExprsToRgGlobs
(
totalIncludePattern
,
folderQuery
.
folder
);
const
result
=
globExprsToRgGlobs
(
totalIncludePattern
,
absoluteGlobs
&&
folderQuery
.
folder
);
globArgs
.
push
(...
result
.
globArgs
);
});
return
globArgs
;
}
function
globExprsToRgGlobs
(
patterns
:
glob
.
IExpression
,
folder
:
string
,
excludesToSkip
?:
Set
<
string
>
):
IRgGlobResult
{
function
globExprsToRgGlobs
(
patterns
:
glob
.
IExpression
,
folder
?
:
string
,
excludesToSkip
?:
Set
<
string
>
):
IRgGlobResult
{
const
globArgs
:
string
[]
=
[];
let
siblingClauses
:
glob
.
IExpression
=
null
;
Object
.
keys
(
patterns
)
...
...
@@ -404,7 +404,7 @@ function globExprsToRgGlobs(patterns: glob.IExpression, folder: string, excludes
}
const
value
=
patterns
[
key
];
key
=
getAbsoluteGlob
(
folder
,
key
);
key
=
trimTrailingSlash
(
folder
?
getAbsoluteGlob
(
folder
,
key
)
:
key
);
if
(
typeof
value
===
'
boolean
'
&&
value
)
{
globArgs
.
push
(
fixDriveC
(
key
));
...
...
@@ -427,11 +427,9 @@ function globExprsToRgGlobs(patterns: glob.IExpression, folder: string, excludes
* Exported for testing
*/
export
function
getAbsoluteGlob
(
folder
:
string
,
key
:
string
):
string
{
const
absolute
=
paths
.
isAbsolute
(
key
)
?
return
paths
.
isAbsolute
(
key
)
?
key
:
path
.
join
(
folder
,
key
);
return
trimTrailingSlash
(
absolute
);
}
function
trimTrailingSlash
(
str
:
string
):
string
{
...
...
src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts
浏览文件 @
0f312a4c
...
...
@@ -12,6 +12,7 @@ import { createSyncDescriptor } from 'vs/platform/instantiation/common/descripto
import
{
IEditorGroupService
}
from
'
vs/workbench/services/group/common/groupService
'
;
import
{
ISearchService
}
from
'
vs/platform/search/common/search
'
;
import
{
ITelemetryService
,
ITelemetryInfo
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
IExperimentService
,
IExperiments
}
from
'
vs/platform/telemetry/common/experiments
'
;
import
{
IUntitledEditorService
,
UntitledEditorService
}
from
'
vs/workbench/services/untitled/common/untitledEditorService
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
*
as
minimist
from
'
minimist
'
;
...
...
@@ -66,9 +67,11 @@ suite('QuickOpen performance (integration)', () => {
const
testWorkspacePath
=
testWorkspaceArg
?
path
.
resolve
(
testWorkspaceArg
)
:
__dirname
;
const
telemetryService
=
new
TestTelemetryService
();
const
experimentService
=
new
TestExperimentService
();
const
configurationService
=
new
SimpleConfigurationService
();
const
instantiationService
=
new
InstantiationService
(
new
ServiceCollection
(
[
ITelemetryService
,
telemetryService
],
[
IExperimentService
,
experimentService
],
[
IConfigurationService
,
configurationService
],
[
IModelService
,
new
ModelServiceImpl
(
null
,
configurationService
)],
[
IWorkspaceContextService
,
new
TestContextService
(
new
LegacyWorkspace
(
URI
.
file
(
testWorkspacePath
)))],
...
...
@@ -177,3 +180,15 @@ class TestTelemetryService implements ITelemetryService {
});
}
};
class
TestExperimentService
implements
IExperimentService
{
_serviceBrand
:
any
;
getExperiments
():
IExperiments
{
return
{
ripgrepQuickSearch
:
true
,
deployToAzureQuickLink
:
false
};
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录