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>
30 * Split a window (add a new pane).
33 #define SPLIT_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
35 static enum cmd_retval
cmd_split_window_exec(struct cmd
*,
38 const struct cmd_entry cmd_split_window_entry
= {
39 .name
= "split-window",
42 .args
= { "bc:de:fF:hIl:p:Pt:vZ", 0, -1, NULL
},
43 .usage
= "[-bdefhIPvZ] [-c start-directory] [-e environment] "
44 "[-F format] [-l size] " CMD_TARGET_PANE_USAGE
47 .target
= { 't', CMD_FIND_PANE
, 0 },
50 .exec
= cmd_split_window_exec
53 static enum cmd_retval
54 cmd_split_window_exec(struct cmd
*self
, struct cmdq_item
*item
)
56 struct args
*args
= cmd_get_args(self
);
57 struct cmd_find_state
*current
= cmdq_get_current(item
);
58 struct cmd_find_state
*target
= cmdq_get_target(item
);
59 struct spawn_context sc
= { 0 };
60 struct client
*tc
= cmdq_get_target_client(item
);
61 struct session
*s
= target
->s
;
62 struct winlink
*wl
= target
->wl
;
63 struct window
*w
= wl
->window
;
64 struct window_pane
*wp
= target
->wp
, *new_wp
;
65 enum layout_type type
;
66 struct layout_cell
*lc
;
67 struct cmd_find_state fs
;
68 int size
, flags
, input
;
70 char *cause
= NULL
, *cp
;
71 struct args_value
*av
;
72 u_int count
= args_count(args
), curval
= 0;
74 type
= LAYOUT_TOPBOTTOM
;
75 if (args_has(args
, 'h'))
76 type
= LAYOUT_LEFTRIGHT
;
78 /* If the 'p' flag is dropped then this bit can be moved into 'l'. */
79 if (args_has(args
, 'l') || args_has(args
, 'p')) {
80 if (args_has(args
, 'f')) {
81 if (type
== LAYOUT_TOPBOTTOM
)
86 if (type
== LAYOUT_TOPBOTTOM
)
94 if (args_has(args
, 'l')) {
95 size
= args_percentage_and_expand(args
, 'l', 0, INT_MAX
, curval
,
97 } else if (args_has(args
, 'p')) {
98 size
= args_strtonum_and_expand(args
, 'l', 0, 100, item
,
101 size
= curval
* size
/ 100;
104 cmdq_error(item
, "size %s", cause
);
106 return (CMD_RETURN_ERROR
);
109 window_push_zoom(wp
->window
, 1, args_has(args
, 'Z'));
110 input
= (args_has(args
, 'I') && count
== 0);
113 if (args_has(args
, 'b'))
114 flags
|= SPAWN_BEFORE
;
115 if (args_has(args
, 'f'))
116 flags
|= SPAWN_FULLSIZE
;
117 if (input
|| (count
== 1 && *args_string(args
, 0) == '\0'))
118 flags
|= SPAWN_EMPTY
;
120 lc
= layout_split_pane(wp
, type
, size
, flags
);
122 cmdq_error(item
, "no space for new pane");
123 return (CMD_RETURN_ERROR
);
133 args_to_vector(args
, &sc
.argc
, &sc
.argv
);
134 sc
.environ
= environ_create();
136 av
= args_first_value(args
, 'e');
138 environ_put(sc
.environ
, av
->string
, 0);
139 av
= args_next_value(av
);
143 sc
.cwd
= args_get(args
, 'c');
146 if (args_has(args
, 'd'))
147 sc
.flags
|= SPAWN_DETACHED
;
148 if (args_has(args
, 'Z'))
149 sc
.flags
|= SPAWN_ZOOM
;
151 if ((new_wp
= spawn_pane(&sc
, &cause
)) == NULL
) {
152 cmdq_error(item
, "create pane failed: %s", cause
);
155 cmd_free_argv(sc
.argc
, sc
.argv
);
156 environ_free(sc
.environ
);
157 return (CMD_RETURN_ERROR
);
160 switch (window_pane_start_input(new_wp
, item
, &cause
)) {
162 server_client_remove_pane(new_wp
);
163 layout_close_pane(new_wp
);
164 window_remove_pane(wp
->window
, new_wp
);
165 cmdq_error(item
, "%s", cause
);
168 cmd_free_argv(sc
.argc
, sc
.argv
);
169 environ_free(sc
.environ
);
170 return (CMD_RETURN_ERROR
);
176 if (!args_has(args
, 'd'))
177 cmd_find_from_winlink_pane(current
, wl
, new_wp
, 0);
178 window_pop_zoom(wp
->window
);
179 server_redraw_window(wp
->window
);
180 server_status_session(s
);
182 if (args_has(args
, 'P')) {
183 if ((template = args_get(args
, 'F')) == NULL
)
184 template = SPLIT_WINDOW_TEMPLATE
;
185 cp
= format_single(item
, template, tc
, s
, wl
, new_wp
);
186 cmdq_print(item
, "%s", cp
);
190 cmd_find_from_winlink_pane(&fs
, wl
, new_wp
, 0);
191 cmdq_insert_hook(s
, item
, &fs
, "after-split-window");
194 cmd_free_argv(sc
.argc
, sc
.argv
);
195 environ_free(sc
.environ
);
197 return (CMD_RETURN_WAIT
);
198 return (CMD_RETURN_NORMAL
);