From 82e0165c49b85ab95663d677fc7d0249b2a4efae Mon Sep 17 00:00:00 2001
From: Nicholas Marriott <nicm@openbsd.org>
Date: Mon, 28 Mar 2011 20:17:39 +0000
Subject: [PATCH] Allow a start and end line to be specified for capture-pane
 which may be negative to capture part of the history. Prompted by request
 from Victor J Orlikowski.

---
 cmd-capture-pane.c | 40 ++++++++++++++++++++++++++++++++++------
 tmux.1             |  9 +++++++++
 2 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c
index 6efbfe97..52f5455c 100644
--- a/cmd-capture-pane.c
+++ b/cmd-capture-pane.c
@@ -31,8 +31,8 @@ int	cmd_capture_pane_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_capture_pane_entry = {
 	"capture-pane", "capturep",
-	"b:t:", 0, 0,
-	"[-b buffer-index] [-t target-pane]",
+	"b:E:S:t:", 0, 0,
+	"[-b buffer-index] [-E end-line] [-S start-line] [-t target-pane]",
 	0,
 	NULL,
 	NULL,
@@ -46,19 +46,47 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
 	struct window_pane	*wp;
 	char 			*buf, *line, *cause;
 	struct screen		*s;
-	int			 buffer;
-	u_int			 i, limit;
+	struct grid		*gd;
+	int			 buffer, n;
+	u_int			 i, limit, top, bottom, tmp;
 	size_t         		 len, linelen;
 
 	if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
 		return (-1);
 	s = &wp->base;
+	gd = s->grid;
 
 	buf = NULL;
 	len = 0;
 
-	for (i = 0; i < screen_size_y(s); i++) {
-	       line = grid_view_string_cells(s->grid, 0, i, screen_size_x(s));
+	n = args_strtonum(args, 'S', SHRT_MIN, SHRT_MAX, &cause);
+	if (cause != NULL)
+		top = gd->hsize;
+	else if (n < 0 && (u_int) -n > gd->hsize)
+		top = 0;
+	else
+		top = gd->hsize + n;
+	if (top > gd->hsize + gd->sy - 1)
+		top = gd->hsize + gd->sy - 1;
+
+	n = args_strtonum(args, 'E', SHRT_MIN, SHRT_MAX, &cause);
+	if (cause != NULL)
+		bottom = gd->hsize + gd->sy - 1;
+	else if (n < 0 && (u_int) -n > gd->hsize)
+		bottom = 0;
+	else
+		bottom = gd->hsize + n;
+	if (bottom > gd->hsize + gd->sy - 1)
+		bottom = gd->hsize + gd->sy - 1;
+
+	if (bottom < top) {
+		tmp = bottom;
+		bottom = top;
+		top = tmp;
+	}
+
+	for (i = top; i <= bottom; i++) {
+	       line = grid_string_cells(s->grid, 0, i, screen_size_x(s));
 	       linelen = strlen(line);
 
 	       buf = xrealloc(buf, 1, len + linelen + 1);
diff --git a/tmux.1 b/tmux.1
index d69321dd..bbd8a80e 100644
--- a/tmux.1
+++ b/tmux.1
@@ -953,11 +953,20 @@ If
 is given, the new window does not become the current window.
 .It Xo Ic capture-pane
 .Op Fl b Ar buffer-index
+.Op Fl E Ar end-line
+.Op Fl S Ar start-line
 .Op Fl t Ar target-pane
 .Xc
 .D1 (alias: Ic capturep )
 Capture the contents of a pane to the specified buffer, or a new buffer if none
 is specified.
+.Pp
+.Fl S
+and
+.Fl E
+specify the starting and ending line numbers, zero is the first line of the
+visible pane and negative numbers are lines in the history.
+The default is to capture only the visible contents of the pane.
 .It Xo
 .Ic choose-client
 .Op Fl t Ar target-window