diff options
-rw-r--r-- | config/config.def.c | 2 | ||||
-rw-r--r-- | include/rofi.h | 2 | ||||
-rw-r--r-- | include/xrmoptions.h | 1 | ||||
-rw-r--r-- | source/rofi.c | 68 | ||||
-rw-r--r-- | source/xrmoptions.c | 208 |
5 files changed, 194 insertions, 87 deletions
diff --git a/config/config.def.c b/config/config.def.c index 1bc122c0..e971737d 100644 --- a/config/config.def.c +++ b/config/config.def.c @@ -110,6 +110,8 @@ Settings config = { .fixed_num_lines = FALSE, /** Do not use history */ .disable_history = FALSE, + /** Use levenshtein sorting when matching */ + .levenshtein_sort = FALSE, /** Case sensitivity of the search */ .case_sensitive = FALSE, /** Separator to use for dmenu mode */ diff --git a/include/rofi.h b/include/rofi.h index cfc6ebc8..27693711 100644 --- a/include/rofi.h +++ b/include/rofi.h @@ -210,6 +210,8 @@ typedef struct _Settings unsigned int fixed_num_lines; /** Do not use history */ unsigned int disable_history; + /** Use levenshtein sorting when matching */ + unsigned int levenshtein_sort; /** Search case sensitivity */ unsigned int case_sensitive; /** Separator to use for dmenu mode */ diff --git a/include/xrmoptions.h b/include/xrmoptions.h index a0233d71..f7e40841 100644 --- a/include/xrmoptions.h +++ b/include/xrmoptions.h @@ -51,4 +51,5 @@ void xresource_dump ( void ); * Add option to the dynamic option parser. */ void config_parser_add_option ( XrmOptionType type, const char *key, void **value ); +void print_options ( void ); #endif diff --git a/source/rofi.c b/source/rofi.c index f6a48ad4..db6ba93f 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -141,6 +141,37 @@ static inline MainLoopEvent wait_for_xevent_or_timeout ( Display *display, int x * Levenshtein Sorting. */ +static int lev_sort ( const void *p1, const void *p2, void *arg ) +{ + const int *a = p1; + const int *b = p2; + int *distances = arg; + + return distances[*a] - distances[*b]; +} + +#define MIN3( a, b, c ) ( ( a ) < ( b ) ? ( ( a ) < ( c ) ? ( a ) : ( c ) ) : ( ( b ) < ( c ) ? ( b ) : ( c ) ) ) + +static int levenshtein ( char *s1, char *s2 ) +{ + unsigned int x, y, lastdiag, olddiag; + size_t s1len = strlen ( s1 ); + size_t s2len = strlen ( s2 ); + unsigned int column[s1len + 1]; + for ( y = 1; y <= s1len; y++ ) { + column[y] = y; + } + for ( x = 1; x <= s2len; x++ ) { + column[0] = x; + for ( y = 1, lastdiag = x - 1; y <= s1len; y++ ) { + olddiag = column[y]; + column[y] = MIN3 ( column[y] + 1, column[y - 1] + 1, lastdiag + ( s1[y - 1] == s2[x - 1] ? 0 : 1 ) ); + lastdiag = olddiag; + } + } + return column[s1len]; +} + // State of the menu. typedef struct MenuState @@ -170,6 +201,7 @@ typedef struct MenuState textbox *case_indicator; textbox **boxes; scrollbar *scrollbar; + int *distance; unsigned int *line_map; unsigned int num_lines; @@ -253,6 +285,7 @@ static void menu_free_state ( MenuState *state ) g_free ( state->boxes ); g_free ( state->line_map ); + g_free ( state->distance ); g_free ( state->lines_not_ascii ); } @@ -672,9 +705,15 @@ static void menu_refilter ( MenuState *state ) // If each token was matched, add it to list. if ( match ) { state->line_map[j] = i; + if ( config.levenshtein_sort ) { + state->distance[i] = levenshtein ( state->text->text, state->lines[i] ); + } j++; } } + if ( config.levenshtein_sort ) { + g_qsort_with_data ( state->line_map, j, sizeof ( int ), lev_sort, state->distance ); + } // Cleanup + bookkeeping. state->filtered_lines = j; @@ -938,6 +977,7 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select .prev_key = 0, .last_button_press = 0, .last_offset = 0, + .distance = NULL, .quit = FALSE, .skip_absorb = FALSE, .filtered_lines = 0, @@ -1058,6 +1098,9 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select scrollbar_set_max_value ( state.scrollbar, state.num_lines ); // filtered list state.line_map = g_malloc0_n ( state.num_lines, sizeof ( unsigned int ) ); + if ( config.levenshtein_sort ) { + state.distance = (int *) g_malloc0_n ( state.num_lines, sizeof ( int ) ); + } // resize window vertically to suit // Subtract the margin of the last row. @@ -1350,6 +1393,7 @@ void error_dialog ( const char *msg, int markup ) .last_button_press = 0, .last_offset = 0, .num_lines = 0, + .distance = NULL, .quit = FALSE, .skip_absorb = FALSE, .filtered_lines = 0, @@ -1572,13 +1616,15 @@ static void handle_keypress ( XEvent *ev ) /** * Help function. This calls man. */ -static void help () +static void help ( G_GNUC_UNUSED int argc, char **argv ) { - int code = execlp ( "man", "man", "-M", MANPAGE_PATH, "rofi", NULL ); - - if ( code == -1 ) { - fprintf ( stderr, "Failed to execute manpage viewer: %s\n", strerror ( errno ) ); - } + printf ( "Rofi: "VERSION "\n\n" ); + printf ( "%s usage:\n", argv[0] ); + printf ( "\t%s [-options ...]\n\n", argv[0] ); + printf ( "where options include:\n" ); + print_options (); + printf ( "\n" ); + printf ( "For more information see: man rofi\n" ); } /** @@ -1937,11 +1983,6 @@ int main ( int argc, char *argv[] ) cmd_set_arguments ( argc, argv ); // Quiet flag int quiet = ( find_arg ( "-quiet" ) >= 0 ); - // catch help request - if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) { - help (); - exit ( EXIT_SUCCESS ); - } // Version if ( find_arg ( "-v" ) >= 0 || find_arg ( "-version" ) >= 0 ) { fprintf ( stdout, "Version: "VERSION "\n" ); @@ -2024,6 +2065,11 @@ int main ( int argc, char *argv[] ) // Sanity check config_sanity_check ( ); // Dump. + // catch help request + if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) { + help ( argc, argv ); + exit ( EXIT_SUCCESS ); + } if ( find_arg ( "-dump-xresources" ) >= 0 ) { xresource_dump (); exit ( EXIT_SUCCESS ); diff --git a/source/xrmoptions.c b/source/xrmoptions.c index 7e144de0..1c5b729f 100644 --- a/source/xrmoptions.c +++ b/source/xrmoptions.c @@ -47,90 +47,92 @@ typedef struct char * charc; } value; char *mem; + char *comment; } XrmOption; /** * Map X resource and commandline options to internal options * Currently supports string, boolean and number (signed and unsigned). */ static XrmOption xrmOptions[] = { - { xrm_String, "switchers", { .str = &config.switchers }, NULL }, - { xrm_String, "modi", { .str = &config.switchers }, NULL }, - { xrm_Number, "opacity", { .num = &config.window_opacity }, NULL }, - { xrm_SNumber, "width", { .snum = &config.menu_width }, NULL }, - { xrm_Number, "lines", { .num = &config.menu_lines }, NULL }, - { xrm_Number, "columns", { .num = &config.menu_columns }, NULL }, - - { xrm_String, "font", { .str = &config.menu_font }, NULL }, + { xrm_String, "switchers", { .str = &config.switchers }, NULL , ""}, + { xrm_String, "modi", { .str = &config.switchers }, NULL , ""}, + { xrm_Number, "opacity", { .num = &config.window_opacity }, NULL , ""}, + { xrm_SNumber, "width", { .snum = &config.menu_width }, NULL , ""}, + { xrm_Number, "lines", { .num = &config.menu_lines }, NULL , ""}, + { xrm_Number, "columns", { .num = &config.menu_columns }, NULL , ""}, + + { xrm_String, "font", { .str = &config.menu_font }, NULL , ""}, /* Foreground color */ - { xrm_String, "foreground", { .str = &config.menu_fg }, NULL }, - { xrm_String, "fg", { .str = &config.menu_fg }, NULL }, - { xrm_String, "background", { .str = &config.menu_bg }, NULL }, - { xrm_String, "bg", { .str = &config.menu_bg }, NULL }, - - { xrm_Boolean, "color-enabled", { .num = &config.color_enabled }, NULL }, - { xrm_String, "color-normal", { .str = &config.color_normal }, NULL }, - { xrm_String, "color-urgent", { .str = &config.color_urgent }, NULL }, - { xrm_String, "color-active", { .str = &config.color_active }, NULL }, - { xrm_String, "color-window", { .str = &config.color_window }, NULL }, - - { xrm_String, "fg-active", { .str = &config.menu_fg_active }, NULL }, - { xrm_String, "fg-urgent", { .str = &config.menu_fg_urgent }, NULL }, - { xrm_String, "hlfg-active", { .str = &config.menu_hlfg_active }, NULL }, - { xrm_String, "hlfg-urgent", { .str = &config.menu_hlfg_urgent }, NULL }, - - { xrm_String, "bg-active", { .str = &config.menu_bg_active }, NULL }, - { xrm_String, "bg-urgent", { .str = &config.menu_bg_urgent }, NULL }, - { xrm_String, "hlbg-active", { .str = &config.menu_hlbg_active }, NULL }, - { xrm_String, "hlbg-urgent", { .str = &config.menu_hlbg_urgent }, NULL }, - - { xrm_String, "background-alternate", { .str = &config.menu_bg_alt }, NULL }, - { xrm_String, "bgalt", { .str = &config.menu_bg_alt }, NULL }, - - { xrm_String, "highlightfg", { .str = &config.menu_hlfg }, NULL }, - { xrm_String, "hlfg", { .str = &config.menu_hlfg }, NULL }, - - { xrm_String, "highlightbg", { .str = &config.menu_hlbg }, NULL }, - { xrm_String, "hlbg", { .str = &config.menu_hlbg }, NULL }, - - { xrm_String, "bordercolor", { .str = &config.menu_bc }, NULL }, - { xrm_String, "bc", { .str = &config.menu_bc }, NULL }, - - { xrm_Number, "borderwidth", { .num = &config.menu_bw }, NULL }, - { xrm_Number, "bw", { .num = &config.menu_bw }, NULL }, - - { xrm_Number, "location", { .num = &config.location }, NULL }, - - { xrm_Number, "padding", { .num = &config.padding }, NULL }, - { xrm_SNumber, "yoffset", { .snum = &config.y_offset }, NULL }, - { xrm_SNumber, "xoffset", { .snum = &config.x_offset }, NULL }, - { xrm_Boolean, "fixed-num-lines", { .num = &config.fixed_num_lines }, NULL }, - - { xrm_String, "terminal", { .str = &config.terminal_emulator }, NULL }, - { xrm_String, "ssh-client", { .str = &config.ssh_client }, NULL }, - { xrm_String, "ssh-command", { .str = &config.ssh_command }, NULL }, - { xrm_String, "run-command", { .str = &config.run_command }, NULL }, - { xrm_String, "run-list-command", { .str = &config.run_list_command }, NULL }, - { xrm_String, "run-shell-command", { .str = &config.run_shell_command }, NULL }, - - { xrm_Boolean, "disable-history", { .num = &config.disable_history }, NULL }, - { xrm_Boolean, "case-sensitive", { .num = &config.case_sensitive }, NULL }, - { xrm_Boolean, "sidebar-mode", { .num = &config.sidebar_mode }, NULL }, - { xrm_Number, "lazy-filter-limit", { .num = &config.lazy_filter_limit }, NULL }, - { xrm_SNumber, "eh", { .snum = &config.element_height }, NULL }, - { xrm_Boolean, "auto-select", { .num = &config.auto_select }, NULL }, - { xrm_Boolean, "parse-hosts", { .num = &config.parse_hosts }, NULL }, - { xrm_String, "combi-modi", { .str = &config.combi_modi }, NULL }, - { xrm_Boolean, "fuzzy", { .num = &config.fuzzy }, NULL }, - { xrm_Boolean, "glob", { .num = &config.glob }, NULL }, - { xrm_Boolean, "tokenize", { .num = &config.tokenize }, NULL }, - { xrm_Number, "monitor", { .snum = &config.monitor }, NULL }, + { xrm_String, "foreground", { .str = &config.menu_fg }, NULL , ""}, + { xrm_String, "fg", { .str = &config.menu_fg }, NULL , ""}, + { xrm_String, "background", { .str = &config.menu_bg }, NULL , ""}, + { xrm_String, "bg", { .str = &config.menu_bg }, NULL , ""}, + + { xrm_Boolean, "color-enabled", { .num = &config.color_enabled }, NULL , ""}, + { xrm_String, "color-normal", { .str = &config.color_normal }, NULL , ""}, + { xrm_String, "color-urgent", { .str = &config.color_urgent }, NULL , ""}, + { xrm_String, "color-active", { .str = &config.color_active }, NULL , ""}, + { xrm_String, "color-window", { .str = &config.color_window }, NULL , ""}, + + { xrm_String, "fg-active", { .str = &config.menu_fg_active }, NULL , ""}, + { xrm_String, "fg-urgent", { .str = &config.menu_fg_urgent }, NULL , ""}, + { xrm_String, "hlfg-active", { .str = &config.menu_hlfg_active }, NULL , ""}, + { xrm_String, "hlfg-urgent", { .str = &config.menu_hlfg_urgent }, NULL , ""}, + + { xrm_String, "bg-active", { .str = &config.menu_bg_active }, NULL , ""}, + { xrm_String, "bg-urgent", { .str = &config.menu_bg_urgent }, NULL , ""}, + { xrm_String, "hlbg-active", { .str = &config.menu_hlbg_active }, NULL , ""}, + { xrm_String, "hlbg-urgent", { .str = &config.menu_hlbg_urgent }, NULL , ""}, + + { xrm_String, "background-alternate", { .str = &config.menu_bg_alt }, NULL , ""}, + { xrm_String, "bgalt", { .str = &config.menu_bg_alt }, NULL , ""}, + + { xrm_String, "highlightfg", { .str = &config.menu_hlfg }, NULL , ""}, + { xrm_String, "hlfg", { .str = &config.menu_hlfg }, NULL , ""}, + + { xrm_String, "highlightbg", { .str = &config.menu_hlbg }, NULL , ""}, + { xrm_String, "hlbg", { .str = &config.menu_hlbg }, NULL , ""}, + + { xrm_String, "bordercolor", { .str = &config.menu_bc }, NULL , ""}, + { xrm_String, "bc", { .str = &config.menu_bc }, NULL , ""}, + + { xrm_Number, "borderwidth", { .num = &config.menu_bw }, NULL , ""}, + { xrm_Number, "bw", { .num = &config.menu_bw }, NULL , ""}, + + { xrm_Number, "location", { .num = &config.location }, NULL , ""}, + + { xrm_Number, "padding", { .num = &config.padding }, NULL , ""}, + { xrm_SNumber, "yoffset", { .snum = &config.y_offset }, NULL , ""}, + { xrm_SNumber, "xoffset", { .snum = &config.x_offset }, NULL , ""}, + { xrm_Boolean, "fixed-num-lines", { .num = &config.fixed_num_lines }, NULL , ""}, + + { xrm_String, "terminal", { .str = &config.terminal_emulator }, NULL , ""}, + { xrm_String, "ssh-client", { .str = &config.ssh_client }, NULL , ""}, + { xrm_String, "ssh-command", { .str = &config.ssh_command }, NULL , ""}, + { xrm_String, "run-command", { .str = &config.run_command }, NULL , ""}, + { xrm_String, "run-list-command", { .str = &config.run_list_command }, NULL , ""}, + { xrm_String, "run-shell-command", { .str = &config.run_shell_command }, NULL , ""}, + + { xrm_Boolean, "disable-history", { .num = &config.disable_history }, NULL , ""}, + { xrm_Boolean, "levenshtein-sort", { .num = &config.levenshtein_sort }, NULL , ""}, + { xrm_Boolean, "case-sensitive", { .num = &config.case_sensitive }, NULL , ""}, + { xrm_Boolean, "sidebar-mode", { .num = &config.sidebar_mode }, NULL , ""}, + { xrm_Number, "lazy-filter-limit", { .num = &config.lazy_filter_limit }, NULL , ""}, + { xrm_SNumber, "eh", { .snum = &config.element_height }, NULL , ""}, + { xrm_Boolean, "auto-select", { .num = &config.auto_select }, NULL , ""}, + { xrm_Boolean, "parse-hosts", { .num = &config.parse_hosts }, NULL , ""}, + { xrm_String, "combi-modi", { .str = &config.combi_modi }, NULL , ""}, + { xrm_Boolean, "fuzzy", { .num = &config.fuzzy }, NULL , ""}, + { xrm_Boolean, "glob", { .num = &config.glob }, NULL , ""}, + { xrm_Boolean, "tokenize", { .num = &config.tokenize }, NULL , ""}, + { xrm_Number, "monitor", { .snum = &config.monitor }, NULL , ""}, /* Alias for dmenu compatibility. */ - { xrm_SNumber, "m", { .snum = &config.monitor }, NULL }, - { xrm_Number, "line-margin", { .num = &config.line_margin }, NULL }, - { xrm_String, "filter", { .str = &config.filter }, NULL }, - { xrm_String, "separator-style", { .str = &config.separator_style }, NULL }, - { xrm_Boolean, "hide-scrollbar", { .num = &config.hide_scrollbar }, NULL }, - { xrm_Boolean, "markup-rows", { .num = &config.markup_rows }, NULL } + { xrm_SNumber, "m", { .snum = &config.monitor }, NULL , ""}, + { xrm_Number, "line-margin", { .num = &config.line_margin }, NULL , ""}, + { xrm_String, "filter", { .str = &config.filter }, NULL , ""}, + { xrm_String, "separator-style", { .str = &config.separator_style }, NULL , ""}, + { xrm_Boolean, "hide-scrollbar", { .num = &config.hide_scrollbar }, NULL , ""}, + { xrm_Boolean, "markup-rows", { .num = &config.markup_rows }, NULL , ""} }; // Dynamic options. @@ -381,3 +383,57 @@ void xresource_dump ( void ) xresource_dump_entry ( namePrefix, &( extra_options[i] ) ); } } + +static void print_option_string ( XrmOption *xo ) +{ + printf ( "\t-%s [string]\n", xo->name ); +} +static void print_option_number ( XrmOption *xo ) +{ + printf ( "\t-%s [number]\n", xo->name ); +} +static void print_option_char ( XrmOption *xo ) +{ + printf ( "\t-%s [character]\n", xo->name ); +} +static void print_option_boolean ( XrmOption *xo ) +{ + printf ( "\t-[no-]%s [character]\n", xo->name ); +} + +static void print_option ( XrmOption *xo ) +{ + switch ( xo->type ) + { + case xrm_String: + print_option_string ( xo ); + break; + case xrm_Number: + case xrm_SNumber: + print_option_number ( xo ); + break; + case xrm_Boolean: + print_option_boolean ( xo ); + break; + case xrm_Char: + print_option_char ( xo ); + break; + default: + break; + } +} +void print_options ( void ) +{ + unsigned int entries = sizeof ( xrmOptions ) / sizeof ( *xrmOptions ); + for ( unsigned int i = 0; i < entries; ++i ) { + if ( ( i + 1 ) < entries ) { + if ( xrmOptions[i].value.str == xrmOptions[i + 1].value.str ) { + continue; + } + } + print_option ( &xrmOptions[i] ); + } + for ( unsigned int i = 0; i < num_extra_options; i++ ) { + print_option ( &extra_options[i] ); + } +} |