4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
30 * Create a new window.
33 #define NEW_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
35 static enum cmd_retval
cmd_new_window_exec(struct cmd
*, struct cmdq_item
*);
37 const struct cmd_entry cmd_new_window_entry
= {
41 .args
= { "abc:de:F:kn:PSt:", 0, -1, NULL
},
42 .usage
= "[-abdkPS] [-c start-directory] [-e environment] [-F format] "
43 "[-n window-name] " CMD_TARGET_WINDOW_USAGE
" [shell-command]",
45 .target
= { 't', CMD_FIND_WINDOW
, CMD_FIND_WINDOW_INDEX
},
48 .exec
= cmd_new_window_exec
51 static enum cmd_retval
52 cmd_new_window_exec(struct cmd
*self
, struct cmdq_item
*item
)
54 struct args
*args
= cmd_get_args(self
);
55 struct client
*c
= cmdq_get_client(item
);
56 struct cmd_find_state
*current
= cmdq_get_current(item
);
57 struct cmd_find_state
*target
= cmdq_get_target(item
);
58 struct spawn_context sc
= { 0 };
59 struct client
*tc
= cmdq_get_target_client(item
);
60 struct session
*s
= target
->s
;
61 struct winlink
*wl
= target
->wl
, *new_wl
= NULL
;
62 int idx
= target
->idx
, before
;
63 char *cause
= NULL
, *cp
, *expanded
;
64 const char *template, *name
;
65 struct cmd_find_state fs
;
66 struct args_value
*av
;
69 * If -S and -n are given and -t is not and a single window with this
70 * name already exists, select it.
72 name
= args_get(args
, 'n');
73 if (args_has(args
, 'S') && name
!= NULL
&& target
->idx
== -1) {
74 expanded
= format_single(item
, name
, c
, s
, NULL
, NULL
);
75 RB_FOREACH(wl
, winlinks
, &s
->windows
) {
76 if (strcmp(wl
->window
->name
, expanded
) != 0)
82 cmdq_error(item
, "multiple windows named %s", name
);
84 return (CMD_RETURN_ERROR
);
88 if (args_has(args
, 'd'))
89 return (CMD_RETURN_NORMAL
);
90 if (session_set_current(s
, new_wl
) == 0)
91 server_redraw_session(s
);
92 if (c
!= NULL
&& c
->session
!= NULL
)
93 s
->curw
->window
->latest
= c
;
95 return (CMD_RETURN_NORMAL
);
99 before
= args_has(args
, 'b');
100 if (args_has(args
, 'a') || before
) {
101 idx
= winlink_shuffle_up(s
, wl
, before
);
110 sc
.name
= args_get(args
, 'n');
111 args_to_vector(args
, &sc
.argc
, &sc
.argv
);
112 sc
.environ
= environ_create();
114 av
= args_first_value(args
, 'e');
116 environ_put(sc
.environ
, av
->string
, 0);
117 av
= args_next_value(av
);
121 sc
.cwd
= args_get(args
, 'c');
124 if (args_has(args
, 'd'))
125 sc
.flags
|= SPAWN_DETACHED
;
126 if (args_has(args
, 'k'))
127 sc
.flags
|= SPAWN_KILL
;
129 if ((new_wl
= spawn_window(&sc
, &cause
)) == NULL
) {
130 cmdq_error(item
, "create window failed: %s", cause
);
133 cmd_free_argv(sc
.argc
, sc
.argv
);
134 environ_free(sc
.environ
);
135 return (CMD_RETURN_ERROR
);
137 if (!args_has(args
, 'd') || new_wl
== s
->curw
) {
138 cmd_find_from_winlink(current
, new_wl
, 0);
139 server_redraw_session_group(s
);
141 server_status_session_group(s
);
143 if (args_has(args
, 'P')) {
144 if ((template = args_get(args
, 'F')) == NULL
)
145 template = NEW_WINDOW_TEMPLATE
;
146 cp
= format_single(item
, template, tc
, s
, new_wl
,
147 new_wl
->window
->active
);
148 cmdq_print(item
, "%s", cp
);
152 cmd_find_from_winlink(&fs
, new_wl
, 0);
153 cmdq_insert_hook(s
, item
, &fs
, "after-new-window");
156 cmd_free_argv(sc
.argc
, sc
.argv
);
157 environ_free(sc
.environ
);
158 return (CMD_RETURN_NORMAL
);