chiark / gitweb /
doxygen: provide a more meaningful order for results.
authorVladimír Vondruš <mosra@centrum.cz>
Tue, 1 Jan 2019 21:10:38 +0000 (22:10 +0100)
committerVladimír Vondruš <mosra@centrum.cz>
Wed, 2 Jan 2019 21:07:11 +0000 (22:07 +0100)
Results of the same length are now ordered like this, instead of
appearing in whatever order they were added:

 * Deprecated and deleted symbols are put on the bottom
 * Then ordered by type:
   * First pages, since they usually provide most information
   * Then namespaces and groups
   * Then classes, structs, unions
   * Then functions
   * Then macros
   * Then enums
   * And enum values and variables last
 * After that, items with the shorter suffix (the least amount of
   function arguments) are preferred over longer
 * Finally, items with shorter prefix are preferred over longer (so e.g.
   it shows a Foo in the root namespace over Foo which is 5 levels deep)

This might get fine-tuned later, but I'm already very happy with the
result.

doxygen/dox2html5.py
doxygen/search.js
doxygen/test/test_search.py

index 020cc89dec5e7685a3979721bb626be712fbe6c5..c13036bef7a6b6d6f70bcf3a083da47b7286ff19 100755 (executable)
@@ -61,22 +61,24 @@ class ResultFlag(Flag):
     DEPRECATED = 1 << 1
     DELETED = 1 << 2
 
+    # Result type. Order defines order in which equally-named symbols appear in
+    # search results. Keep in sync with search.js.
     _TYPE = 0xf << 4
-    ALIAS = 0 << 4
-    NAMESPACE = 1 << 4
-    CLASS = 2 << 4
-    STRUCT = 3 << 4
-    UNION = 4 << 4
-    TYPEDEF = 5 << 4
-    FUNC = 6 << 4
-    VAR = 7 << 4
-    ENUM = 8 << 4
-    ENUM_VALUE = 9 << 4
-    DEFINE = 10 << 4
-    GROUP = 11 << 4
-    PAGE = 12 << 4
-    DIR = 13 << 4
-    FILE = 14 << 4
+    ALIAS = 0 << 4 # This one gets the type from the referenced result
+    PAGE = 1 << 4
+    NAMESPACE = 2 << 4
+    GROUP = 3 << 4
+    CLASS = 4 << 4
+    STRUCT = 5 << 4
+    UNION = 6 << 4
+    TYPEDEF = 7 << 4
+    DIR = 8 << 4
+    FILE = 9 << 4
+    FUNC = 10 << 4
+    DEFINE = 11 << 4
+    ENUM = 12 << 4
+    ENUM_VALUE = 13 << 4
+    VAR = 14 << 4
 
 class ResultMap:
     # item 1 flags | item 2 flags |     | item N flags | file | item 1 |
@@ -165,7 +167,7 @@ class ResultMap:
                     # Allow self-reference only when referenced result suffix
                     # is longer (otherwise cycles happen). This is for
                     # functions that should appear when searching for foo (so
-                    # they get ordered properly based on the name lenght) and
+                    # they get ordered properly based on the name length) and
                     # also when searching for foo() (so everything that's not
                     # a function gets filtered out). Such entries are
                     # completely the same except for a different suffix length.
@@ -292,6 +294,34 @@ class Trie:
     def insert(self, path: str, result, lookahead_barriers=[]):
         self._insert(path.encode('utf-8'), result, lookahead_barriers)
 
+    def _sort(self, key):
+        self.results.sort(key=key)
+        for _, child in self.children.items():
+            child[1]._sort(key)
+
+    def sort(self, result_map: ResultMap):
+        # What the shit, why can't I just take two elements and say which one
+        # is in front of which, this is awful
+        def key(item: int):
+            entry = result_map.entries[item]
+            return [
+                # First order based on deprecation/deletion status, deprecated
+                # always last, deleted in front of them, usable stuff on top
+                2 if entry.flags & ResultFlag.DEPRECATED else 1 if entry.flags & ResultFlag.DELETED else 0,
+
+                # Second order based on type (pages, then namespaces/classes,
+                # later functions, values last)
+                (entry.flags & ResultFlag._TYPE).value,
+
+                # Third on suffix length (shortest first)
+                entry.suffix_length,
+
+                # Lastly on prefix length (shortest first)
+                entry.prefix_length
+            ]
+
+        self._sort(key)
+
     # Returns offset of the serialized thing in `output`
     def _serialize(self, hashtable, output: bytearray, merge_subtrees) -> int:
         # Serialize all children first
