4 * Copyright (c) 2009 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>
31 * Split a window (add a new pane).
34 #define SPLIT_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
36 static enum cmd_retval
cmd_split_window_exec(struct cmd
*,
39 const struct cmd_entry cmd_split_window_entry
= {
40 .name
= "split-window",
43 .args
= { "bc:de:fF:hIl:p:Pt:vZ", 0, -1, NULL
},
44 .usage
= "[-bdefhIPvZ] [-c start-directory] [-e environment] "
45 "[-F format] [-l size] " CMD_TARGET_PANE_USAGE
48 .target
= { 't', CMD_FIND_PANE
, 0 },
51 .exec
= cmd_split_window_exec
54 static enum cmd_retval
55 cmd_split_window_exec(struct cmd
*self
, struct cmdq_item
*item
)
57 struct args
*args
= cmd_get_args(self
);
58 struct cmd_find_state
*current
= cmdq_get_current(item
);
59 struct cmd_find_state
*target
= cmdq_get_target(item
);
60 struct spawn_context sc
= { 0 };
61 struct client
*tc
= cmdq_get_target_client(item
);
62 struct session
*s
= target
->s
;
63 struct winlink
*wl
= target
->wl
;
64 struct window
*w
= wl
->window
;
65 struct window_pane
*wp
= target
->wp
, *new_wp
;
66 enum layout_type type
;
67 struct layout_cell
*lc
;
68 struct cmd_find_state fs
;
69 int size
, flags
, input
;
71 char *cause
= NULL
, *cp
;
72 struct args_value
*av
;
73 u_int count
= args_count(args
), curval
= 0;
75 type
= LAYOUT_TOPBOTTOM
;
76 if (args_has(args
, 'h'))
77 type
= LAYOUT_LEFTRIGHT
;
79 /* If the 'p' flag is dropped then this bit can be moved into 'l'. */
80 if (args_has(args
, 'l') || args_has(args
, 'p')) {
81 if (args_has(args
, 'f')) {
82 if (type
== LAYOUT_TOPBOTTOM
)
87 if (type
== LAYOUT_TOPBOTTOM
)
95 if (args_has(args
, 'l')) {
96 size
= args_percentage_and_expand(args
, 'l', 0, INT_MAX
, curval
,
98 } else if (args_has(args
, 'p')) {
99 size
= args_strtonum_and_expand(args
, 'p', 0, 100, item
,
102 size
= curval
* size
/ 100;
105 cmdq_error(item
, "size %s", cause
);
107 return (CMD_RETURN_ERROR
);
110 window_push_zoom(wp
->window
, 1, args_has(args
, 'Z'));
111 input
= (args_has(args
, 'I') && count
== 0);
114 if (args_has(args
, 'b'))
115 flags
|= SPAWN_BEFORE
;
116 if (args_has(args
, 'f'))
117 flags
|= SPAWN_FULLSIZE
;
118 if (input
|| (count
== 1 && *args_string(args
, 0) == '\0'))
119 flags
|= SPAWN_EMPTY
;
121 lc
= layout_split_pane(wp
, type
, size
, flags
);
123 cmdq_error(item
, "no space for new pane");
124 return (CMD_RETURN_ERROR
);
134 args_to_vector(args
, &sc
.argc
, &sc
.argv
);
135 sc
.environ
= environ_create();
137 av
= args_first_value(args
, 'e');
139 environ_put(sc
.environ
, av
->string
, 0);
140 av
= args_next_value(av
);
144 sc
.cwd
= args_get(args
, 'c');
147 if (args_has(args
, 'd'))
148 sc
.flags
|= SPAWN_DETACHED
;
149 if (args_has(args
, 'Z'))
150 sc
.flags
|= SPAWN_ZOOM
;
152 if ((new_wp
= spawn_pane(&sc
, &cause
)) == NULL
) {
153 cmdq_error(item
, "create pane failed: %s", cause
);
156 cmd_free_argv(sc
.argc
, sc
.argv
);
157 environ_free(sc
.environ
);
158 return (CMD_RETURN_ERROR
);
161 switch (window_pane_start_input(new_wp
, item
, &cause
)) {
163 server_client_remove_pane(new_wp
);
164 layout_close_pane(new_wp
);
165 window_remove_pane(wp
->window
, new_wp
);
166 cmdq_error(item
, "%s", cause
);
169 cmd_free_argv(sc
.argc
, sc
.argv
);
170 environ_free(sc
.environ
);
171 return (CMD_RETURN_ERROR
);
177 if (!args_has(args
, 'd'))
178 cmd_find_from_winlink_pane(current
, wl
, new_wp
, 0);
179 window_pop_zoom(wp
->window
);
180 server_redraw_window(wp
->window
);
181 server_status_session(s
);
183 if (args_has(args
, 'P')) {
184 if ((template = args_get(args
, 'F')) == NULL
)
185 template = SPLIT_WINDOW_TEMPLATE
;
186 cp
= format_single(item
, template, tc
, s
, wl
, new_wp
);
187 cmdq_print(item
, "%s", cp
);
191 cmd_find_from_winlink_pane(&fs
, wl
, new_wp
, 0);
192 cmdq_insert_hook(s
, item
, &fs
, "after-split-window");
195 cmd_free_argv(sc
.argc
, sc
.argv
);
196 environ_free(sc
.environ
);
198 return (CMD_RETURN_WAIT
);
199 return (CMD_RETURN_NORMAL
);