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_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
, percentage
, flags
, input
;
69 const char *template, *errstr
, *p
;
70 char *cause
, *cp
, *copy
;
72 struct args_value
*av
;
73 u_int count
= args_count(args
);
75 if (args_has(args
, 'h'))
76 type
= LAYOUT_LEFTRIGHT
;
78 type
= LAYOUT_TOPBOTTOM
;
79 if ((p
= args_get(args
, 'l')) != NULL
) {
81 if (p
[plen
- 1] == '%') {
83 copy
[plen
- 1] = '\0';
84 percentage
= strtonum(copy
, 0, INT_MAX
, &errstr
);
87 cmdq_error(item
, "percentage %s", errstr
);
88 return (CMD_RETURN_ERROR
);
90 if (type
== LAYOUT_TOPBOTTOM
)
91 size
= (wp
->sy
* percentage
) / 100;
93 size
= (wp
->sx
* percentage
) / 100;
95 size
= args_strtonum(args
, 'l', 0, INT_MAX
, &cause
);
97 cmdq_error(item
, "lines %s", cause
);
99 return (CMD_RETURN_ERROR
);
102 } else if (args_has(args
, 'p')) {
103 percentage
= args_strtonum(args
, 'p', 0, INT_MAX
, &cause
);
105 cmdq_error(item
, "create pane failed: -p %s", cause
);
107 return (CMD_RETURN_ERROR
);
109 if (type
== LAYOUT_TOPBOTTOM
)
110 size
= (wp
->sy
* percentage
) / 100;
112 size
= (wp
->sx
* percentage
) / 100;
116 window_push_zoom(wp
->window
, 1, args_has(args
, 'Z'));
117 input
= (args_has(args
, 'I') && count
== 0);
120 if (args_has(args
, 'b'))
121 flags
|= SPAWN_BEFORE
;
122 if (args_has(args
, 'f'))
123 flags
|= SPAWN_FULLSIZE
;
124 if (input
|| (count
== 1 && *args_string(args
, 0) == '\0'))
125 flags
|= SPAWN_EMPTY
;
127 lc
= layout_split_pane(wp
, type
, size
, flags
);
129 cmdq_error(item
, "no space for new pane");
130 return (CMD_RETURN_ERROR
);
140 args_to_vector(args
, &sc
.argc
, &sc
.argv
);
141 sc
.environ
= environ_create();
143 av
= args_first_value(args
, 'e');
145 environ_put(sc
.environ
, av
->string
, 0);
146 av
= args_next_value(av
);
150 sc
.cwd
= args_get(args
, 'c');
153 if (args_has(args
, 'd'))
154 sc
.flags
|= SPAWN_DETACHED
;
155 if (args_has(args
, 'Z'))
156 sc
.flags
|= SPAWN_ZOOM
;
158 if ((new_wp
= spawn_pane(&sc
, &cause
)) == NULL
) {
159 cmdq_error(item
, "create pane failed: %s", cause
);
162 cmd_free_argv(sc
.argc
, sc
.argv
);
163 environ_free(sc
.environ
);
164 return (CMD_RETURN_ERROR
);
167 switch (window_pane_start_input(new_wp
, item
, &cause
)) {
169 server_client_remove_pane(new_wp
);
170 layout_close_pane(new_wp
);
171 window_remove_pane(wp
->window
, new_wp
);
172 cmdq_error(item
, "%s", cause
);
175 cmd_free_argv(sc
.argc
, sc
.argv
);
176 environ_free(sc
.environ
);
177 return (CMD_RETURN_ERROR
);
183 if (!args_has(args
, 'd'))
184 cmd_find_from_winlink_pane(current
, wl
, new_wp
, 0);
185 window_pop_zoom(wp
->window
);
186 server_redraw_window(wp
->window
);
187 server_status_session(s
);
189 if (args_has(args
, 'P')) {
190 if ((template = args_get(args
, 'F')) == NULL
)
191 template = SPLIT_WINDOW_TEMPLATE
;
192 cp
= format_single(item
, template, tc
, s
, wl
, new_wp
);
193 cmdq_print(item
, "%s", cp
);
197 cmd_find_from_winlink_pane(&fs
, wl
, new_wp
, 0);
198 cmdq_insert_hook(s
, item
, &fs
, "after-split-window");
201 cmd_free_argv(sc
.argc
, sc
.argv
);
202 environ_free(sc
.environ
);
204 return (CMD_RETURN_WAIT
);
205 return (CMD_RETURN_NORMAL
);