*/\r
private String getHighlightedFragment(Analyzer analyzer, Query query,\r
String content, SearchResult result) throws IOException, InvalidTokenOffsetsException {\r
- content = content == null ? "":StringUtils.escapeForHtml(content, false);\r
- \r
+ if (content == null) {\r
+ content = "";\r
+ } \r
+\r
+ int fragmentLength = SearchObjectType.commit == result.type ? 512 : 150;\r
+\r
QueryScorer scorer = new QueryScorer(query, "content");\r
- Fragmenter fragmenter;\r
- \r
- // TODO improve the fragmenter - hopefully on line breaks\r
- if (SearchObjectType.commit == result.type) {\r
- fragmenter = new SimpleSpanFragmenter(scorer, 1024); \r
- } else {\r
- fragmenter = new SimpleSpanFragmenter(scorer, 150);\r
- }\r
+ Fragmenter fragmenter = new SimpleSpanFragmenter(scorer, fragmentLength); \r
\r
// use an artificial delimiter for the token\r
String termTag = "<!--[";\r
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter(termTag, termTagEnd);\r
Highlighter highlighter = new Highlighter(formatter, scorer); \r
highlighter.setTextFragmenter(fragmenter);\r
- \r
+\r
String [] fragments = highlighter.getBestFragments(analyzer, "content", content, 3);\r
if (ArrayUtils.isEmpty(fragments)) {\r
if (SearchObjectType.blob == result.type) {\r
return "";\r
}\r
- return "<pre class=\"text\">" + content + "</pre>";\r
+ // clip commit message\r
+ String fragment = content;\r
+ if (fragment.length() > fragmentLength) {\r
+ fragment = fragment.substring(0, fragmentLength) + "...";\r
+ }\r
+ return "<pre class=\"text\">" + StringUtils.escapeForHtml(fragment, true) + "</pre>";\r
}\r
+ \r
+ int contentPos = 0;\r
StringBuilder sb = new StringBuilder();\r
for (int i = 0, len = fragments.length; i < len; i++) {\r
String fragment = fragments[i];\r
- \r
+ String tag = "<pre class=\"text\">";\r
+\r
// resurrect the raw fragment from removing the artificial delimiters\r
- String raw = fragment.replace(termTag, "").replace(termTagEnd, ""); \r
- sb.append(getPreTag(result, raw, content));\r
+ String raw = fragment.replace(termTag, "").replace(termTagEnd, "");\r
+\r
+ // determine position of the raw fragment in the content\r
+ int pos = content.indexOf(raw, contentPos);\r
+ \r
+ // restore complete first line of fragment\r
+ int c = pos;\r
+ while (c > 0) {\r
+ c--;\r
+ if (content.charAt(c) == '\n') {\r
+ break;\r
+ }\r
+ }\r
+ if (c > 0) {\r
+ // inject leading chunk of first fragment line\r
+ fragment = content.substring(c + 1, pos) + fragment;\r
+ }\r
+ \r
+ if (SearchObjectType.blob == result.type) {\r
+ // count lines as offset into the content for this fragment\r
+ int line = StringUtils.countLines(content.substring(0, pos));\r
+ \r
+ // create fragment tag with line number and language\r
+ String lang = "";\r
+ String ext = StringUtils.getFileExtension(result.path).toLowerCase();\r
+ if (!StringUtils.isEmpty(ext)) {\r
+ // maintain leading space!\r
+ lang = " lang-" + ext;\r
+ }\r
+ tag = MessageFormat.format("<pre class=\"prettyprint linenums:{0,number,0}{1}\">", line, lang);\r
+ \r
+ // update offset into content \r
+ contentPos = pos + raw.length() + 1;\r
+ }\r
\r
+ sb.append(tag);\r
+\r
// replace the artificial delimiter with html tags\r
String html = fragment.replace(termTag, "<span class=\"highlight\">").replace(termTagEnd, "</span>");\r
sb.append(html);\r
}\r
}\r
return sb.toString();\r
- }\r
- \r
- /**\r
- * Returns the appropriate tag for a fragment. Commit messages are visually\r
- * differentiated from blob fragments.\r
- * \r
- * @param result\r
- * @param fragment\r
- * @param content\r
- * @return an html tag appropriate for the fragment\r
- */\r
- private String getPreTag(SearchResult result, String fragment, String content) {\r
- String pre = "<pre class=\"text\">";\r
- if (SearchObjectType.blob == result.type) {\r
- int line = StringUtils.countLines(content.substring(0, content.indexOf(fragment))); \r
- int lastDot = result.path.lastIndexOf('.');\r
- if (lastDot > -1) {\r
- String ext = result.path.substring(lastDot + 1).toLowerCase();\r
- pre = MessageFormat.format("<pre class=\"prettyprint linenums:{0,number,0} lang-{1}\">", line, ext); \r
- } else {\r
- pre = MessageFormat.format("<pre class=\"prettyprint linenums:{0,number,0}\">", line);\r
- }\r
- }\r
- return pre;\r
- }\r
+ } \r
\r
/**\r
* Simple class to track the results of an index update. \r