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
;
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 RB_FOREACH(wl
, winlinks
, &s
->windows
) {
75 if (strcmp(wl
->window
->name
, name
) != 0)
81 cmdq_error(item
, "multiple windows named %s", name
);
82 return (CMD_RETURN_ERROR
);
85 if (args_has(args
, 'd'))
86 return (CMD_RETURN_NORMAL
);
87 if (session_set_current(s
, new_wl
) == 0)
88 server_redraw_session(s
);
89 if (c
!= NULL
&& c
->session
!= NULL
)
90 s
->curw
->window
->latest
= c
;
92 return (CMD_RETURN_NORMAL
);
96 before
= args_has(args
, 'b');
97 if (args_has(args
, 'a') || before
) {
98 idx
= winlink_shuffle_up(s
, wl
, before
);
107 sc
.name
= args_get(args
, 'n');
108 args_to_vector(args
, &sc
.argc
, &sc
.argv
);
109 sc
.environ
= environ_create();
111 av
= args_first_value(args
, 'e');
113 environ_put(sc
.environ
, av
->string
, 0);
114 av
= args_next_value(av
);
118 sc
.cwd
= args_get(args
, 'c');
121 if (args_has(args
, 'd'))
122 sc
.flags
|= SPAWN_DETACHED
;
123 if (args_has(args
, 'k'))
124 sc
.flags
|= SPAWN_KILL
;
126 if ((new_wl
= spawn_window(&sc
, &cause
)) == NULL
) {
127 cmdq_error(item
, "create window failed: %s", cause
);
130 cmd_free_argv(sc
.argc
, sc
.argv
);
131 environ_free(sc
.environ
);
132 return (CMD_RETURN_ERROR
);
134 if (!args_has(args
, 'd') || new_wl
== s
->curw
) {
135 cmd_find_from_winlink(current
, new_wl
, 0);
136 server_redraw_session_group(s
);
138 server_status_session_group(s
);
140 if (args_has(args
, 'P')) {
141 if ((template = args_get(args
, 'F')) == NULL
)
142 template = NEW_WINDOW_TEMPLATE
;
143 cp
= format_single(item
, template, tc
, s
, new_wl
,
144 new_wl
->window
->active
);
145 cmdq_print(item
, "%s", cp
);
149 cmd_find_from_winlink(&fs
, new_wl
, 0);
150 cmdq_insert_hook(s
, item
, &fs
, "after-new-window");
153 cmd_free_argv(sc
.argc
, sc
.argv
);
154 environ_free(sc
.environ
);
155 return (CMD_RETURN_NORMAL
);