Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
5aed010f
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,发现更多精彩内容 >>
未验证
提交
5aed010f
编写于
10月 22, 2020
作者:
L
Ladislau Szomoru
提交者:
GitHub
10月 22, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
SCM viewlet filter on type improvements (#109170)
上级
0f190483
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
92 addition
and
67 deletion
+92
-67
src/vs/base/browser/ui/list/list.ts
src/vs/base/browser/ui/list/list.ts
+4
-4
src/vs/base/browser/ui/tree/abstractTree.ts
src/vs/base/browser/ui/tree/abstractTree.ts
+19
-17
src/vs/workbench/contrib/scm/browser/scmViewPane.ts
src/vs/workbench/contrib/scm/browser/scmViewPane.ts
+69
-46
未找到文件。
src/vs/base/browser/ui/list/list.ts
浏览文件 @
5aed010f
...
...
@@ -66,11 +66,11 @@ export interface IIdentityProvider<T> {
export
interface
IKeyboardNavigationLabelProvider
<
T
>
{
/**
* Return a keyboard navigation label
which will be used by the
*
list for filtering/navigating. Return `undefined` to make an
* element always match.
* Return a keyboard navigation label
(s) which will be used by
*
the list for filtering/navigating. Return `undefined` to make
*
an
element always match.
*/
getKeyboardNavigationLabel
(
element
:
T
):
{
toString
():
string
|
undefined
;
}
|
undefined
;
getKeyboardNavigationLabel
(
element
:
T
):
{
toString
():
string
|
undefined
;
}
|
{
toString
():
string
|
undefined
;
}[]
|
undefined
;
}
export
interface
IKeyboardNavigationDelegate
{
...
...
src/vs/base/browser/ui/tree/abstractTree.ts
浏览文件 @
5aed010f
...
...
@@ -507,8 +507,9 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
}
}
class
TypeFilter
<
T
>
implements
ITreeFilter
<
T
,
FuzzyScore
>
,
IDisposable
{
export
type
LabelFuzzyScore
=
{
label
:
string
;
score
:
FuzzyScore
};
class
TypeFilter
<
T
>
implements
ITreeFilter
<
T
,
FuzzyScore
|
LabelFuzzyScore
>
,
IDisposable
{
private
_totalCount
=
0
;
get
totalCount
():
number
{
return
this
.
_totalCount
;
}
private
_matchCount
=
0
;
...
...
@@ -531,7 +532,7 @@ class TypeFilter<T> implements ITreeFilter<T, FuzzyScore>, IDisposable {
tree
.
onWillRefilter
(
this
.
reset
,
this
,
this
.
disposables
);
}
filter
(
element
:
T
,
parentVisibility
:
TreeVisibility
):
TreeFilterResult
<
FuzzyScore
>
{
filter
(
element
:
T
,
parentVisibility
:
TreeVisibility
):
TreeFilterResult
<
FuzzyScore
|
LabelFuzzyScore
>
{
if
(
this
.
_filter
)
{
const
result
=
this
.
_filter
.
filter
(
element
,
parentVisibility
);
...
...
@@ -562,27 +563,28 @@ class TypeFilter<T> implements ITreeFilter<T, FuzzyScore>, IDisposable {
}
const
label
=
this
.
keyboardNavigationLabelProvider
.
getKeyboardNavigationLabel
(
element
);
const
label
Str
=
label
&&
label
.
toString
()
;
const
label
s
=
Array
.
isArray
(
label
)
?
label
:
[
label
]
;
if
(
typeof
labelStr
===
'
undefined
'
)
{
return
{
data
:
FuzzyScore
.
Default
,
visibility
:
true
};
}
const
score
=
fuzzyScore
(
this
.
_pattern
,
this
.
_lowercasePattern
,
0
,
labelStr
,
labelStr
.
toLowerCase
(),
0
,
true
);
if
(
!
score
)
{
if
(
this
.
tree
.
options
.
filterOnType
)
{
return
TreeVisibility
.
Recurse
;
}
else
{
for
(
const
l
of
labels
)
{
const
labelStr
=
l
&&
l
.
toString
();
if
(
typeof
labelStr
===
'
undefined
'
)
{
return
{
data
:
FuzzyScore
.
Default
,
visibility
:
true
};
}
// DEMO: smarter filter ?
// return parentVisibility === TreeVisibility.Visible ? true : TreeVisibility.Recurse;
const
score
=
fuzzyScore
(
this
.
_pattern
,
this
.
_lowercasePattern
,
0
,
labelStr
,
labelStr
.
toLowerCase
(),
0
,
true
);
if
(
score
)
{
this
.
_matchCount
++
;
return
labels
.
length
===
1
?
{
data
:
score
,
visibility
:
true
}
:
{
data
:
{
label
:
labelStr
,
score
:
score
},
visibility
:
true
};
}
}
this
.
_matchCount
++
;
return
{
data
:
score
,
visibility
:
true
};
if
(
this
.
tree
.
options
.
filterOnType
)
{
return
TreeVisibility
.
Recurse
;
}
else
{
return
{
data
:
FuzzyScore
.
Default
,
visibility
:
true
};
}
}
private
reset
():
void
{
...
...
src/vs/workbench/contrib/scm/browser/scmViewPane.ts
浏览文件 @
5aed010f
...
...
@@ -77,42 +77,10 @@ import { RepositoryRenderer } from 'vs/workbench/contrib/scm/browser/scmReposito
import
{
IPosition
}
from
'
vs/editor/common/core/position
'
;
import
{
ColorScheme
}
from
'
vs/platform/theme/common/theme
'
;
import
{
IUriIdentityService
}
from
'
vs/workbench/services/uriIdentity/common/uriIdentity
'
;
import
{
LabelFuzzyScore
}
from
'
vs/base/browser/ui/tree/abstractTree
'
;
type
TreeElement
=
ISCMRepository
|
ISCMInput
|
ISCMResourceGroup
|
IResourceNode
<
ISCMResource
,
ISCMResourceGroup
>
|
ISCMResource
;
function
splitMatches
(
uri
:
URI
,
filterData
:
FuzzyScore
|
undefined
):
[
IMatch
[]
|
undefined
,
IMatch
[]
|
undefined
]
{
let
matches
:
IMatch
[]
|
undefined
;
let
descriptionMatches
:
IMatch
[]
|
undefined
;
if
(
filterData
)
{
matches
=
[];
descriptionMatches
=
[];
const
fileName
=
basename
(
uri
);
const
allMatches
=
createMatches
(
filterData
);
for
(
const
match
of
allMatches
)
{
if
(
match
.
start
<
fileName
.
length
)
{
matches
!
.
push
(
{
start
:
match
.
start
,
end
:
Math
.
min
(
match
.
end
,
fileName
.
length
)
}
);
}
else
{
descriptionMatches
!
.
push
(
{
start
:
match
.
start
-
(
fileName
.
length
+
1
),
end
:
match
.
end
-
(
fileName
.
length
+
1
)
}
);
}
}
}
return
[
matches
,
descriptionMatches
];
}
interface
ISCMLayout
{
height
:
number
|
undefined
;
width
:
number
|
undefined
;
...
...
@@ -343,7 +311,7 @@ class RepositoryPaneActionRunner extends ActionRunner {
}
}
class
ResourceRenderer
implements
ICompressibleTreeRenderer
<
ISCMResource
|
IResourceNode
<
ISCMResource
,
ISCMResourceGroup
>
,
FuzzyScore
,
ResourceTemplate
>
{
class
ResourceRenderer
implements
ICompressibleTreeRenderer
<
ISCMResource
|
IResourceNode
<
ISCMResource
,
ISCMResourceGroup
>
,
FuzzyScore
|
LabelFuzzyScore
,
ResourceTemplate
>
{
static
readonly
TEMPLATE_ID
=
'
resource
'
;
get
templateId
():
string
{
return
ResourceRenderer
.
TEMPLATE_ID
;
}
...
...
@@ -373,7 +341,7 @@ class ResourceRenderer implements ICompressibleTreeRenderer<ISCMResource | IReso
return
{
element
,
name
,
fileLabel
,
decorationIcon
,
actionBar
,
elementDisposables
:
Disposable
.
None
,
disposables
};
}
renderElement
(
node
:
ITreeNode
<
ISCMResource
,
FuzzyScore
>
|
ITreeNode
<
ISCMResource
|
IResourceNode
<
ISCMResource
,
ISCMResourceGroup
>
,
FuzzyScore
>
,
index
:
number
,
template
:
ResourceTemplate
):
void
{
renderElement
(
node
:
ITreeNode
<
ISCMResource
,
FuzzyScore
|
LabelFuzzyScore
>
|
ITreeNode
<
ISCMResource
|
IResourceNode
<
ISCMResource
,
ISCMResourceGroup
>
,
FuzzyScore
|
Label
FuzzyScore
>
,
index
:
number
,
template
:
ResourceTemplate
):
void
{
template
.
elementDisposables
.
dispose
();
const
elementDisposables
=
new
DisposableStore
();
...
...
@@ -397,13 +365,14 @@ class ResourceRenderer implements ICompressibleTreeRenderer<ISCMResource | IReso
template
.
name
.
classList
.
toggle
(
'
strike-through
'
,
resourceOrFolder
.
element
.
decorations
.
strikeThrough
);
template
.
element
.
classList
.
toggle
(
'
faded
'
,
resourceOrFolder
.
element
.
decorations
.
faded
);
}
else
{
matches
=
createMatches
(
node
.
filterData
as
FuzzyScore
|
undefined
);
const
menus
=
this
.
scmViewService
.
menus
.
getRepositoryMenus
(
resourceOrFolder
.
context
.
provider
);
elementDisposables
.
add
(
connectPrimaryMenuToInlineActionBar
(
menus
.
getResourceFolderMenu
(
resourceOrFolder
.
context
),
template
.
actionBar
));
template
.
name
.
classList
.
remove
(
'
strike-through
'
);
template
.
element
.
classList
.
remove
(
'
faded
'
);
}
}
else
{
[
matches
,
descriptionMatches
]
=
splitMatches
(
uri
,
node
.
filterData
);
[
matches
,
descriptionMatches
]
=
this
.
_processFilterData
(
uri
,
node
.
filterData
);
const
menus
=
this
.
scmViewService
.
menus
.
getRepositoryMenus
(
resourceOrFolder
.
resourceGroup
.
provider
);
elementDisposables
.
add
(
connectPrimaryMenuToInlineActionBar
(
menus
.
getResourceMenu
(
resourceOrFolder
),
template
.
actionBar
));
template
.
name
.
classList
.
toggle
(
'
strike-through
'
,
resourceOrFolder
.
decorations
.
strikeThrough
);
...
...
@@ -440,11 +409,11 @@ class ResourceRenderer implements ICompressibleTreeRenderer<ISCMResource | IReso
template
.
elementDisposables
=
elementDisposables
;
}
disposeElement
(
resource
:
ITreeNode
<
ISCMResource
,
FuzzyScore
>
|
ITreeNode
<
IResourceNode
<
ISCMResource
,
ISCMResourceGroup
>
,
FuzzyScore
>
,
index
:
number
,
template
:
ResourceTemplate
):
void
{
disposeElement
(
resource
:
ITreeNode
<
ISCMResource
,
FuzzyScore
|
LabelFuzzyScore
>
|
ITreeNode
<
IResourceNode
<
ISCMResource
,
ISCMResourceGroup
>
,
FuzzyScore
|
Label
FuzzyScore
>
,
index
:
number
,
template
:
ResourceTemplate
):
void
{
template
.
elementDisposables
.
dispose
();
}
renderCompressedElements
(
node
:
ITreeNode
<
ICompressedTreeNode
<
ISCMResource
>
|
ICompressedTreeNode
<
IResourceNode
<
ISCMResource
,
ISCMResourceGroup
>>
,
FuzzyScore
>
,
index
:
number
,
template
:
ResourceTemplate
,
height
:
number
|
undefined
):
void
{
renderCompressedElements
(
node
:
ITreeNode
<
ICompressedTreeNode
<
ISCMResource
>
|
ICompressedTreeNode
<
IResourceNode
<
ISCMResource
,
ISCMResourceGroup
>>
,
FuzzyScore
|
LabelFuzzyScore
>
,
index
:
number
,
template
:
ResourceTemplate
,
height
:
number
|
undefined
):
void
{
template
.
elementDisposables
.
dispose
();
const
elementDisposables
=
new
DisposableStore
();
...
...
@@ -454,9 +423,11 @@ class ResourceRenderer implements ICompressibleTreeRenderer<ISCMResource | IReso
const
label
=
compressed
.
elements
.
map
(
e
=>
e
.
name
).
join
(
'
/
'
);
const
fileKind
=
FileKind
.
FOLDER
;
const
matches
=
createMatches
(
node
.
filterData
as
FuzzyScore
|
undefined
);
template
.
fileLabel
.
setResource
({
resource
:
folder
.
uri
,
name
:
label
},
{
fileDecorations
:
{
colors
:
false
,
badges
:
true
},
fileKind
fileKind
,
matches
});
template
.
actionBar
.
clear
();
...
...
@@ -474,7 +445,7 @@ class ResourceRenderer implements ICompressibleTreeRenderer<ISCMResource | IReso
template
.
elementDisposables
=
elementDisposables
;
}
disposeCompressedElements
(
node
:
ITreeNode
<
ICompressedTreeNode
<
ISCMResource
>
|
ICompressedTreeNode
<
IResourceNode
<
ISCMResource
,
ISCMResourceGroup
>>
,
FuzzyScore
>
,
index
:
number
,
template
:
ResourceTemplate
,
height
:
number
|
undefined
):
void
{
disposeCompressedElements
(
node
:
ITreeNode
<
ICompressedTreeNode
<
ISCMResource
>
|
ICompressedTreeNode
<
IResourceNode
<
ISCMResource
,
ISCMResourceGroup
>>
,
FuzzyScore
|
LabelFuzzyScore
>
,
index
:
number
,
template
:
ResourceTemplate
,
height
:
number
|
undefined
):
void
{
template
.
elementDisposables
.
dispose
();
}
...
...
@@ -482,6 +453,56 @@ class ResourceRenderer implements ICompressibleTreeRenderer<ISCMResource | IReso
template
.
elementDisposables
.
dispose
();
template
.
disposables
.
dispose
();
}
private
_processFilterData
(
uri
:
URI
,
filterData
:
FuzzyScore
|
LabelFuzzyScore
|
undefined
):
[
IMatch
[]
|
undefined
,
IMatch
[]
|
undefined
]
{
if
(
!
filterData
)
{
return
[
undefined
,
undefined
];
}
if
(
!
(
filterData
as
LabelFuzzyScore
).
label
)
{
const
matches
=
createMatches
(
filterData
as
FuzzyScore
);
return
[
matches
,
undefined
];
}
const
fileName
=
basename
(
uri
);
const
label
=
(
filterData
as
LabelFuzzyScore
).
label
;
const
pathLength
=
label
.
length
-
fileName
.
length
;
const
matches
=
createMatches
((
filterData
as
LabelFuzzyScore
).
score
);
// FileName match
if
(
label
===
fileName
)
{
return
[
matches
,
undefined
];
}
// FilePath match
let
labelMatches
:
IMatch
[]
=
[];
let
descriptionMatches
:
IMatch
[]
=
[];
for
(
const
match
of
matches
)
{
if
(
match
.
start
>
pathLength
)
{
// Label match
labelMatches
.
push
({
start
:
match
.
start
-
pathLength
,
end
:
match
.
end
-
pathLength
});
}
else
if
(
match
.
end
<
pathLength
)
{
// Description match
descriptionMatches
.
push
(
match
);
}
else
{
// Spanning match
labelMatches
.
push
({
start
:
0
,
end
:
match
.
end
-
pathLength
});
descriptionMatches
.
push
({
start
:
match
.
start
,
end
:
pathLength
});
}
}
return
[
labelMatches
,
descriptionMatches
];
}
}
class
ListDelegate
implements
IListVirtualDelegate
<
TreeElement
>
{
...
...
@@ -601,7 +622,7 @@ export class SCMTreeKeyboardNavigationLabelProvider implements ICompressibleKeyb
@
ILabelService
private
readonly
labelService
:
ILabelService
,
)
{
}
getKeyboardNavigationLabel
(
element
:
TreeElement
):
{
toString
():
string
;
}
|
undefined
{
getKeyboardNavigationLabel
(
element
:
TreeElement
):
{
toString
():
string
;
}
|
{
toString
():
string
;
}[]
|
undefined
{
if
(
ResourceTree
.
isResourceNode
(
element
))
{
return
element
.
name
;
}
else
if
(
isSCMRepository
(
element
))
{
...
...
@@ -614,11 +635,13 @@ export class SCMTreeKeyboardNavigationLabelProvider implements ICompressibleKeyb
const
viewModel
=
this
.
viewModelProvider
();
if
(
viewModel
.
mode
===
ViewModelMode
.
List
)
{
// In List mode match using the file name and the path.
// Since a match in the file name takes precedence over a match
// in the folder name we are returning the label as file folder.
// Since we want to match both on the file name and the
// full path we return an array of labels. A match in the
// file name takes precedence over a match in the path.
const
fileName
=
basename
(
element
.
sourceUri
);
const
filePath
=
this
.
labelService
.
getUriLabel
(
dirname
(
element
.
sourceUri
),
{
relative
:
true
});
return
filePath
.
length
!==
0
?
`
${
fileName
}
${
filePath
}
`
:
fileName
;
const
filePath
=
this
.
labelService
.
getUriLabel
(
element
.
sourceUri
,
{
relative
:
true
});
return
[
fileName
,
filePath
];
}
else
{
// In Tree mode only match using the file name
return
basename
(
element
.
sourceUri
);
...
...
@@ -1637,7 +1660,7 @@ export class SCMViewPane extends ViewPane {
this
.
_register
(
actionRunner
);
this
.
_register
(
actionRunner
.
onDidBeforeRun
(()
=>
this
.
tree
.
domFocus
()));
const
renderers
:
ICompressibleTreeRenderer
<
any
,
FuzzyScore
,
any
>
[]
=
[
const
renderers
:
ICompressibleTreeRenderer
<
any
,
any
,
any
>
[]
=
[
this
.
instantiationService
.
createInstance
(
RepositoryRenderer
,
actionViewItemProvider
),
this
.
inputRenderer
,
this
.
instantiationService
.
createInstance
(
ResourceGroupRenderer
,
actionViewItemProvider
),
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录