with the given name already exists rather than failing with an error.
Also add a format to check if a window or session name exists which
allows the same with other commands. Requested by and discussed with
kn@.
-/* $OpenBSD: cmd-new-window.c,v 1.89 2020/06/25 08:56:02 nicm Exp $ */
+/* $OpenBSD: cmd-new-window.c,v 1.90 2021/02/05 12:23:49 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.name = "new-window",
.alias = "neww",
- .args = { "abc:de:F:kn:Pt:", 0, -1 },
- .usage = "[-abdkP] [-c start-directory] [-e environment] [-F format] "
+ .args = { "abc:de:F:kn:PSt:", 0, -1 },
+ .usage = "[-abdkPS] [-c start-directory] [-e environment] [-F format] "
"[-n window-name] " CMD_TARGET_WINDOW_USAGE " [command]",
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX },
cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
+ struct client *c = cmdq_get_client(item);
struct cmd_find_state *current = cmdq_get_current(item);
struct cmd_find_state *target = cmdq_get_target(item);
struct spawn_context sc;
struct session *s = target->s;
struct winlink *wl = target->wl;
int idx = target->idx, before;
- struct winlink *new_wl;
+ struct winlink *new_wl = NULL;
char *cause = NULL, *cp;
- const char *template, *add;
+ const char *template, *add, *name;
struct cmd_find_state fs;
struct args_value *value;
+ /*
+ * If -S and -n are given and -t is not and a single window with this
+ * name already exists, select it.
+ */
+ name = args_get(args, 'n');
+ if (args_has(args, 'S') && name != NULL && target->idx == -1) {
+ RB_FOREACH(wl, winlinks, &s->windows) {
+ if (strcmp(wl->window->name, name) != 0)
+ continue;
+ if (new_wl == NULL) {
+ new_wl = wl;
+ continue;
+ }
+ cmdq_error(item, "multiple windows named %s", name);
+ return (CMD_RETURN_ERROR);
+ }
+ if (new_wl != NULL) {
+ if (args_has(args, 'd'))
+ return (CMD_RETURN_NORMAL);
+ if (session_set_current(s, new_wl) == 0)
+ server_redraw_session(s);
+ if (c != NULL && c->session != NULL)
+ s->curw->window->latest = c;
+ recalculate_sizes();
+ return (CMD_RETURN_NORMAL);
+ }
+ }
+
+
before = args_has(args, 'b');
if (args_has(args, 'a') || before) {
idx = winlink_shuffle_up(s, wl, before);
-/* $OpenBSD: format.c,v 1.271 2021/01/29 09:48:43 nicm Exp $ */
+/* $OpenBSD: format.c,v 1.272 2021/02/05 12:23:49 nicm Exp $ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
#define FORMAT_LENGTH 0x800
#define FORMAT_WIDTH 0x1000
#define FORMAT_QUOTE_STYLE 0x2000
+#define FORMAT_WINDOW_NAME 0x4000
+#define FORMAT_SESSION_NAME 0x8000
/* Limit on recursion. */
#define FORMAT_LOOP_LIMIT 10
}
/* Now try single character with arguments. */
- if (strchr("mCst=peq", cp[0]) == NULL)
+ if (strchr("mCNst=peq", cp[0]) == NULL)
break;
c = cp[0];
return (value);
}
+/* Does session name exist? */
+static char *
+format_session_name(struct format_expand_state *es, const char *fmt)
+{
+ char *name;
+ struct session *s;
+
+ name = format_expand1(es, fmt);
+ RB_FOREACH(s, sessions, &sessions) {
+ if (strcmp(s->name, name) == 0) {
+ free(name);
+ return (xstrdup("1"));
+ }
+ }
+ free(name);
+ return (xstrdup("0"));
+}
+
/* Loop over sessions. */
static char *
format_loop_sessions(struct format_expand_state *es, const char *fmt)
return (value);
}
+/* Does window name exist? */
+static char *
+format_window_name(struct format_expand_state *es, const char *fmt)
+{
+ struct format_tree *ft = es->ft;
+ char *name;
+ struct winlink *wl;
+
+ if (ft->s == NULL) {
+ format_log(es, "window name but no session");
+ return (NULL);
+ }
+
+ name = format_expand1(es, fmt);
+ RB_FOREACH(wl, winlinks, &ft->s->windows) {
+ if (strcmp(wl->window->name, name) == 0) {
+ free(name);
+ return (xstrdup("1"));
+ }
+ }
+ free(name);
+ return (xstrdup("0"));
+}
+
/* Loop over windows. */
static char *
format_loop_windows(struct format_expand_state *es, const char *fmt)
case 'T':
modifiers |= FORMAT_EXPANDTIME;
break;
+ case 'N':
+ if (fm->argc < 1 ||
+ strchr(fm->argv[0], 'w') != NULL)
+ modifiers |= FORMAT_WINDOW_NAME;
+ else if (strchr(fm->argv[0], 's') != NULL)
+ modifiers |= FORMAT_SESSION_NAME;
+ break;
case 'S':
modifiers |= FORMAT_SESSIONS;
break;
value = format_loop_panes(es, copy);
if (value == NULL)
goto fail;
+ } else if (modifiers & FORMAT_WINDOW_NAME) {
+ value = format_window_name(es, copy);
+ if (value == NULL)
+ goto fail;
+ } else if (modifiers & FORMAT_SESSION_NAME) {
+ value = format_session_name(es, copy);
+ if (value == NULL)
+ goto fail;
} else if (search != NULL) {
/* Search in pane. */
new = format_expand1(es, copy);
-.\" $OpenBSD: tmux.1,v 1.816 2021/02/02 07:33:29 jmc Exp $
+.\" $OpenBSD: tmux.1,v 1.817 2021/02/05 12:23:49 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\"
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: February 2 2021 $
+.Dd $Mdocdate: February 5 2021 $
.Dt TMUX 1
.Os
.Sh NAME
.Ic base-index
option.
.It Xo Ic new-window
-.Op Fl abdkP
+.Op Fl abdkPS
.Op Fl c Ar start-directory
.Op Fl e Ar environment
.Op Fl F Ar format
shown, unless the
.Fl k
flag is used, in which case it is destroyed.
+If
+.Fl S
+is given and a window named
+.Ar window-name
+already exists, it is selected (unless
+.Fl d
+is also given in which case the command does nothing).
+.Pp
.Ar shell-command
is the command to execute.
If
#{W:#{E:window-status-format} ,#{E:window-status-current-format} }
.Ed
.Pp
+.Ql N:\&
+checks if a window (without any suffix or with the
+.Ql w
+suffix) or a session (with the
+.Ql s
+suffix) name exists, for example
+.Ql `N/w:foo`
+is replaced with 1 if a window named
+.Ql foo
+exists.
+.Pp
A prefix of the form
.Ql s/foo/bar/:\&
will substitute