[geany/geany-plugins] cb1f5a: commander: Switch to a better sort algorithm
Jonathan Michalon
git-noreply at xxxxx
Sat Aug 4 15:08:40 UTC 2012
Branch: refs/heads/master
Author: Jonathan Michalon <jonathan at michalon.eu>
Committer: Colomban Wendling <ban at herbesfolles.org>
Date: Sat, 04 Aug 2012 15:08:40
Commit: cb1f5acfe4d8e1d2c26f62d36f66b7fbc7ee7813
https://github.com/geany/geany-plugins/commit/cb1f5acfe4d8e1d2c26f62d36f66b7fbc7ee7813
Log Message:
-----------
commander: Switch to a better sort algorithm
Modified Paths:
--------------
commander/src/commander-plugin.c
Modified: commander/src/commander-plugin.c
97 files changed, 48 insertions(+), 49 deletions(-)
===================================================================
@@ -78,56 +78,55 @@ enum {
};
-/* TODO: improve this algorithm for better matches.
- * what's needed is probably not to simply eat a letter when it matches, but
- * rather give it a chance to provide an heavier match... whatever, be smart. */
+#define SEPARATORS " -_/\\\"'"
+#define IS_SEPARATOR(c) (strchr (SEPARATORS, (c)))
+#define next_separator(p) (strpbrk (p, SEPARATORS))
+
+/* TODO: be more tolerant regarding unmatched character in the needle.
+ * Right now, we implicitly accept unmatched characters at the end of the
+ * needle but absolutely not at the start. e.g. "xpy" won't match "python" at
+ * all, though "pyx" will. */
+static inline gint
+get_score (const gchar *needle,
+ const gchar *haystack)
+{
+ if (needle == NULL || haystack == NULL ||
+ *needle == '\0' || *haystack == '\0') {
+ return 0;
+ }
+
+ if (IS_SEPARATOR (*haystack)) {
+ return get_score (needle, haystack + 1);
+ }
+
+ if (IS_SEPARATOR (*needle)) {
+ return get_score (needle + 1, next_separator (haystack));
+ }
+
+ if (*needle == *haystack) {
+ gint a = get_score (needle + 1, haystack + 1) + 1;
+ gint b = get_score (needle, next_separator (haystack));
+
+ return MAX (a, b);
+ } else {
+ return get_score (needle, next_separator (haystack));
+ }
+}
+
static gint
-key_dist (const gchar *key_,
- const gchar *text_)
+key_score (const gchar *key_,
+ const gchar *text_)
{
gchar *text = g_utf8_casefold (text_, -1);
gchar *key = g_utf8_casefold (key_, -1);
- gint dist = 0;
-
-#if 0
- const gchar *text_p = text;
- const gchar *key_p = key;
- gint weight = 0;
-
- while (*key_p && *text_p) {
- if (*text_p == *key_p) {
- text_p ++;
- key_p ++;
- weight ++;
- dist -= weight * 2;
- } else {
- text_p ++;
- dist ++;
- weight = 0;
- }
-#else /* rather search end to start because end of paths are more interesting */
- const gchar *text_p = text + strlen (text) - 1;
- const gchar *key_p = key + strlen (key) - 1;
- gint weight = 0;
-
- while (key_p >= key && text_p >= text) {
- if (*text_p == *key_p) {
- text_p --;
- key_p --;
- weight ++;
- dist -= weight * 2;
- } else {
- text_p --;
- dist ++;
- weight = 0;
- }
- }
-#endif
+ gint score;
+
+ score = get_score (key, text);
g_free (text);
g_free (key);
- return dist;
+ return score;
}
static const gchar *
@@ -364,8 +363,8 @@ enum {
GtkTreeIter *b,
gpointer dummy)
{
- gint dista;
- gint distb;
+ gint scorea;
+ gint scoreb;
gchar *patha;
gchar *pathb;
gint typea;
@@ -376,20 +375,20 @@ enum {
gtk_tree_model_get (model, a, COL_PATH, &patha, COL_TYPE, &typea, -1);
gtk_tree_model_get (model, b, COL_PATH, &pathb, COL_TYPE, &typeb, -1);
- dista = key_dist (key, patha);
- distb = key_dist (key, pathb);
+ scorea = key_score (key, patha);
+ scoreb = key_score (key, pathb);
if (! (typea & type)) {
- dista += 0xf000;
+ scorea -= 0xf000;
}
if (! (typeb & type)) {
- distb += 0xf000;
+ scoreb -= 0xf000;
}
g_free (patha);
g_free (pathb);
- return dista - distb;
+ return scoreb - scorea;
}
static gboolean
@@ Diff output truncated at 100000 characters. @@
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: TBD).
More information about the Plugins-Commits
mailing list