Browse Source

Select non-perfect matches if necessary in the Search Help dialog

(cherry picked from commit 77597ea47cb6c5e7e0b9506cc8e8c305f0f59d9c)
Michael Alexsander 4 years ago
parent
commit
917630107c
2 changed files with 16 additions and 9 deletions
  1. 15 9
      editor/editor_help_search.cpp
  2. 1 0
      editor/editor_help_search.h

+ 15 - 9
editor/editor_help_search.cpp

@@ -127,7 +127,7 @@ void EditorHelpSearch::_notification(int p_what) {
 				if (search->work()) {
 					// Search done.
 
-					// Only point to the perfect match if it's a new search, and not just reopening a old one.
+					// Only point to the match if it's a new search, and not just reopening a old one.
 					if (!old_search)
 						results_tree->ensure_cursor_is_visible();
 					else
@@ -321,6 +321,7 @@ bool EditorHelpSearch::Runner::_phase_match_classes_init() {
 	iterator_doc = EditorHelp::get_doc_data()->class_list.front();
 	matches.clear();
 	matched_item = NULL;
+	match_highest_score = 0;
 
 	return true;
 }
@@ -444,15 +445,20 @@ bool EditorHelpSearch::Runner::_match_string(const String &p_term, const String
 }
 
 void EditorHelpSearch::Runner::_match_item(TreeItem *p_item, const String &p_text) {
+	float inverse_length = 1.f / float(p_text.length());
 
-	if (!matched_item) {
-		if (search_flags & SEARCH_CASE_SENSITIVE) {
-			if (p_text.casecmp_to(term) == 0)
-				matched_item = p_item;
-		} else {
-			if (p_text.nocasecmp_to(term) == 0)
-				matched_item = p_item;
-		}
+	// Favor types where search term is a substring close to the start of the type.
+	float w = 0.5f;
+	int pos = p_text.findn(term);
+	float score = (pos > -1) ? 1.0f - w * MIN(1, 3 * pos * inverse_length) : MAX(0.f, .9f - w);
+
+	// Favor shorter items: they resemble the search term more.
+	w = 0.1f;
+	score *= (1 - w) + w * (term.length() * inverse_length);
+
+	if (match_highest_score == 0 || score > match_highest_score) {
+		matched_item = p_item;
+		match_highest_score = score;
 	}
 }
 

+ 1 - 0
editor/editor_help_search.h

@@ -125,6 +125,7 @@ class EditorHelpSearch::Runner : public Reference {
 	TreeItem *root_item;
 	Map<String, TreeItem *> class_items;
 	TreeItem *matched_item;
+	float match_highest_score = 0;
 
 	bool _is_class_disabled_by_feature_profile(const StringName &p_class);