Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
8eb4e841
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,发现更多精彩内容 >>
提交
8eb4e841
编写于
3月 17, 2020
作者:
B
Benjamin Pasero
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
quick access - first cut open anything
上级
b7bfce30
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
592 addition
and
51 deletion
+592
-51
src/vs/platform/quickinput/browser/commandsQuickAccess.ts
src/vs/platform/quickinput/browser/commandsQuickAccess.ts
+4
-4
src/vs/platform/quickinput/browser/pickerQuickAccess.ts
src/vs/platform/quickinput/browser/pickerQuickAccess.ts
+7
-10
src/vs/workbench/browser/parts/editor/editorQuickAccess.ts
src/vs/workbench/browser/parts/editor/editorQuickAccess.ts
+2
-8
src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts
...s/workbench/contrib/search/browser/anythingQuickAccess.ts
+338
-0
src/vs/workbench/contrib/search/browser/search.contribution.ts
...s/workbench/contrib/search/browser/search.contribution.ts
+11
-1
src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts
...vs/workbench/contrib/search/browser/symbolsQuickAccess.ts
+9
-15
src/vs/workbench/contrib/search/common/cacheState.ts
src/vs/workbench/contrib/search/common/cacheState.ts
+108
-0
src/vs/workbench/contrib/search/common/search.ts
src/vs/workbench/contrib/search/common/search.ts
+61
-0
src/vs/workbench/contrib/search/test/common/cacheState.test.ts
...s/workbench/contrib/search/test/common/cacheState.test.ts
+4
-4
src/vs/workbench/contrib/search/test/common/extractRange.test.ts
...workbench/contrib/search/test/common/extractRange.test.ts
+45
-0
src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts
...rkbench/contrib/terminal/browser/terminal.contribution.ts
+1
-1
src/vs/workbench/contrib/terminal/browser/terminalsQuickAccess.ts
...orkbench/contrib/terminal/browser/terminalsQuickAccess.ts
+2
-8
未找到文件。
src/vs/platform/quickinput/browser/commandsQuickAccess.ts
浏览文件 @
8eb4e841
...
...
@@ -5,7 +5,7 @@
import
{
localize
}
from
'
vs/nls
'
;
import
{
IQuickPickSeparator
}
from
'
vs/platform/quickinput/common/quickInput
'
;
import
{
PickerQuickAccessProvider
,
IPickerQuickAccessItem
}
from
'
vs/platform/quickinput/browser/pickerQuickAccess
'
;
import
{
PickerQuickAccessProvider
,
IPickerQuickAccessItem
,
IPickerQuickAccessProviderOptions
}
from
'
vs/platform/quickinput/browser/pickerQuickAccess
'
;
import
{
distinct
}
from
'
vs/base/common/arrays
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
DisposableStore
,
Disposable
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
...
...
@@ -30,7 +30,7 @@ export interface ICommandQuickPick extends IPickerQuickAccessItem {
commandAlias
:
string
|
undefined
;
}
export
interface
ICommandsQuickAccessOptions
{
export
interface
ICommandsQuickAccessOptions
extends
IPickerQuickAccessProviderOptions
{
showAlias
:
boolean
;
}
...
...
@@ -43,14 +43,14 @@ export abstract class AbstractCommandsQuickAccessProvider extends PickerQuickAcc
private
readonly
commandsHistory
=
this
.
_register
(
this
.
instantiationService
.
createInstance
(
CommandsHistory
));
constructor
(
pr
ivate
options
:
ICommandsQuickAccessOptions
,
pr
otected
options
:
ICommandsQuickAccessOptions
,
@
IInstantiationService
private
readonly
instantiationService
:
IInstantiationService
,
@
IKeybindingService
private
readonly
keybindingService
:
IKeybindingService
,
@
ICommandService
private
readonly
commandService
:
ICommandService
,
@
ITelemetryService
private
readonly
telemetryService
:
ITelemetryService
,
@
INotificationService
private
readonly
notificationService
:
INotificationService
)
{
super
(
AbstractCommandsQuickAccessProvider
.
PREFIX
);
super
(
AbstractCommandsQuickAccessProvider
.
PREFIX
,
options
);
}
protected
async
getPicks
(
filter
:
string
,
disposables
:
DisposableStore
,
token
:
CancellationToken
):
Promise
<
Array
<
ICommandQuickPick
|
IQuickPickSeparator
>>
{
...
...
src/vs/platform/quickinput/browser/pickerQuickAccess.ts
浏览文件 @
8eb4e841
...
...
@@ -53,17 +53,21 @@ export interface IPickerQuickAccessItem extends IQuickPickItem {
trigger
?(
buttonIndex
:
number
,
keyMods
:
IKeyMods
):
TriggerAction
|
Promise
<
TriggerAction
>
;
}
export
interface
IPickerQuickAccessProviderOptions
{
canAcceptInBackground
?:
boolean
;
}
export
abstract
class
PickerQuickAccessProvider
<
T
extends
IPickerQuickAccessItem
>
extends
Disposable
implements
IQuickAccessProvider
{
constructor
(
private
prefix
:
string
)
{
constructor
(
private
prefix
:
string
,
protected
options
?:
IPickerQuickAccessProviderOptions
)
{
super
();
}
provide
(
picker
:
IQuickPick
<
T
>
,
token
:
CancellationToken
):
IDisposable
{
const
disposables
=
new
DisposableStore
();
// A
llow subclasses to configure picker
this
.
configure
(
picker
)
;
// A
pply options if any
picker
.
canAcceptInBackground
=
!!
this
.
options
?.
canAcceptInBackground
;
// Disable filtering & sorting, we control the results
picker
.
matchOnLabel
=
picker
.
matchOnDescription
=
picker
.
matchOnDetail
=
picker
.
sortByLabel
=
false
;
...
...
@@ -142,13 +146,6 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
return
disposables
;
}
/**
* Subclasses can override this method to configure the picker before showing it.
*
* @param picker the picker instance used for the quick access before it opens.
*/
protected
configure
(
picker
:
IQuickPick
<
T
>
):
void
{
}
/**
* Returns an array of picks and separators as needed. If the picks are resolved
* long running, the provided cancellation token should be used to cancel the
...
...
src/vs/workbench/browser/parts/editor/editorQuickAccess.ts
浏览文件 @
8eb4e841
...
...
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import
{
localize
}
from
'
vs/nls
'
;
import
{
IQuickPickSeparator
,
quickPickItemScorerAccessor
,
IQuickPickItemWithResource
,
IQuickPick
}
from
'
vs/platform/quickinput/common/quickInput
'
;
import
{
IQuickPickSeparator
,
quickPickItemScorerAccessor
,
IQuickPickItemWithResource
}
from
'
vs/platform/quickinput/common/quickInput
'
;
import
{
PickerQuickAccessProvider
,
IPickerQuickAccessItem
,
TriggerAction
}
from
'
vs/platform/quickinput/browser/pickerQuickAccess
'
;
import
{
IEditorGroupsService
,
GroupsOrder
}
from
'
vs/workbench/services/editor/common/editorGroupsService
'
;
import
{
EditorsOrder
,
IEditorIdentifier
,
toResource
,
SideBySideEditor
}
from
'
vs/workbench/common/editor
'
;
...
...
@@ -25,13 +25,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
@
IModelService
private
readonly
modelService
:
IModelService
,
@
IModeService
private
readonly
modeService
:
IModeService
)
{
super
(
prefix
);
}
protected
configure
(
picker
:
IQuickPick
<
IEditorQuickPickItem
>
):
void
{
// Allow to open editors in background without closing picker
picker
.
canAcceptInBackground
=
true
;
super
(
prefix
,
{
canAcceptInBackground
:
true
});
}
protected
getPicks
(
filter
:
string
):
Array
<
IEditorQuickPickItem
|
IQuickPickSeparator
>
{
...
...
src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts
0 → 100644
浏览文件 @
8eb4e841
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
IQuickPickSeparator
,
IQuickInputButton
,
IKeyMods
,
quickPickItemScorerAccessor
}
from
'
vs/platform/quickinput/common/quickInput
'
;
import
{
IPickerQuickAccessItem
,
PickerQuickAccessProvider
,
TriggerAction
}
from
'
vs/platform/quickinput/browser/pickerQuickAccess
'
;
import
{
prepareQuery
,
IPreparedQuery
,
compareItemsByScore
,
scoreItem
}
from
'
vs/base/common/fuzzyScorer
'
;
import
{
IFileQueryBuilderOptions
,
QueryBuilder
}
from
'
vs/workbench/contrib/search/common/queryBuilder
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
getOutOfWorkspaceEditorResources
,
extractRangeFromFilter
,
IWorkbenchSearchConfiguration
}
from
'
vs/workbench/contrib/search/common/search
'
;
import
{
ISearchService
,
IFileMatch
}
from
'
vs/workbench/services/search/common/search
'
;
import
{
IWorkspaceContextService
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
untildify
}
from
'
vs/base/common/labels
'
;
import
{
IRemotePathService
}
from
'
vs/workbench/services/path/common/remotePathService
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
toLocalResource
,
basename
,
dirname
}
from
'
vs/base/common/resources
'
;
import
{
IWorkbenchEnvironmentService
}
from
'
vs/workbench/services/environment/common/environmentService
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
DisposableStore
}
from
'
vs/base/common/lifecycle
'
;
import
{
ILabelService
}
from
'
vs/platform/label/common/label
'
;
import
{
getIconClasses
}
from
'
vs/editor/common/services/getIconClasses
'
;
import
{
IModelService
}
from
'
vs/editor/common/services/modelService
'
;
import
{
IModeService
}
from
'
vs/editor/common/services/modeService
'
;
import
{
localize
}
from
'
vs/nls
'
;
import
{
IWorkingCopyService
}
from
'
vs/workbench/services/workingCopy/common/workingCopyService
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
IWorkbenchEditorConfiguration
}
from
'
vs/workbench/common/editor
'
;
import
{
IEditorService
,
SIDE_GROUP
,
ACTIVE_GROUP
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
Range
,
IRange
}
from
'
vs/editor/common/core/range
'
;
import
{
ThrottledDelayer
}
from
'
vs/base/common/async
'
;
import
{
top
}
from
'
vs/base/common/arrays
'
;
import
{
FileQueryCacheState
}
from
'
vs/workbench/contrib/search/common/cacheState
'
;
interface
IAnythingQuickPickItem
extends
IPickerQuickAccessItem
{
resource
:
URI
;
}
export
class
AnythingQuickAccessProvider
extends
PickerQuickAccessProvider
<
IAnythingQuickPickItem
>
{
static
PREFIX
=
''
;
private
static
readonly
MAX_RESULTS
=
512
;
constructor
(
@
IInstantiationService
private
readonly
instantiationService
:
IInstantiationService
,
@
ISearchService
private
readonly
searchService
:
ISearchService
,
@
IWorkspaceContextService
private
readonly
contextService
:
IWorkspaceContextService
,
@
IRemotePathService
private
readonly
remotePathService
:
IRemotePathService
,
@
IWorkbenchEnvironmentService
private
readonly
environmentService
:
IWorkbenchEnvironmentService
,
@
IFileService
private
readonly
fileService
:
IFileService
,
@
ILabelService
private
readonly
labelService
:
ILabelService
,
@
IModelService
private
readonly
modelService
:
IModelService
,
@
IModeService
private
readonly
modeService
:
IModeService
,
@
IWorkingCopyService
private
readonly
workingCopyService
:
IWorkingCopyService
,
@
IConfigurationService
private
readonly
configurationService
:
IConfigurationService
,
@
IEditorService
private
readonly
editorService
:
IEditorService
)
{
super
(
AnythingQuickAccessProvider
.
PREFIX
,
{
canAcceptInBackground
:
true
});
}
private
get
configuration
()
{
const
editorConfig
=
this
.
configurationService
.
getValue
<
IWorkbenchEditorConfiguration
>
().
workbench
.
editor
;
const
searchConfig
=
this
.
configurationService
.
getValue
<
IWorkbenchSearchConfiguration
>
();
return
{
openEditorPinned
:
!
editorConfig
.
enablePreviewFromQuickOpen
,
openSideBySideDirection
:
editorConfig
.
openSideBySideDirection
,
includeSymbols
:
searchConfig
.
search
.
quickOpen
.
includeSymbols
};
}
protected
async
getPicks
(
filter
:
string
,
disposables
:
DisposableStore
,
token
:
CancellationToken
):
Promise
<
Array
<
IAnythingQuickPickItem
|
IQuickPickSeparator
>>
{
// TODO this should run just once when picker opens
this
.
warmUpFileQueryCache
();
// Find a suitable range from the pattern looking for ":", "#" or ","
let
range
:
IRange
|
undefined
=
undefined
;
const
filterWithRange
=
extractRangeFromFilter
(
filter
);
if
(
filterWithRange
)
{
filter
=
filterWithRange
.
filter
;
range
=
filterWithRange
.
range
;
}
const
query
=
prepareQuery
(
filter
);
// TODO include history results
// TODO exclude duplicates from editor history!
// TODO groups ("recently opened", "file results", "file and symbol results")
// Resolve file and symbol picks (if enabled)
const
[
filePicks
,
symbolPicks
]
=
await
Promise
.
all
([
this
.
getFilePicks
(
query
,
range
,
token
),
this
.
getSymbolPicks
(
query
,
range
,
token
)
]);
if
(
token
.
isCancellationRequested
)
{
return
[];
}
// Sort top 512 items by score
const
scorerCache
=
Object
.
create
(
null
);
// TODO should keep this for as long as the picker is opened (also check other pickers)
const
sortedAnythingPicks
=
top
(
[...
filePicks
,
...
symbolPicks
],
(
anyPickA
,
anyPickB
)
=>
compareItemsByScore
(
anyPickA
,
anyPickB
,
query
,
true
,
quickPickItemScorerAccessor
,
scorerCache
),
AnythingQuickAccessProvider
.
MAX_RESULTS
);
// Adjust highlights
for
(
const
anythingPick
of
sortedAnythingPicks
)
{
const
{
labelMatch
,
descriptionMatch
}
=
scoreItem
(
anythingPick
,
query
,
true
,
quickPickItemScorerAccessor
,
scorerCache
);
anythingPick
.
highlights
=
{
label
:
labelMatch
,
description
:
descriptionMatch
};
}
return
sortedAnythingPicks
;
}
//#region Editor History
protected
getHistoryPicks
(
filter
:
string
):
Array
<
IAnythingQuickPickItem
>
{
return
[];
}
//#endregion
//# File Search
private
static
readonly
FILE_QUERY_DELAY
=
200
;
// this delay accommodates for the user typing a word and then stops typing to start searching
private
fileQueryDelayer
=
this
.
_register
(
new
ThrottledDelayer
<
IFileMatch
[]
>
(
AnythingQuickAccessProvider
.
FILE_QUERY_DELAY
));
private
fileQueryBuilder
=
this
.
instantiationService
.
createInstance
(
QueryBuilder
);
private
fileQueryCacheState
:
FileQueryCacheState
|
undefined
;
private
warmUpFileQueryCache
():
void
{
this
.
fileQueryCacheState
=
new
FileQueryCacheState
(
cacheKey
=>
this
.
fileQueryBuilder
.
file
(
this
.
contextService
.
getWorkspace
().
folders
,
this
.
getFileQueryOptions
({
cacheKey
})),
query
=>
this
.
searchService
.
fileSearch
(
query
),
cacheKey
=>
this
.
searchService
.
clearCache
(
cacheKey
),
this
.
fileQueryCacheState
);
this
.
fileQueryCacheState
.
load
();
}
protected
async
getFilePicks
(
query
:
IPreparedQuery
,
range
:
IRange
|
undefined
,
token
:
CancellationToken
):
Promise
<
Array
<
IAnythingQuickPickItem
>>
{
if
(
!
query
.
value
)
{
return
[];
}
// Absolute path result
const
absolutePathResult
=
await
this
.
getAbsolutePathFileResult
(
query
,
token
);
if
(
token
.
isCancellationRequested
)
{
return
[];
}
// Use absolute path result as only results if present
let
fileMatches
:
Array
<
IFileMatch
<
URI
>>
;
if
(
absolutePathResult
)
{
fileMatches
=
[{
resource
:
absolutePathResult
}];
}
// Otherwise run the file search (with a delayer if cache is not ready yet)
else
{
if
(
this
.
fileQueryCacheState
?.
isLoaded
)
{
fileMatches
=
await
this
.
doFileSearch
(
query
,
token
);
}
else
{
fileMatches
=
await
this
.
fileQueryDelayer
.
trigger
(()
=>
this
.
doFileSearch
(
query
,
token
));
}
}
if
(
token
.
isCancellationRequested
)
{
return
[];
}
// Convert to picks
return
fileMatches
.
map
(
fileMatch
=>
this
.
createFilePick
(
fileMatch
.
resource
,
range
,
false
));
}
private
async
doFileSearch
(
query
:
IPreparedQuery
,
token
:
CancellationToken
):
Promise
<
IFileMatch
[]
>
{
if
(
token
.
isCancellationRequested
)
{
return
[];
}
const
{
results
}
=
await
this
.
searchService
.
fileSearch
(
this
.
fileQueryBuilder
.
file
(
this
.
contextService
.
getWorkspace
().
folders
,
this
.
getFileQueryOptions
({
filePattern
:
query
.
original
,
cacheKey
:
this
.
fileQueryCacheState
?.
cacheKey
,
maxResults
:
AnythingQuickAccessProvider
.
MAX_RESULTS
})
),
token
);
return
results
;
}
private
createFilePick
(
resource
:
URI
,
range
:
IRange
|
undefined
,
isHistoryResult
:
boolean
):
IAnythingQuickPickItem
{
const
label
=
basename
(
resource
);
const
description
=
this
.
labelService
.
getUriLabel
(
dirname
(
resource
),
{
relative
:
true
});
const
isDirty
=
this
.
workingCopyService
.
isDirty
(
resource
);
const
openSideBySideDirection
=
this
.
configuration
.
openSideBySideDirection
;
return
{
resource
,
label
,
ariaLabel
:
localize
(
'
filePickAriaLabel
'
,
"
{0}, file picker
"
,
label
),
description
,
iconClasses
:
getIconClasses
(
this
.
modelService
,
this
.
modeService
,
resource
),
// TODO force 'file' icon if symbols are merged in for better looks
buttonsAlwaysVisible
:
isDirty
,
buttons
:
(()
=>
{
const
buttons
:
IQuickInputButton
[]
=
[];
// Open to side / below
buttons
.
push
({
iconClass
:
openSideBySideDirection
===
'
right
'
?
'
codicon-split-horizontal
'
:
'
codicon-split-vertical
'
,
tooltip
:
openSideBySideDirection
===
'
right
'
?
localize
(
'
openToSide
'
,
"
Open to the Side
"
)
:
localize
(
'
openToBottom
'
,
"
Open to the Bottom
"
)
});
// Remove from History
if
(
isHistoryResult
)
{
buttons
.
push
({
iconClass
:
isDirty
?
'
codicon-circle-filled
'
:
'
codicon-close
'
,
tooltip
:
localize
(
'
closeEditor
'
,
"
Close Editor
"
)
});
}
// Dirty indicator
else
if
(
isDirty
)
{
buttons
.
push
({
iconClass
:
'
codicon-circle-filled
'
,
tooltip
:
localize
(
'
dirtyFile
'
,
"
Dirty File
"
)
});
}
return
buttons
;
})(),
trigger
:
async
(
buttonIndex
,
keyMods
)
=>
{
switch
(
buttonIndex
)
{
// Open to side / below
case
0
:
this
.
openFile
(
resource
,
{
keyMods
,
range
,
forceOpenSideBySide
:
true
});
return
TriggerAction
.
CLOSE_PICKER
;
// Remove from History / Dirty Indicator
case
1
:
//TODO
return
TriggerAction
.
REFRESH_PICKER
;
}
return
TriggerAction
.
NO_ACTION
;
},
accept
:
(
keyMods
,
event
)
=>
this
.
openFile
(
resource
,
{
keyMods
,
range
,
preserveFocus
:
event
.
inBackground
})
};
}
private
async
openFile
(
resource
:
URI
,
options
:
{
keyMods
?:
IKeyMods
,
preserveFocus
?:
boolean
,
range
?:
IRange
,
forceOpenSideBySide
?:
boolean
}):
Promise
<
void
>
{
await
this
.
editorService
.
openEditor
({
resource
,
options
:
{
preserveFocus
:
options
.
preserveFocus
,
pinned
:
options
.
keyMods
?.
alt
||
this
.
configuration
.
openEditorPinned
,
selection
:
options
.
range
?
Range
.
collapseToStart
(
options
.
range
)
:
undefined
}
},
options
.
keyMods
?.
ctrlCmd
||
options
.
forceOpenSideBySide
?
SIDE_GROUP
:
ACTIVE_GROUP
);
}
private
getFileQueryOptions
(
input
:
{
filePattern
?:
string
,
cacheKey
?:
string
,
maxResults
?:
number
}):
IFileQueryBuilderOptions
{
const
fileQueryOptions
:
IFileQueryBuilderOptions
=
{
_reason
:
'
openFileHandler
'
,
extraFileResources
:
this
.
instantiationService
.
invokeFunction
(
getOutOfWorkspaceEditorResources
),
filePattern
:
input
.
filePattern
||
''
,
cacheKey
:
input
.
cacheKey
,
maxResults
:
input
.
maxResults
||
0
,
sortByScore
:
true
};
return
fileQueryOptions
;
}
private
async
getAbsolutePathFileResult
(
query
:
IPreparedQuery
,
token
:
CancellationToken
):
Promise
<
URI
|
undefined
>
{
const
detildifiedQuery
=
untildify
(
query
.
original
,
(
await
this
.
remotePathService
.
userHome
).
path
);
if
(
token
.
isCancellationRequested
)
{
return
;
}
const
isAbsolutePathQuery
=
(
await
this
.
remotePathService
.
path
).
isAbsolute
(
detildifiedQuery
);
if
(
token
.
isCancellationRequested
)
{
return
;
}
if
(
isAbsolutePathQuery
)
{
const
resource
=
toLocalResource
(
await
this
.
remotePathService
.
fileURI
(
detildifiedQuery
),
this
.
environmentService
.
configuration
.
remoteAuthority
);
if
(
token
.
isCancellationRequested
)
{
return
;
}
try
{
return
(
await
this
.
fileService
.
resolve
(
resource
)).
isDirectory
?
undefined
:
resource
;
}
catch
(
error
)
{
// ignore
}
}
return
;
}
//#endregion
//#region Symbols (if enabled)
protected
async
getSymbolPicks
(
query
:
IPreparedQuery
,
range
:
IRange
|
undefined
,
token
:
CancellationToken
):
Promise
<
Array
<
IAnythingQuickPickItem
>>
{
if
(
!
query
.
value
||
// we need a value for search for
!
this
.
configuration
.
includeSymbols
||
// we need to enable symbols in search
range
// a range is an indicator for just searching for files
)
{
return
[];
}
return
[];
}
//#endregion
}
src/vs/workbench/contrib/search/browser/search.contribution.ts
浏览文件 @
8eb4e841
...
...
@@ -57,6 +57,7 @@ import { SearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEd
import
{
ViewPaneContainer
}
from
'
vs/workbench/browser/parts/views/viewPaneContainer
'
;
import
{
IQuickAccessRegistry
,
Extensions
as
QuickAccessExtensions
}
from
'
vs/platform/quickinput/common/quickAccess
'
;
import
{
SymbolsQuickAccessProvider
}
from
'
vs/workbench/contrib/search/browser/symbolsQuickAccess
'
;
import
{
AnythingQuickAccessProvider
}
from
'
vs/workbench/contrib/search/browser/anythingQuickAccess
'
;
registerSingleton
(
ISearchWorkbenchService
,
SearchWorkbenchService
,
true
);
registerSingleton
(
ISearchHistoryService
,
SearchHistoryService
,
true
);
...
...
@@ -654,8 +655,17 @@ Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen).registerQuickOpen
);
// Register Quick Access Handler
const
quickAccessRegistry
=
Registry
.
as
<
IQuickAccessRegistry
>
(
QuickAccessExtensions
.
Quickaccess
);
Registry
.
as
<
IQuickAccessRegistry
>
(
QuickAccessExtensions
.
Quickaccess
).
registerQuickAccessProvider
({
quickAccessRegistry
.
registerQuickAccessProvider
({
ctor
:
AnythingQuickAccessProvider
,
prefix
:
AnythingQuickAccessProvider
.
PREFIX
,
placeholder
:
nls
.
localize
(
'
anythingQuickAccessPlaceholder
'
,
"
Type '?' to get help on the actions you can take from here
"
),
contextKey
:
'
inFilesPicker
'
,
helpEntries
:
[{
description
:
nls
.
localize
(
'
anythingQuickAccess
'
,
"
Go to File
"
),
needsEditor
:
false
}]
});
quickAccessRegistry
.
registerQuickAccessProvider
({
ctor
:
SymbolsQuickAccessProvider
,
prefix
:
SymbolsQuickAccessProvider
.
PREFIX
,
placeholder
:
nls
.
localize
(
'
symbolsQuickAccessPlaceholder
'
,
"
Type the name of a symbol to open.
"
),
...
...
src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts
浏览文件 @
8eb4e841
...
...
@@ -19,7 +19,7 @@ import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
IWorkbenchEditorConfiguration
}
from
'
vs/workbench/common/editor
'
;
import
{
IKeyMods
,
IQuickPick
}
from
'
vs/platform/quickinput/common/quickInput
'
;
import
{
IKeyMods
}
from
'
vs/platform/quickinput/common/quickInput
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
createResourceExcludeMatcher
}
from
'
vs/workbench/services/search/common/search
'
;
import
{
ResourceMap
}
from
'
vs/base/common/map
'
;
...
...
@@ -35,7 +35,7 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider<ISymbo
private
static
readonly
TYPING_SEARCH_DELAY
=
200
;
// this delay accommodates for the user typing a word and then stops typing to start searching
private
delayer
=
new
ThrottledDelayer
<
ISymbolsQuickPickItem
[]
>
(
SymbolsQuickAccessProvider
.
TYPING_SEARCH_DELAY
);
private
delayer
=
this
.
_register
(
new
ThrottledDelayer
<
ISymbolsQuickPickItem
[]
>
(
SymbolsQuickAccessProvider
.
TYPING_SEARCH_DELAY
)
);
private
readonly
resourceExcludeMatcher
=
this
.
_register
(
createResourceExcludeMatcher
(
this
.
instantiationService
,
this
.
configurationService
));
...
...
@@ -46,13 +46,7 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider<ISymbo
@
IConfigurationService
private
readonly
configurationService
:
IConfigurationService
,
@
IInstantiationService
private
readonly
instantiationService
:
IInstantiationService
)
{
super
(
SymbolsQuickAccessProvider
.
PREFIX
);
}
protected
configure
(
picker
:
IQuickPick
<
ISymbolsQuickPickItem
>
):
void
{
// Allow to open symbols in background without closing picker
picker
.
canAcceptInBackground
=
true
;
super
(
SymbolsQuickAccessProvider
.
PREFIX
,
{
canAcceptInBackground
:
true
});
}
private
get
configuration
()
{
...
...
@@ -156,12 +150,12 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider<ISymbo
tooltip
:
openSideBySideDirection
===
'
right
'
?
localize
(
'
openToSide
'
,
"
Open to the Side
"
)
:
localize
(
'
openToBottom
'
,
"
Open to the Bottom
"
)
}
],
accept
:
async
(
keyMods
,
event
)
=>
this
.
openSymbol
(
provider
,
symbol
,
token
,
keyMods
,
{
preserveFocus
:
event
.
inBackground
}),
trigger
:
(
buttonIndex
,
keyMods
)
=>
{
this
.
openSymbol
(
provider
,
symbol
,
token
,
keyMods
,
{
forceOpenSideBySide
:
true
});
this
.
openSymbol
(
provider
,
symbol
,
token
,
{
keyMods
,
forceOpenSideBySide
:
true
});
return
TriggerAction
.
CLOSE_PICKER
;
}
},
accept
:
async
(
keyMods
,
event
)
=>
this
.
openSymbol
(
provider
,
symbol
,
token
,
{
keyMods
,
preserveFocus
:
event
.
inBackground
}),
});
}
}
...
...
@@ -172,7 +166,7 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider<ISymbo
return
symbolPicks
;
}
private
async
openSymbol
(
provider
:
IWorkspaceSymbolProvider
,
symbol
:
IWorkspaceSymbol
,
token
:
CancellationToken
,
keyMods
:
IKeyMods
,
options
:
{
forceOpenSideBySide
?:
boolean
,
preserveFocus
?:
boolean
}):
Promise
<
void
>
{
private
async
openSymbol
(
provider
:
IWorkspaceSymbolProvider
,
symbol
:
IWorkspaceSymbol
,
token
:
CancellationToken
,
options
:
{
keyMods
:
IKeyMods
,
forceOpenSideBySide
?:
boolean
,
preserveFocus
?:
boolean
}):
Promise
<
void
>
{
// Resolve actual symbol to open for providers that can resolve
let
symbolToOpen
=
symbol
;
...
...
@@ -195,10 +189,10 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider<ISymbo
resource
:
symbolToOpen
.
location
.
uri
,
options
:
{
preserveFocus
:
options
?.
preserveFocus
,
pinned
:
keyMods
.
alt
||
this
.
configuration
.
openEditorPinned
,
pinned
:
options
.
keyMods
.
alt
||
this
.
configuration
.
openEditorPinned
,
selection
:
symbolToOpen
.
location
.
range
?
Range
.
collapseToStart
(
symbolToOpen
.
location
.
range
)
:
undefined
}
},
keyMods
.
ctrlCmd
||
options
?.
forceOpenSideBySide
?
SIDE_GROUP
:
ACTIVE_GROUP
);
},
options
.
keyMods
.
ctrlCmd
||
options
?.
forceOpenSideBySide
?
SIDE_GROUP
:
ACTIVE_GROUP
);
}
}
...
...
src/vs/workbench/contrib/search/common/cacheState.ts
0 → 100644
浏览文件 @
8eb4e841
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
defaultGenerator
}
from
'
vs/base/common/idGenerator
'
;
import
{
IFileQuery
}
from
'
vs/workbench/services/search/common/search
'
;
import
{
assign
,
equals
}
from
'
vs/base/common/objects
'
;
enum
LoadingPhase
{
Created
=
1
,
Loading
=
2
,
Loaded
=
3
,
Errored
=
4
,
Disposed
=
5
}
export
class
FileQueryCacheState
{
private
readonly
_cacheKey
=
defaultGenerator
.
nextId
();
get
cacheKey
():
string
{
if
(
this
.
loadingPhase
===
LoadingPhase
.
Loaded
||
!
this
.
previousCacheState
)
{
return
this
.
_cacheKey
;
}
return
this
.
previousCacheState
.
cacheKey
;
}
get
isLoaded
():
boolean
{
const
isLoaded
=
this
.
loadingPhase
===
LoadingPhase
.
Loaded
;
return
isLoaded
||
!
this
.
previousCacheState
?
isLoaded
:
this
.
previousCacheState
.
isLoaded
;
}
get
isUpdating
():
boolean
{
const
isUpdating
=
this
.
loadingPhase
===
LoadingPhase
.
Loading
;
return
isUpdating
||
!
this
.
previousCacheState
?
isUpdating
:
this
.
previousCacheState
.
isUpdating
;
}
private
readonly
query
=
this
.
cacheQuery
(
this
.
_cacheKey
);
private
loadingPhase
=
LoadingPhase
.
Created
;
private
loadPromise
:
Promise
<
void
>
|
undefined
;
constructor
(
private
cacheQuery
:
(
cacheKey
:
string
)
=>
IFileQuery
,
private
loadFn
:
(
query
:
IFileQuery
)
=>
Promise
<
any
>
,
private
disposeFn
:
(
cacheKey
:
string
)
=>
Promise
<
void
>
,
private
previousCacheState
:
FileQueryCacheState
|
undefined
)
{
if
(
this
.
previousCacheState
)
{
const
current
=
assign
({},
this
.
query
,
{
cacheKey
:
null
});
const
previous
=
assign
({},
this
.
previousCacheState
.
query
,
{
cacheKey
:
null
});
if
(
!
equals
(
current
,
previous
))
{
this
.
previousCacheState
.
dispose
();
this
.
previousCacheState
=
undefined
;
}
}
}
load
():
void
{
if
(
this
.
isUpdating
)
{
return
;
}
this
.
loadingPhase
=
LoadingPhase
.
Loading
;
this
.
loadPromise
=
(
async
()
=>
{
try
{
await
this
.
loadFn
(
this
.
query
);
this
.
loadingPhase
=
LoadingPhase
.
Loaded
;
if
(
this
.
previousCacheState
)
{
this
.
previousCacheState
.
dispose
();
this
.
previousCacheState
=
undefined
;
}
}
catch
(
error
)
{
this
.
loadingPhase
=
LoadingPhase
.
Errored
;
throw
error
;
}
})();
}
dispose
():
void
{
if
(
this
.
loadPromise
)
{
(
async
()
=>
{
try
{
await
this
.
loadPromise
;
}
catch
(
error
)
{
// ignore
}
this
.
loadingPhase
=
LoadingPhase
.
Disposed
;
this
.
disposeFn
(
this
.
_cacheKey
);
})();
}
else
{
this
.
loadingPhase
=
LoadingPhase
.
Disposed
;
}
if
(
this
.
previousCacheState
)
{
this
.
previousCacheState
.
dispose
();
this
.
previousCacheState
=
undefined
;
}
}
}
src/vs/workbench/contrib/search/common/search.ts
浏览文件 @
8eb4e841
...
...
@@ -14,6 +14,8 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
ServicesAccessor
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
IRange
}
from
'
vs/editor/common/core/range
'
;
import
{
isNumber
}
from
'
vs/base/common/types
'
;
export
interface
IWorkspaceSymbol
{
name
:
string
;
...
...
@@ -95,3 +97,62 @@ export function getOutOfWorkspaceEditorResources(accessor: ServicesAccessor): UR
return
resources
as
URI
[];
}
// Supports patterns of <path><#|:|(><line><#|:|,><col?>
const
LINE_COLON_PATTERN
=
/
\s?[
#:
\(](\d
*
)([
#:,
](\d
*
))?\)?\s
*$/
;
export
function
extractRangeFromFilter
(
filter
:
string
):
{
filter
:
string
,
range
:
IRange
}
|
undefined
{
if
(
!
filter
)
{
return
undefined
;
}
let
range
:
IRange
|
undefined
=
undefined
;
// Find Line/Column number from search value using RegExp
const
patternMatch
=
LINE_COLON_PATTERN
.
exec
(
filter
);
if
(
patternMatch
&&
patternMatch
.
length
>
1
)
{
const
startLineNumber
=
parseInt
(
patternMatch
[
1
],
10
);
// Line Number
if
(
isNumber
(
startLineNumber
))
{
range
=
{
startLineNumber
:
startLineNumber
,
startColumn
:
1
,
endLineNumber
:
startLineNumber
,
endColumn
:
1
};
// Column Number
if
(
patternMatch
.
length
>
3
)
{
const
startColumn
=
parseInt
(
patternMatch
[
3
],
10
);
if
(
isNumber
(
startColumn
))
{
range
=
{
startLineNumber
:
range
.
startLineNumber
,
startColumn
:
startColumn
,
endLineNumber
:
range
.
endLineNumber
,
endColumn
:
startColumn
};
}
}
}
// User has typed "something:" or "something#" without a line number, in this case treat as start of file
else
if
(
patternMatch
[
1
]
===
''
)
{
range
=
{
startLineNumber
:
1
,
startColumn
:
1
,
endLineNumber
:
1
,
endColumn
:
1
};
}
}
if
(
patternMatch
&&
range
)
{
return
{
filter
:
filter
.
substr
(
0
,
patternMatch
.
index
),
// clear range suffix from search value
range
:
range
};
}
return
undefined
;
}
src/vs/workbench/contrib/search/test/
browser/openFileHandler
.test.ts
→
src/vs/workbench/contrib/search/test/
common/cacheState
.test.ts
浏览文件 @
8eb4e841
...
...
@@ -6,11 +6,11 @@
import
*
as
assert
from
'
assert
'
;
import
*
as
errors
from
'
vs/base/common/errors
'
;
import
*
as
objects
from
'
vs/base/common/objects
'
;
import
{
CacheState
}
from
'
vs/workbench/contrib/search/browser/openFileHandler
'
;
import
{
DeferredPromise
}
from
'
vs/base/test/common/utils
'
;
import
{
QueryType
,
IFileQuery
}
from
'
vs/workbench/services/search/common/search
'
;
import
{
FileQueryCacheState
}
from
'
vs/workbench/contrib/search/common/cacheState
'
;
suite
(
'
CacheState
'
,
()
=>
{
suite
(
'
FileQuery
CacheState
'
,
()
=>
{
test
(
'
reuse old cacheKey until new cache is loaded
'
,
async
function
()
{
...
...
@@ -162,8 +162,8 @@ suite('CacheState', () => {
assert
.
strictEqual
(
third
.
cacheKey
,
thirdKey
);
// recover with next successful load
});
function
createCacheState
(
cache
:
MockCache
,
previous
?:
CacheState
):
CacheState
{
return
new
CacheState
(
function
createCacheState
(
cache
:
MockCache
,
previous
?:
FileQueryCacheState
):
FileQuery
CacheState
{
return
new
FileQuery
CacheState
(
cacheKey
=>
cache
.
query
(
cacheKey
),
query
=>
cache
.
load
(
query
),
cacheKey
=>
cache
.
dispose
(
cacheKey
),
...
...
src/vs/workbench/contrib/search/test/common/extractRange.test.ts
0 → 100644
浏览文件 @
8eb4e841
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
*
as
assert
from
'
assert
'
;
import
{
extractRangeFromFilter
}
from
'
vs/workbench/contrib/search/common/search
'
;
suite
(
'
extractRangeFromFilter
'
,
()
=>
{
test
(
'
basics
'
,
async
function
()
{
assert
.
ok
(
!
extractRangeFromFilter
(
''
));
assert
.
ok
(
!
extractRangeFromFilter
(
'
/some/path
'
));
assert
.
ok
(
!
extractRangeFromFilter
(
'
/some/path/file.txt
'
));
for
(
const
lineSep
of
[
'
:
'
,
'
#
'
,
'
(
'
])
{
for
(
const
colSep
of
[
'
:
'
,
'
#
'
,
'
,
'
])
{
const
base
=
'
/some/path/file.txt
'
;
let
res
=
extractRangeFromFilter
(
`
${
base
}${
lineSep
}
20`
);
assert
.
equal
(
res
?.
filter
,
base
);
assert
.
equal
(
res
?.
range
.
startLineNumber
,
20
);
assert
.
equal
(
res
?.
range
.
startColumn
,
1
);
res
=
extractRangeFromFilter
(
`
${
base
}${
lineSep
}
20
${
colSep
}
`
);
assert
.
equal
(
res
?.
filter
,
base
);
assert
.
equal
(
res
?.
range
.
startLineNumber
,
20
);
assert
.
equal
(
res
?.
range
.
startColumn
,
1
);
res
=
extractRangeFromFilter
(
`
${
base
}${
lineSep
}
20
${
colSep
}
3`
);
assert
.
equal
(
res
?.
filter
,
base
);
assert
.
equal
(
res
?.
range
.
startLineNumber
,
20
);
assert
.
equal
(
res
?.
range
.
startColumn
,
3
);
}
}
});
test
(
'
allow space after path
'
,
async
function
()
{
let
res
=
extractRangeFromFilter
(
'
/some/path/file.txt (19,20)
'
);
assert
.
equal
(
res
?.
filter
,
'
/some/path/file.txt
'
);
assert
.
equal
(
res
?.
range
.
startLineNumber
,
19
);
assert
.
equal
(
res
?.
range
.
startColumn
,
20
);
});
});
src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts
浏览文件 @
8eb4e841
...
...
@@ -40,7 +40,7 @@ import { BrowserFeatures } from 'vs/base/browser/canIUse';
import
{
SyncDescriptor
}
from
'
vs/platform/instantiation/common/descriptors
'
;
import
{
ViewPaneContainer
}
from
'
vs/workbench/browser/parts/views/viewPaneContainer
'
;
import
{
IQuickAccessRegistry
,
Extensions
as
QuickAccessExtensions
}
from
'
vs/platform/quickinput/common/quickAccess
'
;
import
{
TerminalQuickAccessProvider
}
from
'
vs/workbench/contrib/terminal/browser/terminaQuickAccess
'
;
import
{
TerminalQuickAccessProvider
}
from
'
vs/workbench/contrib/terminal/browser/termina
ls
QuickAccess
'
;
registerSingleton
(
ITerminalService
,
TerminalService
,
true
);
...
...
src/vs/workbench/contrib/terminal/browser/terminaQuickAccess.ts
→
src/vs/workbench/contrib/terminal/browser/termina
ls
QuickAccess.ts
浏览文件 @
8eb4e841
...
...
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import
{
localize
}
from
'
vs/nls
'
;
import
{
IQuickPickSeparator
,
IQuickPick
}
from
'
vs/platform/quickinput/common/quickInput
'
;
import
{
IQuickPickSeparator
}
from
'
vs/platform/quickinput/common/quickInput
'
;
import
{
IPickerQuickAccessItem
,
PickerQuickAccessProvider
,
TriggerAction
}
from
'
vs/platform/quickinput/browser/pickerQuickAccess
'
;
import
{
matchesFuzzy
}
from
'
vs/base/common/filters
'
;
import
{
ITerminalService
}
from
'
vs/workbench/contrib/terminal/browser/terminal
'
;
...
...
@@ -19,13 +19,7 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider<IPick
@
ITerminalService
private
readonly
terminalService
:
ITerminalService
,
@
ICommandService
private
readonly
commandService
:
ICommandService
,
)
{
super
(
TerminalQuickAccessProvider
.
PREFIX
);
}
protected
configure
(
picker
:
IQuickPick
<
IPickerQuickAccessItem
>
):
void
{
// Allow to open terminals in background without closing picker
picker
.
canAcceptInBackground
=
true
;
super
(
TerminalQuickAccessProvider
.
PREFIX
,
{
canAcceptInBackground
:
true
});
}
protected
getPicks
(
filter
:
string
):
Array
<
IPickerQuickAccessItem
|
IQuickPickSeparator
>
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录