@@ -2273,6 +2303,10 @@ def build_search_data(state: State, merge_subtrees=True, add_lookahead_barriers=
         # Add this symbol and all its aliases to total symbol count
         symbol_count += len(result.keywords) + 1
 
+    # For each node in the trie sort the results so the found items have sane
+    # order by default
+    trie.sort(map)
+
     return serialize_search_data(trie, map, symbol_count, merge_subtrees=merge_subtrees, merge_prefixes=merge_prefixes)
 
 def base85encode_search_data(data: bytearray) -> bytearray:
index f58d987bb89a9851e95490672a603cbf9caa00f0..c95260af2d32750a319d257976d9851cec9f8f52 100644 (file)
@@ -377,61 +377,62 @@ var Search = {
                 let type = '';
                 let color = '';
                 switch(results[i].flags >> 4) {
+                    /* Keep in sync with dox2html5.py */
                     case 1:
-                        type = 'namespace';
-                        color = 'm-primary';
+                        type = 'page';
+                        color = 'm-success';
                         break;
                     case 2:
-                        type = 'class';
+                        type = 'namespace';
                         color = 'm-primary';
                         break;
                     case 3:
-                        type = 'struct';
-                        color = 'm-primary';
+                        type = 'group';
+                        color = 'm-success';
                         break;
                     case 4:
-                        type = 'union';
+                        type = 'class';
                         color = 'm-primary';
                         break;
                     case 5:
-                        type = 'typedef';
+                        type = 'struct';
                         color = 'm-primary';
                         break;
                     case 6:
-                        type = 'func';
-                        color = 'm-info';
+                        type = 'union';
+                        color = 'm-primary';
                         break;
                     case 7:
-                        type = 'var';
-                        color = 'm-default';
+                        type = 'typedef';
+                        color = 'm-primary';
                         break;
                     case 8:
-                        type = 'enum';
-                        color = 'm-primary';
+                        type = 'dir';
+                        color = 'm-warning';
                         break;
                     case 9:
-                        type = 'enum val';
-                        color = 'm-default';
+                        type = 'file';
+                        color = 'm-warning';
                         break;
                     case 10:
-                        type = 'define';
+                        type = 'func';
                         color = 'm-info';
                         break;
                     case 11:
-                        type = 'group';
-                        color = 'm-success';
+                        type = 'define';
+                        color = 'm-info';
                         break;
                     case 12:
-                        type = 'page';
-                        color = 'm-success';
+                        type = 'enum';
+                        color = 'm-primary';
                         break;
                     case 13:
-                        type = 'dir';
-                        color = 'm-warning';
+                        type = 'enum val';
+                        color = 'm-default';
                         break;
                     case 14:
-                        type = 'file';
-                        color = 'm-warning';
+                        type = 'var';
+                        color = 'm-default';
                         break;
                 }
 
index 8a2aa6dbe6aa04d3955b11c830f20e77b30a46e0..e25c505b925001decc82d0294be8e6df52cfd15d 100755 (executable)
@@ -440,16 +440,16 @@ glmacro() [4]
 | struct() [56]
 | union() [60]
 file.h [9]
-|oo [11, 14, 16, 18]
+|oo [11, 14, 18, 16]
 || ($
-||  ) [12, 15, 17, 19]
+||  ) [12, 15, 19, 17]
 namespace [50]
 |        :$
 |         :class [20]
 |          |    :$
-|          |     :foo [11, 14, 16, 18]
+|          |     :foo [11, 14, 18, 16]
 |          |         ($
-|          |          ) [12, 15, 17, 19]
+|          |          ) [12, 15, 19, 17]
 |          enum [44]
 |          |   :$
 |          |    :onlyabrief [40]
@@ -460,10 +460,10 @@ namespace [50]
 |          union [59]
 class [20]
 |    :$
-|     :foo [11, 14, 16, 18]
+|     :foo [11, 14, 18, 16]
 |         ($
-|          ) [12, 15, 17, 19]
-a group [28, 29]
+|          ) [12, 15, 19, 17]
+a group [29, 28]
 | page [52]
 value [31, 41]
 | riable [48]