+<% query_mark = c.searcher.query_to_mark(c.cur_query, 'content') %>
+
%for entry in c.formatted_results:
+
+ <%
+ file_content = entry['content_highlight'] or entry['content']
+ mimetype = entry.get('mimetype')
+ filepath = entry.get('path')
+ max_lines = h.safe_int(request.GET.get('max_lines', '10'))
+ line_context = h.safe_int(request.GET.get('line_contenxt', '3'))
+
+ match_file_url=h.route_path('repo_files',repo_name=entry['repository'], commit_id=entry.get('commit_id', 'tip'),f_path=entry['f_path'], _query={"mark": query_mark})
+ terms = c.cur_query
+
+ if c.searcher.is_es_6:
+ # use empty terms so we default to markers usage
+ total_lines, matching_lines = h.get_matching_line_offsets(file_content, terms=None)
+ else:
+ total_lines, matching_lines = h.get_matching_line_offsets(file_content, terms)
+
+ shown_matching_lines = 0
+ lines_of_interest = set()
+ for line_number in matching_lines:
+ if len(lines_of_interest) < max_lines:
+ lines_of_interest |= set(range(
+ max(line_number - line_context, 0),
+ min(line_number + line_context, total_lines + 1)))
+ shown_matching_lines += 1
+ lexer = h.get_lexer_safe(mimetype=mimetype, filepath=filepath)
+
+ html_formatter = h.SearchContentCodeHtmlFormatter(
+ linenos=True,
+ cssclass="code-highlight",
+ url=match_file_url,
+ query_terms=terms,
+ only_line_numbers=lines_of_interest
+ )
+
+ has_matched_content = len(lines_of_interest) >= 1
+
+ %>
## search results are additionally filtered, and this check is just a safe gate
% if h.HasRepoPermissionAny('repository.write','repository.read','repository.admin')(entry['repository'], 'search results content check'):
- ${highlight_text_file(c.cur_query, entry['content'],
- url=h.route_path('repo_files',repo_name=entry['repository'],commit_id=entry.get('commit_id', 'tip'),f_path=entry['f_path']),
- mimetype=entry.get('mimetype'), filepath=entry.get('path'))}
+
+ ${highlight_text_file(
+ has_matched_content=has_matched_content,
+ file_content=file_content,
+ lexer=lexer,
+ html_formatter=html_formatter,
+ matching_lines=matching_lines,
+ shown_matching_lines=shown_matching_lines,
+ url=match_file_url,
+ use_hl_filter=c.searcher.is_es_6
+ )}
+
% endif
%endfor
@@ -91,10 +138,14 @@ for line_number in matching_lines:
%if c.cur_query:
-%endif
\ No newline at end of file
+%endif
diff --git a/rhodecode/templates/search/search_path.mako b/rhodecode/templates/search/search_path.mako
--- a/rhodecode/templates/search/search_path.mako
+++ b/rhodecode/templates/search/search_path.mako
@@ -1,3 +1,5 @@
+% if c.formatted_results:
+
${_('Repository')} |
@@ -27,8 +29,10 @@
%endfor
-%if c.cur_query and c.formatted_results:
+%if c.cur_query:
-%endif
\ No newline at end of file
+%endif
+
+% endif
diff --git a/rhodecode/tests/lib/test_helpers.py b/rhodecode/tests/lib/test_helpers.py
--- a/rhodecode/tests/lib/test_helpers.py
+++ b/rhodecode/tests/lib/test_helpers.py
@@ -208,44 +208,3 @@ def test_get_visual_attr(baseapp):
def test_chop_at(test_text, inclusive, expected_text):
assert helpers.chop_at_smart(
test_text, '\n', inclusive, '...') == expected_text
-
-
-@pytest.mark.parametrize('test_text, expected_output', [
- ('some text', ['some', 'text']),
- ('some text', ['some', 'text']),
- ('some text "with a phrase"', ['some', 'text', 'with a phrase']),
- ('"a phrase" "another phrase"', ['a phrase', 'another phrase']),
- ('"justphrase"', ['justphrase']),
- ('""', []),
- ('', []),
- (' ', []),
- ('" "', []),
-])
-def test_extract_phrases(test_text, expected_output):
- assert helpers.extract_phrases(test_text) == expected_output
-
-
-@pytest.mark.parametrize('test_text, text_phrases, expected_output', [
- ('some text here', ['some', 'here'], [(0, 4), (10, 14)]),
- ('here here there', ['here'], [(0, 4), (5, 9), (11, 15)]),
- ('irrelevant', ['not found'], []),
- ('irrelevant', ['not found'], []),
-])
-def test_get_matching_offsets(test_text, text_phrases, expected_output):
- assert helpers.get_matching_offsets(
- test_text, text_phrases) == expected_output
-
-
-def test_normalize_text_for_matching():
- assert helpers.normalize_text_for_matching(
- 'OJjfe)*#$*@)$JF*)3r2f80h') == 'ojjfe jf 3r2f80h'
-
-
-def test_get_matching_line_offsets():
- assert helpers.get_matching_line_offsets([
- 'words words words',
- 'words words words',
- 'some text some',
- 'words words words',
- 'words words words',
- 'text here what'], 'text') == {3: [(5, 9)], 6: [(0, 4)]}
diff --git a/rhodecode/tests/lib/test_search_utils.py b/rhodecode/tests/lib/test_search_utils.py
new file mode 100644
--- /dev/null
+++ b/rhodecode/tests/lib/test_search_utils.py
@@ -0,0 +1,100 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2010-2018 RhodeCode GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License, version 3
+# (only), as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see
.
+#
+# This program is dual-licensed. If you wish to learn more about the
+# RhodeCode Enterprise Edition, including its added features, Support services,
+# and proprietary license terms, please see https://rhodecode.com/licenses/
+
+import copy
+import mock
+import pytest
+
+from rhodecode.lib.index import search_utils
+
+
+@pytest.mark.parametrize('test_text, expected_output', [
+ ('some text', ['some', 'text']),
+ ('some text', ['some', 'text']),
+ ('some text "with a phrase"', ['some', 'text', 'with a phrase']),
+ ('"a phrase" "another phrase"', ['a phrase', 'another phrase']),
+ ('"justphrase"', ['justphrase']),
+ ('""', []),
+ ('', []),
+ (' ', []),
+ ('" "', []),
+])
+def test_extract_phrases(test_text, expected_output):
+ assert search_utils.extract_phrases(test_text) == expected_output
+
+
+@pytest.mark.parametrize('test_text, text_phrases, expected_output', [
+ ('some text here', ['some', 'here'], [(0, 4), (10, 14)]),
+ ('here here there', ['here'], [(0, 4), (5, 9), (11, 15)]),
+ ('irrelevant', ['not found'], []),
+ ('irrelevant', ['not found'], []),
+])
+def test_get_matching_phrase_offsets(test_text, text_phrases, expected_output):
+ assert search_utils.get_matching_phrase_offsets(
+ test_text, text_phrases) == expected_output
+
+
+@pytest.mark.parametrize('test_text, text_phrases, expected_output', [
+ ('__RCSearchHLMarkBEG__some__RCSearchHLMarkEND__ text __RCSearchHLMarkBEG__here__RCSearchHLMarkEND__', [], [(0, 46), (52, 98)]),
+ ('__RCSearchHLMarkBEG__here__RCSearchHLMarkEND__ __RCSearchHLMarkBEG__here__RCSearchHLMarkEND__ there', [], [(0, 46), (47, 93)]),
+ ('some text __RCSearchHLMarkBEG__here__RCSearchHLMarkEND__', [], [(10, 56)]),
+ ('__RCSearchHLMarkBEG__here__RCSearchHLMarkEND__ __RCSearchHLMarkBEG__here__RCSearchHLMarkEND__ __RCSearchHLMarkBEG__there__RCSearchHLMarkEND__', [], [(0, 46), (47, 93), (94, 141)]),
+ ('irrelevant', ['not found'], []),
+ ('irrelevant', ['not found'], []),
+])
+def test_get_matching_marker_offsets(test_text, text_phrases, expected_output):
+
+ assert search_utils.get_matching_markers_offsets(test_text) == expected_output
+
+
+def test_normalize_text_for_matching():
+ assert search_utils.normalize_text_for_matching(
+ 'OJjfe)*#$*@)$JF*)3r2f80h') == 'ojjfe jf 3r2f80h'
+
+
+def test_get_matching_line_offsets():
+ words = '\n'.join([
+ 'words words words',
+ 'words words words',
+ 'some text some',
+ 'words words words',
+ 'words words words',
+ 'text here what'
+ ])
+ total_lines, matched_offsets = \
+ search_utils.get_matching_line_offsets(words, terms='text')
+ assert total_lines == 6
+ assert matched_offsets == {3: [(5, 9)], 6: [(0, 4)]}
+
+
+def test_get_matching_line_offsets_using_markers():
+ words = '\n'.join([
+ 'words words words',
+ 'words words words',
+ 'some __1__text__2__ some',
+ 'words words words',
+ 'words words words',
+ '__1__text__2__ here what'
+ ])
+ total_lines, matched_offsets = \
+ search_utils.get_matching_line_offsets(words, terms=None,
+ markers=['__1__(.*?)__2__'])
+ assert total_lines == 6
+ assert matched_offsets == {3: [(5, 19)], 6: [(0, 14)]}