4 * Copyright (c) 2009 Jonathan Alvarado <radobobo@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>
27 * Write the entire contents of a pane to a buffer or stdout.
30 static enum cmd_retval
cmd_capture_pane_exec(struct cmd
*, struct cmdq_item
*);
32 static char *cmd_capture_pane_append(char *, size_t *, char *, size_t);
33 static char *cmd_capture_pane_pending(struct args
*, struct window_pane
*,
35 static char *cmd_capture_pane_history(struct args
*, struct cmdq_item
*,
36 struct window_pane
*, size_t *);
38 const struct cmd_entry cmd_capture_pane_entry
= {
39 .name
= "capture-pane",
42 .args
= { "ab:CeE:JNpPqS:Tt:", 0, 0, NULL
},
43 .usage
= "[-aCeJNpPqT] " CMD_BUFFER_USAGE
" [-E end-line] "
44 "[-S start-line] " CMD_TARGET_PANE_USAGE
,
46 .target
= { 't', CMD_FIND_PANE
, 0 },
48 .flags
= CMD_AFTERHOOK
,
49 .exec
= cmd_capture_pane_exec
52 const struct cmd_entry cmd_clear_history_entry
= {
53 .name
= "clear-history",
56 .args
= { "Ht:", 0, 0, NULL
},
57 .usage
= "[-H] " CMD_TARGET_PANE_USAGE
,
59 .target
= { 't', CMD_FIND_PANE
, 0 },
61 .flags
= CMD_AFTERHOOK
,
62 .exec
= cmd_capture_pane_exec
66 cmd_capture_pane_append(char *buf
, size_t *len
, char *line
, size_t linelen
)
68 buf
= xrealloc(buf
, *len
+ linelen
+ 1);
69 memcpy(buf
+ *len
, line
, linelen
);
75 cmd_capture_pane_pending(struct args
*args
, struct window_pane
*wp
,
78 struct evbuffer
*pending
;
79 char *buf
, *line
, tmp
[5];
83 pending
= input_pending(wp
->ictx
);
87 line
= EVBUFFER_DATA(pending
);
88 linelen
= EVBUFFER_LENGTH(pending
);
91 if (args_has(args
, 'C')) {
92 for (i
= 0; i
< linelen
; i
++) {
93 if (line
[i
] >= ' ' && line
[i
] != '\\') {
97 xsnprintf(tmp
, sizeof tmp
, "\\%03hho", line
[i
]);
98 buf
= cmd_capture_pane_append(buf
, len
, tmp
,
102 buf
= cmd_capture_pane_append(buf
, len
, line
, linelen
);
107 cmd_capture_pane_history(struct args
*args
, struct cmdq_item
*item
,
108 struct window_pane
*wp
, size_t *len
)
111 const struct grid_line
*gl
;
112 struct grid_cell
*gc
= NULL
;
113 int n
, join_lines
, flags
= 0;
114 u_int i
, sx
, top
, bottom
, tmp
;
115 char *cause
, *buf
, *line
;
116 const char *Sflag
, *Eflag
;
119 sx
= screen_size_x(&wp
->base
);
120 if (args_has(args
, 'a')) {
121 gd
= wp
->base
.saved_grid
;
123 if (!args_has(args
, 'q')) {
124 cmdq_error(item
, "no alternate screen");
127 return (xstrdup(""));
132 Sflag
= args_get(args
, 'S');
133 if (Sflag
!= NULL
&& strcmp(Sflag
, "-") == 0)
136 n
= args_strtonum_and_expand(args
, 'S', INT_MIN
, SHRT_MAX
,
141 } else if (n
< 0 && (u_int
) -n
> gd
->hsize
)
145 if (top
> gd
->hsize
+ gd
->sy
- 1)
146 top
= gd
->hsize
+ gd
->sy
- 1;
149 Eflag
= args_get(args
, 'E');
150 if (Eflag
!= NULL
&& strcmp(Eflag
, "-") == 0)
151 bottom
= gd
->hsize
+ gd
->sy
- 1;
153 n
= args_strtonum_and_expand(args
, 'E', INT_MIN
, SHRT_MAX
,
156 bottom
= gd
->hsize
+ gd
->sy
- 1;
158 } else if (n
< 0 && (u_int
) -n
> gd
->hsize
)
161 bottom
= gd
->hsize
+ n
;
162 if (bottom
> gd
->hsize
+ gd
->sy
- 1)
163 bottom
= gd
->hsize
+ gd
->sy
- 1;
172 join_lines
= args_has(args
, 'J');
173 if (args_has(args
, 'e'))
174 flags
|= GRID_STRING_WITH_SEQUENCES
;
175 if (args_has(args
, 'C'))
176 flags
|= GRID_STRING_ESCAPE_SEQUENCES
;
177 if (!join_lines
&& !args_has(args
, 'T'))
178 flags
|= GRID_STRING_EMPTY_CELLS
;
179 if (!join_lines
&& !args_has(args
, 'N'))
180 flags
|= GRID_STRING_TRIM_SPACES
;
183 for (i
= top
; i
<= bottom
; i
++) {
184 line
= grid_string_cells(gd
, 0, i
, sx
, &gc
, flags
, wp
->screen
);
185 linelen
= strlen(line
);
187 buf
= cmd_capture_pane_append(buf
, len
, line
, linelen
);
189 gl
= grid_peek_line(gd
, i
);
190 if (!join_lines
|| !(gl
->flags
& GRID_LINE_WRAPPED
))
191 buf
[(*len
)++] = '\n';
198 static enum cmd_retval
199 cmd_capture_pane_exec(struct cmd
*self
, struct cmdq_item
*item
)
201 struct args
*args
= cmd_get_args(self
);
202 struct client
*c
= cmdq_get_client(item
);
203 struct window_pane
*wp
= cmdq_get_target(item
)->wp
;
208 if (cmd_get_entry(self
) == &cmd_clear_history_entry
) {
209 window_pane_reset_mode_all(wp
);
210 grid_clear_history(wp
->base
.grid
);
211 if (args_has(args
, 'H'))
212 screen_reset_hyperlinks(wp
->screen
);
213 return (CMD_RETURN_NORMAL
);
217 if (args_has(args
, 'P'))
218 buf
= cmd_capture_pane_pending(args
, wp
, &len
);
220 buf
= cmd_capture_pane_history(args
, item
, wp
, &len
);
222 return (CMD_RETURN_ERROR
);
224 if (args_has(args
, 'p')) {
225 if (len
> 0 && buf
[len
- 1] == '\n')
227 if (c
->flags
& CLIENT_CONTROL
)
228 control_write(c
, "%.*s", (int)len
, buf
);
230 if (!file_can_print(c
)) {
231 cmdq_error(item
, "can't write to client");
233 return (CMD_RETURN_ERROR
);
235 file_print_buffer(c
, buf
, len
);
241 if (args_has(args
, 'b'))
242 bufname
= args_get(args
, 'b');
244 if (paste_set(buf
, len
, bufname
, &cause
) != 0) {
245 cmdq_error(item
, "%s", cause
);
248 return (CMD_RETURN_ERROR
);
252 return (CMD_RETURN_NORMAL
);