]> source.dussan.org Git - gitblit.git/commitdiff
A bunch more Lucene work
authorJames Moger <james.moger@gitblit.com>
Wed, 14 Mar 2012 20:31:28 +0000 (16:31 -0400)
committerJames Moger <james.moger@gitblit.com>
Wed, 14 Mar 2012 20:31:28 +0000 (16:31 -0400)
* Only list user-accessible repositories
* Syntax-highlight matched blob fragments
* Improve look and layout of search results

resources/gitblit.css
src/com/gitblit/utils/LuceneUtils.java
src/com/gitblit/utils/StringUtils.java
src/com/gitblit/wicket/pages/LucenePage.html
src/com/gitblit/wicket/pages/LucenePage.java

index 0e8e753204bf3bf7f1c1fbeb4ab5a027cfcdc02b..0701a7cf5ce5e48bd9c1a71df127606b0b01b238 100644 (file)
@@ -267,7 +267,7 @@ img.gravatar {
 }\r
 \r
 div.searchResult {\r
-       padding:5px;\r
+       padding: 10px 5px 10px 5px;\r
 }\r
 \r
 div.searchResult .summary {\r
@@ -300,18 +300,24 @@ div.searchResult .highlight {
        padding: 0 2px;\r
 }\r
 \r
-div.searchResult .ellipses {\r
-       font-family: sans-serif;\r
-       font-size: 9px;\r
-       font-weight: normal;    \r
-       background-color: #eee; \r
-       border: 1px solid #ccc;\r
-       padding: 0 3px;\r
-       margin: 0px;\r
+div.searchResult .ellipses {   \r
+       padding-left:25px;\r
+       color: #aaa;\r
 }\r
 \r
 div.searchResult pre {\r
        margin: 1px 0px;\r
+       border: 0px;\r
+}\r
+\r
+div.searchResult .text {\r
+       border-left: 5px solid #EEEEEE;\r
+       \r
+    padding: 0 0 0 15px;\r
+}\r
+\r
+div.searchResult ol {  \r
+       margin-bottom: 0px !important;\r
 }\r
 \r
 div.header, div.commitHeader, table.repositories th {\r
index 1c24f287ae312d31edfac2db72c0806500bf603c..ca1bbf1d3eec75b6a84436d67de543ea4eaaec16 100644 (file)
@@ -21,6 +21,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.File;\r
 import java.io.IOException;\r
 import java.io.InputStream;\r
+import java.text.MessageFormat;\r
 import java.text.ParseException;\r
 import java.util.ArrayList;\r
 import java.util.Arrays;\r
@@ -903,7 +904,8 @@ public class LuceneUtils {
                                Document doc = searcher.doc(docId);\r
                                SearchResult result = createSearchResult(doc, hits[i].score);\r
                                String content = doc.get(FIELD_CONTENT);\r
-                               result.fragment = getHighlightedFragment(analyzer, query, content);\r
+                               \r
+                               result.fragment = getHighlightedFragment(analyzer, query, content, result);\r
                                results.add(result);\r
                        }\r
                } catch (Exception e) {\r
@@ -913,28 +915,44 @@ public class LuceneUtils {
        }\r
        \r
        private static String getHighlightedFragment(Analyzer analyzer, Query query,\r
-                       String content) throws IOException, InvalidTokenOffsetsException {\r
-               content = content == null ? "":StringUtils.escapeForHtml(content, false);       \r
+                       String content, SearchResult result) throws IOException, InvalidTokenOffsetsException {\r
+               content = content == null ? "":StringUtils.escapeForHtml(content, false);\r
+               \r
                TokenStream stream = TokenSources.getTokenStream("content", content, analyzer);\r
                QueryScorer scorer = new QueryScorer(query, "content");\r
-               Fragmenter fragmenter = new SimpleSpanFragmenter(scorer, 150);\r
-\r
-               SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<span class=\"highlight\">", "</span>");\r
-               Highlighter highlighter = new Highlighter(formatter, scorer);\r
+               Fragmenter fragmenter;\r
                \r
+               if (ObjectType.commit == result.type) {\r
+                       fragmenter = new SimpleSpanFragmenter(scorer, 1024); \r
+               } else {\r
+                       fragmenter = new SimpleSpanFragmenter(scorer, 150);\r
+               }\r
+\r
+               // use an artificial delimiter for the token\r
+               String termTag = "<!--[";\r
+               String termTagEnd = "]-->";\r
+               SimpleHTMLFormatter formatter = new SimpleHTMLFormatter(termTag, termTagEnd);\r
+               Highlighter highlighter = new Highlighter(formatter, scorer);           \r
                highlighter.setTextFragmenter(fragmenter);\r
+               \r
                String [] fragments = highlighter.getBestFragments(stream, content, 5);\r
                if (ArrayUtils.isEmpty(fragments)) {\r
-                       return content;\r
-               }\r
-               if (fragments.length == 1) {\r
-                       return "<pre>" + fragments[0] + "</pre>";\r
+                       if (ObjectType.blob  == result.type) {\r
+                               return "";\r
+                       }\r
+                       return "<pre class=\"text\">" + content + "</pre>";\r
                }\r
                StringBuilder sb = new StringBuilder();\r
                for (int i = 0, len = fragments.length; i < len; i++) {\r
-                       String fragment = fragments[i].trim();                  \r
-                       sb.append("<pre>");\r
-                       sb.append(fragment);\r
+                       String fragment = fragments[i];\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
+                       \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
                        sb.append("</pre>");\r
                        if (i < len - 1) {\r
                                sb.append("<span class=\"ellipses\">...</span><br/>");\r
@@ -942,6 +960,21 @@ public class LuceneUtils {
                }\r
                return sb.toString();\r
        }\r
+       \r
+       private static String getPreTag(SearchResult result, String fragment, String content) {\r
+               String pre = "<pre class=\"text\">";\r
+               if (ObjectType.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
         * Close all the index writers and searchers\r
index a465e0d7e8068fd8c08102ec75f64a2b10e6a86a..adede1fa9dcd03dbbf345132ea3804b106cc140f 100644 (file)
@@ -485,4 +485,11 @@ public class StringUtils {
                }\r
                return value;\r
        }\r
+       \r
+       public static int countLines(String value) {\r
+               if (isEmpty(value)) {\r
+                       return 0;\r
+               }\r
+               return value.split("\n").length;\r
+       }\r
 }
\ No newline at end of file
index 0abe3d15bf0e998914e6bc6e295d1045c346fcfb..e6a9b932dbddc1411feca5d7610f75a05a4cc5b2 100644 (file)
@@ -3,8 +3,17 @@
       xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  \r
       xml:lang="en"  \r
       lang="en"> \r
-<body onload="document.getElementById('fragment').focus();">\r
+\r
+<!-- contribute google-code-prettify resources to the page header -->\r
+<wicket:head>\r
+  <wicket:link>\r
+       <link href="prettify/prettify.css" type="text/css" rel="stylesheet" />\r
+       <script type="text/javascript" src="prettify/prettify.js"></script>\r
+  </wicket:link>\r
+</wicket:head>\r
+      \r
 <wicket:extend>\r
+<body onload="document.getElementById('query').focus(); prettyPrint();">\r
        <div class="pageTitle">\r
                <h2><wicket:message key="gb.search"></wicket:message></h2>\r
        </div>\r
@@ -17,7 +26,7 @@
                        <div class="span9">\r
                                <div>\r
                                        <h3><wicket:message key="gb.query"></wicket:message></h3>\r
-                                       <input class="span8" wicket:id="query" placeholder="enter search text"></input>\r
+                                       <input class="span8" id="query" wicket:id="query" placeholder="enter search text"></input>\r
                                        <button class="btn btn-primary" type="submit" value="Search"><wicket:message key="gb.search"></wicket:message></button>\r
                                </div>\r
                                <div style="margin-top:10px;">\r
                <div><i wicket:id="type"></i><span class="summary" wicket:id="summary"></span></div>\r
                <div class="body">\r
                        <div class="fragment" wicket:id="fragment"></div>\r
-                       <span class="author" wicket:id="author"></span> committed to <span class="repository" wicket:id="repository"></span>:<span class="branch" wicket:id="branch"></span><br/>\r
-                       <span class="date" wicket:id="date"></span>\r
-                       <hr/>\r
+                       <div><span class="author" wicket:id="author"></span> <span class="date" ><wicket:message key="gb.authored"></wicket:message> <span class="date" wicket:id="date"></span></span></div>\r
+                       <span class="repository" wicket:id="repository"></span>:<span class="branch" wicket:id="branch"></span>                 \r
                </div>\r
        </div>\r
        </div>\r
-</wicket:extend>\r
 </body>\r
+</wicket:extend>\r
 </html>
\ No newline at end of file
index dc740125e025c4b88ebffb80d32da3b565ee42f8..39d33b34f1681782406ff2de14062b7d0f8da4bb 100644 (file)
@@ -32,10 +32,14 @@ import org.eclipse.jgit.lib.Repository;
 \r
 import com.gitblit.Constants.SearchType;\r
 import com.gitblit.GitBlit;\r
+import com.gitblit.models.RepositoryModel;\r
 import com.gitblit.models.SearchResult;\r
+import com.gitblit.models.UserModel;\r
 import com.gitblit.utils.ArrayUtils;\r
 import com.gitblit.utils.LuceneUtils;\r
 import com.gitblit.utils.StringUtils;\r
+import com.gitblit.wicket.GitBlitWebSession;\r
+import com.gitblit.wicket.StringChoiceRenderer;\r
 import com.gitblit.wicket.WicketUtils;\r
 import com.gitblit.wicket.panels.LinkPanel;\r
 \r
@@ -110,7 +114,14 @@ public class LucenePage extends RootPage {
                                setResponsePage(LucenePage.class, params);\r
                        }\r
                };\r
-               ListMultipleChoice<String> selections = new ListMultipleChoice<String>("repositories", repositoriesModel, GitBlit.self().getRepositoryList());\r
+               \r
+               UserModel user = GitBlitWebSession.get().getUser();\r
+               List<String> availableRepositories = new ArrayList<String>();\r
+               for (RepositoryModel model : GitBlit.self().getRepositoryModels(user)) {\r
+                       availableRepositories.add(model.name);\r
+               }\r
+               ListMultipleChoice<String> selections = new ListMultipleChoice<String>("repositories", \r
+                               repositoriesModel, availableRepositories, new StringChoiceRenderer());\r
                selections.setMaxRows(10);\r
                form.add(selections);\r
                form.add(new TextField<String>("query", queryModel));\r
@@ -153,7 +164,7 @@ public class LucenePage extends RootPage {
                                item.add(new LinkPanel("repository", null, sr.repository, SummaryPage.class, WicketUtils.newRepositoryParameter(sr.repository)));\r
                                item.add(new LinkPanel("branch", "branch", StringUtils.getRelativePath(Constants.R_HEADS, sr.branch), LogPage.class, WicketUtils.newObjectParameter(sr.repository, sr.branch)));\r
                                item.add(new Label("author", sr.author));\r
-                               item.add(WicketUtils.createTimestampLabel("date", sr.date, getTimeZone()));\r
+                               item.add(WicketUtils.createDatestampLabel("date", sr.date, getTimeZone()));\r
                        }\r
                };\r
                add(resultsView.setVisible(results.size() > 0));\r