1
0
Fork 0
mirror of https://github.com/davatorium/rofi.git synced 2024-11-18 13:54:36 -05:00

Go Regex Go

This commit is contained in:
Dave Davenport 2016-05-21 10:37:23 +02:00
parent 2a20821ddd
commit 8091558ed8
6 changed files with 74 additions and 168 deletions

View file

@ -67,7 +67,7 @@ Settings config = {
/** Command executed when running application in terminal */
.run_shell_command = "{terminal} -e {cmd}",
/** Command executed on accep-entry-custom for window modus */
.window_command = "xkill -id {window}",
.window_command = "xkill -id {window}",
/**
* Location of the window.
* Enumeration indicating location or gravity of window.

View file

@ -24,18 +24,6 @@
*/
int helper_parse_setup ( char * string, char ***output, int *length, ... );
/**
* @param token The string for which we want a collation key.
* @param case_sensitive Whether case is significant.
*
* Get a collation key for @p token. @p token must be a null-terminated string.
* This collation key can be used for matching the user input against the list
* of commands, windows, or ssh commands.
*
* @returns A newly allocated string containing the collation key.
*/
char *token_collate_key ( const char *token, int case_sensitive );
/**
* @param input The input string.
* @param case_sensitive Whether case is significant.
@ -172,6 +160,6 @@ unsigned int levenshtein ( const char *needle, const char *haystack );
*/
char * rofi_force_utf8 ( gchar *data );
char * rofi_latin_to_utf8_strdup ( const char *input, gssize length );
PangoAttrList *regex_token_match_get_pango_attr ( char **tokens, const char *input, PangoAttrList *retv );
PangoAttrList *token_match_get_pango_attr ( char **tokens, const char *input, PangoAttrList *retv );
/*@}*/
#endif // ROFI_HELPER_H

View file

@ -39,15 +39,15 @@ typedef struct
typedef enum
{
TB_AUTOHEIGHT = 1 << 0,
TB_AUTOWIDTH = 1 << 1,
TB_LEFT = 1 << 16,
TB_RIGHT = 1 << 17,
TB_CENTER = 1 << 18,
TB_EDITABLE = 1 << 19,
TB_MARKUP = 1 << 20,
TB_WRAP = 1 << 21,
TB_PASSWORD = 1 << 22,
TB_AUTOHEIGHT = 1 << 0,
TB_AUTOWIDTH = 1 << 1,
TB_LEFT = 1 << 16,
TB_RIGHT = 1 << 17,
TB_CENTER = 1 << 18,
TB_EDITABLE = 1 << 19,
TB_MARKUP = 1 << 20,
TB_WRAP = 1 << 21,
TB_PASSWORD = 1 << 22,
} TextboxFlags;
typedef enum

View file

@ -534,7 +534,7 @@ static inline int act_on_window ( xcb_window_t window )
int argc = 0;
char window_str[100]; /* We are probably safe here */
g_snprintf(window_str, sizeof window_str, "%d", window);
g_snprintf ( window_str, sizeof window_str, "%d", window );
helper_parse_setup ( config.window_command, &args, &argc, "{window}", window_str, NULL );

View file

@ -136,70 +136,75 @@ int helper_parse_setup ( char * string, char ***output, int *length, ... )
return FALSE;
}
char *token_collate_key ( const char *token, int case_sensitive )
{
char *tmp, *compk;
if ( case_sensitive ) {
tmp = g_strdup ( token );
}
else {
tmp = g_utf8_casefold ( token, -1 );
}
compk = g_utf8_normalize ( tmp, -1, G_NORMALIZE_ALL );
g_free ( tmp );
return compk;
}
void tokenize_free ( char ** tokens )
{
if ( config.glob ) {
for ( size_t i = 0; tokens && tokens[i]; i++ ) {
g_pattern_spec_free ( (GPatternSpec *) tokens[i] );
for ( size_t i = 0; tokens && tokens[i]; i++ ) {
g_regex_unref ( (GRegex *) tokens[i] );
}
g_free ( tokens );
}
static gchar *glob_to_regex ( const char *input )
{
gchar *r = g_regex_escape_string ( input, -1 );
size_t str_l = strlen ( r );
for ( size_t i = 0; i < str_l; i++ ) {
if ( r[i] == '\\' ) {
if ( r[i + 1] == '*' ) {
r[i] = '.';
}
else if ( r[i + 1] == '?' ) {
r[i + 1] = 'S';
}
i++;
}
g_free ( tokens );
}
return r;
}
static GRegex * create_regex ( const char *input, int case_sensitive )
{
#define R( s ) g_regex_new ( s, G_REGEX_OPTIMIZE | ( ( case_sensitive ) ? 0 : G_REGEX_CASELESS ), G_REGEX_MATCH_PARTIAL, NULL )
GRegex *retv = NULL;
if ( config.glob ) {
gchar *r = glob_to_regex ( input );
retv = R ( r );
g_free ( r );
}
else if ( config.regex ) {
for ( size_t i = 0; tokens && tokens[i]; i++ ) {
g_regex_unref ( (GRegex *) tokens[i] );
retv = R ( input );
if ( retv == NULL ) {
gchar *r = g_regex_escape_string ( input, -1 );
retv = R ( r );
g_free ( r );
}
g_free ( tokens );
}
else {
g_strfreev ( tokens );
else if ( config.fuzzy ) {
gchar *r = g_regex_escape_string ( input, -1 );
// TODO either strip fuzzy, or fix this pattern.
gchar *str = g_strdup_printf ( "[%s]+", r );
retv = R ( str );
g_free ( r );
g_free ( str );
}
else{
// TODO; regex should be default?
gchar *r = g_regex_escape_string ( input, -1 );
retv = R ( r );
g_free ( r );
}
return retv;
}
char **tokenize ( const char *input, int case_sensitive )
{
if ( input == NULL ) {
if ( input == NULL || strlen(input) == 0 ) {
return NULL;
}
char *saveptr = NULL, *token;
char **retv = NULL;
if ( !config.tokenize ) {
retv = g_malloc0 ( sizeof ( char* ) * 2 );
if ( config.glob ) {
token = g_strdup_printf ( "*%s*", input );
char *str = token_collate_key ( token, case_sensitive );
retv[0] = (char *) g_pattern_spec_new ( str );
g_free ( token ); token = NULL;
g_free ( str );
}
else if ( config.regex ) {
GRegex *reg = g_regex_new ( input, ( case_sensitive ) ? 0 : G_REGEX_CASELESS, G_REGEX_MATCH_PARTIAL, NULL );
if ( reg == NULL ) {
gchar *r = g_regex_escape_string ( input, -1 );
reg = g_regex_new ( r, ( case_sensitive ) ? 0 : G_REGEX_CASELESS, G_REGEX_MATCH_PARTIAL, NULL );
g_free ( r );
g_free ( retv );
}
retv[0] = (char *) reg;
}
else{
retv[0] = token_collate_key ( input, case_sensitive );
}
retv = g_malloc0 ( sizeof ( char* ) * 2 );
retv[0] = (char *) create_regex ( input, case_sensitive );
return retv;
}
@ -213,25 +218,8 @@ char **tokenize ( const char *input, int case_sensitive )
// strtok should still be valid for utf8.
const char * const sep = " ";
for ( token = strtok_r ( str, sep, &saveptr ); token != NULL; token = strtok_r ( NULL, sep, &saveptr ) ) {
retv = g_realloc ( retv, sizeof ( char* ) * ( num_tokens + 2 ) );
if ( config.glob ) {
char *str = g_strdup_printf ( "*%s*", token );
char *t = token_collate_key ( str, case_sensitive );
retv[num_tokens] = (char *) g_pattern_spec_new ( t );
g_free ( t );
g_free ( str );
}
else if ( config.regex ) {
retv[num_tokens] = (char *) g_regex_new ( token, case_sensitive ? 0 : G_REGEX_CASELESS, 0, NULL );
if ( retv[num_tokens] == NULL ) {
gchar *r = g_regex_escape_string ( input, -1 );
retv[num_tokens] = (char *) g_regex_new ( r, ( case_sensitive ) ? 0 : G_REGEX_CASELESS, G_REGEX_MATCH_PARTIAL, NULL );
g_free ( r );
}
}
else {
retv[num_tokens] = token_collate_key ( token, case_sensitive );
}
retv = g_realloc ( retv, sizeof ( char* ) * ( num_tokens + 2 ) );
retv[num_tokens] = (char *) create_regex ( token, case_sensitive );
retv[num_tokens + 1] = NULL;
num_tokens++;
}
@ -347,56 +335,6 @@ int find_arg_char ( const char * const key, char *val )
return FALSE;
}
/**
* Shared 'token_match' function.
* Matches tokenized.
*/
static int fuzzy_token_match ( char **tokens, const char *input, __attribute__( ( unused ) ) int not_ascii, int case_sensitive )
{
int match = 1;
// Do a tokenized match.
if ( tokens ) {
char *compk = not_ascii ? token_collate_key ( input, case_sensitive ) : (char *) g_ascii_strdown ( input, -1 );
for ( int j = 0; match && tokens[j]; j++ ) {
char *t = compk;
char *token = tokens[j];
while ( *t && *token ) {
if ( ( g_utf8_get_char ( t ) == g_utf8_get_char ( token ) ) ) {
token = g_utf8_next_char ( token );
}
t = g_utf8_next_char ( t );
}
match = !( *token );
}
g_free ( compk );
}
return match;
}
static int normal_token_match ( char **tokens, const char *input, int not_ascii, int case_sensitive )
{
int match = 1;
// Do a tokenized match.
if ( tokens ) {
char *compk = not_ascii ? token_collate_key ( input, case_sensitive ) : (char *) input;
char *( *comparison )( const char *, const char * );
comparison = ( case_sensitive || not_ascii ) ? strstr : strcasestr;
for ( int j = 0; match && tokens[j]; j++ ) {
match = ( comparison ( compk, tokens[j] ) != NULL );
}
if ( not_ascii ) {
g_free ( compk );
}
}
return match;
}
static int regex_token_match ( char **tokens, const char *input, G_GNUC_UNUSED int not_ascii, G_GNUC_UNUSED int case_sensitive )
{
int match = 1;
@ -410,9 +348,8 @@ static int regex_token_match ( char **tokens, const char *input, G_GNUC_UNUSED i
return match;
}
PangoAttrList *regex_token_match_get_pango_attr ( char **tokens, const char *input, PangoAttrList *retv )
static PangoAttrList *regex_token_match_get_pango_attr ( char **tokens, const char *input, PangoAttrList *retv )
{
if ( config.regex == FALSE ) return retv;
// Do a tokenized match.
if ( tokens ) {
for ( int j = 0; tokens[j]; j++ ) {
@ -432,34 +369,14 @@ PangoAttrList *regex_token_match_get_pango_attr ( char **tokens, const char *inp
}
return retv;
}
static int glob_token_match ( char **tokens, const char *input, int not_ascii, int case_sensitive )
PangoAttrList *token_match_get_pango_attr ( char **tokens, const char *input, PangoAttrList *retv )
{
int match = 1;
char *compk = not_ascii ? token_collate_key ( input, case_sensitive ) : g_ascii_strdown ( input, -1 );
// Do a tokenized match.
if ( tokens ) {
for ( int j = 0; match && tokens[j]; j++ ) {
match = g_pattern_match_string ( (GPatternSpec *) tokens[j], compk );
}
}
g_free ( compk );
return match;
return regex_token_match_get_pango_attr ( tokens, input, retv );
}
int token_match ( char **tokens, const char *input, int not_ascii, int case_sensitive )
{
if ( config.glob ) {
return glob_token_match ( tokens, input, not_ascii, case_sensitive );
}
else if ( config.regex ) {
return regex_token_match ( tokens, input, not_ascii, case_sensitive );
}
else if ( config.fuzzy ) {
return fuzzy_token_match ( tokens, input, not_ascii, case_sensitive );
}
return normal_token_match ( tokens, input, not_ascii, case_sensitive );
return regex_token_match ( tokens, input, not_ascii, case_sensitive );
}
int execute_generator ( const char * cmd )

View file

@ -949,10 +949,11 @@ static void rofi_view_draw ( RofiViewState *state, cairo_t *d )
textbox_text ( state->boxes[i], text );
PangoAttrList *list = textbox_get_pango_attributes ( state->boxes[i] );
if ( list != NULL )
if ( list != NULL ) {
pango_attr_list_ref ( list );
else list = pango_attr_list_new ();
regex_token_match_get_pango_attr ( tokens, textbox_get_visible_text ( state->boxes[i] ), list );
}
else{ list = pango_attr_list_new (); }
token_match_get_pango_attr ( tokens, textbox_get_visible_text ( state->boxes[i] ), list );
textbox_set_pango_attributes ( state->boxes[i], list );
pango_attr_list_unref ( list );
g_free ( text );