awesome-menu: match string mode and autocomplete

I'm made some simple modifications of awesome-menu.c
to achieve the following:

1. Match the string entered by the user with the whole search string.
So far, it only matches from the start of the string. For menu entries
like 'gksu synaptic', the default behaviour is very inconvenient,
because obviously, I don't want to enter the 'gksu' part every time.
Another example: I have iceweasel, iceape and icedove installed.
Entering 'wea' is enough to find 'iceweasel' exclusively if the whole
string is searched. 'ice', on the other hand, won't do much good.

2. If there's just one single match, select that one automatically.
This saves hitting tab once in the cases when the choice is obvious
(because there is only one).

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Hannes 2008-08-01 10:34:15 +02:00 committed by Julien Danjou
parent c12f0ff3aa
commit 4ee816510f
2 changed files with 31 additions and 8 deletions

View File

@ -122,6 +122,8 @@ typedef struct
char *exec; char *exec;
/** Prompt */ /** Prompt */
char *prompt; char *prompt;
/** String match mode */
Bool match_string;
} AwesomeMenuConf; } AwesomeMenuConf;
static AwesomeMenuConf globalconf; static AwesomeMenuConf globalconf;
@ -196,6 +198,7 @@ config_parse(int screen, const char *confpatharg,
geometry->width = i; geometry->width = i;
if((i = cfg_getint(cfg_menu, "height")) > 0) if((i = cfg_getint(cfg_menu, "height")) > 0)
geometry->height = i; geometry->height = i;
globalconf.match_string = cfg_getbool(cfg_menu, "match_string");
} }
if(cfg_screen if(cfg_screen
@ -373,11 +376,12 @@ complete(Bool reverse)
/** Compute a match from completion list for word. /** Compute a match from completion list for word.
* \param word the word to match * \param word the word to match
*/ */
static void static int
compute_match(const char *word) compute_match(const char *word)
{ {
ssize_t len = a_strlen(word); ssize_t len = a_strlen(word);
item_t *item; item_t *item;
int matches = 0;
/* reset the selected item to NULL */ /* reset the selected item to NULL */
globalconf.item_selected = NULL; globalconf.item_selected = NULL;
@ -389,8 +393,11 @@ compute_match(const char *word)
item_list_fill_file(word); item_list_fill_file(word);
for(item = globalconf.items; item; item = item->next) for(item = globalconf.items; item; item = item->next)
if(!a_strncmp(word, item->data, a_strlen(word))) if((globalconf.match_string && strstr(item->data, word) != NULL) || (!globalconf.match_string && !a_strncmp(word, item->data, a_strlen(word))))
{
item->match = True; item->match = True;
matches++;
}
else else
item->match = False; item->match = False;
} }
@ -399,8 +406,14 @@ compute_match(const char *word)
if(a_strlen(globalconf.text)) if(a_strlen(globalconf.text))
item_list_fill_file(NULL); item_list_fill_file(NULL);
for(item = globalconf.items; item; item = item->next) for(item = globalconf.items; item; item = item->next)
{
item->match = True; item->match = True;
matches++;
}
} }
return matches;
} }
/* Why not? */ /* Why not? */
@ -498,7 +511,7 @@ handle_kpress(XKeyEvent *e)
{ {
char buf[32]; char buf[32];
KeySym ksym; KeySym ksym;
int num; int num, matches;
ssize_t len; ssize_t len;
size_t text_dst_len; size_t text_dst_len;
@ -538,7 +551,9 @@ handle_kpress(XKeyEvent *e)
globalconf.text[i--] = '\0'; globalconf.text[i--] = '\0';
while(i >= 0 && globalconf.text[i] != ' ') while(i >= 0 && globalconf.text[i] != ' ')
globalconf.text[i--] = '\0'; globalconf.text[i--] = '\0';
compute_match(get_last_word(globalconf.text)); matches = compute_match(get_last_word(globalconf.text));
if (matches == 1)
complete(False);
redraw(); redraw();
} }
return; return;
@ -576,7 +591,9 @@ handle_kpress(XKeyEvent *e)
} }
a_strncat(globalconf.text, globalconf.text_size, buf, num); a_strncat(globalconf.text, globalconf.text_size, buf, num);
} }
compute_match(get_last_word(globalconf.text)); matches = compute_match(get_last_word(globalconf.text));
if (matches == 1)
complete(False);
redraw(); redraw();
} }
break; break;
@ -584,7 +601,9 @@ handle_kpress(XKeyEvent *e)
if(len) if(len)
{ {
globalconf.text[--len] = '\0'; globalconf.text[--len] = '\0';
compute_match(get_last_word(globalconf.text)); matches = compute_match(get_last_word(globalconf.text));
if (matches == 1)
complete(False);
redraw(); redraw();
} }
break; break;
@ -696,7 +715,7 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
XEvent ev; XEvent ev;
int opt, ret, x, y, i, screen = 0; int opt, ret, x, y, i, screen = 0, matches;
char *configfile = NULL, *cmd; char *configfile = NULL, *cmd;
ssize_t len; ssize_t len;
const char *shell = getenv("SHELL"); const char *shell = getenv("SHELL");
@ -800,7 +819,9 @@ main(int argc, char **argv)
item_list_fill_file(NULL); item_list_fill_file(NULL);
} }
compute_match(NULL); matches = compute_match(NULL);
if (matches == 1)
complete(False);
redraw(); redraw();

View File

@ -631,6 +631,8 @@ cfg_opt_t menu_opts[] =
CFG_INT((char *) "x", 0xffffffff, CFGF_NONE), CFG_INT((char *) "x", 0xffffffff, CFGF_NONE),
/** Y coordinate, do not set for auto. */ /** Y coordinate, do not set for auto. */
CFG_INT((char *) "y", 0xffffffff, CFGF_NONE), CFG_INT((char *) "y", 0xffffffff, CFGF_NONE),
/** String matching mode (true to complete string) */
CFG_BOOL((char *) "match_string", cfg_false, CFGF_NONE),
/** Styles to use for this menu. */ /** Styles to use for this menu. */
CFG_SEC((char *) "styles", styles_opts, CFGF_NONE), CFG_SEC((char *) "styles", styles_opts, CFGF_NONE),
CFG_AWESOME_END() CFG_AWESOME_END()