Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
3a8fa7a8
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3a8fa7a8
编写于
6月 23, 2016
作者:
S
Sandeep Somavarapu
浏览文件
操作
浏览文件
下载
差异文件
Search and Replace - #7602
上级
84d5f9cb
2cc6cf6f
变更
22
展开全部
隐藏空白更改
内联
并排
Showing
22 changed file
with
883 addition
and
236 deletion
+883
-236
src/vs/base/browser/ui/button/button.css
src/vs/base/browser/ui/button/button.css
+20
-10
src/vs/base/browser/ui/button/button.ts
src/vs/base/browser/ui/button/button.ts
+7
-0
src/vs/base/browser/ui/inputbox/inputBox.css
src/vs/base/browser/ui/inputbox/inputBox.css
+11
-1
src/vs/editor/common/services/bulkEdit.ts
src/vs/editor/common/services/bulkEdit.ts
+28
-4
src/vs/workbench/electron-browser/media/shell.css
src/vs/workbench/electron-browser/media/shell.css
+3
-3
src/vs/workbench/parts/search/browser/media/expando-collapsed-dark.svg
...nch/parts/search/browser/media/expando-collapsed-dark.svg
+1
-0
src/vs/workbench/parts/search/browser/media/expando-collapsed.svg
...orkbench/parts/search/browser/media/expando-collapsed.svg
+1
-0
src/vs/workbench/parts/search/browser/media/expando-expanded-dark.svg
...ench/parts/search/browser/media/expando-expanded-dark.svg
+1
-0
src/vs/workbench/parts/search/browser/media/expando-expanded.svg
...workbench/parts/search/browser/media/expando-expanded.svg
+1
-0
src/vs/workbench/parts/search/browser/media/replace-all-inverse.svg
...kbench/parts/search/browser/media/replace-all-inverse.svg
+11
-0
src/vs/workbench/parts/search/browser/media/replace-all.svg
src/vs/workbench/parts/search/browser/media/replace-all.svg
+11
-0
src/vs/workbench/parts/search/browser/media/replace-inverse.svg
.../workbench/parts/search/browser/media/replace-inverse.svg
+13
-0
src/vs/workbench/parts/search/browser/media/replace.svg
src/vs/workbench/parts/search/browser/media/replace.svg
+13
-0
src/vs/workbench/parts/search/browser/media/searchviewlet.css
...vs/workbench/parts/search/browser/media/searchviewlet.css
+94
-14
src/vs/workbench/parts/search/browser/replaceService.ts
src/vs/workbench/parts/search/browser/replaceService.ts
+53
-0
src/vs/workbench/parts/search/browser/search.contribution.ts
src/vs/workbench/parts/search/browser/search.contribution.ts
+6
-1
src/vs/workbench/parts/search/browser/searchActions.ts
src/vs/workbench/parts/search/browser/searchActions.ts
+32
-59
src/vs/workbench/parts/search/browser/searchResultsView.ts
src/vs/workbench/parts/search/browser/searchResultsView.ts
+44
-10
src/vs/workbench/parts/search/browser/searchViewlet.ts
src/vs/workbench/parts/search/browser/searchViewlet.ts
+218
-134
src/vs/workbench/parts/search/browser/searchWidget.ts
src/vs/workbench/parts/search/browser/searchWidget.ts
+257
-0
src/vs/workbench/parts/search/common/replace.ts
src/vs/workbench/parts/search/common/replace.ts
+27
-0
src/vs/workbench/parts/search/common/searchModel.ts
src/vs/workbench/parts/search/common/searchModel.ts
+31
-0
未找到文件。
src/vs/base/browser/ui/button/button.css
浏览文件 @
3a8fa7a8
...
...
@@ -3,7 +3,12 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-button
{
.monaco-button.disabled
{
opacity
:
0.4
;
cursor
:
default
;
}
.monaco-text-button
{
-moz-box-sizing
:
border-box
;
box-sizing
:
border-box
;
display
:
inline-block
;
...
...
@@ -15,24 +20,29 @@
cursor
:
pointer
;
}
.monaco-button.disabled
{
opacity
:
0.4
;
cursor
:
default
;
}
.monaco-button
:hover
{
.monaco-text-button
:hover
{
text-decoration
:
none
!important
;
color
:
white
!important
;
}
.monaco-button
:not
(
.disabled
)
:hover
{
/*Theming support*/
.vs
.monaco-button
:not
(
.disabled
)
:hover
{
background-color
:
#DDD
}
.monaco-text-button
:not
(
.disabled
)
:hover
{
background
:
#006BB3
;
}
.monaco-button
:not
(
.disabled
)
:active
{
.monaco-
text-
button
:not
(
.disabled
)
:active
{
background
:
#005F9E
;
}
.vs-dark
.monaco-button
{
.vs-dark
.monaco-
text-
button
{
background
:
#0E639C
;
}
.vs-dark
.monaco-button
:not
(
.disabled
)
:hover
,
.hc-black
.monaco-button
:not
(
.disabled
)
:hover
{
background-color
:
#2f3334
;
}
\ No newline at end of file
src/vs/base/browser/ui/button/button.ts
浏览文件 @
3a8fa7a8
...
...
@@ -57,9 +57,16 @@ export class Button extends EventEmitter {
}
public
set
label
(
value
:
string
)
{
if
(
!
this
.
$el
.
hasClass
(
'
monaco-text-button
'
))
{
this
.
$el
.
addClass
(
'
monaco-text-button
'
);
}
this
.
$el
.
text
(
value
);
}
public
set
icon
(
iconClassName
:
string
)
{
this
.
$el
.
addClass
(
iconClassName
);
}
public
set
enabled
(
value
:
boolean
)
{
if
(
value
)
{
this
.
$el
.
removeClass
(
'
disabled
'
);
...
...
src/vs/base/browser/ui/inputbox/inputBox.css
浏览文件 @
3a8fa7a8
...
...
@@ -106,10 +106,20 @@
/* Action bar support */
.monaco-inputbox
.monaco-action-bar
{
position
:
absolute
;
right
:
0
px
;
right
:
2
px
;
top
:
4px
;
}
.monaco-inputbox
.monaco-action-bar
.action-item
{
margin-left
:
2px
;
}
.monaco-inputbox
.monaco-action-bar
.action-item
.icon
{
background-repeat
:
no-repeat
;
width
:
16px
;
height
:
16px
;
}
/* Theming */
.monaco-inputbox.idle
{
...
...
src/vs/editor/common/services/bulkEdit.ts
浏览文件 @
3a8fa7a8
...
...
@@ -17,6 +17,7 @@ import {Range} from 'vs/editor/common/core/range';
import
{
Selection
}
from
'
vs/editor/common/core/selection
'
;
import
{
IIdentifiedSingleEditOperation
,
IModel
,
IRange
,
ISelection
}
from
'
vs/editor/common/editorCommon
'
;
import
{
ICommonCodeEditor
}
from
'
vs/editor/common/editorCommon
'
;
import
{
IProgressRunner
}
from
'
vs/platform/progress/common/progress
'
;
export
interface
IResourceEdit
{
resource
:
URI
;
...
...
@@ -165,7 +166,7 @@ class BulkEditModel {
private
_sourceSelections
:
Selection
[];
private
_sourceModelTask
:
SourceModelEditTask
;
constructor
(
editorService
:
IEditorService
,
sourceModel
:
URI
,
sourceSelections
:
Selection
[],
edits
:
IResourceEdit
[])
{
constructor
(
editorService
:
IEditorService
,
sourceModel
:
URI
,
sourceSelections
:
Selection
[],
edits
:
IResourceEdit
[]
,
private
progress
:
IProgressRunner
=
null
)
{
this
.
_editorService
=
editorService
;
this
.
_sourceModel
=
sourceModel
;
this
.
_sourceSelections
=
sourceSelections
;
...
...
@@ -203,6 +204,10 @@ class BulkEditModel {
this
.
_tasks
=
[];
var
promises
:
TPromise
<
any
>
[]
=
[];
if
(
this
.
progress
)
{
this
.
progress
.
total
(
this
.
_numberOfResourcesToModify
*
2
);
}
forEach
(
this
.
_edits
,
entry
=>
{
var
promise
=
this
.
_editorService
.
resolveEditorModel
({
resource
:
URI
.
parse
(
entry
.
key
)
}).
then
(
model
=>
{
if
(
!
model
||
!
model
.
textEditorModel
)
{
...
...
@@ -221,31 +226,44 @@ class BulkEditModel {
entry
.
value
.
forEach
(
edit
=>
task
.
addEdit
(
edit
));
this
.
_tasks
.
push
(
task
);
if
(
this
.
progress
)
{
this
.
progress
.
worked
(
1
);
}
});
promises
.
push
(
promise
);
});
return
TPromise
.
join
(
promises
).
then
(
_
=>
this
);
}
public
apply
():
Selection
{
this
.
_tasks
.
forEach
(
task
=>
t
ask
.
apply
(
));
this
.
_tasks
.
forEach
(
task
=>
t
his
.
applyTask
(
task
));
var
r
:
Selection
=
null
;
if
(
this
.
_sourceModelTask
)
{
r
=
this
.
_sourceModelTask
.
getEndCursorSelection
();
}
return
r
;
}
private
applyTask
(
task
):
void
{
task
.
apply
();
if
(
this
.
progress
)
{
this
.
progress
.
worked
(
1
);
}
}
}
export
interface
BulkEdit
{
progress
(
progress
:
IProgressRunner
);
add
(
edit
:
IResourceEdit
[]):
void
;
finish
():
TPromise
<
ISelection
>
;
}
export
function
bulkEdit
(
eventService
:
IEventService
,
editorService
:
IEditorService
,
editor
:
ICommonCodeEditor
,
edits
:
IResourceEdit
[]):
TPromise
<
any
>
{
export
function
bulkEdit
(
eventService
:
IEventService
,
editorService
:
IEditorService
,
editor
:
ICommonCodeEditor
,
edits
:
IResourceEdit
[]
,
progress
:
IProgressRunner
=
null
):
TPromise
<
any
>
{
let
bulk
=
createBulkEdit
(
eventService
,
editorService
,
editor
);
bulk
.
add
(
edits
);
bulk
.
progress
(
progress
);
return
bulk
.
finish
();
}
...
...
@@ -253,6 +271,11 @@ export function createBulkEdit(eventService: IEventService, editorService: IEdit
let
all
:
IResourceEdit
[]
=
[];
let
recording
=
new
ChangeRecorder
(
eventService
).
start
();
let
progressRunner
:
IProgressRunner
;
function
progress
(
progress
:
IProgressRunner
)
{
progressRunner
=
progress
;
}
function
add
(
edits
:
IResourceEdit
[]):
void
{
all
.
push
(...
edits
);
...
...
@@ -292,7 +315,7 @@ export function createBulkEdit(eventService: IEventService, editorService: IEdit
selections
=
editor
.
getSelections
();
}
let
model
=
new
BulkEditModel
(
editorService
,
uri
,
selections
,
all
);
let
model
=
new
BulkEditModel
(
editorService
,
uri
,
selections
,
all
,
progressRunner
);
return
model
.
prepare
().
then
(
_
=>
{
...
...
@@ -307,6 +330,7 @@ export function createBulkEdit(eventService: IEventService, editorService: IEdit
}
return
{
progress
,
add
,
finish
};
...
...
src/vs/workbench/electron-browser/media/shell.css
浏览文件 @
3a8fa7a8
...
...
@@ -101,14 +101,14 @@
outline-offset
:
-1px
;
}
.monaco-shell.vs
.monaco-button
:focus
,
.monaco-shell.vs-dark
.monaco-button
:focus
,
.monaco-shell.vs
.monaco-
text-
button
:focus
,
.monaco-shell.vs-dark
.monaco-
text-
button
:focus
,
.monaco-shell.vs
.action-button
:focus
,
.monaco-shell.vs-dark
.action-button
:focus
{
outline-color
:
rgba
(
255
,
255
,
255
,
.5
);
/* buttons have a blue color, so focus indication needs to be different */
}
.monaco-shell.vs
.monaco-button
:focus
,
.monaco-shell.vs
.monaco-
text-
button
:focus
,
.monaco-shell.vs
.action-button
:focus
{
outline-offset
:
-2px
;
/* Inset outline so it stands out on light background. */
}
...
...
src/vs/workbench/parts/search/browser/media/expando-collapsed-dark.svg
0 → 100644
浏览文件 @
3a8fa7a8
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
><path
fill=
"#e8e8e8"
d=
"M6 4v8l4-4-4-4zm1 2.414l1.586 1.586-1.586 1.586v-3.172z"
/></svg>
\ No newline at end of file
src/vs/workbench/parts/search/browser/media/expando-collapsed.svg
0 → 100644
浏览文件 @
3a8fa7a8
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
><path
fill=
"#646465"
d=
"M6 4v8l4-4-4-4zm1 2.414l1.586 1.586-1.586 1.586v-3.172z"
/></svg>
\ No newline at end of file
src/vs/workbench/parts/search/browser/media/expando-expanded-dark.svg
0 → 100644
浏览文件 @
3a8fa7a8
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
><path
fill=
"#e8e8e8"
d=
"M11 10.07h-5.656l5.656-5.656v5.656z"
/></svg>
\ No newline at end of file
src/vs/workbench/parts/search/browser/media/expando-expanded.svg
0 → 100644
浏览文件 @
3a8fa7a8
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
><path
fill=
"#646465"
d=
"M11 10.07h-5.656l5.656-5.656v5.656z"
/></svg>
\ No newline at end of file
src/vs/workbench/parts/search/browser/media/replace-all-inverse.svg
0 → 100644
浏览文件 @
3a8fa7a8
<svg
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
x=
"0px"
y=
"0px"
width=
"16px"
height=
"16px"
viewBox=
"0 0 16 16"
enable-background=
"new 0 0 16 16"
xml:space=
"preserve"
>
<g
id=
"icon_x5F_bg"
>
<path
fill=
"#C5C5C5"
d=
"M11,15V9H1v6H11z M2,14v-2h1v-1H2v-1h3v4H2z M10,11H8v2h2v1H7v-4h3V11z M3,13v-1h1v1H3z M13,7v6h-1V8H5V7
H13z M13,2V1h-1v5h3V2H13z M14,5h-1V3h1V5z M11,2v4H8V4h1v1h1V4H9V3H8V2H11z"
/>
</g>
<g
id=
"color_x5F_action"
>
<path
fill=
"#75BEFF"
d=
"M1.979,3.5L2,6L1,5v1.5L2.5,8L4,6.5V5L3,6L2.979,3.5c0-0.275,0.225-0.5,0.5-0.5H7V2H3.479
C2.651,2,1.979,2.673,1.979,3.5z"
/>
</g>
</svg>
src/vs/workbench/parts/search/browser/media/replace-all.svg
0 → 100644
浏览文件 @
3a8fa7a8
<svg
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
x=
"0px"
y=
"0px"
width=
"16px"
height=
"16px"
viewBox=
"0 0 16 16"
enable-background=
"new 0 0 16 16"
xml:space=
"preserve"
>
<g
id=
"icon_x5F_bg"
>
<path
fill=
"#424242"
d=
"M11,15V9H1v6H11z M2,14v-2h1v-1H2v-1h3v4H2z M10,11H8v2h2v1H7v-4h3V11z M3,13v-1h1v1H3z M13,7v6h-1V8H5V7
H13z M13,2V1h-1v5h3V2H13z M14,5h-1V3h1V5z M11,2v4H8V4h1v1h1V4H9V3H8V2H11z"
/>
</g>
<g
id=
"color_x5F_action"
>
<path
fill=
"#00539C"
d=
"M1.979,3.5L2,6L1,5v1.5L2.5,8L4,6.5V5L3,6L2.979,3.5c0-0.275,0.225-0.5,0.5-0.5H7V2H3.479
C2.651,2,1.979,2.673,1.979,3.5z"
/>
</g>
</svg>
src/vs/workbench/parts/search/browser/media/replace-inverse.svg
0 → 100644
浏览文件 @
3a8fa7a8
<svg
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
x=
"0px"
y=
"0px"
width=
"16px"
height=
"16px"
viewBox=
"0 0 16 16"
enable-background=
"new 0 0 16 16"
xml:space=
"preserve"
>
<g
id=
"icon_x5F_bg"
>
<g>
<path
fill=
"#C5C5C5"
d=
"M11,3V1h-1v5v1h1h2h1V4V3H11z M13,6h-2V4h2V6z"
/>
<path
fill=
"#C5C5C5"
d=
"M2,15h7V9H2V15z M4,10h3v1H5v2h2v1H4V10z"
/>
</g>
</g>
<g
id=
"color_x5F_importance"
>
<path
fill=
"#75BEFF"
d=
"M3.979,3.5L4,6L3,5v1.5L4.5,8L6,6.5V5L5,6L4.979,3.5c0-0.275,0.225-0.5,0.5-0.5H9V2H5.479
C4.651,2,3.979,2.673,3.979,3.5z"
/>
</g>
</svg>
src/vs/workbench/parts/search/browser/media/replace.svg
0 → 100644
浏览文件 @
3a8fa7a8
<svg
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
x=
"0px"
y=
"0px"
width=
"16px"
height=
"16px"
viewBox=
"0 0 16 16"
enable-background=
"new 0 0 16 16"
xml:space=
"preserve"
>
<g
id=
"icon_x5F_bg"
>
<g>
<path
fill=
"#424242"
d=
"M11,3V1h-1v5v1h1h2h1V4V3H11z M13,6h-2V4h2V6z"
/>
<path
fill=
"#424242"
d=
"M2,15h7V9H2V15z M4,10h3v1H5v2h2v1H4V10z"
/>
</g>
</g>
<g
id=
"color_x5F_importance"
>
<path
fill=
"#00539C"
d=
"M3.979,3.5L4,6L3,5v1.5L4.5,8L6,6.5V5L5,6L4.979,3.5c0-0.275,0.225-0.5,0.5-0.5H9V2H5.479
C4.651,2,3.979,2.673,3.979,3.5z"
/>
</g>
</svg>
src/vs/workbench/parts/search/browser/media/searchviewlet.css
浏览文件 @
3a8fa7a8
...
...
@@ -3,20 +3,45 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.search-viewlet
.highlight
{
color
:
black
;
background-color
:
rgba
(
234
,
92
,
0
,
0.3
);
.search-viewlet
.search-widgets-container
{
margin
:
6px
17px
0
2px
;
}
.search-viewlet
.search-widget
.toggle-replace-button
{
position
:
absolute
;
top
:
0
;
left
:
0
;
width
:
16px
;
height
:
100%
;
-webkit-box-sizing
:
border-box
;
-o-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
-ms-box-sizing
:
border-box
;
box-sizing
:
border-box
;
background-position
:
center
center
;
background-repeat
:
no-repeat
;
cursor
:
pointer
;
}
.search-viewlet
.
query
-box
{
margin
:
6px
17px
0
17px
;
.search-viewlet
.
search-widget
.input
-box
{
margin
-left
:
17px
;
}
.search-viewlet
.
query-box
.monaco-findInput
{
.search-viewlet
.
search-widget
.monaco-findInput
{
display
:
inline-block
;
vertical-align
:
middle
;
}
.search-viewlet
.search-widget
.replace-box
{
margin-top
:
6px
;
}
.search-viewlet
.search-widget
.replace-box.disabled
{
display
:
none
;
}
.search-viewlet
.query-clear
{
width
:
20px
;
height
:
20px
;
...
...
@@ -29,14 +54,13 @@
.search-viewlet
.query-details
{
min-height
:
1em
;
position
:
relative
;
margin
:
0
17px
6px
17px
;
padding
:
0
4px
;
margin
:
0
0
6px
17px
;
}
.search-viewlet
.query-details
.more
{
position
:
absolute
;
right
:
0
;
margin-right
:
0.5em
;
right
:
0
;
cursor
:
pointer
;
width
:
16px
;
height
:
13px
;
...
...
@@ -163,6 +187,24 @@
background
:
url("action-remove.svg")
center
center
no-repeat
;
}
.search-viewlet
.action-replace
{
background-image
:
url('replace.svg')
;
}
.search-viewlet
.action-replace-all
{
background-image
:
url('replace-all.svg')
;
}
.monaco-editor.hc-black
.search-viewlet
.action-replace
,
.monaco-editor.vs-dark
.search-viewlet
.action-replace
{
background-image
:
url('replace-inverse.svg')
;
}
.monaco-editor.hc-black
.search-viewlet
.action-replace-all
,
.monaco-editor.vs-dark
.search-viewlet
.action-replace-all
{
background-image
:
url('replace-all-inverse.svg')
;
}
.search-viewlet
.label
{
font-style
:
italic
;
}
...
...
@@ -248,8 +290,28 @@
box-sizing
:
border-box
;
}
.search-viewlet
.replaceMatch
{
background-color
:
rgba
(
234
,
92
,
0
,
0.45
);
}
.search-viewlet
.removeMatch
{
text-decoration
:
line-through
;
}
.hc-black
.monaco-workbench
.search-viewlet
.replaceMatch
,
.monaco-editor.hc-black
.replaceMatch
{
border-color
:
#F44336
;
}
/* Theming */
.vs
.search-viewlet
.query-box
,
.search-viewlet
.highlight
{
color
:
black
;
background-color
:
rgba
(
234
,
92
,
0
,
0.3
);
}
.vs
.search-viewlet
.input-box
,
.vs
.search-viewlet
.file-types
.monaco-inputbox
{
background-color
:
white
;
}
...
...
@@ -262,7 +324,15 @@
color
:
#FFF
;
}
.vs-dark
.search-viewlet
.query-box
,
.vs
.search-viewlet
.search-widget
.toggle-replace-button.collapse
{
background-image
:
url('expando-collapsed.svg')
;
}
.vs
.search-viewlet
.search-widget
.toggle-replace-button.expand
{
background-image
:
url('expando-expanded.svg')
;
}
.vs-dark
.search-viewlet
.input-box
,
.vs-dark
.search-viewlet
.file-types
.monaco-inputbox
{
background-color
:
#3C3C3C
;
}
...
...
@@ -287,8 +357,18 @@
padding
:
0
;
}
.vs-dark
.search-viewlet
.search-widget
.toggle-replace-button.expand
,
.hc-black
.search-viewlet
.search-widget
.toggle-replace-button.expand
{
background-image
:
url('expando-expanded-dark.svg')
;
}
.vs-dark
.search-viewlet
.search-widget
.toggle-replace-button.collapse
,
.hc-black
.search-viewlet
.search-widget
.toggle-replace-button.collapse
{
background-image
:
url('expando-collapsed-dark.svg')
;
}
/* High Contrast Theming */
.hc-black
.monaco-workbench
.search-viewlet
.
query
-box
,
.hc-black
.monaco-workbench
.search-viewlet
.
input
-box
,
.hc-black
.monaco-workbench
.search-viewlet
.file-types
.monaco-inputbox
{
background-color
:
#000
;
}
...
...
@@ -331,11 +411,11 @@
width
:
16px
;
}
.hc-black
.monaco-workbench
.
query
-box
{
.hc-black
.monaco-workbench
.
input
-box
{
border
:
1px
solid
#6FC3DF
;
}
.hc-black
.monaco-workbench
.
query
-box
.monaco-inputbox.idle
{
.hc-black
.monaco-workbench
.
input
-box
.monaco-inputbox.idle
{
border
:
none
;
}
...
...
src/vs/workbench/parts/search/browser/replaceService.ts
0 → 100644
浏览文件 @
3a8fa7a8
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IReplaceService
}
from
'
vs/workbench/parts/search/common/replace
'
;
import
{
IEditorService
}
from
'
vs/platform/editor/common/editor
'
;
import
{
IEventService
}
from
'
vs/platform/event/common/event
'
;
import
{
Match
,
FileMatch
}
from
'
vs/workbench/parts/search/common/searchModel
'
;
import
{
BulkEdit
,
IResourceEdit
,
createBulkEdit
}
from
'
vs/editor/common/services/bulkEdit
'
;
import
{
IProgressRunner
}
from
'
vs/platform/progress/common/progress
'
;
export
class
ReplaceService
implements
IReplaceService
{
public
serviceId
=
IReplaceService
;
constructor
(@
IEventService
private
eventService
:
IEventService
,
@
IEditorService
private
editorService
)
{
}
public
replace
(
match
:
Match
,
text
:
string
):
TPromise
<
any
>
public
replace
(
files
:
FileMatch
[],
text
:
string
,
progress
?:
IProgressRunner
):
TPromise
<
any
>
public
replace
(
arg
:
any
,
text
:
string
,
progress
:
IProgressRunner
=
null
):
TPromise
<
any
>
{
let
bulkEdit
:
BulkEdit
=
createBulkEdit
(
this
.
eventService
,
this
.
editorService
,
null
);
bulkEdit
.
progress
(
progress
);
if
(
arg
instanceof
Match
)
{
bulkEdit
.
add
([
this
.
createEdit
(
arg
,
text
)]);
}
if
(
arg
instanceof
Array
)
{
arg
.
forEach
(
element
=>
{
let
fileMatch
=
<
FileMatch
>
element
;
fileMatch
.
matches
().
forEach
(
match
=>
{
bulkEdit
.
add
([
this
.
createEdit
(
match
,
text
)]);
});
});
}
return
bulkEdit
.
finish
();
}
private
createEdit
(
match
:
Match
,
text
:
string
):
IResourceEdit
{
let
fileMatch
:
FileMatch
=
match
.
parent
();
let
resourceEdit
:
IResourceEdit
=
{
resource
:
fileMatch
.
resource
(),
range
:
match
.
range
(),
newText
:
text
};
return
resourceEdit
;
}
}
\ No newline at end of file
src/vs/workbench/parts/search/browser/search.contribution.ts
浏览文件 @
3a8fa7a8
...
...
@@ -27,6 +27,11 @@ import {IViewletService} from 'vs/workbench/services/viewlet/common/viewletServi
import
{
KeyMod
,
KeyCode
}
from
'
vs/base/common/keyCodes
'
;
import
{
OpenSearchViewletAction
}
from
'
vs/workbench/parts/search/browser/searchActions
'
;
import
{
VIEWLET_ID
}
from
'
vs/workbench/parts/search/common/constants
'
;
import
{
registerSingleton
}
from
'
vs/platform/instantiation/common/extensions
'
;
import
{
IReplaceService
}
from
'
vs/workbench/parts/search/common/replace
'
;
import
{
ReplaceService
}
from
'
vs/workbench/parts/search/browser/replaceService
'
;
registerSingleton
(
IReplaceService
,
ReplaceService
);
KeybindingsRegistry
.
registerCommandDesc
({
id
:
'
workbench.action.search.toggleQueryDetails
'
,
...
...
@@ -185,4 +190,4 @@ configurationRegistry.registerConfiguration({
}
}
}
});
});
\ No newline at end of file
src/vs/workbench/parts/search/browser/searchActions.ts
浏览文件 @
3a8fa7a8
...
...
@@ -12,12 +12,13 @@ import { ToggleViewletAction } from 'vs/workbench/browser/viewlet';
import
{
IViewletService
}
from
'
vs/workbench/services/viewlet/common/viewletService
'
;
import
{
ITree
}
from
'
vs/base/parts/tree/browser/tree
'
;
import
{
SearchViewlet
}
from
'
vs/workbench/parts/search/browser/searchViewlet
'
;
import
{
Match
,
FileMatch
}
from
'
vs/workbench/parts/search/common/searchModel
'
;
import
{
SearchResult
,
Match
,
FileMatch
,
FileMatchOrMatch
}
from
'
vs/workbench/parts/search/common/searchModel
'
;
import
{
IReplaceService
}
from
'
vs/workbench/parts/search/common/replace
'
;
import
*
as
Constants
from
'
vs/workbench/parts/search/common/constants
'
;
import
{
CollapseAllAction
as
TreeCollapseAction
}
from
'
vs/base/parts/tree/browser/treeDefaults
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
OpenGlobalSettingsAction
}
from
'
vs/workbench/browser/actions/openSettings
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
export
class
OpenSearchViewletAction
extends
ToggleViewletAction
{
...
...
@@ -27,6 +28,7 @@ export class OpenSearchViewletAction extends ToggleViewletAction {
constructor
(
id
:
string
,
label
:
string
,
@
IViewletService
viewletService
:
IViewletService
,
@
IWorkbenchEditorService
editorService
:
IWorkbenchEditorService
)
{
super
(
id
,
label
,
Constants
.
VIEWLET_ID
,
viewletService
,
editorService
);
}
}
export
class
FindInFolderAction
extends
Action
{
...
...
@@ -88,82 +90,53 @@ export class ClearSearchResultsAction extends Action {
}
}
export
class
SelectOrRemoveAction
extends
Action
{
private
selectMode
:
boolean
;
private
viewlet
:
SearchViewlet
;
constructor
(
viewlet
:
SearchViewlet
)
{
super
(
'
selectOrRemove
'
);
export
class
RemoveAction
extends
Action
{
this
.
label
=
nls
.
localize
(
'
SelectOrRemoveAction.selectLabel
'
,
"
Select
"
);
this
.
enabled
=
false
;
this
.
selectMode
=
true
;
this
.
viewlet
=
viewlet
;
constructor
(
private
viewer
:
ITree
,
private
element
:
FileMatchOrMatch
)
{
super
(
'
remove
'
,
nls
.
localize
(
'
RemoveAction.label
'
,
"
Remove
"
),
'
action-remove
'
);
}
public
run
():
TPromise
<
any
>
{
let
result
:
TPromise
<
any
>
;
if
(
this
.
selectMode
)
{
result
=
this
.
runAsSelect
();
if
(
this
.
element
instanceof
FileMatch
)
{
let
parent
:
SearchResult
=
<
SearchResult
>
this
.
element
.
parent
();
parent
.
remove
(
<
FileMatch
>
this
.
element
);
}
else
{
result
=
this
.
runAsRemove
();
let
parent
:
FileMatch
=
<
FileMatch
>
this
.
element
.
parent
();
parent
.
remove
(
<
Match
>
this
.
element
);
}
this
.
selectMode
=
!
this
.
selectMode
;
this
.
label
=
this
.
selectMode
?
nls
.
localize
(
'
SelectOrRemoveAction.selectLabel
'
,
"
Select
"
)
:
nls
.
localize
(
'
SelectOrRemoveAction.removeLabel
'
,
"
Remove
"
);
return
result
;
return
this
.
viewer
.
refresh
(
parent
);
}
}
private
runAsSelect
():
TPromise
<
void
>
{
this
.
viewlet
.
getResults
().
addClass
(
'
select
'
);
export
class
ReplaceAllAction
extends
Action
{
return
TPromise
.
as
(
null
);
constructor
(
private
viewer
:
ITree
,
private
fileMatch
:
FileMatch
,
private
viewlet
:
SearchViewlet
,
@
IReplaceService
private
replaceService
:
IReplaceService
)
{
super
(
'
file-action-replace-all
'
,
nls
.
localize
(
'
file.replaceAll.label
'
,
"
Replace All
"
),
'
action-replace-all
'
);
}
private
runAsRemove
():
TPromise
<
void
>
{
let
elements
:
any
[]
=
[];
let
tree
:
ITree
=
this
.
viewlet
.
getControl
();
tree
.
getInput
().
matches
().
forEach
((
fileMatch
:
FileMatch
)
=>
{
fileMatch
.
matches
().
filter
((
lineMatch
:
Match
)
=>
{
return
(
<
any
>
lineMatch
).
$checked
;
}).
forEach
((
lineMatch
:
Match
)
=>
{
lineMatch
.
parent
().
remove
(
lineMatch
);
elements
.
push
(
lineMatch
.
parent
());
});
public
run
():
TPromise
<
any
>
{
return
this
.
replaceService
.
replace
([
this
.
fileMatch
],
this
.
fileMatch
.
parent
().
replaceText
).
then
(()
=>
{
this
.
viewlet
.
open
(
this
.
fileMatch
).
done
(()
=>
{
new
RemoveAction
(
this
.
viewer
,
this
.
fileMatch
).
run
();
},
errors
.
onUnexpectedError
);
});
this
.
viewlet
.
getResults
().
removeClass
(
'
select
'
);
if
(
elements
.
length
>
0
)
{
return
tree
.
refreshAll
(
elements
).
then
(()
=>
{
return
tree
.
refresh
();
});
}
return
TPromise
.
as
(
null
);
}
}
export
class
Re
mov
eAction
extends
Action
{
export
class
Re
plac
eAction
extends
Action
{
private
viewer
:
ITree
;
private
fileMatch
:
FileMatch
;
constructor
(
viewer
:
ITree
,
element
:
FileMatch
)
{
super
(
'
remove
'
,
nls
.
localize
(
'
RemoveAction.label
'
,
"
Remove
"
),
'
action-remove
'
);
this
.
viewer
=
viewer
;
this
.
fileMatch
=
element
;
constructor
(
private
viewer
:
ITree
,
private
element
:
Match
,
private
viewlet
:
SearchViewlet
,
@
IReplaceService
private
replaceService
:
IReplaceService
)
{
super
(
'
action-replace
'
,
nls
.
localize
(
'
match.replace.label
'
,
"
Replace
"
),
'
action-replace
'
);
}
public
run
():
TPromise
<
any
>
{
let
parent
=
this
.
fileMatch
.
parent
();
parent
.
remove
(
this
.
fileMatch
);
return
this
.
viewer
.
refresh
(
parent
);
return
this
.
replaceService
.
replace
(
this
.
element
,
this
.
element
.
parent
().
parent
().
replaceText
).
then
(()
=>
{
this
.
viewlet
.
open
(
this
.
element
).
done
(()
=>
{
new
RemoveAction
(
this
.
viewer
,
this
.
element
).
run
();
},
errors
.
onUnexpectedError
);
});
}
}
...
...
src/vs/workbench/parts/search/browser/searchResultsView.ts
浏览文件 @
3a8fa7a8
...
...
@@ -19,15 +19,14 @@ import { LeftRightWidget, IRenderer } from 'vs/base/browser/ui/leftRightWidget/l
import
{
ITree
,
IElementCallback
,
IDataSource
,
ISorter
,
IAccessibilityProvider
,
IFilter
}
from
'
vs/base/parts/tree/browser/tree
'
;
import
{
ClickBehavior
,
DefaultController
}
from
'
vs/base/parts/tree/browser/treeDefaults
'
;
import
{
ContributableActionProvider
}
from
'
vs/workbench/browser/actionBarRegistry
'
;
import
{
Match
,
EmptyMatch
,
SearchResult
,
FileMatch
}
from
'
vs/workbench/parts/search/common/searchModel
'
;
import
{
Match
,
EmptyMatch
,
SearchResult
,
FileMatch
,
FileMatchOrMatch
}
from
'
vs/workbench/parts/search/common/searchModel
'
;
import
{
IWorkspaceContextService
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
IKeyboardEvent
}
from
'
vs/base/browser/keyboardEvent
'
;
import
{
CommonKeybindings
}
from
'
vs/base/common/keyCodes
'
;
import
{
SearchViewlet
}
from
'
vs/workbench/parts/search/browser/searchViewlet
'
;
import
{
RemoveAction
}
from
'
vs/workbench/parts/search/browser/searchActions
'
;
export
type
FileMatchOrMatch
=
FileMatch
|
Match
;
import
{
RemoveAction
,
ReplaceAllAction
,
ReplaceAction
}
from
'
vs/workbench/parts/search/browser/searchActions
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
export
class
SearchDataSource
implements
IDataSource
{
...
...
@@ -87,14 +86,26 @@ export class SearchSorter implements ISorter {
class
SearchActionProvider
extends
ContributableActionProvider
{
constructor
(
private
viewlet
:
SearchViewlet
,
@
IInstantiationService
private
instantiationService
:
IInstantiationService
)
{
super
();
}
public
hasActions
(
tree
:
ITree
,
element
:
any
):
boolean
{
return
element
instanceof
FileMatch
||
super
.
hasActions
(
tree
,
element
);
return
element
instanceof
FileMatch
||
(
tree
.
getInput
().
isReplaceActive
()
||
element
instanceof
Match
)
||
super
.
hasActions
(
tree
,
element
);
}
public
getActions
(
tree
:
ITree
,
element
:
any
):
TPromise
<
IAction
[]
>
{
return
super
.
getActions
(
tree
,
element
).
then
(
actions
=>
{
if
(
element
instanceof
FileMatch
)
{
actions
.
unshift
(
new
RemoveAction
(
tree
,
element
));
if
(
tree
.
getInput
().
isReplaceActive
()
&&
element
.
count
()
>
0
)
{
actions
.
unshift
(
this
.
instantiationService
.
createInstance
(
ReplaceAllAction
,
tree
,
element
,
this
.
viewlet
));
}
}
if
(
element
instanceof
Match
&&
!
(
element
instanceof
EmptyMatch
))
{
if
(
tree
.
getInput
().
isReplaceActive
())
{
actions
.
unshift
(
this
.
instantiationService
.
createInstance
(
ReplaceAction
,
tree
,
element
,
this
.
viewlet
),
new
RemoveAction
(
tree
,
element
));
}
}
return
actions
;
...
...
@@ -104,9 +115,10 @@ class SearchActionProvider extends ContributableActionProvider {
export
class
SearchRenderer
extends
ActionsRenderer
{
constructor
(
actionRunner
:
IActionRunner
,
@
IWorkspaceContextService
private
contextService
:
IWorkspaceContextService
)
{
constructor
(
actionRunner
:
IActionRunner
,
viewlet
:
SearchViewlet
,
@
IWorkspaceContextService
private
contextService
:
IWorkspaceContextService
,
@
IInstantiationService
private
instantiationService
:
IInstantiationService
)
{
super
({
actionProvider
:
new
SearchActionProvider
(
),
actionProvider
:
instantiationService
.
createInstance
(
SearchActionProvider
,
viewlet
),
actionRunner
:
actionRunner
});
}
...
...
@@ -159,8 +171,21 @@ export class SearchRenderer extends ActionsRenderer {
elements
.
push
(
'
<span>
'
);
elements
.
push
(
strings
.
escape
(
preview
.
before
));
elements
.
push
(
'
</span><span class="findInFileMatch">
'
);
elements
.
push
(
strings
.
escape
(
preview
.
inside
));
let
input
=
<
SearchResult
>
tree
.
getInput
();
if
(
input
.
isReplaceActive
())
{
let
replaceValue
=
input
.
replaceText
;
if
(
replaceValue
)
{
elements
.
push
(
'
</span><span class="findInFileMatch replaceMatch">
'
);
elements
.
push
(
strings
.
escape
(
replaceValue
));
}
else
{
elements
.
push
(
'
</span><span class="findInFileMatch replaceMatch removeMatch">
'
);
elements
.
push
(
strings
.
escape
(
preview
.
inside
));
}
}
else
{
elements
.
push
(
'
</span><span class="findInFileMatch">
'
);
elements
.
push
(
strings
.
escape
(
preview
.
inside
));
}
elements
.
push
(
'
</span><span>
'
);
elements
.
push
(
strings
.
escape
(
preview
.
after
));
elements
.
push
(
'
</span>
'
);
...
...
@@ -220,13 +245,22 @@ export class SearchController extends DefaultController {
private
onDelete
(
tree
:
ITree
,
event
:
IKeyboardEvent
):
boolean
{
let
result
=
false
;
let
element
=
tree
.
getFocus
();
if
(
element
instanceof
FileMatch
)
{
if
(
element
instanceof
FileMatch
||
(
element
instanceof
Match
&&
tree
.
getInput
().
isReplaceActive
()
&&
!
(
element
instanceof
EmptyMatch
)))
{
new
RemoveAction
(
tree
,
element
).
run
().
done
(
null
,
errors
.
onUnexpectedError
);
result
=
true
;
}
return
result
;
}
protected
onUp
(
tree
:
ITree
,
event
:
IKeyboardEvent
):
boolean
{
if
(
tree
.
getNavigator
().
first
()
===
tree
.
getFocus
())
{
this
.
viewlet
.
moveFocusFromResults
();
return
true
;
}
return
super
.
onUp
(
tree
,
event
);
}
}
export
class
SearchFilter
implements
IFilter
{
...
...
src/vs/workbench/parts/search/browser/searchViewlet.ts
浏览文件 @
3a8fa7a8
此差异已折叠。
点击以展开。
src/vs/workbench/parts/search/browser/searchWidget.ts
0 → 100644
浏览文件 @
3a8fa7a8
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
nls
=
require
(
'
vs/nls
'
);
import
strings
=
require
(
'
vs/base/common/strings
'
);
import
dom
=
require
(
'
vs/base/browser/dom
'
);
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
Widget
}
from
'
vs/base/browser/ui/widget
'
;
import
{
Action
}
from
'
vs/base/common/actions
'
;
import
{
FindInput
,
IFindInputOptions
}
from
'
vs/base/browser/ui/findinput/findInput
'
;
import
{
InputBox
}
from
'
vs/base/browser/ui/inputbox/inputBox
'
;
import
{
Button
}
from
'
vs/base/browser/ui/button/button
'
;
import
{
IKeyboardEvent
}
from
'
vs/base/browser/keyboardEvent
'
;
import
{
IContextViewService
}
from
'
vs/platform/contextview/browser/contextView
'
;
import
{
KeyCode
}
from
'
vs/base/common/keyCodes
'
;
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
{
Builder
}
from
'
vs/base/browser/builder
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
export
interface
ISearchWidgetOptions
{
value
?:
string
;
isRegex
?:
boolean
;
isCaseSensitive
?:
boolean
;
isWholeWords
?:
boolean
;
}
export
class
SearchWidget
extends
Widget
{
public
static
REPLACE_PLACE_HOLD
=
nls
.
localize
(
'
search.replace.placeHolder
'
,
"
Replace
"
);
public
domNode
:
HTMLElement
;
public
searchInput
:
FindInput
;
private
replaceInput
:
InputBox
;
private
replaceInputContainer
:
HTMLElement
;
private
toggleReplaceButton
:
Button
;
private
replaceAllAction
:
Action
;
private
_onSearchSubmit
=
this
.
_register
(
new
Emitter
<
boolean
>
());
public
onSearchSubmit
:
Event
<
boolean
>
=
this
.
_onSearchSubmit
.
event
;
private
_onSearchCancel
=
this
.
_register
(
new
Emitter
<
void
>
());
public
onSearchCancel
:
Event
<
void
>
=
this
.
_onSearchCancel
.
event
;
private
_onReplaceToggled
=
this
.
_register
(
new
Emitter
<
void
>
());
public
onReplaceToggled
:
Event
<
void
>
=
this
.
_onReplaceToggled
.
event
;
private
_onReplaceState
=
this
.
_register
(
new
Emitter
<
void
>
());
public
onReplaceStateChange
:
Event
<
void
>
=
this
.
_onReplaceState
.
event
;
private
_onReplaceValueChanged
=
this
.
_register
(
new
Emitter
<
string
>
());
public
onReplaceValueChanged
:
Event
<
string
>
=
this
.
_onReplaceValueChanged
.
event
;
private
_onKeyDownArrow
=
this
.
_register
(
new
Emitter
<
void
>
());
public
onKeyDownArrow
:
Event
<
void
>
=
this
.
_onKeyDownArrow
.
event
;
private
_onReplaceAll
=
this
.
_register
(
new
Emitter
<
void
>
());
public
onReplaceAll
:
Event
<
void
>
=
this
.
_onReplaceAll
.
event
;
constructor
(
container
:
Builder
,
private
contextViewService
:
IContextViewService
,
options
:
ISearchWidgetOptions
=
Object
.
create
(
null
),
@
IInstantiationService
private
instantiationService
:
IInstantiationService
)
{
super
();
this
.
render
(
container
,
options
);
}
public
focus
(
select
:
boolean
=
true
,
focusReplace
:
boolean
=
false
):
void
{
if
(
this
.
searchInput
.
inputBox
.
hasFocus
()
||
this
.
replaceInput
.
hasFocus
())
{
return
;
}
if
(
focusReplace
&&
this
.
isReplaceShown
())
{
this
.
replaceInput
.
focus
();
if
(
select
)
{
this
.
replaceInput
.
select
();
}
}
else
{
this
.
searchInput
.
focus
();
if
(
select
)
{
this
.
searchInput
.
select
();
}
}
}
public
setWidth
(
width
:
number
)
{
this
.
searchInput
.
setWidth
(
width
-
2
);
this
.
replaceInput
.
width
=
width
-
28
;
}
public
clear
()
{
this
.
searchInput
.
clear
();
this
.
replaceInput
.
value
=
''
;
}
public
isReplaceActive
():
boolean
{
return
this
.
isReplaceShown
()
&&
this
.
replaceAllAction
.
enabled
;
}
public
isReplaceShown
():
boolean
{
return
!
dom
.
hasClass
(
this
.
replaceInputContainer
,
'
disabled
'
);
}
public
getReplaceValue
():
string
{
return
this
.
isReplaceActive
()
?
this
.
replaceInput
.
value
:
null
;
}
private
render
(
container
:
Builder
,
options
:
ISearchWidgetOptions
):
void
{
this
.
domNode
=
container
.
div
({
'
class
'
:
'
search-widget
'
}).
style
({
position
:
'
relative
'
}).
getHTMLElement
();
this
.
renderToggleReplaceButton
(
this
.
domNode
);
this
.
renderSearchInput
(
this
.
domNode
,
options
);
this
.
renderReplaceInput
(
this
.
domNode
);
}
private
renderToggleReplaceButton
(
parent
:
HTMLElement
):
void
{
this
.
toggleReplaceButton
=
this
.
_register
(
new
Button
(
parent
));
this
.
toggleReplaceButton
.
icon
=
'
toggle-replace-button collapse
'
;
this
.
toggleReplaceButton
.
addListener2
(
'
click
'
,
()
=>
this
.
onToggleReplaceButton
());
this
.
toggleReplaceButton
.
getElement
().
title
=
nls
.
localize
(
'
search.replace.toggle.button.title
'
,
"
Toggle Replace
"
);
}
private
renderSearchInput
(
parent
:
HTMLElement
,
options
:
ISearchWidgetOptions
):
void
{
let
inputOptions
:
IFindInputOptions
=
{
label
:
nls
.
localize
(
'
label.Search
'
,
'
Search: Type Search Term and press Enter to search or Escape to cancel
'
),
validation
:
(
value
:
string
)
=>
this
.
validatSearchInput
(
value
),
placeholder
:
nls
.
localize
(
'
search.placeHolder
'
,
"
Search
"
)
};
let
searchInputContainer
=
dom
.
append
(
parent
,
dom
.
emmet
(
'
.search-box.input-box
'
));
this
.
searchInput
=
this
.
_register
(
new
FindInput
(
searchInputContainer
,
this
.
contextViewService
,
inputOptions
));
this
.
searchInput
.
onKeyUp
((
keyboardEvent
:
IKeyboardEvent
)
=>
this
.
onSearchInputKeyUp
(
keyboardEvent
));
this
.
searchInput
.
onKeyDown
((
keyboardEvent
:
IKeyboardEvent
)
=>
this
.
onSearchInputKeyDown
(
keyboardEvent
));
this
.
searchInput
.
setValue
(
options
.
value
||
''
);
this
.
searchInput
.
setRegex
(
!!
options
.
isRegex
);
this
.
searchInput
.
setCaseSensitive
(
!!
options
.
isCaseSensitive
);
this
.
searchInput
.
setWholeWords
(
!!
options
.
isWholeWords
);
this
.
_register
(
dom
.
addDisposableListener
(
this
.
searchInput
.
inputBox
.
inputElement
,
dom
.
EventType
.
FOCUS
,
()
=>
this
.
updateReplaceActionState
()));
this
.
_register
(
dom
.
addDisposableListener
(
this
.
searchInput
.
inputBox
.
inputElement
,
dom
.
EventType
.
BLUR
,
()
=>
this
.
updateReplaceActionState
()));
}
private
renderReplaceInput
(
parent
:
HTMLElement
):
void
{
this
.
replaceAllAction
=
new
Action
(
'
action-replace-all
'
,
nls
.
localize
(
'
file.replaceAll.label
'
,
"
Replace All
"
),
'
action-replace-all
'
,
false
,
()
=>
{
this
.
_onReplaceAll
.
fire
();
return
TPromise
.
as
(
null
);
});
this
.
replaceInputContainer
=
dom
.
append
(
parent
,
dom
.
emmet
(
'
.replace-box.input-box.disabled
'
));
this
.
replaceInput
=
this
.
_register
(
new
InputBox
(
this
.
replaceInputContainer
,
this
.
contextViewService
,
{
placeholder
:
SearchWidget
.
REPLACE_PLACE_HOLD
,
actions
:
[
this
.
replaceAllAction
]
}));
this
.
onkeydown
(
this
.
replaceInput
.
inputElement
,
(
keyboardEvent
)
=>
this
.
onReplaceInputKeyDown
(
keyboardEvent
));
this
.
onkeyup
(
this
.
replaceInput
.
inputElement
,
(
keyboardEvent
)
=>
this
.
onReplaceInputKeyUp
(
keyboardEvent
));
this
.
replaceInput
.
onDidChange
(()
=>
this
.
_onReplaceValueChanged
.
fire
());
}
private
onToggleReplaceButton
():
void
{
dom
.
toggleClass
(
this
.
replaceInputContainer
,
'
disabled
'
);
dom
.
toggleClass
(
this
.
toggleReplaceButton
.
getElement
(),
'
collapse
'
);
dom
.
toggleClass
(
this
.
toggleReplaceButton
.
getElement
(),
'
expand
'
);
this
.
_onReplaceToggled
.
fire
();
this
.
updateReplaceActionState
();
}
private
updateReplaceActionState
():
boolean
{
let
enabled
=
this
.
isReplaceShown
()
&&
!
this
.
searchInput
.
inputBox
.
hasFocus
();
if
(
this
.
replaceAllAction
.
enabled
!==
enabled
)
{
this
.
replaceAllAction
.
enabled
=
enabled
;
this
.
_onReplaceState
.
fire
();
return
true
;
}
return
false
;
}
private
validatSearchInput
(
value
:
string
):
any
{
if
(
value
.
length
===
0
)
{
return
null
;
}
if
(
!
this
.
searchInput
.
getRegex
())
{
return
null
;
}
let
regExp
:
RegExp
;
try
{
regExp
=
new
RegExp
(
value
);
}
catch
(
e
)
{
return
{
content
:
e
.
message
};
}
if
(
strings
.
regExpLeadsToEndlessLoop
(
regExp
))
{
return
{
content
:
nls
.
localize
(
'
regexp.validationFailure
'
,
"
Expression matches everything
"
)
};
}
}
private
onSearchInputKeyUp
(
keyboardEvent
:
IKeyboardEvent
)
{
switch
(
keyboardEvent
.
keyCode
)
{
case
KeyCode
.
Enter
:
this
.
submitSearch
();
return
;
case
KeyCode
.
Escape
:
this
.
_onSearchCancel
.
fire
();
return
;
default
:
return
;
}
}
private
onSearchInputKeyDown
(
keyboardEvent
:
IKeyboardEvent
)
{
switch
(
keyboardEvent
.
keyCode
)
{
case
KeyCode
.
DownArrow
:
if
(
this
.
isReplaceShown
())
{
this
.
replaceInput
.
focus
();
keyboardEvent
.
stopPropagation
();
}
else
{
this
.
_onKeyDownArrow
.
fire
();
}
return
;
default
:
return
;
}
}
private
onReplaceInputKeyUp
(
keyboardEvent
:
IKeyboardEvent
)
{
switch
(
keyboardEvent
.
keyCode
)
{
case
KeyCode
.
Enter
:
this
.
submitSearch
();
return
;
case
KeyCode
.
Escape
:
this
.
onToggleReplaceButton
();
this
.
searchInput
.
focus
();
return
;
default
:
return
;
}
}
private
onReplaceInputKeyDown
(
keyboardEvent
:
IKeyboardEvent
)
{
switch
(
keyboardEvent
.
keyCode
)
{
case
KeyCode
.
UpArrow
:
this
.
searchInput
.
focus
();
return
;
case
KeyCode
.
DownArrow
:
this
.
_onKeyDownArrow
.
fire
();
return
;
default
:
return
;
}
}
private
submitSearch
(
refresh
:
boolean
=
true
):
void
{
if
(
this
.
searchInput
.
getValue
())
{
this
.
_onSearchSubmit
.
fire
(
refresh
);
}
}
public
dispose
():
void
{
super
.
dispose
();
}
}
\ No newline at end of file
src/vs/workbench/parts/search/common/replace.ts
0 → 100644
浏览文件 @
3a8fa7a8
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
Match
,
FileMatch
}
from
'
vs/workbench/parts/search/common/searchModel
'
;
import
{
createDecorator
,
ServiceIdentifier
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IProgressRunner
}
from
'
vs/platform/progress/common/progress
'
;
export
var
IReplaceService
=
createDecorator
<
IReplaceService
>
(
'
replaceService
'
);
export
interface
IReplaceService
{
serviceId
:
ServiceIdentifier
<
any
>
;
/**
* Replace the match with the given text.
*/
replace
(
match
:
Match
,
text
:
string
):
TPromise
<
any
>
;
/**
* Replace all the matches in the given file matches with provided text.
* You can also pass the progress runner to update the progress of replacing.
*/
replace
(
files
:
FileMatch
[],
text
:
string
,
progress
?:
IProgressRunner
):
TPromise
<
any
>
;
}
src/vs/workbench/parts/search/common/searchModel.ts
浏览文件 @
3a8fa7a8
...
...
@@ -123,6 +123,8 @@ export class FileMatch implements lifecycle.IDisposable {
}
}
export
type
FileMatchOrMatch
=
FileMatch
|
Match
;
export
class
LiveFileMatch
extends
FileMatch
implements
lifecycle
.
IDisposable
{
private
static
DecorationOption
:
IModelDecorationOptions
=
{
...
...
@@ -199,12 +201,21 @@ export class LiveFileMatch extends FileMatch implements lifecycle.IDisposable {
private
_isTextModelDisposed
():
boolean
{
return
!
this
.
_model
||
(
<
ITextModel
>
this
.
_model
).
isDisposed
();
}
public
remove
(
match
:
Match
):
void
{
super
.
remove
(
match
);
if
(
this
.
count
()
===
0
)
{
this
.
add
(
new
EmptyMatch
(
this
));
}
}
}
export
class
SearchResult
extends
EventEmitter
{
private
_modelService
:
IModelService
;
private
_query
:
Search
.
IPatternInfo
;
private
_replace
:
string
=
null
;
private
_disposables
:
lifecycle
.
IDisposable
[]
=
[];
private
_matches
:
{
[
key
:
string
]:
FileMatch
;
}
=
Object
.
create
(
null
);
...
...
@@ -221,6 +232,26 @@ export class SearchResult extends EventEmitter {
}
}
/**
* Return true if replace is enabled otherwise false
*/
public
isReplaceActive
():
boolean
{
return
this
.
replaceText
!==
null
&&
this
.
replaceText
!==
void
0
;
}
/**
* Returns the text to replace.
* Can be null if replace is not enabled. Use replace() before.
* Can be empty.
*/
public
get
replaceText
():
string
{
return
this
.
_replace
;
}
public
set
replaceText
(
replace
:
string
)
{
this
.
_replace
=
replace
;
}
private
_onModelAdded
(
model
:
IModel
):
void
{
let
resource
=
model
.
uri
,
fileMatch
=
this
.
_matches
[
resource
.
toString
()];
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录