diff --git a/doc/ratpoison.mdoc.1 b/doc/ratpoison.mdoc.1 index 2e3c356..bcd38b1 100644 --- a/doc/ratpoison.mdoc.1 +++ b/doc/ratpoison.mdoc.1 @@ -1141,6 +1141,16 @@ Decide if history expansion using ! is available. Default is .Li 0 (off). +.It Cm selectstyle Li first_match | prefer_deselected +If this is set to first_match, the select command starts +comparing window names sequentially at the first (oldest) window. +If set to prefer_deselected, it will start with the +window after the currently selected one, thus only +choosing it if no other window matches the input. +.Pp +Default is +.Li prefer_deselected + .El .Sh FILES .Bl -tag -width "%%sysconfdir%%/ratpoisonrc" -compact diff --git a/doc/ratpoison.texi b/doc/ratpoison.texi index d12501f..0aa5ce7 100644 --- a/doc/ratpoison.texi +++ b/doc/ratpoison.texi @@ -230,7 +230,13 @@ frame, type @samp{select -}. @end deffn @deffn Command select @var{window-name} -Go to a window by name. A shortcut is @kbd{C-t '}. +Go to a window by name. If no window named WINDOW-NAME is found, +ratpoison looks for a window whose name starts with WINDOW-NAME +(first case-sensitively, then ignoring case). +If selectstyle is set to ``prefer_deselected'' (default), then it starts +comparing names at the window after the currently selected one. If it is +set to ``first_match'', ratpoison starts comparing at the first window. +A shortcut is @kbd{C-t '}. @end deffn @deffn Command windows @var{fmt} @@ -1670,6 +1676,7 @@ Here is a list of variables that can be set: @item historysize @item historycompaction @item historyexpansion address@hidden selectstyle @end itemize @end deffn diff --git a/src/actions.c b/src/actions.c index 7579101..7dfaff8 100644 --- a/src/actions.c +++ b/src/actions.c @@ -81,6 +81,7 @@ static cmdret * set_topkmap (struct cmdarg **args); static cmdret * set_historysize (struct cmdarg **args); static cmdret * set_historycompaction (struct cmdarg **args); static cmdret * set_historyexpansion (struct cmdarg **args); +static cmdret * set_selectstyle (struct cmdarg **args); LIST_HEAD(set_vars); @@ -150,6 +151,7 @@ init_set_vars(void) add_set_var ("historysize", set_historysize, 1, "", arg_NUMBER); add_set_var ("historycompaction", set_historycompaction, 1, "", arg_NUMBER); add_set_var ("historyexpansion", set_historyexpansion, 1, "", arg_NUMBER); + add_set_var ("selectstyle", set_selectstyle, 1, "", arg_STRING); } /* rp_keymaps is ratpoison's list of keymaps. */ @@ -1412,10 +1414,16 @@ cmd_select (int interactive UNUSED, struct cmdarg **args) else /* try by name */ { - rp_window *win = find_window_name (str, 1); + rp_window *win = find_window_name (str, strncmp, MAX_WINDOW_NAME_LENGTH); - if (!win) - win = find_window_name (str, 0); + if (!win) /* try finding one ignoring case */ + win = find_window_name (str, strncasecmp, MAX_WINDOW_NAME_LENGTH); + + if (!win) /* try if str is a prefix to a window name */ + win = find_window_name (str, strncmp, strlen(str)); + + if (!win) /* same as above, ignoring case */ + win = find_window_name (str, strncasecmp, strlen(str)); if (win) { @@ -1885,56 +1893,6 @@ read_frame (struct sbuf *s, struct cmdarg **arg) return cmdret_new (RET_FAILURE, "frame not found"); } -static cmdret * -read_window (struct argspec *spec, struct sbuf *s, struct cmdarg **arg) -{ - rp_window *win = NULL; - char *name; - int n; - - if (s) - name = xstrdup (sbuf_get (s)); - else - name = get_input (spec->prompt, hist_WINDOW, window_completions); - - if (name) - { - /* try by number */ - if ((n = string_to_positive_int (name)) >= 0) - { - rp_window_elem *elem = group_find_window_by_number (rp_current_group, n); - if (elem) - win = elem->win; - } - else - /* try by name */ - { - win = find_window_name (name, 1); - if (win == NULL) - win = find_window_name (name, 0); - } - - if (win) - { - *arg = xmalloc (sizeof(struct cmdarg)); - (*arg)->type = arg_WINDOW; - (*arg)->arg.win = win; - (*arg)->string = name; - return NULL; - } - else - { - free (name); - *arg = NULL; - return cmdret_new (RET_SUCCESS, NULL); - } - } - - /* user abort. */ - *arg = NULL; - return cmdret_new (RET_SUCCESS, NULL); -} - static int parse_wingravity (char *data) { @@ -2237,9 +2195,6 @@ read_arg (struct argspec *spec, struct sbuf *s, struct cmdarg **arg, const char case arg_SHELLCMD: ret = read_shellcmd (spec, s, arg, command_name); break; - case arg_WINDOW: - ret = read_window (spec, s, arg); - break; case arg_FRAME: ret = read_frame (s, arg); break; @@ -2460,7 +2415,6 @@ arg_free (struct cmdarg *arg) case arg_REST: case arg_STRING: case arg_NUMBER: - case arg_WINDOW: case arg_FRAME: case arg_COMMAND: case arg_SHELLCMD: @@ -5684,6 +5638,25 @@ set_maxundos (struct cmdarg **args) return cmdret_new (RET_SUCCESS, NULL); } +static cmdret * +set_selectstyle (struct cmdarg **args) +{ + if (args[0] == NULL) + return cmdret_new (RET_SUCCESS, "%s", + defaults.select_style == SELECT_OK_SELECTED + ? "ok_selected" + : "prefer_unselected" + ); + + if (!strncmp ("first_match", ARG_STRING(0), 5)) + defaults.select_style = SELECT_OK_SELECTED; + else if (!strncmp ("prefer_deselected", ARG_STRING(0), 5)) + defaults.select_style = SELECT_PREFER_NOTSELECTED; + else + return cmdret_new (RET_FAILURE, "set selectstyle: invalid argument"); + return cmdret_new (RET_SUCCESS, NULL); +} + cmdret * cmd_cnext (int interactive, struct cmdarg **args) { diff --git a/src/actions.h b/src/actions.h index 519c1a7..d813bc9 100644 --- a/src/actions.h +++ b/src/actions.h @@ -34,7 +34,6 @@ enum argtype { arg_REST, arg_NUMBER, arg_STRING, arg_FRAME, - arg_WINDOW, arg_COMMAND, arg_SHELLCMD, arg_KEYMAP, diff --git a/src/conf.h b/src/conf.h index 708b688..014e938 100644 --- a/src/conf.h +++ b/src/conf.h @@ -131,4 +131,7 @@ * the double of this value is tried before giving up */ #define MAX_LEGACY_SNPRINTF_SIZE 102400 +/* Window names will only be compared by ther first 1024 chars */ +#define MAX_WINDOW_NAME_LENGTH 1024 + #endif /* !_ _RATPOISON_CONF_H */ diff --git a/src/data.h b/src/data.h index f4bd185..01a8f1a 100644 --- a/src/data.h +++ b/src/data.h @@ -275,6 +275,9 @@ struct rp_defaults /* Frame indicator format */ char *frame_fmt; + + /* How the select command behaves */ + int select_style; }; /* Information about a child process. */ diff --git a/src/globals.h b/src/globals.h index 1fb7e0f..2100a79 100644 --- a/src/globals.h +++ b/src/globals.h @@ -76,6 +76,10 @@ #define UNUSED #endif +/* toggles select behavior */ +#define SELECT_OK_SELECTED 0 +#define SELECT_PREFER_NOTSELECTED 1 + /* The list of groups. */ extern struct list_head rp_groups; diff --git a/src/main.c b/src/main.c index 52dbcce..8f0146e 100644 --- a/src/main.c +++ b/src/main.c @@ -599,6 +599,7 @@ init_defaults (void) defaults.history_expansion = False; defaults.frame_selectors = xstrdup (""); defaults.maxundos = 20; + defaults.select_style = SELECT_PREFER_NOTSELECTED ; } int diff --git a/src/window.c b/src/window.c index de9032a..6fbbef5 100644 --- a/src/window.c +++ b/src/window.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "ratpoison.h" @@ -283,31 +284,40 @@ find_window_number (int n) } rp_window * -find_window_name (char *name, int exact_match) +find_window_name ( char *name + , int (*compare_names)(const char*, const char*, size_t) + , size_t compare_length) { + int current_win_number = current_window() ? current_window()->number : 0; rp_window_elem *cur; - if (!exact_match) - { - list_for_each_entry (cur, &rp_current_group->mapped_windows, node) - { - if (str_comp (name, window_name (cur->win), strlen (name))) - return cur->win; - } - } - else + int may_return = 1; + if (defaults.select_style == SELECT_PREFER_NOTSELECTED) + may_return = 0; + + rp_window *first_match = NULL; + + list_for_each_entry (cur, &rp_current_group->mapped_windows, node) { - list_for_each_entry (cur, &rp_current_group->mapped_windows, node) + if (!compare_names (name, window_name(cur->win), compare_length)) { - if (!strcmp (name, window_name (cur->win))) - return cur->win; + if (may_return) + { + return cur->win; + } + else + { + if(cur->win->number == current_win_number) + may_return = 1; + if(!first_match) + first_match = cur->win; + } } } - - /* didn't find it */ - return NULL; + return first_match; } + /* Return the previous window in the list. Assumes window is in the mapped window list. */ rp_window* diff --git a/src/window.h b/src/window.h index fdd246c..3bf9d18 100644 --- a/src/window.h +++ b/src/window.h @@ -40,7 +40,9 @@ char *window_name (rp_window *win); /* int goto_window_name (char *name); */ rp_window *find_window_other (rp_screen *screen); rp_window *find_window_by_number (int n); -rp_window *find_window_name (char *name, int exact_match); +rp_window * find_window_name ( char *name + , int (*compare_names)(const char*, const char*, size_t) + , size_t compare_length); rp_window *find_window_prev (rp_window *w); rp_window *find_window_prev_with_frame (rp_window *w); rp_window *find_window_next (rp_window *w);