From b4bbce4af5593486ce322bfaa55ef83f75a8b7a6 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Wed, 30 Sep 2020 21:56:37 +0200 Subject: [PATCH] [Helper] Add -normalize-match option. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decomposes string and remove accent characters before matching. This makes o match ö, é match e and more. It is not a perfect implementation but works. Currently disables the match highlighting. Fixes: #1119 --- config/config.c | 5 ++++- doc/rofi.1 | 8 ++++++++ doc/rofi.1.markdown | 6 ++++++ include/settings.h | 2 ++ source/helper.c | 50 +++++++++++++++++++++++++++++++++++++++++++-- source/xrmoptions.c | 2 ++ 6 files changed, 70 insertions(+), 3 deletions(-) diff --git a/config/config.c b/config/config.c index 05723e5a..111ec742 100644 --- a/config/config.c +++ b/config/config.c @@ -170,5 +170,8 @@ Settings config = { .drun_reload_desktop_cache = FALSE, /** Benchmarks */ - .benchmark_ui = FALSE + .benchmark_ui = FALSE, + + /** normalize match */ + .normalize_match = FALSE }; diff --git a/doc/rofi.1 b/doc/rofi.1 index 8edd8174..f527bffb 100644 --- a/doc/rofi.1 +++ b/doc/rofi.1 @@ -372,6 +372,14 @@ Default: *true* .fi .RE +.PP +\fB\fC\-normalize\-match\fR + +.PP +Normalize the string before matching, so o will match ö, and é matches e. +This is not a perfect implementation, but works. +For now it disabled highlighting of the matched part. + .PP \fB\fC\-no\-lazy\-grab\fR diff --git a/doc/rofi.1.markdown b/doc/rofi.1.markdown index 4325ce2b..3c287361 100644 --- a/doc/rofi.1.markdown +++ b/doc/rofi.1.markdown @@ -214,6 +214,12 @@ Show the indicator that shows what part of the string is matched. Default: *true* +`-normalize-match` + +Normalize the string before matching, so o will match ö, and é matches e. +This is not a perfect implementation, but works. +For now it disabled highlighting of the matched part. + `-no-lazy-grab` Disables lazy grab, this forces the keyboard being grabbed before gui is shown. diff --git a/include/settings.h b/include/settings.h index cecb9c34..491036b5 100644 --- a/include/settings.h +++ b/include/settings.h @@ -203,6 +203,8 @@ typedef struct /** Benchmark */ gboolean benchmark_ui; + + gboolean normalize_match; } Settings; /** Global Settings structure. */ extern Settings config; diff --git a/source/helper.c b/source/helper.c index a7bfa3e8..0a5e86ca 100644 --- a/source/helper.c +++ b/source/helper.c @@ -180,10 +180,43 @@ static gchar *fuzzy_to_regex ( const char * input ) return retv; } +static char *utf8_helper_simplify_string ( const char *s) +{ + gunichar buf2[G_UNICHAR_MAX_DECOMPOSITION_LENGTH] = {0,}; + char buf[6] = {0,}; + // Compose the string in maximally composed form. + char * str = g_malloc0((g_utf8_strlen(s,0)*6+2)); + char *striter = str; + for ( const char *iter = s; iter && *iter; iter = g_utf8_next_char ( iter )) { + gunichar uc = g_utf8_get_char ( iter ); + int l = 0; + gsize dl = g_unichar_fully_decompose ( uc, FALSE, buf2, G_UNICHAR_MAX_DECOMPOSITION_LENGTH) ; + if ( dl ) { + l = g_unichar_to_utf8 ( buf2[0], buf); + } else { + l = g_unichar_to_utf8 ( uc, buf); + } + memcpy(striter, buf, l); + striter+=l; + } + + return str; +} + // Macro for quickly generating regex for matching. static inline GRegex * R ( const char *s, int case_sensitive ) { + if ( config.normalize_match ) { + char *str = utf8_helper_simplify_string ( s ); + + GRegex *r = g_regex_new ( str, G_REGEX_OPTIMIZE | ( ( case_sensitive ) ? 0 : G_REGEX_CASELESS ), 0, NULL ); + + g_free ( str ); + return r; + } else { return g_regex_new ( s, G_REGEX_OPTIMIZE | ( ( case_sensitive ) ? 0 : G_REGEX_CASELESS ), 0, NULL ); + + } } static rofi_int_matcher * create_regex ( const char *input, int case_sensitive ) @@ -380,6 +413,10 @@ int find_arg_char ( const char * const key, char *val ) PangoAttrList *helper_token_match_get_pango_attr ( RofiHighlightColorStyle th, rofi_int_matcher**tokens, const char *input, PangoAttrList *retv ) { + // Disable highlighting for normalize match, not supported atm. + if ( config.normalize_match ) { + return retv; + } // Do a tokenized match. if ( tokens ) { for ( int j = 0; tokens[j]; j++ ) { @@ -453,10 +490,19 @@ int helper_token_match ( rofi_int_matcher* const *tokens, const char *input ) int match = TRUE; // Do a tokenized match. if ( tokens ) { + if ( config.normalize_match ) { + char *r = utf8_helper_simplify_string(input); for ( int j = 0; match && tokens[j]; j++ ) { - match = g_regex_match ( tokens[j]->regex, input, 0, NULL ); - match ^= tokens[j]->invert; + match = g_regex_match ( tokens[j]->regex, r, 0, NULL ); + match ^= tokens[j]->invert; } + g_free(r); + } else { + for ( int j = 0; match && tokens[j]; j++ ) { + match = g_regex_match ( tokens[j]->regex, input, 0, NULL ); + match ^= tokens[j]->invert; + } + } } return match; } diff --git a/source/xrmoptions.c b/source/xrmoptions.c index aff2ec9b..9e4289d0 100644 --- a/source/xrmoptions.c +++ b/source/xrmoptions.c @@ -231,6 +231,8 @@ static XrmOption xrmOptions[] = { "DRUN: build and use a cache with desktop file content.", CONFIG_DEFAULT }, { xrm_Boolean, "drun-reload-desktop-cache", { .snum = &config.drun_reload_desktop_cache }, NULL, "DRUN: If enabled, reload the cache with desktop file content.", CONFIG_DEFAULT }, + { xrm_Boolean, "normalize-match", { .snum = &config.normalize_match }, NULL, + "Normalize string when matching (implies -no-show-match).", CONFIG_DEFAULT }, }; /** Dynamic array of extra options */