1
0
Fork 0
mirror of https://github.com/davatorium/rofi.git synced 2024-11-25 13:55:34 -05:00

[Helper] Add -normalize-match option.

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
This commit is contained in:
Dave Davenport 2020-09-30 21:56:37 +02:00
parent 96c7ab0fff
commit b4bbce4af5
6 changed files with 70 additions and 3 deletions

View file

@ -170,5 +170,8 @@ Settings config = {
.drun_reload_desktop_cache = FALSE, .drun_reload_desktop_cache = FALSE,
/** Benchmarks */ /** Benchmarks */
.benchmark_ui = FALSE .benchmark_ui = FALSE,
/** normalize match */
.normalize_match = FALSE
}; };

View file

@ -372,6 +372,14 @@ Default: *true*
.fi .fi
.RE .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 .PP
\fB\fC\-no\-lazy\-grab\fR \fB\fC\-no\-lazy\-grab\fR

View file

@ -214,6 +214,12 @@ Show the indicator that shows what part of the string is matched.
Default: *true* 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` `-no-lazy-grab`
Disables lazy grab, this forces the keyboard being grabbed before gui is shown. Disables lazy grab, this forces the keyboard being grabbed before gui is shown.

View file

@ -203,6 +203,8 @@ typedef struct
/** Benchmark */ /** Benchmark */
gboolean benchmark_ui; gboolean benchmark_ui;
gboolean normalize_match;
} Settings; } Settings;
/** Global Settings structure. */ /** Global Settings structure. */
extern Settings config; extern Settings config;

View file

@ -180,10 +180,43 @@ static gchar *fuzzy_to_regex ( const char * input )
return retv; 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. // Macro for quickly generating regex for matching.
static inline GRegex * R ( const char *s, int case_sensitive ) 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 ); 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 ) 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 ) 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. // Do a tokenized match.
if ( tokens ) { if ( tokens ) {
for ( int j = 0; tokens[j]; j++ ) { for ( int j = 0; tokens[j]; j++ ) {
@ -453,11 +490,20 @@ int helper_token_match ( rofi_int_matcher* const *tokens, const char *input )
int match = TRUE; int match = TRUE;
// Do a tokenized match. // Do a tokenized match.
if ( tokens ) { 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, r, 0, NULL );
match ^= tokens[j]->invert;
}
g_free(r);
} else {
for ( int j = 0; match && tokens[j]; j++ ) { for ( int j = 0; match && tokens[j]; j++ ) {
match = g_regex_match ( tokens[j]->regex, input, 0, NULL ); match = g_regex_match ( tokens[j]->regex, input, 0, NULL );
match ^= tokens[j]->invert; match ^= tokens[j]->invert;
} }
} }
}
return match; return match;
} }

View file

@ -231,6 +231,8 @@ static XrmOption xrmOptions[] = {
"DRUN: build and use a cache with desktop file content.", CONFIG_DEFAULT }, "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, { 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 }, "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 */ /** Dynamic array of extra options */