=== modified file 'src/Makefile.am' --- src/Makefile.am 2011-02-11 12:28:14 +0000 +++ src/Makefile.am 2011-03-07 09:14:59 +0000 @@ -51,8 +51,19 @@ utils.vala \ $(NULL) +unity_package_search_CPPFLAGS = \ + -DDATADIR=\"$(DATADIR)\" \ + -DPKGDATADIR=\"$(PKGDATADIR)\" \ + -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \ + -DG_LOG_DOMAIN=\"unity-applications-daemon\" \ + -DGMENU_I_KNOW_THIS_IS_UNSTABLE \ + $(unity_package_search_libs) \ + `pkg-config --cflags --libs glib-2.0 libgnome-menu unity` \ + -g + + unity-package-search.o : $(srcdir)/unity-package-search.cc $(srcdir)/unity-package-search.h - g++ -g $(unity_package_search_libs) -DGMENU_I_KNOW_THIS_IS_UNSTABLE `pkg-config --cflags --libs glib-2.0 libgnome-menu unity gee-1.0` -c $(srcdir)/unity-package-search.cc + g++ $(unity_package_search_CPPFLAGS) -c $(srcdir)/unity-package-search.cc unity_applications_daemon_SOURCES = \ $(unity_applications_daemon_VALASOURCES:.vala=.c) \ === modified file 'src/unity-package-search.cc' --- src/unity-package-search.cc 2011-03-06 15:24:13 +0000 +++ src/unity-package-search.cc 2011-03-07 09:50:37 +0000 @@ -32,6 +32,7 @@ #include #include #include +#include #define SOFTWARE_CENTER_INDEX "/var/cache/software-center/xapian" #define QUERY_PARSER_FLAGS Xapian::QueryParser::FLAG_BOOLEAN|Xapian::QueryParser::FLAG_PHRASE|Xapian::QueryParser::FLAG_LOVEHATE|Xapian::QueryParser::FLAG_WILDCARD|Xapian::QueryParser::FLAG_PARTIAL @@ -50,10 +51,13 @@ #include "unity-package-search.h" +const gchar *STOP_WORDS[] = {"a", "an", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "no", "not", "of", "on", "or", "s", "such", "t", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"}; + struct _UnityPackageSearcher { Xapian::Database *db; Xapian::KeyMaker *sorter; + Xapian::Stopper *stopper; Xapian::Enquire *enquire; Xapian::QueryParser *query_parser; }; @@ -83,31 +87,73 @@ } }; +// A stopword detector using the stopwords defined for the current locale +class LocaleStopper : public Xapian::Stopper +{ + private: + GHashTable *stopword_set; + + public: + LocaleStopper () + { + stopword_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + /* TRANSLATORS: This is a list of "stopwords" ie. words that are ignored when you search. Feel free to shrink or expand the list as fits for your language. Tokens must be separated with a semicolon and no whitespace. Notice that a search engine may, or may not, break a words like "Wilson's" into "wilson" and "s" - so to fix this for English we mark "s" and "t" as stopwords because they are the common letters for which this will happen. This is very much a fuzzy science :-) */ + const gchar *stopwords = _("a;an;and;are;as;at;be;but;by;for;if;in;into;is;it;no;not;of;on;or;s;such;t;that;the;their;then;there;these;they;this;to;was;will;with") ; + + gint i; + gchar **stopwordsa = g_strsplit (stopwords, ";", 0); + for (i = 0; stopwordsa[i] != NULL; i++) + { + g_debug ("STOP: %s", stopwordsa[i]); + g_hash_table_insert (stopword_set, g_strdup (stopwordsa[i]), NULL); + } + + g_strfreev (stopwordsa); + } + + virtual ~LocaleStopper() + { + g_hash_table_unref (stopword_set); + } + + virtual bool operator() (const std::string &term) const + { + g_debug ("TESTSTOP: %s %i", term.c_str(), g_hash_table_lookup_extended (stopword_set, term.c_str(), + NULL, NULL)); + return g_hash_table_lookup_extended (stopword_set, term.c_str(), + NULL, NULL); + } +}; + /* Do generic searcher setup */ static void init_searcher (UnityPackageSearcher *searcher) { - Xapian::Database db = *searcher->db; + Xapian::Database db = *searcher->db; // Start an enquire session Xapian::Enquire *enquire = new Xapian::Enquire (db); - //enquire->set_sort_by_value (XAPIAN_VALUE_APPNAME, FALSE); searcher->enquire = enquire; - // Make sure we respect sorting rules for the current locale + // Respect stopwords for the current locale + Xapian::Stopper *stopper = new LocaleStopper (); + searcher->stopper = stopper; + searcher->sorter = new LocaleKeyMaker (XAPIAN_VALUE_APPNAME); - enquire->set_sort_by_key (searcher->sorter, FALSE); - // Create query parser - Xapian::QueryParser *query_parser = new Xapian::QueryParser (); - query_parser->add_prefix ("section", "AE"); - query_parser->add_prefix ("type", "AT"); - query_parser->add_prefix ("category", "AC"); - query_parser->add_prefix ("name", "AA"); - query_parser->add_prefix ("pkgname", "AP"); - query_parser->set_default_op (Xapian::Query::OP_AND); - query_parser->set_database (db); - searcher->query_parser = query_parser; + // Create query parser + Xapian::QueryParser *query_parser = new Xapian::QueryParser (); + query_parser->add_prefix ("section", "AE"); + query_parser->add_prefix ("type", "AT"); + query_parser->add_prefix ("category", "AC"); + query_parser->add_prefix ("name", "AA"); + query_parser->add_prefix ("pkgname", "AP"); + query_parser->set_default_op (Xapian::Query::OP_AND); + query_parser->set_database (db); + query_parser->set_stemmer (Xapian::Stem()); + query_parser->set_stopper (stopper); + searcher->query_parser = query_parser; } /* Recursively traverse a menu tree and add it to the index */ @@ -252,6 +298,10 @@ /* Index the menu recursively */ Xapian::TermGenerator *indexer = new Xapian::TermGenerator (); + + /* We need to set a no-op stemmer in order to get Xapian to call the Stopper */ + indexer->set_stemmer (Xapian::Stem("english")); + indexer->set_stopper (searcher->stopper); index_menu_item (db, indexer, GMENU_TREE_ITEM (gmenu_tree_get_root_directory (menu))); delete indexer; @@ -288,6 +338,7 @@ delete searcher->db; delete searcher->sorter; + delete searcher->stopper; delete searcher->enquire; delete searcher->query_parser; g_free (searcher);