redcar 0.10 → 0.11.0dev
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +14 -0
- data/Rakefile +68 -29
- data/lib/redcar.rb +2 -2
- data/plugins/application/lib/application/dialogs/filter_list_dialog.rb +2 -1
- data/plugins/application_swt/spec/application_swt/gradient_spec.rb +3 -12
- data/plugins/core/lib/core/resource.rb +13 -5
- data/plugins/document_search/features/find.feature +366 -214
- data/plugins/document_search/features/incremental_search.feature +351 -0
- data/plugins/document_search/features/replace.feature +16 -16
- data/plugins/document_search/features/step_definitions/find_steps.rb +16 -0
- data/plugins/document_search/features/support/env.rb +11 -0
- data/plugins/document_search/lib/document_search.rb +149 -109
- data/plugins/document_search/lib/document_search/commands.rb +251 -202
- data/plugins/document_search/lib/document_search/find_speedbar.rb +138 -81
- data/plugins/document_search/lib/document_search/incremental_search_speedbar.rb +70 -0
- data/plugins/document_search/lib/document_search/query_options.rb +15 -39
- data/plugins/document_search/plugin.rb +1 -1
- data/plugins/edit_view/features/step_definitions/editing_steps.rb +6 -2
- data/plugins/edit_view_swt/lib/edit_view_swt.rb +2 -2
- data/plugins/file_parser/lib/file_parser.rb +6 -1
- data/plugins/html_view/features/step_definitions/web_view_steps.rb +12 -0
- data/plugins/html_view/features/support/env.rb +16 -0
- data/plugins/html_view/lib/html_view.rb +5 -1
- data/plugins/line_tools/lib/line_tools.rb +16 -0
- data/plugins/project/features/find_file.feature +28 -0
- data/plugins/project/features/open_and_save_files.feature +11 -0
- data/plugins/project/features/step_definitions/file_steps.rb +6 -1
- data/plugins/project/features/support/env.rb +2 -0
- data/plugins/project/lib/project.rb +49 -6
- data/plugins/project/lib/project/commands.rb +18 -6
- data/plugins/project/lib/project/find_file_dialog.rb +19 -8
- data/plugins/project/lib/project/find_recent_dialog.rb +30 -0
- data/plugins/project/lib/project/manager.rb +41 -10
- data/plugins/project/lib/project/recent.rb +64 -0
- data/plugins/project/spec/fixtures/myproject/vendor/bar.rb +0 -0
- data/plugins/project/spec/fixtures/myproject/vendor/plugins/bar.rb +0 -0
- data/plugins/{find-in-project → project_search}/TODO.md +3 -3
- data/plugins/project_search/features/support/env.rb +6 -0
- data/plugins/project_search/features/word_search.feature +34 -0
- data/plugins/project_search/lib/project_search.rb +73 -0
- data/plugins/project_search/lib/project_search/binary_data_detector.rb +46 -0
- data/plugins/project_search/lib/project_search/commands.rb +62 -0
- data/plugins/project_search/lib/project_search/hit.rb +17 -0
- data/plugins/{find-in-project/lib/find_in_project → project_search/lib/project_search}/images/collapsed.png +0 -0
- data/plugins/{find-in-project/lib/find_in_project → project_search/lib/project_search}/images/expanded.png +0 -0
- data/plugins/{find-in-project/lib/find_in_project → project_search/lib/project_search}/images/spinner.gif +0 -0
- data/plugins/project_search/lib/project_search/lucene_index.rb +64 -0
- data/plugins/project_search/lib/project_search/lucene_refresh.rb +22 -0
- data/plugins/project_search/lib/project_search/project.rb +14 -0
- data/plugins/project_search/lib/project_search/query.rb +29 -0
- data/plugins/{find-in-project/lib/find_in_project → project_search/lib/project_search}/stylesheets/style.css +14 -3
- data/plugins/project_search/lib/project_search/views/_file.html.erb +60 -0
- data/plugins/{find-in-project/lib/find_in_project → project_search/lib/project_search}/views/index.html.erb +12 -9
- data/plugins/project_search/lib/project_search/word_search.rb +105 -0
- data/plugins/project_search/lib/project_search/word_search_controller.rb +207 -0
- data/plugins/project_search/plugin.rb +8 -0
- data/plugins/project_search/spec/fixtures/project/binary_file.bin +0 -0
- data/plugins/project_search/spec/fixtures/project/foo.txt +43 -0
- data/plugins/project_search/spec/fixtures/project/qux.rb +3 -0
- data/plugins/project_search/spec/project_search/binary_data_detector_spec.rb +24 -0
- data/plugins/project_search/spec/project_search/word_search_spec.rb +157 -0
- data/plugins/project_search/spec/spec_helper.rb +27 -0
- data/plugins/redcar/redcar.rb +77 -71
- data/plugins/ruby/lib/ruby/syntax_checker.rb +1 -1
- data/plugins/snippets/features/snippets.feature +12 -0
- data/plugins/snippets/lib/snippets/tab_handler.rb +1 -1
- metadata +46 -25
- data/plugins/document_search/features/find_and_replace.feature +0 -723
- data/plugins/document_search/lib/document_search/find_and_replace_speedbar.rb +0 -142
- data/plugins/find-in-project/lib/find_in_project.rb +0 -35
- data/plugins/find-in-project/lib/find_in_project/commands.rb +0 -30
- data/plugins/find-in-project/lib/find_in_project/controllers.rb +0 -170
- data/plugins/find-in-project/lib/find_in_project/views/_divider.html.erb +0 -4
- data/plugins/find-in-project/lib/find_in_project/views/_file_heading.html.erb +0 -10
- data/plugins/find-in-project/lib/find_in_project/views/_file_line.html.erb +0 -6
- data/plugins/find-in-project/plugin.rb +0 -11
- data/plugins/project/lib/project/recent_directories.rb +0 -54
@@ -3,6 +3,7 @@
|
|
3
3
|
padding: 0;
|
4
4
|
font-weight: normal;
|
5
5
|
font-size: 14px;
|
6
|
+
font-family: sans-serif;
|
6
7
|
}
|
7
8
|
|
8
9
|
#search_form_container {
|
@@ -34,6 +35,7 @@
|
|
34
35
|
#search_form_container .input .field input {
|
35
36
|
width: 100%;
|
36
37
|
height: 20px;
|
38
|
+
font-family: monospace;
|
37
39
|
}
|
38
40
|
|
39
41
|
#search_form_container .input .expand {
|
@@ -122,7 +124,7 @@
|
|
122
124
|
}
|
123
125
|
|
124
126
|
#results .even {
|
125
|
-
background-color: #
|
127
|
+
background-color: #F4F4F4;
|
126
128
|
}
|
127
129
|
|
128
130
|
#results .odd {
|
@@ -141,6 +143,7 @@
|
|
141
143
|
|
142
144
|
#results .file_heading a {
|
143
145
|
font-weight: bold;
|
146
|
+
font-family: sans-serif;
|
144
147
|
}
|
145
148
|
|
146
149
|
#results .expand_collapse img {
|
@@ -155,6 +158,7 @@
|
|
155
158
|
cursor: hand;
|
156
159
|
font-size: 12px;
|
157
160
|
line-height: 12px;
|
161
|
+
font-family: sans-serif;
|
158
162
|
}
|
159
163
|
|
160
164
|
#results .divider .line_num {
|
@@ -168,17 +172,22 @@
|
|
168
172
|
padding: 3px 10px;
|
169
173
|
width: 100%;
|
170
174
|
cursor: hand;
|
175
|
+
}
|
176
|
+
|
177
|
+
#results .text pre {
|
171
178
|
font-size: 14px;
|
172
179
|
line-height: 17px;
|
180
|
+
font-family: monospace;
|
173
181
|
}
|
174
182
|
|
175
183
|
#results .divider .text {
|
176
184
|
cursor: default;
|
177
185
|
}
|
178
186
|
|
179
|
-
#results .text span {
|
180
|
-
background-color:
|
187
|
+
#results .text pre span {
|
188
|
+
background-color: #FFCCCC;
|
181
189
|
font-weight: bold;
|
190
|
+
font-family: monospace;
|
182
191
|
}
|
183
192
|
|
184
193
|
#results .break {
|
@@ -190,6 +199,8 @@
|
|
190
199
|
bottom: 0;
|
191
200
|
left: 0;
|
192
201
|
right: 0;
|
202
|
+
font-size: 1.5em;
|
203
|
+
font-family: sans-serif;
|
193
204
|
}
|
194
205
|
|
195
206
|
#results_summary .text {
|
@@ -0,0 +1,60 @@
|
|
1
|
+
|
2
|
+
<tr><td class='break' colspan='2'></td></tr>
|
3
|
+
<tr>
|
4
|
+
<td class="file_heading" colspan="2">
|
5
|
+
<a class="expand_collapse" data-file_num="<%= file %>">
|
6
|
+
<img src="<%= image_path %>/expanded.png" />
|
7
|
+
<%= CGI::escapeHTML(file.gsub(@word_search.project.path + "/", "")) %>
|
8
|
+
</a>
|
9
|
+
</td>
|
10
|
+
</tr>
|
11
|
+
|
12
|
+
<% line_index = 0 %>
|
13
|
+
<% last_matching_line_num = nil %>
|
14
|
+
<% last_displayed_line_num = -1 %>
|
15
|
+
<% hits.each_with_index do |hit, i| %>
|
16
|
+
<% next_hit = hits[i + 1] %>
|
17
|
+
<% next_hit_line_num = next_hit ? next_hit.line_num : 100_000_000 %>
|
18
|
+
|
19
|
+
<% if @word_search.context? and last_matching_line_num and (hit.line_num - last_matching_line_num) > (@word_search.context_size * 2) %>
|
20
|
+
<tr class="divider file_<%= file_num %>">
|
21
|
+
<td class="line_num">. . .</td>
|
22
|
+
<td class="text"> </td> <!-- extra space to ensure line-height is respected -->
|
23
|
+
</tr>
|
24
|
+
<% end %>
|
25
|
+
|
26
|
+
<% hit.pre_context.each_with_index do |context_line, i| %>
|
27
|
+
<% this_line_num = hit.line_num - @word_search.context_size + i %>
|
28
|
+
<% unless this_line_num <= last_displayed_line_num %>
|
29
|
+
<% line_index += 1 %>
|
30
|
+
<tr class="result file_<%= file_num %> line_<%= this_line_num %> <%= (line_index % 2 == 0 ? 'even' : 'odd') %>" data-href='<%= CGI::escapeHTML(file) %>' data-line_num='<%= this_line_num %>'>
|
31
|
+
<td class='line_num'><%= this_line_num %></td>
|
32
|
+
<% text = CGI.escapeHTML(context_line).gsub(@word_search.regex) { "<span>#{$&}</span>" } %>
|
33
|
+
<td class='text'><pre><%= text.chomp + " " %></pre></td> <!-- extra space to ensure line-height is respected -->
|
34
|
+
</tr>
|
35
|
+
<% end %>
|
36
|
+
<% end %>
|
37
|
+
|
38
|
+
<% line_index += 1 %>
|
39
|
+
<% last_displayed_line_num = hit.line_num %>
|
40
|
+
<tr class="result file_<%= file_num %> line_<%= hit.line_num %> <%= (line_index % 2 == 0 ? 'even' : 'odd') %>" data-href='<%= CGI::escapeHTML(file) %>' data-line_num='<%= hit.line_num %>'>
|
41
|
+
<td class='line_num'><%= hit.line_num %></td>
|
42
|
+
<% text = CGI.escapeHTML(hit.line).gsub(@word_search.regex) { "<span>#{$&}</span>" } %>
|
43
|
+
<td class='text'><pre><%= text.chomp + " " %></pre></td> <!-- extra space to ensure line-height is respected -->
|
44
|
+
</tr>
|
45
|
+
|
46
|
+
<% hit.post_context.each_with_index do |context_line, i| %>
|
47
|
+
<% this_line_num = hit.line_num + i + 1%>
|
48
|
+
<% unless this_line_num >= next_hit_line_num %>
|
49
|
+
<% last_displayed_line_num = this_line_num %>
|
50
|
+
<% line_index += 1 %>
|
51
|
+
<tr class="result file_<%= file_num %> line_<%= this_line_num %> <%= (line_index % 2 == 0 ? 'even' : 'odd') %>" data-href='<%= CGI::escapeHTML(file) %>' data-line_num='<%= this_line_num %>'>
|
52
|
+
<td class='line_num'><%= this_line_num %></td>
|
53
|
+
<% text = CGI.escapeHTML(context_line).gsub(@word_search.regex) { "<span>#{$&}</span>" } %>
|
54
|
+
<td class='text'><pre><%= text.chomp + " " %></pre></td> <!-- extra space to ensure line-height is respected -->
|
55
|
+
</tr>
|
56
|
+
<% end %>
|
57
|
+
<% end %>
|
58
|
+
|
59
|
+
<% last_matching_line_num = hit.line_num %>
|
60
|
+
<% end %>
|
@@ -3,10 +3,10 @@
|
|
3
3
|
<% json_path = File.expand_path(File.join(Redcar.root, %w(plugins html_view assets json2.js))) %>
|
4
4
|
<script type="text/javascript" src="file://<%= json_path %>"></script>
|
5
5
|
|
6
|
-
<% plugin_css = File.expand_path(File.join(
|
6
|
+
<% plugin_css = File.expand_path(File.join(plugin_root, %w(lib project_search stylesheets style.css))) %>
|
7
7
|
<link rel="stylesheet" href="file://<%= plugin_css %>" type="text/css" media="screen">
|
8
8
|
|
9
|
-
<% image_path = File.expand_path(File.join(
|
9
|
+
<% image_path = File.expand_path(File.join(plugin_root, %w(lib project_search images))) %>
|
10
10
|
|
11
11
|
<div id="search_form_container">
|
12
12
|
<form id="search_form">
|
@@ -14,14 +14,14 @@
|
|
14
14
|
<tr class="input">
|
15
15
|
<td class="label"><label for="query">Search Term</label></td>
|
16
16
|
<td class="field">
|
17
|
-
<input id="query" type="text" value="<%=
|
18
|
-
|
17
|
+
<input id="query" type="text" value="<%= default_query %>" />
|
18
|
+
|
19
19
|
<!-- keeps a cache of the current query so if the user changes the query field, this remains the same as the results -->
|
20
20
|
<input id="cached_query" type="hidden" />
|
21
21
|
|
22
22
|
<div id="recent_queries" style="display: none;">
|
23
23
|
<ul>
|
24
|
-
<% (
|
24
|
+
<% (settings['recent_queries'] || []).each do |query| %>
|
25
25
|
<li><%= CGI::escapeHTML(query) %></li>
|
26
26
|
<% end %>
|
27
27
|
</ul>
|
@@ -36,12 +36,15 @@
|
|
36
36
|
<td class="controls">
|
37
37
|
<input id="search" type="submit" value="Find In Project" />
|
38
38
|
<img id="spinner" src="<%= image_path %>/spinner.gif" style="display:none;" />
|
39
|
+
<% if show_literal_match_option? %>
|
39
40
|
<input type="checkbox" id="literal_match" <%="checked=checked" if @literal_match %>>
|
40
|
-
|
41
|
-
|
41
|
+
<label for="literal_match">Literal Match</label>
|
42
|
+
<% end %>
|
43
|
+
<input type="checkbox" id="match_case" <%="checked=checked" if match_case? %>>
|
42
44
|
<label for="match_case">Match case</label>
|
43
|
-
<input type="checkbox" id="with_context" <%="checked=checked" if
|
45
|
+
<input type="checkbox" id="with_context" <%="checked=checked" if context? %>>
|
44
46
|
<label for="with_context">With context</label>
|
47
|
+
<%= search_copy %>
|
45
48
|
<a href="#" title="Edit Preferences" id="edit_preferences">Edit Preferences...</a>
|
46
49
|
</td>
|
47
50
|
<td></td>
|
@@ -99,7 +102,7 @@
|
|
99
102
|
});
|
100
103
|
|
101
104
|
$('#edit_preferences').click(function(ev) {
|
102
|
-
Controller.
|
105
|
+
Controller.editPreferences();
|
103
106
|
});
|
104
107
|
|
105
108
|
// in the case the user wants to search for things like <table>, we need to unescape the entities
|
@@ -0,0 +1,105 @@
|
|
1
|
+
|
2
|
+
class ProjectSearch
|
3
|
+
class WordSearch
|
4
|
+
attr_reader :query_string, :context_size, :project
|
5
|
+
|
6
|
+
def initialize(project, query_string, match_case, context_size)
|
7
|
+
@project = project
|
8
|
+
@query_string = query_string
|
9
|
+
@match_case = !!match_case
|
10
|
+
@context_size = context_size
|
11
|
+
end
|
12
|
+
|
13
|
+
def match_case?
|
14
|
+
@match_case
|
15
|
+
end
|
16
|
+
|
17
|
+
def context?
|
18
|
+
@context_size > 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def matching_line?(line)
|
22
|
+
line =~ regex
|
23
|
+
end
|
24
|
+
|
25
|
+
def regex
|
26
|
+
@regex ||= begin
|
27
|
+
regexp_text = Regexp.escape(@query_string)
|
28
|
+
match_case? ? /#{regexp_text}/ : /#{regexp_text}/i
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_file_results(&block)
|
33
|
+
@on_file_results_block = block
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate_results
|
37
|
+
hits = []
|
38
|
+
doc_ids.each do |doc_id|
|
39
|
+
next unless File.exist?(doc_id)
|
40
|
+
contents = File.read(doc_id).split(/\n|\r/)
|
41
|
+
pre_context = []
|
42
|
+
hits_needing_post_context = []
|
43
|
+
remove_hits = []
|
44
|
+
file_hits = []
|
45
|
+
contents.each_with_index do |line, line_num|
|
46
|
+
hits_needing_post_context.each do |hit|
|
47
|
+
hit.post_context << line
|
48
|
+
if hit.post_context.length == context_size
|
49
|
+
remove_hits << hit
|
50
|
+
end
|
51
|
+
end
|
52
|
+
hits_needing_post_context -= remove_hits
|
53
|
+
|
54
|
+
if matching_line?(line)
|
55
|
+
hit = Hit.new(doc_id, line_num, line, regex, pre_context.dup, [])
|
56
|
+
hits << hit
|
57
|
+
file_hits << hit
|
58
|
+
if context_size > 0
|
59
|
+
hits_needing_post_context << hit
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
if pre_context.length == context_size
|
64
|
+
pre_context.shift
|
65
|
+
end
|
66
|
+
pre_context << line
|
67
|
+
end
|
68
|
+
send_file_results(file_hits)
|
69
|
+
end
|
70
|
+
hits
|
71
|
+
end
|
72
|
+
|
73
|
+
def send_file_results(hits)
|
74
|
+
if @on_file_results_block
|
75
|
+
@on_file_results_block.call(hits)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def results
|
80
|
+
@results ||= generate_results
|
81
|
+
end
|
82
|
+
|
83
|
+
def bits
|
84
|
+
query_string.
|
85
|
+
gsub(/[^\w]/, " ").
|
86
|
+
gsub("_", " ").
|
87
|
+
split(/\s/).
|
88
|
+
map {|b| b.strip}.
|
89
|
+
reject {|b| b == "" or org.apache.lucene.analysis.standard.StandardAnalyzer::STOP_WORDS_SET.to_a.include?(b)}
|
90
|
+
end
|
91
|
+
|
92
|
+
def doc_ids
|
93
|
+
@doc_ids ||= begin
|
94
|
+
index = ProjectSearch.indexes[project.path].lucene_index
|
95
|
+
doc_ids = nil
|
96
|
+
bits.each do |bit|
|
97
|
+
new_doc_ids = index.find(:contents => bit.downcase).map {|doc| doc.id }
|
98
|
+
doc_ids = doc_ids ? (doc_ids & new_doc_ids) : new_doc_ids
|
99
|
+
end
|
100
|
+
doc_ids
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
@@ -0,0 +1,207 @@
|
|
1
|
+
|
2
|
+
class ProjectSearch
|
3
|
+
class WordSearchController
|
4
|
+
include Redcar::HtmlController
|
5
|
+
|
6
|
+
TITLE = "Project Search"
|
7
|
+
|
8
|
+
def title
|
9
|
+
TITLE
|
10
|
+
end
|
11
|
+
|
12
|
+
def search_copy
|
13
|
+
"Search for complete words only"
|
14
|
+
end
|
15
|
+
|
16
|
+
def show_literal_match_option?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def num_context_lines
|
21
|
+
settings['context_lines']
|
22
|
+
end
|
23
|
+
|
24
|
+
def plugin_root
|
25
|
+
File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
26
|
+
end
|
27
|
+
|
28
|
+
def settings
|
29
|
+
ProjectSearch.storage
|
30
|
+
end
|
31
|
+
|
32
|
+
def match_case?
|
33
|
+
ProjectSearch.storage['match_case']
|
34
|
+
end
|
35
|
+
|
36
|
+
def context?
|
37
|
+
ProjectSearch.storage['with_context']
|
38
|
+
end
|
39
|
+
|
40
|
+
def context_size
|
41
|
+
context? ? num_context_lines : 0
|
42
|
+
end
|
43
|
+
|
44
|
+
def default_query
|
45
|
+
doc.selected_text if doc && doc.selection?
|
46
|
+
end
|
47
|
+
|
48
|
+
def index
|
49
|
+
render('index')
|
50
|
+
end
|
51
|
+
|
52
|
+
def edit_preferences
|
53
|
+
Redcar.app.make_sure_at_least_one_window_open # open a new window if needed
|
54
|
+
Redcar::FindInProject.storage # populate the file if it isn't already
|
55
|
+
tab = Redcar.app.focussed_window.new_tab(Redcar::EditTab)
|
56
|
+
mirror = Project::FileMirror.new(File.join(Redcar.user_dir, "storage", "find_in_project.yaml"))
|
57
|
+
tab.edit_view.document.mirror = mirror
|
58
|
+
tab.edit_view.reset_undo
|
59
|
+
tab.focus
|
60
|
+
end
|
61
|
+
|
62
|
+
def open_file(file, line, query, literal_match, match_case)
|
63
|
+
Redcar::Project::Manager.open_file(File.expand_path(file, Redcar::Project::Manager.focussed_project.path))
|
64
|
+
doc.cursor_offset = doc.offset_at_line(line.to_i - 1)
|
65
|
+
regexp_text = literal_match ? Regexp.escape(query) : query
|
66
|
+
regex = match_case ? /(#{regexp_text})/ : /(#{regexp_text})/i
|
67
|
+
index = doc.get_line(line.to_i - 1).index(regex)
|
68
|
+
if index
|
69
|
+
length = doc.get_line(line.to_i - 1).match(regex)[1].length
|
70
|
+
doc.set_selection_range(doc.cursor_line_start_offset + index, doc.cursor_line_start_offset + index + length)
|
71
|
+
end
|
72
|
+
doc.scroll_to_line(line.to_i)
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
def close
|
77
|
+
Thread.kill(@thread) if @thread
|
78
|
+
@thread = nil
|
79
|
+
super
|
80
|
+
end
|
81
|
+
|
82
|
+
def render(view, bg=nil)
|
83
|
+
erb(view).result(bg || binding)
|
84
|
+
end
|
85
|
+
|
86
|
+
def render_file(bg)
|
87
|
+
@erb ||= erb("_file")
|
88
|
+
@erb.result(bg)
|
89
|
+
end
|
90
|
+
|
91
|
+
def erb(view)
|
92
|
+
ERB.new(File.read(File.join(File.dirname(__FILE__), "views", "#{view.to_s}.html.erb")))
|
93
|
+
end
|
94
|
+
|
95
|
+
def doc
|
96
|
+
Redcar.app.focussed_window.focussed_notebook_tab.edit_view.document rescue false
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_or_move_to_top(item, array)
|
100
|
+
return array if item.strip.empty?
|
101
|
+
array.delete_at(array.index(item)) if array.include?(item)
|
102
|
+
array.unshift(item)
|
103
|
+
end
|
104
|
+
|
105
|
+
def search(query, literal_match, match_case, with_context)
|
106
|
+
ProjectSearch.storage['recent_queries'] = add_or_move_to_top(query, ProjectSearch.storage['recent_queries'])
|
107
|
+
ProjectSearch.storage['match_case'] = (match_case == 'true')
|
108
|
+
ProjectSearch.storage['with_context'] = (with_context == 'true')
|
109
|
+
|
110
|
+
project = Redcar::Project::Manager.focussed_project
|
111
|
+
|
112
|
+
@word_search = WordSearch.new(project, query, match_case?, context_size)
|
113
|
+
|
114
|
+
# kill any existing running search to prevent memory bloat
|
115
|
+
Thread.kill(@thread) if @thread
|
116
|
+
@thread = nil
|
117
|
+
@thread = Thread.new do
|
118
|
+
begin
|
119
|
+
initialize_search_output
|
120
|
+
file_num = 0
|
121
|
+
line_num = 0
|
122
|
+
have_prepared_table = false
|
123
|
+
have_results = false
|
124
|
+
|
125
|
+
@word_search.on_file_results do |hits|
|
126
|
+
next unless hits.any?
|
127
|
+
have_results = true
|
128
|
+
file_num += 1
|
129
|
+
line_num += hits.length
|
130
|
+
set_file_count(file_num)
|
131
|
+
set_line_count(line_num)
|
132
|
+
file = hits.first.file
|
133
|
+
|
134
|
+
unless have_prepared_table
|
135
|
+
prepare_results_table
|
136
|
+
have_prepared_table = true
|
137
|
+
end
|
138
|
+
|
139
|
+
file_html = render_file(binding)
|
140
|
+
escaped_file_html = escape_javascript(file_html)
|
141
|
+
execute("$('#results table tr:last').after(\"#{escaped_file_html}\");")
|
142
|
+
end
|
143
|
+
|
144
|
+
@word_search.generate_results
|
145
|
+
|
146
|
+
if have_results
|
147
|
+
remove_initial_blank_tr
|
148
|
+
else
|
149
|
+
render_no_results
|
150
|
+
end
|
151
|
+
|
152
|
+
hide_spinner
|
153
|
+
Thread.kill(@thread) if @thread
|
154
|
+
@thread = nil
|
155
|
+
rescue => e
|
156
|
+
puts e.message
|
157
|
+
puts e.backtrace
|
158
|
+
end
|
159
|
+
end
|
160
|
+
nil
|
161
|
+
end
|
162
|
+
|
163
|
+
def initialize_search_output
|
164
|
+
execute("$('#cached_query').val(\"#{escape_javascript(@word_search.query_string)}\");")
|
165
|
+
execute("$('#results').html(\"<div id='no_results'>Searching...</div>\");")
|
166
|
+
execute("$('#spinner').show();")
|
167
|
+
execute("$('#results_summary').hide();")
|
168
|
+
execute("$('#file_results_count').html(0);")
|
169
|
+
execute("$('#line_results_count').html(0);")
|
170
|
+
end
|
171
|
+
|
172
|
+
def prepare_results_table
|
173
|
+
execute("if ($('#results table').size() == 0) { $('#results').html(\"<table><tr></tr></table>\"); }")
|
174
|
+
execute("if ($('#results_summary').first().is(':hidden')) { $('#results_summary').show(); }")
|
175
|
+
end
|
176
|
+
|
177
|
+
def set_file_count(value)
|
178
|
+
execute("$('#file_results_count').html(\"#{value}\");")
|
179
|
+
end
|
180
|
+
|
181
|
+
def set_line_count(value)
|
182
|
+
execute("$('#line_results_count').html(\"#{value}\");")
|
183
|
+
end
|
184
|
+
|
185
|
+
def remove_initial_blank_tr
|
186
|
+
execute("$('#results table tr:first').remove();")
|
187
|
+
end
|
188
|
+
|
189
|
+
def render_no_results
|
190
|
+
result = "<div id='no_results'>No results were found using the search terms you provided.</div>"
|
191
|
+
execute("$('#results').html(\"#{escape_javascript(result)}\");")
|
192
|
+
end
|
193
|
+
|
194
|
+
def hide_spinner
|
195
|
+
execute("$('#spinner').hide();")
|
196
|
+
end
|
197
|
+
|
198
|
+
def escape_javascript(text)
|
199
|
+
escape_map = { '\\' => '\\\\', '</' => '<\/', "\r\n" => '\n', "\n" => '\n', "\r" => '\n', '"' => '\\"', "'" => "\\'" }
|
200
|
+
text.to_s.gsub(/(\\|<\/|\r\n|[\n\r"'])/) { escape_map[$1] }
|
201
|
+
end
|
202
|
+
|
203
|
+
def image_path
|
204
|
+
File.expand_path(File.join(plugin_root, %w(lib project_search images)))
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|