Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
b9efdab4
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,发现更多精彩内容 >>
未验证
提交
b9efdab4
编写于
5月 30, 2020
作者:
J
Jody Heavener
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor find widget to support multiple selection find/replace
上级
fcd551f9
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
246 addition
and
96 deletion
+246
-96
src/vs/editor/common/model.ts
src/vs/editor/common/model.ts
+2
-2
src/vs/editor/common/model/textModel.ts
src/vs/editor/common/model/textModel.ts
+19
-7
src/vs/editor/contrib/find/findController.ts
src/vs/editor/contrib/find/findController.ts
+19
-9
src/vs/editor/contrib/find/findDecorations.ts
src/vs/editor/contrib/find/findDecorations.ts
+27
-14
src/vs/editor/contrib/find/findModel.ts
src/vs/editor/contrib/find/findModel.ts
+37
-24
src/vs/editor/contrib/find/findState.ts
src/vs/editor/contrib/find/findState.ts
+8
-4
src/vs/editor/contrib/find/findWidget.ts
src/vs/editor/contrib/find/findWidget.ts
+32
-15
src/vs/editor/contrib/find/test/findController.test.ts
src/vs/editor/contrib/find/test/findController.test.ts
+15
-9
src/vs/editor/contrib/find/test/findModel.test.ts
src/vs/editor/contrib/find/test/findModel.test.ts
+77
-4
src/vs/editor/contrib/multicursor/multicursor.ts
src/vs/editor/contrib/multicursor/multicursor.ts
+8
-6
src/vs/monaco.d.ts
src/vs/monaco.d.ts
+2
-2
未找到文件。
src/vs/editor/common/model.ts
浏览文件 @
b9efdab4
...
...
@@ -800,7 +800,7 @@ export interface ITextModel {
/**
* Search the model.
* @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
* @param searchScope Limit the searching to only search inside th
is range
.
* @param searchScope Limit the searching to only search inside th
ese ranges
.
* @param isRegex Used to indicate that `searchString` is a regular expression.
* @param matchCase Force the matching to match lower/upper case exactly.
* @param wordSeparators Force the matching to match entire words only. Pass null otherwise.
...
...
@@ -808,7 +808,7 @@ export interface ITextModel {
* @param limitResultCount Limit the number of results
* @return The ranges where the matches are. It is empty if no matches have been found.
*/
findMatches
(
searchString
:
string
,
searchScope
:
IRange
,
isRegex
:
boolean
,
matchCase
:
boolean
,
wordSeparators
:
string
|
null
,
captureMatches
:
boolean
,
limitResultCount
?:
number
):
FindMatch
[];
findMatches
(
searchString
:
string
,
searchScope
:
IRange
|
IRange
[]
,
isRegex
:
boolean
,
matchCase
:
boolean
,
wordSeparators
:
string
|
null
,
captureMatches
:
boolean
,
limitResultCount
?:
number
):
FindMatch
[];
/**
* Search the model for the next match. Loops to the beginning of the model if needed.
* @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
...
...
src/vs/editor/common/model/textModel.ts
浏览文件 @
b9efdab4
...
...
@@ -1112,13 +1112,23 @@ export class TextModel extends Disposable implements model.ITextModel {
public
findMatches
(
searchString
:
string
,
rawSearchScope
:
any
,
isRegex
:
boolean
,
matchCase
:
boolean
,
wordSeparators
:
string
|
null
,
captureMatches
:
boolean
,
limitResultCount
:
number
=
LIMIT_FIND_COUNT
):
model
.
FindMatch
[]
{
this
.
_assertNotDisposed
();
let
searchRange
:
Range
;
if
(
Range
.
isIRange
(
rawSearchScope
))
{
searchRange
=
this
.
validateRange
(
rawSearchScope
);
}
else
{
searchRange
=
this
.
getFullModelRange
();
let
searchRanges
:
Range
[]
|
null
=
null
;
if
(
rawSearchScope
!==
null
)
{
if
(
!
Array
.
isArray
(
rawSearchScope
))
{
rawSearchScope
=
[
rawSearchScope
];
}
if
(
rawSearchScope
.
every
((
searchScope
:
Range
)
=>
Range
.
isIRange
(
searchScope
)))
{
searchRanges
=
rawSearchScope
.
map
((
searchScope
:
Range
)
=>
this
.
validateRange
(
searchScope
));
}
}
if
(
searchRanges
===
null
)
{
searchRanges
=
[
this
.
getFullModelRange
()];
}
let
matchMapper
:
(
value
:
Range
,
index
:
number
,
array
:
Range
[])
=>
model
.
FindMatch
[];
if
(
!
isRegex
&&
searchString
.
indexOf
(
'
\n
'
)
<
0
)
{
// not regex, not multi line
const
searchParams
=
new
SearchParams
(
searchString
,
isRegex
,
matchCase
,
wordSeparators
);
...
...
@@ -1128,10 +1138,12 @@ export class TextModel extends Disposable implements model.ITextModel {
return
[];
}
return
this
.
findMatchesLineByLine
(
searchRange
,
searchData
,
captureMatches
,
limitResultCount
);
matchMapper
=
(
searchRange
:
Range
)
=>
this
.
findMatchesLineByLine
(
searchRange
,
searchData
,
captureMatches
,
limitResultCount
);
}
else
{
matchMapper
=
(
searchRange
:
Range
)
=>
TextModelSearch
.
findMatches
(
this
,
new
SearchParams
(
searchString
,
isRegex
,
matchCase
,
wordSeparators
),
searchRange
,
captureMatches
,
limitResultCount
);
}
return
TextModelSearch
.
findMatches
(
this
,
new
SearchParams
(
searchString
,
isRegex
,
matchCase
,
wordSeparators
),
searchRange
,
captureMatches
,
limitResultCount
);
return
searchRanges
.
map
(
matchMapper
).
reduce
((
arr
,
matches
:
model
.
FindMatch
[])
=>
arr
.
concat
(
matches
),
[]
);
}
public
findNextMatch
(
searchString
:
string
,
rawSearchStart
:
IPosition
,
isRegex
:
boolean
,
matchCase
:
boolean
,
wordSeparators
:
string
,
captureMatches
:
boolean
):
model
.
FindMatch
|
null
{
...
...
src/vs/editor/contrib/find/findController.ts
浏览文件 @
b9efdab4
...
...
@@ -233,12 +233,22 @@ export class CommonFindController extends Disposable implements IEditorContribut
this
.
_state
.
change
({
searchScope
:
null
},
true
);
}
else
{
if
(
this
.
_editor
.
hasModel
())
{
let
selection
=
this
.
_editor
.
getSelection
();
if
(
selection
.
endColumn
===
1
&&
selection
.
endLineNumber
>
selection
.
startLineNumber
)
{
selection
=
selection
.
setEndPosition
(
selection
.
endLineNumber
-
1
,
this
.
_editor
.
getModel
().
getLineMaxColumn
(
selection
.
endLineNumber
-
1
));
}
if
(
!
selection
.
isEmpty
())
{
this
.
_state
.
change
({
searchScope
:
selection
},
true
);
let
selections
=
this
.
_editor
.
getSelections
();
selections
.
map
(
selection
=>
{
if
(
selection
.
endColumn
===
1
&&
selection
.
endLineNumber
>
selection
.
startLineNumber
)
{
selection
=
selection
.
setEndPosition
(
selection
.
endLineNumber
-
1
,
this
.
_editor
.
getModel
()
!
.
getLineMaxColumn
(
selection
.
endLineNumber
-
1
)
);
}
if
(
!
selection
.
isEmpty
())
{
return
selection
;
}
return
null
;
}).
filter
(
element
=>
!!
element
);
if
(
selections
.
length
)
{
this
.
_state
.
change
({
searchScope
:
selections
},
true
);
}
}
}
...
...
@@ -293,9 +303,9 @@ export class CommonFindController extends Disposable implements IEditorContribut
}
if
(
opts
.
updateSearchScope
)
{
let
currentSelection
=
this
.
_editor
.
getSelection
();
if
(
!
currentSelection
.
isEmpty
(
))
{
stateChanges
.
searchScope
=
currentSelection
;
let
currentSelection
s
=
this
.
_editor
.
getSelections
();
if
(
currentSelections
.
some
(
selection
=>
!
selection
.
isEmpty
()
))
{
stateChanges
.
searchScope
=
currentSelection
s
;
}
}
...
...
src/vs/editor/contrib/find/findDecorations.ts
浏览文件 @
b9efdab4
...
...
@@ -17,7 +17,7 @@ export class FindDecorations implements IDisposable {
private
readonly
_editor
:
IActiveCodeEditor
;
private
_decorations
:
string
[];
private
_overviewRulerApproximateDecorations
:
string
[];
private
_findScopeDecorationId
:
string
|
null
;
private
_findScopeDecorationId
s
:
string
[]
;
private
_rangeHighlightDecorationId
:
string
|
null
;
private
_highlightedDecorationId
:
string
|
null
;
private
_startPosition
:
Position
;
...
...
@@ -26,7 +26,7 @@ export class FindDecorations implements IDisposable {
this
.
_editor
=
editor
;
this
.
_decorations
=
[];
this
.
_overviewRulerApproximateDecorations
=
[];
this
.
_findScopeDecorationId
=
null
;
this
.
_findScopeDecorationId
s
=
[]
;
this
.
_rangeHighlightDecorationId
=
null
;
this
.
_highlightedDecorationId
=
null
;
this
.
_startPosition
=
this
.
_editor
.
getPosition
();
...
...
@@ -37,7 +37,7 @@ export class FindDecorations implements IDisposable {
this
.
_decorations
=
[];
this
.
_overviewRulerApproximateDecorations
=
[];
this
.
_findScopeDecorationId
=
null
;
this
.
_findScopeDecorationId
s
=
[]
;
this
.
_rangeHighlightDecorationId
=
null
;
this
.
_highlightedDecorationId
=
null
;
}
...
...
@@ -45,7 +45,7 @@ export class FindDecorations implements IDisposable {
public
reset
():
void
{
this
.
_decorations
=
[];
this
.
_overviewRulerApproximateDecorations
=
[];
this
.
_findScopeDecorationId
=
null
;
this
.
_findScopeDecorationId
s
=
[]
;
this
.
_rangeHighlightDecorationId
=
null
;
this
.
_highlightedDecorationId
=
null
;
}
...
...
@@ -54,9 +54,22 @@ export class FindDecorations implements IDisposable {
return
this
.
_decorations
.
length
;
}
/** @deprecated use getFindScopes to support multiple selections */
public
getFindScope
():
Range
|
null
{
if
(
this
.
_findScopeDecorationId
)
{
return
this
.
_editor
.
getModel
().
getDecorationRange
(
this
.
_findScopeDecorationId
);
if
(
this
.
_findScopeDecorationIds
[
0
])
{
return
this
.
_editor
.
getModel
().
getDecorationRange
(
this
.
_findScopeDecorationIds
[
0
]);
}
return
null
;
}
public
getFindScopes
():
Range
[]
|
null
{
if
(
this
.
_findScopeDecorationIds
.
length
)
{
const
scopes
=
this
.
_findScopeDecorationIds
.
map
(
findScopeDecorationId
=>
this
.
_editor
.
getModel
().
getDecorationRange
(
findScopeDecorationId
)
).
filter
(
element
=>
!!
element
);
if
(
scopes
.
length
)
{
return
scopes
as
Range
[];
}
}
return
null
;
}
...
...
@@ -133,7 +146,7 @@ export class FindDecorations implements IDisposable {
return
matchPosition
;
}
public
set
(
findMatches
:
FindMatch
[],
findScope
:
Range
|
null
):
void
{
public
set
(
findMatches
:
FindMatch
[],
findScope
s
:
Range
[]
|
null
):
void
{
this
.
_editor
.
changeDecorations
((
accessor
)
=>
{
let
findMatchesOptions
:
ModelDecorationOptions
=
FindDecorations
.
_FIND_MATCH_DECORATION
;
...
...
@@ -195,12 +208,12 @@ export class FindDecorations implements IDisposable {
}
// Find scope
if
(
this
.
_findScopeDecorationId
)
{
accessor
.
removeDecoration
(
this
.
_findScopeDecorationId
);
this
.
_findScopeDecorationId
=
null
;
if
(
this
.
_findScopeDecorationId
s
.
length
)
{
this
.
_findScopeDecorationIds
.
forEach
(
findScopeDecorationId
=>
accessor
.
removeDecoration
(
findScopeDecorationId
)
);
this
.
_findScopeDecorationId
s
=
[]
;
}
if
(
findScope
)
{
this
.
_findScopeDecorationId
=
accessor
.
addDecoration
(
findScope
,
FindDecorations
.
_FIND_SCOPE_DECORATION
);
if
(
findScope
s
?.
length
)
{
this
.
_findScopeDecorationId
s
=
findScopes
.
map
(
findScope
=>
accessor
.
addDecoration
(
findScope
,
FindDecorations
.
_FIND_SCOPE_DECORATION
)
);
}
});
}
...
...
@@ -253,8 +266,8 @@ export class FindDecorations implements IDisposable {
let
result
:
string
[]
=
[];
result
=
result
.
concat
(
this
.
_decorations
);
result
=
result
.
concat
(
this
.
_overviewRulerApproximateDecorations
);
if
(
this
.
_findScopeDecorationId
)
{
result
.
push
(
this
.
_findScopeDecorationId
);
if
(
this
.
_findScopeDecorationId
s
.
length
)
{
result
.
push
(
...
this
.
_findScopeDecorationIds
);
}
if
(
this
.
_rangeHighlightDecorationId
)
{
result
.
push
(
this
.
_rangeHighlightDecorationId
);
...
...
src/vs/editor/contrib/find/findModel.ts
浏览文件 @
b9efdab4
...
...
@@ -168,26 +168,36 @@ export class FindModelBoundToEditorModel {
return
model
.
getFullModelRange
();
}
private
research
(
moveCursor
:
boolean
,
newFindScope
?:
Range
|
null
):
void
{
let
findScope
:
Range
|
null
=
null
;
private
research
(
moveCursor
:
boolean
,
newFindScope
?:
Range
|
Range
[]
|
null
):
void
{
let
findScope
s
:
Range
[]
|
null
=
null
;
if
(
typeof
newFindScope
!==
'
undefined
'
)
{
findScope
=
newFindScope
;
}
else
{
findScope
=
this
.
_decorations
.
getFindScope
();
}
if
(
findScope
!==
null
)
{
if
(
findScope
.
startLineNumber
!==
findScope
.
endLineNumber
)
{
if
(
findScope
.
endColumn
===
1
)
{
findScope
=
new
Range
(
findScope
.
startLineNumber
,
1
,
findScope
.
endLineNumber
-
1
,
this
.
_editor
.
getModel
().
getLineMaxColumn
(
findScope
.
endLineNumber
-
1
));
if
(
newFindScope
!==
null
)
{
if
(
!
Array
.
isArray
(
newFindScope
))
{
findScopes
=
[
newFindScope
as
Range
];
}
else
{
// multiline find scope => expand to line starts / ends
findScope
=
new
Range
(
findScope
.
startLineNumber
,
1
,
findScope
.
endLineNumber
,
this
.
_editor
.
getModel
().
getLineMaxColumn
(
findScope
.
endLineNumber
));
findScopes
=
newFindScope
;
}
}
}
else
{
findScopes
=
this
.
_decorations
.
getFindScopes
();
}
if
(
findScopes
!==
null
)
{
findScopes
=
findScopes
.
map
(
findScope
=>
{
if
(
findScope
.
startLineNumber
!==
findScope
.
endLineNumber
)
{
let
endLineNumber
=
findScope
.
endLineNumber
;
let
findMatches
=
this
.
_findMatches
(
findScope
,
false
,
MATCHES_LIMIT
);
this
.
_decorations
.
set
(
findMatches
,
findScope
);
if
(
findScope
.
endColumn
===
1
)
{
endLineNumber
=
endLineNumber
-
1
;
}
return
new
Range
(
findScope
.
startLineNumber
,
1
,
endLineNumber
,
this
.
_editor
.
getModel
().
getLineMaxColumn
(
endLineNumber
));
}
return
findScope
;
});
}
let
findMatches
=
this
.
_findMatches
(
findScopes
,
false
,
MATCHES_LIMIT
);
this
.
_decorations
.
set
(
findMatches
,
findScopes
);
this
.
_state
.
changeMatchInfo
(
this
.
_decorations
.
getCurrentMatchesPosition
(
this
.
_editor
.
getSelection
()),
...
...
@@ -443,9 +453,12 @@ export class FindModelBoundToEditorModel {
}
}
private
_findMatches
(
findScope
:
Range
|
null
,
captureMatches
:
boolean
,
limitResultCount
:
number
):
FindMatch
[]
{
let
searchRange
=
FindModelBoundToEditorModel
.
_getSearchRange
(
this
.
_editor
.
getModel
(),
findScope
);
return
this
.
_editor
.
getModel
().
findMatches
(
this
.
_state
.
searchString
,
searchRange
,
this
.
_state
.
isRegex
,
this
.
_state
.
matchCase
,
this
.
_state
.
wholeWord
?
this
.
_editor
.
getOption
(
EditorOption
.
wordSeparators
)
:
null
,
captureMatches
,
limitResultCount
);
private
_findMatches
(
findScopes
:
Range
[]
|
null
,
captureMatches
:
boolean
,
limitResultCount
:
number
):
FindMatch
[]
{
const
searchRanges
=
(
findScopes
as
[]
||
[
null
]).
map
((
scope
:
Range
|
null
)
=>
FindModelBoundToEditorModel
.
_getSearchRange
(
this
.
_editor
.
getModel
(),
scope
)
);
return
this
.
_editor
.
getModel
().
findMatches
(
this
.
_state
.
searchString
,
searchRanges
,
this
.
_state
.
isRegex
,
this
.
_state
.
matchCase
,
this
.
_state
.
wholeWord
?
this
.
_editor
.
getOption
(
EditorOption
.
wordSeparators
)
:
null
,
captureMatches
,
limitResultCount
);
}
public
replaceAll
():
void
{
...
...
@@ -453,13 +466,13 @@ export class FindModelBoundToEditorModel {
return
;
}
const
findScope
=
this
.
_decorations
.
getFindScope
();
const
findScope
s
=
this
.
_decorations
.
getFindScopes
();
if
(
findScope
===
null
&&
this
.
_state
.
matchesCount
>=
MATCHES_LIMIT
)
{
if
(
findScope
s
===
null
&&
this
.
_state
.
matchesCount
>=
MATCHES_LIMIT
)
{
// Doing a replace on the entire file that is over ${MATCHES_LIMIT} matches
this
.
_largeReplaceAll
();
}
else
{
this
.
_regularReplaceAll
(
findScope
);
this
.
_regularReplaceAll
(
findScope
s
);
}
this
.
research
(
false
);
...
...
@@ -504,10 +517,10 @@ export class FindModelBoundToEditorModel {
this
.
_executeEditorCommand
(
'
replaceAll
'
,
command
);
}
private
_regularReplaceAll
(
findScope
:
Range
|
null
):
void
{
private
_regularReplaceAll
(
findScope
s
:
Range
[]
|
null
):
void
{
const
replacePattern
=
this
.
_getReplacePattern
();
// Get all the ranges (even more than the highlighted ones)
let
matches
=
this
.
_findMatches
(
findScope
,
replacePattern
.
hasReplacementPatterns
||
this
.
_state
.
preserveCase
,
Constants
.
MAX_SAFE_SMALL_INTEGER
);
let
matches
=
this
.
_findMatches
(
findScope
s
,
replacePattern
.
hasReplacementPatterns
||
this
.
_state
.
preserveCase
,
Constants
.
MAX_SAFE_SMALL_INTEGER
);
let
replaceStrings
:
string
[]
=
[];
for
(
let
i
=
0
,
len
=
matches
.
length
;
i
<
len
;
i
++
)
{
...
...
@@ -523,10 +536,10 @@ export class FindModelBoundToEditorModel {
return
;
}
let
findScope
=
this
.
_decorations
.
getFindScope
();
let
findScope
s
=
this
.
_decorations
.
getFindScopes
();
// Get all the ranges (even more than the highlighted ones)
let
matches
=
this
.
_findMatches
(
findScope
,
false
,
Constants
.
MAX_SAFE_SMALL_INTEGER
);
let
matches
=
this
.
_findMatches
(
findScope
s
,
false
,
Constants
.
MAX_SAFE_SMALL_INTEGER
);
let
selections
=
matches
.
map
(
m
=>
new
Selection
(
m
.
range
.
startLineNumber
,
m
.
range
.
startColumn
,
m
.
range
.
endLineNumber
,
m
.
range
.
endColumn
));
// If one of the ranges is the editor selection, then maintain it as primary
...
...
src/vs/editor/contrib/find/findState.ts
浏览文件 @
b9efdab4
...
...
@@ -46,7 +46,7 @@ export interface INewFindReplaceState {
matchCaseOverride
?:
FindOptionOverride
;
preserveCase
?:
boolean
;
preserveCaseOverride
?:
FindOptionOverride
;
searchScope
?:
Range
|
null
;
searchScope
?:
Range
[]
|
null
;
loop
?:
boolean
;
}
...
...
@@ -73,7 +73,7 @@ export class FindReplaceState extends Disposable {
private
_matchCaseOverride
:
FindOptionOverride
;
private
_preserveCase
:
boolean
;
private
_preserveCaseOverride
:
FindOptionOverride
;
private
_searchScope
:
Range
|
null
;
private
_searchScope
:
Range
[]
|
null
;
private
_matchesPosition
:
number
;
private
_matchesCount
:
number
;
private
_currentMatch
:
Range
|
null
;
...
...
@@ -94,7 +94,7 @@ export class FindReplaceState extends Disposable {
public
get
actualMatchCase
():
boolean
{
return
this
.
_matchCase
;
}
public
get
actualPreserveCase
():
boolean
{
return
this
.
_preserveCase
;
}
public
get
searchScope
():
Range
|
null
{
return
this
.
_searchScope
;
}
public
get
searchScope
():
Range
[]
|
null
{
return
this
.
_searchScope
;
}
public
get
matchesPosition
():
number
{
return
this
.
_matchesPosition
;
}
public
get
matchesCount
():
number
{
return
this
.
_matchesCount
;
}
public
get
currentMatch
():
Range
|
null
{
return
this
.
_currentMatch
;
}
...
...
@@ -238,7 +238,11 @@ export class FindReplaceState extends Disposable {
this
.
_preserveCase
=
newState
.
preserveCase
;
}
if
(
typeof
newState
.
searchScope
!==
'
undefined
'
)
{
if
(
!
Range
.
equalsRange
(
this
.
_searchScope
,
newState
.
searchScope
))
{
if
(
!
newState
.
searchScope
?.
every
((
newSearchScope
)
=>
{
return
this
.
_searchScope
?.
some
(
existingSearchScope
=>
{
return
!
Range
.
equalsRange
(
existingSearchScope
,
newSearchScope
);
});
}))
{
this
.
_searchScope
=
newState
.
searchScope
;
changeEvent
.
searchScope
=
true
;
somethingChanged
=
true
;
...
...
src/vs/editor/contrib/find/findWidget.ts
浏览文件 @
b9efdab4
...
...
@@ -803,16 +803,26 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL
}
if
(
this
.
_toggleSelectionFind
.
checked
)
{
let
selection
=
this
.
_codeEditor
.
getSelection
();
if
(
selection
.
endColumn
===
1
&&
selection
.
endLineNumber
>
selection
.
startLineNumber
)
{
selection
=
selection
.
setEndPosition
(
selection
.
endLineNumber
-
1
,
this
.
_codeEditor
.
getModel
().
getLineMaxColumn
(
selection
.
endLineNumber
-
1
));
}
const
currentMatch
=
this
.
_state
.
currentMatch
;
if
(
selection
.
startLineNumber
!==
selection
.
endLineNumber
)
{
if
(
!
Range
.
equalsRange
(
selection
,
currentMatch
))
{
// Reseed find scope
this
.
_state
.
change
({
searchScope
:
selection
},
true
);
let
selections
=
this
.
_codeEditor
.
getSelections
();
selections
.
map
(
selection
=>
{
if
(
selection
.
endColumn
===
1
&&
selection
.
endLineNumber
>
selection
.
startLineNumber
)
{
selection
=
selection
.
setEndPosition
(
selection
.
endLineNumber
-
1
,
this
.
_codeEditor
.
getModel
()
!
.
getLineMaxColumn
(
selection
.
endLineNumber
-
1
)
);
}
const
currentMatch
=
this
.
_state
.
currentMatch
;
if
(
selection
.
startLineNumber
!==
selection
.
endLineNumber
)
{
if
(
!
Range
.
equalsRange
(
selection
,
currentMatch
))
{
return
selection
;
}
}
return
null
;
}).
filter
(
element
=>
!!
element
);
if
(
selections
.
length
)
{
this
.
_state
.
change
({
searchScope
:
selections
as
Range
[]
},
true
);
}
}
}
...
...
@@ -1027,12 +1037,19 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL
this
.
_register
(
this
.
_toggleSelectionFind
.
onChange
(()
=>
{
if
(
this
.
_toggleSelectionFind
.
checked
)
{
if
(
this
.
_codeEditor
.
hasModel
())
{
let
selection
=
this
.
_codeEditor
.
getSelection
();
if
(
selection
.
endColumn
===
1
&&
selection
.
endLineNumber
>
selection
.
startLineNumber
)
{
selection
=
selection
.
setEndPosition
(
selection
.
endLineNumber
-
1
,
this
.
_codeEditor
.
getModel
().
getLineMaxColumn
(
selection
.
endLineNumber
-
1
));
}
if
(
!
selection
.
isEmpty
())
{
this
.
_state
.
change
({
searchScope
:
selection
},
true
);
let
selections
=
this
.
_codeEditor
.
getSelections
();
selections
.
map
(
selection
=>
{
if
(
selection
.
endColumn
===
1
&&
selection
.
endLineNumber
>
selection
.
startLineNumber
)
{
selection
=
selection
.
setEndPosition
(
selection
.
endLineNumber
-
1
,
this
.
_codeEditor
.
getModel
()
!
.
getLineMaxColumn
(
selection
.
endLineNumber
-
1
));
}
if
(
!
selection
.
isEmpty
())
{
return
selection
;
}
return
null
;
}).
filter
(
element
=>
!!
element
);
if
(
selections
.
length
)
{
this
.
_state
.
change
({
searchScope
:
selections
as
Range
[]
},
true
);
}
}
}
else
{
...
...
src/vs/editor/contrib/find/test/findController.test.ts
浏览文件 @
b9efdab4
...
...
@@ -309,10 +309,10 @@ suite('FindController', () => {
assert
.
equal
(
findController
.
getState
().
searchScope
,
null
);
findController
.
getState
().
change
({
searchScope
:
new
Range
(
1
,
1
,
1
,
5
)
searchScope
:
[
new
Range
(
1
,
1
,
1
,
5
)]
},
false
);
assert
.
deepEqual
(
findController
.
getState
().
searchScope
,
new
Range
(
1
,
1
,
1
,
5
)
);
assert
.
deepEqual
(
findController
.
getState
().
searchScope
,
[
new
Range
(
1
,
1
,
1
,
5
)]
);
findController
.
closeFindWidget
();
assert
.
equal
(
findController
.
getState
().
searchScope
,
null
);
...
...
@@ -523,10 +523,8 @@ suite('FindController query options persistence', () => {
'
var z = (3 * 5)
'
,
],
{
serviceCollection
:
serviceCollection
,
find
:
{
autoFindInSelection
:
'
always
'
,
globalFindClipboard
:
false
}
},
(
editor
)
=>
{
// clipboardState = '';
editor
.
setSelection
(
new
Range
(
1
,
1
,
2
,
1
));
let
findController
=
editor
.
registerAndInstantiateContribution
(
TestFindController
.
ID
,
TestFindController
);
findController
.
start
({
const
findConfig
=
{
forceRevealReplace
:
false
,
seedSearchStringFromSelection
:
false
,
seedSearchStringFromGlobalClipboard
:
false
,
...
...
@@ -534,9 +532,17 @@ suite('FindController query options persistence', () => {
shouldAnimate
:
false
,
updateSearchScope
:
true
,
loop
:
true
});
};
editor
.
setSelection
(
new
Range
(
1
,
1
,
2
,
1
));
findController
.
start
(
findConfig
);
assert
.
deepEqual
(
findController
.
getState
().
searchScope
,
[
new
Selection
(
1
,
1
,
2
,
1
)]);
findController
.
closeFindWidget
();
assert
.
deepEqual
(
findController
.
getState
().
searchScope
,
new
Selection
(
1
,
1
,
2
,
1
));
editor
.
setSelections
([
new
Selection
(
1
,
1
,
2
,
1
),
new
Selection
(
2
,
1
,
2
,
5
)]);
findController
.
start
(
findConfig
);
assert
.
deepEqual
(
findController
.
getState
().
searchScope
,
[
new
Selection
(
1
,
1
,
2
,
1
),
new
Selection
(
2
,
1
,
2
,
5
)]);
});
});
...
...
@@ -584,7 +590,7 @@ suite('FindController query options persistence', () => {
loop
:
true
});
assert
.
deepEqual
(
findController
.
getState
().
searchScope
,
new
Selection
(
1
,
2
,
1
,
3
)
);
assert
.
deepEqual
(
findController
.
getState
().
searchScope
,
[
new
Selection
(
1
,
2
,
1
,
3
)]
);
});
});
...
...
@@ -609,7 +615,7 @@ suite('FindController query options persistence', () => {
loop
:
true
});
assert
.
deepEqual
(
findController
.
getState
().
searchScope
,
new
Selection
(
1
,
6
,
2
,
1
)
);
assert
.
deepEqual
(
findController
.
getState
().
searchScope
,
[
new
Selection
(
1
,
6
,
2
,
1
)]
);
});
});
});
src/vs/editor/contrib/find/test/findModel.test.ts
浏览文件 @
b9efdab4
...
...
@@ -210,7 +210,7 @@ suite('FindModel', () => {
);
// simulate adding a search scope
findState
.
change
({
searchScope
:
new
Range
(
8
,
1
,
10
,
1
)
},
true
);
findState
.
change
({
searchScope
:
[
new
Range
(
8
,
1
,
10
,
1
)]
},
true
);
assertFindState
(
editor
,
[
8
,
14
,
8
,
19
],
...
...
@@ -443,7 +443,7 @@ suite('FindModel', () => {
findTest
(
'
find model next stays in scope
'
,
(
editor
)
=>
{
let
findState
=
new
FindReplaceState
();
findState
.
change
({
searchString
:
'
hello
'
,
wholeWord
:
true
,
searchScope
:
new
Range
(
7
,
1
,
9
,
1
)
},
false
);
findState
.
change
({
searchString
:
'
hello
'
,
wholeWord
:
true
,
searchScope
:
[
new
Range
(
7
,
1
,
9
,
1
)]
},
false
);
let
findModel
=
new
FindModelBoundToEditorModel
(
editor
,
findState
);
assertFindState
(
...
...
@@ -493,6 +493,79 @@ suite('FindModel', () => {
findState
.
dispose
();
});
findTest
(
'
multi-selection find model next stays in scope
'
,
(
editor
)
=>
{
let
findState
=
new
FindReplaceState
();
findState
.
change
({
searchString
:
'
hello
'
,
matchCase
:
true
,
wholeWord
:
false
,
searchScope
:
[
new
Range
(
6
,
1
,
7
,
38
),
new
Range
(
9
,
3
,
9
,
38
)]
},
false
);
let
findModel
=
new
FindModelBoundToEditorModel
(
editor
,
findState
);
assertFindState
(
editor
,
[
1
,
1
,
1
,
1
],
null
,
[
[
6
,
14
,
6
,
19
],
// `matchCase: false` would
// find this match as well:
// [6, 27, 6, 32],
[
7
,
14
,
7
,
19
],
// `wholeWord: true` would
// exclude this match:
[
9
,
14
,
9
,
19
],
]
);
findModel
.
moveToNextMatch
();
assertFindState
(
editor
,
[
6
,
14
,
6
,
19
],
[
6
,
14
,
6
,
19
],
[
[
6
,
14
,
6
,
19
],
[
7
,
14
,
7
,
19
],
[
9
,
14
,
9
,
19
],
]
);
findModel
.
moveToNextMatch
();
assertFindState
(
editor
,
[
7
,
14
,
7
,
19
],
[
7
,
14
,
7
,
19
],
[
[
6
,
14
,
6
,
19
],
[
7
,
14
,
7
,
19
],
[
9
,
14
,
9
,
19
],
]
);
findModel
.
moveToNextMatch
();
assertFindState
(
editor
,
[
9
,
14
,
9
,
19
],
[
9
,
14
,
9
,
19
],
[
[
6
,
14
,
6
,
19
],
[
7
,
14
,
7
,
19
],
[
9
,
14
,
9
,
19
],
]
);
findModel
.
moveToNextMatch
();
assertFindState
(
editor
,
[
6
,
14
,
6
,
19
],
[
6
,
14
,
6
,
19
],
[
[
6
,
14
,
6
,
19
],
[
7
,
14
,
7
,
19
],
[
9
,
14
,
9
,
19
],
]
);
findModel
.
dispose
();
findState
.
dispose
();
});
findTest
(
'
find model prev
'
,
(
editor
)
=>
{
let
findState
=
new
FindReplaceState
();
findState
.
change
({
searchString
:
'
hello
'
,
wholeWord
:
true
},
false
);
...
...
@@ -581,7 +654,7 @@ suite('FindModel', () => {
findTest
(
'
find model prev stays in scope
'
,
(
editor
)
=>
{
let
findState
=
new
FindReplaceState
();
findState
.
change
({
searchString
:
'
hello
'
,
wholeWord
:
true
,
searchScope
:
new
Range
(
7
,
1
,
9
,
1
)
},
false
);
findState
.
change
({
searchString
:
'
hello
'
,
wholeWord
:
true
,
searchScope
:
[
new
Range
(
7
,
1
,
9
,
1
)]
},
false
);
let
findModel
=
new
FindModelBoundToEditorModel
(
editor
,
findState
);
assertFindState
(
...
...
@@ -2073,7 +2146,7 @@ suite('FindModel', () => {
findTest
(
'
issue #27083. search scope works even if it is a single line
'
,
(
editor
)
=>
{
let
findState
=
new
FindReplaceState
();
findState
.
change
({
searchString
:
'
hello
'
,
wholeWord
:
true
,
searchScope
:
new
Range
(
7
,
1
,
8
,
1
)
},
false
);
findState
.
change
({
searchString
:
'
hello
'
,
wholeWord
:
true
,
searchScope
:
[
new
Range
(
7
,
1
,
8
,
1
)]
},
false
);
let
findModel
=
new
FindModelBoundToEditorModel
(
editor
,
findState
);
assertFindState
(
...
...
src/vs/editor/contrib/multicursor/multicursor.ts
浏览文件 @
b9efdab4
...
...
@@ -601,13 +601,15 @@ export class MultiCursorSelectionController extends Disposable implements IEdito
}
if
(
findState
.
searchScope
)
{
const
state
=
findState
.
searchScope
;
const
state
s
=
findState
.
searchScope
;
let
inSelection
:
FindMatch
[]
|
null
=
[];
for
(
let
i
=
0
;
i
<
matches
.
length
;
i
++
)
{
if
(
matches
[
i
].
range
.
endLineNumber
<=
state
.
endLineNumber
&&
matches
[
i
].
range
.
startLineNumber
>=
state
.
startLineNumber
)
{
inSelection
.
push
(
matches
[
i
]);
}
}
matches
.
forEach
((
match
)
=>
{
states
.
forEach
((
state
)
=>
{
if
(
match
.
range
.
endLineNumber
<=
state
.
endLineNumber
&&
match
.
range
.
startLineNumber
>=
state
.
startLineNumber
)
{
inSelection
!
.
push
(
match
);
}
});
});
matches
=
inSelection
;
}
...
...
src/vs/monaco.d.ts
浏览文件 @
b9efdab4
...
...
@@ -1758,7 +1758,7 @@ declare namespace monaco.editor {
/**
* Search the model.
* @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
* @param searchScope Limit the searching to only search inside th
is range
.
* @param searchScope Limit the searching to only search inside th
ese ranges
.
* @param isRegex Used to indicate that `searchString` is a regular expression.
* @param matchCase Force the matching to match lower/upper case exactly.
* @param wordSeparators Force the matching to match entire words only. Pass null otherwise.
...
...
@@ -1766,7 +1766,7 @@ declare namespace monaco.editor {
* @param limitResultCount Limit the number of results
* @return The ranges where the matches are. It is empty if no matches have been found.
*/
findMatches
(
searchString
:
string
,
searchScope
:
IRange
,
isRegex
:
boolean
,
matchCase
:
boolean
,
wordSeparators
:
string
|
null
,
captureMatches
:
boolean
,
limitResultCount
?:
number
):
FindMatch
[];
findMatches
(
searchString
:
string
,
searchScope
:
IRange
|
IRange
[]
,
isRegex
:
boolean
,
matchCase
:
boolean
,
wordSeparators
:
string
|
null
,
captureMatches
:
boolean
,
limitResultCount
?:
number
):
FindMatch
[];
/**
* Search the model for the next match. Loops to the beginning of the model if needed.
* @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录