Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
5f8d2ef5
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,发现更多精彩内容 >>
未验证
提交
5f8d2ef5
编写于
7月 25, 2019
作者:
P
Peng Lyu
提交者:
GitHub
7月 25, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #60311 from JulienMalige/preserve-case
#42382 Preserve case while search and replace
上级
9d8d0841
53f95f8d
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
112 addition
and
6 deletion
+112
-6
src/vs/editor/contrib/find/findController.ts
src/vs/editor/contrib/find/findController.ts
+12
-2
src/vs/editor/contrib/find/findModel.ts
src/vs/editor/contrib/find/findModel.ts
+3
-2
src/vs/editor/contrib/find/findState.ts
src/vs/editor/contrib/find/findState.ts
+21
-0
src/vs/editor/contrib/find/findWidget.css
src/vs/editor/contrib/find/findWidget.css
+16
-0
src/vs/editor/contrib/find/findWidget.ts
src/vs/editor/contrib/find/findWidget.ts
+22
-0
src/vs/editor/contrib/find/replacePattern.ts
src/vs/editor/contrib/find/replacePattern.ts
+16
-2
src/vs/editor/contrib/find/test/replacePattern.test.ts
src/vs/editor/contrib/find/test/replacePattern.test.ts
+22
-0
未找到文件。
src/vs/editor/contrib/find/findController.ts
浏览文件 @
5f8d2ef5
...
...
@@ -112,7 +112,8 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
searchScope
:
null
,
matchCase
:
this
.
_storageService
.
getBoolean
(
'
editor.matchCase
'
,
StorageScope
.
WORKSPACE
,
false
),
wholeWord
:
this
.
_storageService
.
getBoolean
(
'
editor.wholeWord
'
,
StorageScope
.
WORKSPACE
,
false
),
isRegex
:
this
.
_storageService
.
getBoolean
(
'
editor.isRegex
'
,
StorageScope
.
WORKSPACE
,
false
)
isRegex
:
this
.
_storageService
.
getBoolean
(
'
editor.isRegex
'
,
StorageScope
.
WORKSPACE
,
false
),
preserveCase
:
this
.
_storageService
.
getBoolean
(
'
editor.preserveCase
'
,
StorageScope
.
WORKSPACE
,
false
)
},
false
);
if
(
shouldRestartFind
)
{
...
...
@@ -170,13 +171,17 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
if
(
e
.
matchCase
)
{
this
.
_storageService
.
store
(
'
editor.matchCase
'
,
this
.
_state
.
actualMatchCase
,
StorageScope
.
WORKSPACE
);
}
if
(
e
.
preserveCase
)
{
this
.
_storageService
.
store
(
'
editor.preserveCase
'
,
this
.
_state
.
actualPreserveCase
,
StorageScope
.
WORKSPACE
);
}
}
private
loadQueryState
()
{
this
.
_state
.
change
({
matchCase
:
this
.
_storageService
.
getBoolean
(
'
editor.matchCase
'
,
StorageScope
.
WORKSPACE
,
this
.
_state
.
matchCase
),
wholeWord
:
this
.
_storageService
.
getBoolean
(
'
editor.wholeWord
'
,
StorageScope
.
WORKSPACE
,
this
.
_state
.
wholeWord
),
isRegex
:
this
.
_storageService
.
getBoolean
(
'
editor.isRegex
'
,
StorageScope
.
WORKSPACE
,
this
.
_state
.
isRegex
)
isRegex
:
this
.
_storageService
.
getBoolean
(
'
editor.isRegex
'
,
StorageScope
.
WORKSPACE
,
this
.
_state
.
isRegex
),
preserveCase
:
this
.
_storageService
.
getBoolean
(
'
editor.preserveCase
'
,
StorageScope
.
WORKSPACE
,
this
.
_state
.
preserveCase
)
},
false
);
}
...
...
@@ -217,6 +222,11 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
}
}
public
togglePreserveCase
():
void
{
this
.
_state
.
change
({
preserveCase
:
!
this
.
_state
.
preserveCase
},
false
);
this
.
highlightFindOptions
();
}
public
toggleSearchScope
():
void
{
if
(
this
.
_state
.
searchScope
)
{
this
.
_state
.
change
({
searchScope
:
null
},
true
);
...
...
src/vs/editor/contrib/find/findModel.ts
浏览文件 @
5f8d2ef5
...
...
@@ -59,6 +59,7 @@ export const FIND_IDS = {
ToggleWholeWordCommand
:
'
toggleFindWholeWord
'
,
ToggleRegexCommand
:
'
toggleFindRegex
'
,
ToggleSearchScopeCommand
:
'
toggleFindInSelection
'
,
TogglePreserveCaseCommand
:
'
togglePreserveCase
'
,
ReplaceOneAction
:
'
editor.action.replaceOne
'
,
ReplaceAllAction
:
'
editor.action.replaceAll
'
,
SelectAllMatchesAction
:
'
editor.action.selectAllMatches
'
...
...
@@ -416,11 +417,11 @@ export class FindModelBoundToEditorModel {
let
replacePattern
=
this
.
_getReplacePattern
();
let
selection
=
this
.
_editor
.
getSelection
();
let
nextMatch
=
this
.
_getNextMatch
(
selection
.
getStartPosition
(),
replacePattern
.
hasReplacementPatterns
,
false
);
let
nextMatch
=
this
.
_getNextMatch
(
selection
.
getStartPosition
(),
true
,
false
);
if
(
nextMatch
)
{
if
(
selection
.
equalsRange
(
nextMatch
.
range
))
{
// selection sits on a find match => replace it!
let
replaceString
=
replacePattern
.
buildReplaceString
(
nextMatch
.
matches
);
let
replaceString
=
replacePattern
.
buildReplaceString
(
nextMatch
.
matches
,
this
.
_state
.
preserveCase
);
let
command
=
new
ReplaceCommand
(
selection
,
replaceString
);
...
...
src/vs/editor/contrib/find/findState.ts
浏览文件 @
5f8d2ef5
...
...
@@ -18,6 +18,7 @@ export interface FindReplaceStateChangedEvent {
isRegex
:
boolean
;
wholeWord
:
boolean
;
matchCase
:
boolean
;
preserveCase
:
boolean
;
searchScope
:
boolean
;
matchesPosition
:
boolean
;
matchesCount
:
boolean
;
...
...
@@ -41,6 +42,8 @@ export interface INewFindReplaceState {
wholeWordOverride
?:
FindOptionOverride
;
matchCase
?:
boolean
;
matchCaseOverride
?:
FindOptionOverride
;
preserveCase
?:
boolean
;
preserveCaseOverride
?:
FindOptionOverride
;
searchScope
?:
Range
|
null
;
}
...
...
@@ -65,6 +68,8 @@ export class FindReplaceState implements IDisposable {
private
_wholeWordOverride
:
FindOptionOverride
;
private
_matchCase
:
boolean
;
private
_matchCaseOverride
:
FindOptionOverride
;
private
_preserveCase
:
boolean
;
private
_preserveCaseOverride
:
FindOptionOverride
;
private
_searchScope
:
Range
|
null
;
private
_matchesPosition
:
number
;
private
_matchesCount
:
number
;
...
...
@@ -78,10 +83,12 @@ export class FindReplaceState implements IDisposable {
public
get
isRegex
():
boolean
{
return
effectiveOptionValue
(
this
.
_isRegexOverride
,
this
.
_isRegex
);
}
public
get
wholeWord
():
boolean
{
return
effectiveOptionValue
(
this
.
_wholeWordOverride
,
this
.
_wholeWord
);
}
public
get
matchCase
():
boolean
{
return
effectiveOptionValue
(
this
.
_matchCaseOverride
,
this
.
_matchCase
);
}
public
get
preserveCase
():
boolean
{
return
effectiveOptionValue
(
this
.
_preserveCaseOverride
,
this
.
_preserveCase
);
}
public
get
actualIsRegex
():
boolean
{
return
this
.
_isRegex
;
}
public
get
actualWholeWord
():
boolean
{
return
this
.
_wholeWord
;
}
public
get
actualMatchCase
():
boolean
{
return
this
.
_matchCase
;
}
public
get
actualPreserveCase
():
boolean
{
return
this
.
_preserveCase
;
}
public
get
searchScope
():
Range
|
null
{
return
this
.
_searchScope
;
}
public
get
matchesPosition
():
number
{
return
this
.
_matchesPosition
;
}
...
...
@@ -100,6 +107,8 @@ export class FindReplaceState implements IDisposable {
this
.
_wholeWordOverride
=
FindOptionOverride
.
NotSet
;
this
.
_matchCase
=
false
;
this
.
_matchCaseOverride
=
FindOptionOverride
.
NotSet
;
this
.
_preserveCase
=
false
;
this
.
_preserveCaseOverride
=
FindOptionOverride
.
NotSet
;
this
.
_searchScope
=
null
;
this
.
_matchesPosition
=
0
;
this
.
_matchesCount
=
0
;
...
...
@@ -120,6 +129,7 @@ export class FindReplaceState implements IDisposable {
isRegex
:
false
,
wholeWord
:
false
,
matchCase
:
false
,
preserveCase
:
false
,
searchScope
:
false
,
matchesPosition
:
false
,
matchesCount
:
false
,
...
...
@@ -169,6 +179,7 @@ export class FindReplaceState implements IDisposable {
isRegex
:
false
,
wholeWord
:
false
,
matchCase
:
false
,
preserveCase
:
false
,
searchScope
:
false
,
matchesPosition
:
false
,
matchesCount
:
false
,
...
...
@@ -179,6 +190,7 @@ export class FindReplaceState implements IDisposable {
const
oldEffectiveIsRegex
=
this
.
isRegex
;
const
oldEffectiveWholeWords
=
this
.
wholeWord
;
const
oldEffectiveMatchCase
=
this
.
matchCase
;
const
oldEffectivePreserveCase
=
this
.
preserveCase
;
if
(
typeof
newState
.
searchString
!==
'
undefined
'
)
{
if
(
this
.
_searchString
!==
newState
.
searchString
)
{
...
...
@@ -217,6 +229,9 @@ export class FindReplaceState implements IDisposable {
if
(
typeof
newState
.
matchCase
!==
'
undefined
'
)
{
this
.
_matchCase
=
newState
.
matchCase
;
}
if
(
typeof
newState
.
preserveCase
!==
'
undefined
'
)
{
this
.
_preserveCase
=
newState
.
preserveCase
;
}
if
(
typeof
newState
.
searchScope
!==
'
undefined
'
)
{
if
(
!
Range
.
equalsRange
(
this
.
_searchScope
,
newState
.
searchScope
))
{
this
.
_searchScope
=
newState
.
searchScope
;
...
...
@@ -229,6 +244,7 @@ export class FindReplaceState implements IDisposable {
this
.
_isRegexOverride
=
(
typeof
newState
.
isRegexOverride
!==
'
undefined
'
?
newState
.
isRegexOverride
:
FindOptionOverride
.
NotSet
);
this
.
_wholeWordOverride
=
(
typeof
newState
.
wholeWordOverride
!==
'
undefined
'
?
newState
.
wholeWordOverride
:
FindOptionOverride
.
NotSet
);
this
.
_matchCaseOverride
=
(
typeof
newState
.
matchCaseOverride
!==
'
undefined
'
?
newState
.
matchCaseOverride
:
FindOptionOverride
.
NotSet
);
this
.
_preserveCaseOverride
=
(
typeof
newState
.
preserveCaseOverride
!==
'
undefined
'
?
newState
.
preserveCaseOverride
:
FindOptionOverride
.
NotSet
);
if
(
oldEffectiveIsRegex
!==
this
.
isRegex
)
{
somethingChanged
=
true
;
...
...
@@ -243,6 +259,11 @@ export class FindReplaceState implements IDisposable {
changeEvent
.
matchCase
=
true
;
}
if
(
oldEffectivePreserveCase
!==
this
.
preserveCase
)
{
somethingChanged
=
true
;
changeEvent
.
preserveCase
=
true
;
}
if
(
somethingChanged
)
{
this
.
_onFindReplaceStateChange
.
fire
(
changeEvent
);
}
...
...
src/vs/editor/contrib/find/findWidget.css
浏览文件 @
5f8d2ef5
...
...
@@ -79,6 +79,15 @@
height
:
25px
;
}
.monaco-editor
.find-widget
>
.find-part
.monaco-inputbox
>
.wrapper
>
.input
{
width
:
100%
!important
;
padding-right
:
66px
;
}
.monaco-editor
.find-widget
>
.replace-part
.monaco-inputbox
>
.wrapper
>
.input
{
padding-right
:
22px
;
}
.monaco-editor
.find-widget
>
.find-part
.monaco-inputbox
>
.wrapper
>
.input
,
.monaco-editor
.find-widget
>
.replace-part
.monaco-inputbox
>
.wrapper
>
.input
{
padding-top
:
2px
;
...
...
@@ -224,12 +233,19 @@
}
.monaco-editor
.find-widget
>
.replace-part
>
.replace-input
{
position
:
relative
;
display
:
flex
;
display
:
-webkit-flex
;
vertical-align
:
middle
;
width
:
auto
!important
;
}
.monaco-editor
.find-widget
>
.replace-part
>
.replace-input
>
.controls
{
position
:
absolute
;
top
:
3px
;
right
:
2px
;
}
/* REDUCED */
.monaco-editor
.find-widget.reduced-find-widget
.matchesCount
,
.monaco-editor
.find-widget.reduced-find-widget
.monaco-checkbox
{
...
...
src/vs/editor/contrib/find/findWidget.ts
浏览文件 @
5f8d2ef5
...
...
@@ -13,6 +13,7 @@ import { FindInput, IFindInputStyles } from 'vs/base/browser/ui/findinput/findIn
import
{
HistoryInputBox
,
IMessage
as
InputBoxMessage
}
from
'
vs/base/browser/ui/inputbox/inputBox
'
;
import
{
IHorizontalSashLayoutProvider
,
ISashEvent
,
Orientation
,
Sash
}
from
'
vs/base/browser/ui/sash/sash
'
;
import
{
Widget
}
from
'
vs/base/browser/ui/widget
'
;
import
{
Checkbox
}
from
'
vs/base/browser/ui/checkbox/checkbox
'
;
import
{
Delayer
}
from
'
vs/base/common/async
'
;
import
{
Color
}
from
'
vs/base/common/color
'
;
import
{
onUnexpectedError
}
from
'
vs/base/common/errors
'
;
...
...
@@ -47,6 +48,7 @@ const NLS_TOGGLE_SELECTION_FIND_TITLE = nls.localize('label.toggleSelectionFind'
const
NLS_CLOSE_BTN_LABEL
=
nls
.
localize
(
'
label.closeButton
'
,
"
Close
"
);
const
NLS_REPLACE_INPUT_LABEL
=
nls
.
localize
(
'
label.replace
'
,
"
Replace
"
);
const
NLS_REPLACE_INPUT_PLACEHOLDER
=
nls
.
localize
(
'
placeholder.replace
'
,
"
Replace
"
);
const
NLS_PRESERVE_CASE_LABEL
=
nls
.
localize
(
'
label.preserveCaseCheckbox
'
,
"
Preserve Case
"
);
const
NLS_REPLACE_BTN_LABEL
=
nls
.
localize
(
'
label.replaceButton
'
,
"
Replace
"
);
const
NLS_REPLACE_ALL_BTN_LABEL
=
nls
.
localize
(
'
label.replaceAllButton
'
,
"
Replace All
"
);
const
NLS_TOGGLE_REPLACE_MODE_BTN_LABEL
=
nls
.
localize
(
'
label.toggleReplaceButton
'
,
"
Toggle Replace mode
"
);
...
...
@@ -101,6 +103,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
private
_nextBtn
:
SimpleButton
;
private
_toggleSelectionFind
:
SimpleCheckbox
;
private
_closeBtn
:
SimpleButton
;
private
_preserveCase
:
Checkbox
;
private
_replaceBtn
:
SimpleButton
;
private
_replaceAllBtn
:
SimpleButton
;
...
...
@@ -913,6 +916,19 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
this
.
_state
.
change
({
replaceString
:
this
.
_replaceInputBox
.
value
},
false
);
}));
this
.
_preserveCase
=
this
.
_register
(
new
Checkbox
({
actionClassName
:
'
monaco-case-sensitive
'
,
title
:
NLS_PRESERVE_CASE_LABEL
,
isChecked
:
false
,
}));
this
.
_preserveCase
.
checked
=
!!
this
.
_state
.
preserveCase
;
this
.
_register
(
this
.
_preserveCase
.
onChange
(
viaKeyboard
=>
{
if
(
!
viaKeyboard
)
{
this
.
_state
.
change
({
preserveCase
:
!
this
.
_state
.
preserveCase
},
false
);
this
.
_replaceInputBox
.
focus
();
}
}));
// Replace one button
this
.
_replaceBtn
=
this
.
_register
(
new
SimpleButton
({
label
:
NLS_REPLACE_BTN_LABEL
+
this
.
_keybindingLabelFor
(
FIND_IDS
.
ReplaceOneAction
),
...
...
@@ -937,6 +953,12 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
}
}));
let
controls
=
document
.
createElement
(
'
div
'
);
controls
.
className
=
'
controls
'
;
controls
.
style
.
display
=
'
block
'
;
controls
.
appendChild
(
this
.
_preserveCase
.
domNode
);
replaceInput
.
appendChild
(
controls
);
let
replacePart
=
document
.
createElement
(
'
div
'
);
replacePart
.
className
=
'
replace-part
'
;
replacePart
.
appendChild
(
replaceInput
);
...
...
src/vs/editor/contrib/find/replacePattern.ts
浏览文件 @
5f8d2ef5
...
...
@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import
{
CharCode
}
from
'
vs/base/common/charCode
'
;
import
{
containsUppercaseCharacter
}
from
'
vs/base/common/strings
'
;
const
enum
ReplacePatternKind
{
StaticValue
=
0
,
...
...
@@ -48,9 +49,22 @@ export class ReplacePattern {
}
}
public
buildReplaceString
(
matches
:
string
[]
|
null
):
string
{
public
buildReplaceString
(
matches
:
string
[]
|
null
,
preserveCase
?:
boolean
):
string
{
if
(
this
.
_state
.
kind
===
ReplacePatternKind
.
StaticValue
)
{
return
this
.
_state
.
staticValue
;
if
(
preserveCase
&&
matches
&&
(
matches
[
0
]
!==
''
))
{
if
(
matches
[
0
].
toUpperCase
()
===
matches
[
0
])
{
return
this
.
_state
.
staticValue
.
toUpperCase
();
}
else
if
(
matches
[
0
].
toLowerCase
()
===
matches
[
0
])
{
return
this
.
_state
.
staticValue
.
toLowerCase
();
}
else
if
(
containsUppercaseCharacter
(
matches
[
0
][
0
]))
{
return
this
.
_state
.
staticValue
[
0
].
toUpperCase
()
+
this
.
_state
.
staticValue
.
substr
(
1
);
}
else
{
// we don't understand its pattern yet.
return
this
.
_state
.
staticValue
;
}
}
else
{
return
this
.
_state
.
staticValue
;
}
}
let
result
=
''
;
...
...
src/vs/editor/contrib/find/test/replacePattern.test.ts
浏览文件 @
5f8d2ef5
...
...
@@ -153,4 +153,26 @@ suite('Replace Pattern test', () => {
let
actual
=
replacePattern
.
buildReplaceString
(
matches
);
assert
.
equal
(
actual
,
'
a{}
'
);
});
test
(
'
preserve case
'
,
()
=>
{
let
replacePattern
=
parseReplaceString
(
'
Def
'
);
let
actual
=
replacePattern
.
buildReplaceString
([
'
abc
'
],
true
);
assert
.
equal
(
actual
,
'
def
'
);
actual
=
replacePattern
.
buildReplaceString
([
'
Abc
'
],
true
);
assert
.
equal
(
actual
,
'
Def
'
);
actual
=
replacePattern
.
buildReplaceString
([
'
ABC
'
],
true
);
assert
.
equal
(
actual
,
'
DEF
'
);
actual
=
replacePattern
.
buildReplaceString
([
'
abc
'
,
'
Abc
'
],
true
);
assert
.
equal
(
actual
,
'
def
'
);
actual
=
replacePattern
.
buildReplaceString
([
'
Abc
'
,
'
abc
'
],
true
);
assert
.
equal
(
actual
,
'
Def
'
);
actual
=
replacePattern
.
buildReplaceString
([
'
ABC
'
,
'
abc
'
],
true
);
assert
.
equal
(
actual
,
'
DEF
'
);
actual
=
replacePattern
.
buildReplaceString
([
'
AbC
'
],
true
);
assert
.
equal
(
actual
,
'
Def
'
);
actual
=
replacePattern
.
buildReplaceString
([
'
aBC
'
],
true
);
assert
.
equal
(
actual
,
'
Def
'
);
});
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录