Hi all! [ I'm not subscribed to this list so please CC me on your replies. ]
This patch adds an option to use either substring match, regular expression match, or keywords search in the "make xconfig" Edit->Find dialog. It also allows searching on the "help" field of the menus as well as the "name" of the symbol. This change involved adding the sym_generic_search function to the LKC, and implementing sym_re_search using it. Regards, Shlomi Fish --- linux-2.6.23-rc4/scripts/kconfig/qconf.cc.orig 2007-09-01 21:15:39.017466409 +0300 +++ linux-2.6.23-rc4/scripts/kconfig/qconf.cc 2007-09-08 11:29:31.357869409 +0300 @@ -1199,6 +1199,23 @@ layout2->addWidget(searchButton); layout1->addLayout(layout2); + // Initialize the "Search Type" button group. + searchType = new QVButtonGroup("Search Type", this, "searchType"); + + substringSearch = new QRadioButton( + "Substring Match", searchType, "Substring Match" + ); + + keywordsSearch = new QRadioButton("Keywords", searchType, "Keywords"); + + regexSearch = new QRadioButton( + "Regular Expression", searchType, "Regular Expression" + ); + + substringSearch->setChecked(TRUE); + layout1->addWidget(searchType); + + // Initialize the ConfigView and ConfigInfoView split = new QSplitter(this); split->setOrientation(QSplitter::Vertical); list = new ConfigView(split, name); @@ -1245,6 +1262,20 @@ } } +SEARCH_TYPE ConfigSearchWindow::getSearchType() +{ + return substringSearch->isChecked() ? SUBSTRING : + regexSearch->isChecked() ? REGEX : + KEYWORDS; +} + + +static int search_filter(struct symbol *sym, void *context) +{ + FindQuery *query = (FindQuery *)context; + return query->sym_matches(sym); +} + void ConfigSearchWindow::search(void) { struct symbol **p; @@ -1255,7 +1286,9 @@ list->list->clear(); info->clear(); - result = sym_re_search(editField->text().latin1()); + FindQuery query(editField->text(), getSearchType()); + + result = sym_generic_search(search_filter, (void *)&query); if (!result) return; for (p = result; *p; p++) { @@ -1265,6 +1298,114 @@ } } +FindQuery::FindQuery(QString q, SEARCH_TYPE t, bool a_case) : + query(q), search_type(t), case_sensitive(a_case) +{ + compiled_regex = NULL; + if (search_type == REGEX) + { + compiled_regex = new QRegExp(query, case_sensitive); + } + else if (search_type == KEYWORDS) + { + compile_keywords(); + } +} + +void FindQuery::compile_keywords() +{ + QRegExp split_words("\\s+"); + QStringList bare_words = QStringList::split(split_words, query); + + QStringList::iterator it; + for ( it = bare_words.begin(); it != bare_words.end(); ++it ) + { + QString escaped = QRegExp::escape(*it); + + keywords.append(QRegExp(QString("\\b") + escaped + "\\b")); + } +} + +FindQuery::~FindQuery() +{ + if (compiled_regex) + { + delete compiled_regex; + compiled_regex = NULL; + } +} + +bool FindQuery::string_matches_regex(QRegExp & re, const char *string) +{ + QString qs(string); + + return (re.search(qs) >= 0); +} + +bool FindQuery::string_matches(const char *string) +{ + QString qs(string); + + if (search_type == SUBSTRING) + { + return qs.contains(query, case_sensitive); + } + else if (search_type == REGEX) + { + return string_matches_regex(*compiled_regex, string); + } + else + { + return false; + } +} + +bool FindQuery::sym_matches(struct symbol *sym) +{ + if (!sym) + { + return false; + } + + if (search_type == KEYWORDS) + { + return sym_matches_keywords(sym); + } + else + { + return sym_matches_atom(sym); + } + +} + +bool FindQuery::sym_matches_atom(struct symbol *sym) +{ + return (string_matches(sym->name) || + (sym->prop && + sym->prop->menu && + string_matches(sym->prop->menu->help) + )); +} + +bool FindQuery::sym_matches_keywords(struct symbol *sym) +{ + QValueList<QRegExp>::iterator it; + + for ( it = keywords.begin(); it != keywords.end(); ++it ) + { + if (!(string_matches_regex(*it, sym->name) + || + (sym->prop && + sym->prop->menu && + string_matches_regex(*it, sym->prop->menu->help)))) + { + return false; + } + } + + return true; +} + /* * Construct the complete config widget */ --- linux-2.6.23-rc4/scripts/kconfig/qconf.h.orig 2007-09-01 21:15:33.537030610 +0300 +++ linux-2.6.23-rc4/scripts/kconfig/qconf.h 2007-09-08 11:12:18.015699416 +0300 @@ -4,6 +4,8 @@ */ #include <qlistview.h> +#include <qradiobutton.h> +#include <qvbuttongroup.h> #if QT_VERSION >= 300 #include <qsettings.h> #else @@ -275,6 +277,7 @@ bool _showDebug; }; +enum SEARCH_TYPE { SUBSTRING, KEYWORDS, REGEX }; class ConfigSearchWindow : public QDialog { Q_OBJECT typedef class QDialog Parent; @@ -288,11 +291,15 @@ protected: QLineEdit* editField; QPushButton* searchButton; + QVButtonGroup *searchType; + QRadioButton *substringSearch, *keywordsSearch, *regexSearch; QSplitter* split; ConfigView* list; ConfigInfoView* info; struct symbol **result; + + SEARCH_TYPE getSearchType(); }; class ConfigMainWindow : public QMainWindow { @@ -332,3 +339,25 @@ QSplitter* split1; QSplitter* split2; }; + +class FindQuery +{ + public: + bool case_sensitive; + SEARCH_TYPE search_type; + QString query; + QRegExp * compiled_regex; + QValueList<QRegExp> keywords; + + public: + FindQuery() : query("") { case_sensitive = false; search_type = SUBSTRING; } + FindQuery(QString q, SEARCH_TYPE t, bool a_case = false); + ~FindQuery(); + void compile_keywords(); + bool string_matches(const char *); + bool string_matches_regex(QRegExp & re, const char *string); + bool sym_matches(struct symbol *sym); + bool sym_matches_keywords(struct symbol *sym); + bool sym_matches_atom(struct symbol *sym); +}; + --- linux-2.6.23-rc4/scripts/kconfig/lkc.h.orig 2007-09-01 19:56:36.528350007 +0300 +++ linux-2.6.23-rc4/scripts/kconfig/lkc.h 2007-09-01 19:57:57.758809341 +0300 @@ -111,6 +111,9 @@ struct property *prop_alloc(enum prop_type type, struct symbol *sym); struct symbol *prop_get_symbol(struct property *prop); +typedef int (*sym_search_filter_t)(struct symbol *sym, void *context); +struct symbol **sym_generic_search(sym_search_filter_t filter, void *context); + static inline tristate sym_get_tristate_value(struct symbol *sym) { return sym->curr.tri; --- linux-2.6.23-rc4/scripts/kconfig/symbol.c.orig 2007-09-01 21:24:07.885930947 +0300 +++ linux-2.6.23-rc4/scripts/kconfig/symbol.c 2007-09-01 20:41:58.420791258 +0300 @@ -717,23 +717,39 @@ return symbol; } +static int re_search_filter(struct symbol *sym, void *re_void) +{ + return (regexec((regex_t*)re_void, sym->name, 0, NULL, 0) == 0); +} + struct symbol **sym_re_search(const char *pattern) { - struct symbol *sym, **sym_arr = NULL; - int i, cnt, size; regex_t re; + struct symbol **results; - cnt = size = 0; - /* Skip if empty */ if (strlen(pattern) == 0) return NULL; if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) return NULL; + results = sym_generic_search(re_search_filter, (void *)&re); + + regfree(&re); + + return results; +} + +struct symbol **sym_generic_search(sym_search_filter_t filter, void *context) +{ + struct symbol *sym, **sym_arr = NULL; + int i, cnt, size; + + cnt = size = 0; + for_all_symbols(i, sym) { if (sym->flags & SYMBOL_CONST || !sym->name) continue; - if (regexec(&re, sym->name, 0, NULL, 0)) + if (!filter(sym, context)) continue; if (cnt + 1 >= size) { void *tmp = sym_arr; @@ -748,7 +764,6 @@ } if (sym_arr) sym_arr[cnt] = NULL; - regfree(&re); return sym_arr; } --------------------------------------------------------------------- Shlomi Fish [EMAIL PROTECTED] Homepage: http://www.shlomifish.org/ If it's not in my E-mail it doesn't happen. And if my E-mail is saying one thing, and everything else says something else - E-mail will conquer. -- An Israeli Linuxer -- --------------------------------------------------------------------- Shlomi Fish [EMAIL PROTECTED] Homepage: http://www.shlomifish.org/ If it's not in my E-mail it doesn't happen. And if my E-mail is saying one thing, and everything else says something else - E-mail will conquer. -- An Israeli Linuxer - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/