4 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
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>
28 * Split a window (add a new pane).
31 int cmd_split_window_parse(struct cmd
*, int, char **, char **);
32 int cmd_split_window_exec(struct cmd
*, struct cmd_ctx
*);
33 void cmd_split_window_free(struct cmd
*);
34 void cmd_split_window_init(struct cmd
*, int);
35 size_t cmd_split_window_print(struct cmd
*, char *, size_t);
37 struct cmd_split_window_data
{
46 const struct cmd_entry cmd_split_window_entry
= {
47 "split-window", "splitw",
48 "[-dhv] [-p percentage|-l size] [-t target-pane] [command]",
50 cmd_split_window_init
,
51 cmd_split_window_parse
,
52 cmd_split_window_exec
,
53 cmd_split_window_free
,
54 cmd_split_window_print
58 cmd_split_window_init(struct cmd
*self
, int key
)
60 struct cmd_split_window_data
*data
;
62 self
->data
= data
= xmalloc(sizeof *data
);
65 data
->flag_detached
= 0;
66 data
->flag_horizontal
= 0;
67 data
->percentage
= -1;
72 data
->flag_horizontal
= 1;
75 data
->flag_horizontal
= 0;
81 cmd_split_window_parse(struct cmd
*self
, int argc
, char **argv
, char **cause
)
83 struct cmd_split_window_data
*data
;
87 self
->entry
->init(self
, KEYC_NONE
);
90 while ((opt
= getopt(argc
, argv
, "dhl:p:t:v")) != -1) {
93 data
->flag_detached
= 1;
96 data
->flag_horizontal
= 1;
99 if (data
->target
== NULL
)
100 data
->target
= xstrdup(optarg
);
103 if (data
->percentage
!= -1 || data
->size
!= -1)
105 data
->size
= strtonum(optarg
, 1, INT_MAX
, &errstr
);
106 if (errstr
!= NULL
) {
107 xasprintf(cause
, "size %s", errstr
);
112 if (data
->size
!= -1 || data
->percentage
!= -1)
114 data
->percentage
= strtonum(optarg
, 1, 100, &errstr
);
115 if (errstr
!= NULL
) {
116 xasprintf(cause
, "percentage %s", errstr
);
121 data
->flag_horizontal
= 0;
129 if (argc
!= 0 && argc
!= 1)
133 data
->cmd
= xstrdup(argv
[0]);
138 xasprintf(cause
, "usage: %s %s", self
->entry
->name
, self
->entry
->usage
);
141 self
->entry
->free(self
);
146 cmd_split_window_exec(struct cmd
*self
, struct cmd_ctx
*ctx
)
148 struct cmd_split_window_data
*data
= self
->data
;
152 struct window_pane
*wp
, *new_wp
= NULL
;
154 char *cmd
, *cwd
, *cause
;
158 enum layout_type type
;
159 struct layout_cell
*lc
;
161 if ((wl
= cmd_find_pane(ctx
, data
->target
, &s
, &wp
)) == NULL
)
166 environ_copy(&global_environ
, &env
);
167 environ_copy(&s
->environ
, &env
);
168 server_fill_environ(s
, &env
);
172 cmd
= options_get_string(&s
->options
, "default-command");
173 cwd
= options_get_string(&s
->options
, "default-path");
175 if (ctx
->cmdclient
!= NULL
&& ctx
->cmdclient
->cwd
!= NULL
)
176 cwd
= ctx
->cmdclient
->cwd
;
181 type
= LAYOUT_TOPBOTTOM
;
182 if (data
->flag_horizontal
)
183 type
= LAYOUT_LEFTRIGHT
;
186 if (data
->size
!= -1)
188 else if (data
->percentage
!= -1) {
189 if (type
== LAYOUT_TOPBOTTOM
)
190 size
= (wp
->sy
* data
->percentage
) / 100;
192 size
= (wp
->sx
* data
->percentage
) / 100;
194 hlimit
= options_get_number(&s
->options
, "history-limit");
196 shell
= options_get_string(&s
->options
, "default-shell");
197 if (*shell
== '\0' || areshell(shell
))
198 shell
= _PATH_BSHELL
;
200 if ((lc
= layout_split_pane(wp
, type
, size
)) == NULL
) {
201 cause
= xstrdup("pane too small");
204 new_wp
= window_add_pane(w
, hlimit
);
205 if (window_pane_spawn(
206 new_wp
, cmd
, shell
, cwd
, &env
, s
->tio
, &cause
) != 0)
208 layout_assign_pane(lc
, new_wp
);
210 server_redraw_window(w
);
212 if (!data
->flag_detached
) {
213 window_set_active_pane(w
, new_wp
);
214 session_select(s
, wl
->idx
);
215 server_redraw_session(s
);
217 server_status_session(s
);
225 window_remove_pane(w
, new_wp
);
226 ctx
->error(ctx
, "create pane failed: %s", cause
);
232 cmd_split_window_free(struct cmd
*self
)
234 struct cmd_split_window_data
*data
= self
->data
;
236 if (data
->target
!= NULL
)
238 if (data
->cmd
!= NULL
)
244 cmd_split_window_print(struct cmd
*self
, char *buf
, size_t len
)
246 struct cmd_split_window_data
*data
= self
->data
;
249 off
+= xsnprintf(buf
, len
, "%s", self
->entry
->name
);
252 if (off
< len
&& data
->flag_detached
)
253 off
+= xsnprintf(buf
+ off
, len
- off
, " -d");
254 if (off
< len
&& data
->flag_horizontal
)
255 off
+= xsnprintf(buf
+ off
, len
- off
, " -h");
256 if (off
< len
&& data
->size
> 0)
257 off
+= xsnprintf(buf
+ off
, len
- off
, " -l %d", data
->size
);
258 if (off
< len
&& data
->percentage
> 0) {
260 buf
+ off
, len
- off
, " -p %d", data
->percentage
);
262 if (off
< len
&& data
->target
!= NULL
)
263 off
+= cmd_prarg(buf
+ off
, len
- off
, " -t ", data
->target
);
264 if (off
< len
&& data
->cmd
!= NULL
)
265 off
+= cmd_prarg(buf
+ off
, len
- off
, " ", data
->cmd
);