Discussion:
Don't wrap the cursor in tmux in copy mode
Michal Mazurek
2016-01-26 15:32:39 UTC
Permalink
If the cursor is in position 0, 0 in copy mode, and the left arrow is
pressed, the cursor position is wrapped to the end of line. A similar
situation occurs at the last position and the right arrow. The following
patch prevents that, and makes the behaviour more consistent with other
software, such as nvi:


Index: window-copy.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/window-copy.c,v
retrieving revision 1.144
diff -u -p -r1.144 window-copy.c
--- window-copy.c 19 Jan 2016 15:59:12 -0000 1.144
+++ window-copy.c 26 Jan 2016 11:43:38 -0000
@@ -1776,10 +1776,10 @@ window_copy_cursor_left(struct window_pa
{
struct window_copy_mode_data *data = wp->modedata;

- if (data->cx == 0) {
+ if (data->cx == 0 && data->cy > 0) {
window_copy_cursor_up(wp, 0);
window_copy_cursor_end_of_line(wp);
- } else {
+ } else if (data->cx > 0) {
window_copy_update_cursor(wp, data->cx - 1, data->cy);
if (window_copy_update_selection(wp, 1))
window_copy_redraw_lines(wp, data->cy, 1);
@@ -1799,10 +1799,10 @@ window_copy_cursor_right(struct window_p
px = window_copy_find_length(wp, py);
}

- if (data->cx >= px) {
+ if (data->cx >= px && data->cy < screen_size_y(&data->screen) - 1) {
window_copy_cursor_start_of_line(wp);
window_copy_cursor_down(wp, 0);
- } else {
+ } else if (data->cx < px) {
window_copy_update_cursor(wp, data->cx + 1, data->cy);
if (window_copy_update_selection(wp, 1))
window_copy_redraw_lines(wp, data->cy, 1);


Also remove two unused variables (no binary change):

Index: cmd-swap-pane.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cmd-swap-pane.c,v
retrieving revision 1.25
diff -u -p -r1.25 cmd-swap-pane.c
--- cmd-swap-pane.c 19 Jan 2016 15:59:12 -0000 1.25
+++ cmd-swap-pane.c 26 Jan 2016 15:26:14 -0000
@@ -45,28 +45,23 @@ const struct cmd_entry cmd_swap_pane_ent
enum cmd_retval
cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
- struct winlink *src_wl, *dst_wl;
struct window *src_w, *dst_w;
struct window_pane *tmp_wp, *src_wp, *dst_wp;
struct layout_cell *src_lc, *dst_lc;
u_int sx, sy, xoff, yoff;

- dst_wl = cmdq->state.tflag.wl;
- dst_w = dst_wl->window;
+ dst_w = cmdq->state.tflag.wl->window;
dst_wp = cmdq->state.tflag.wp;
- src_wl = cmdq->state.sflag.wl;
- src_w = src_wl->window;
+ src_w = cmdq->state.sflag.wl->window;
src_wp = cmdq->state.sflag.wp;
server_unzoom_window(dst_w);

if (args_has(self->args, 'D')) {
- src_wl = dst_wl;
src_w = dst_w;
src_wp = TAILQ_NEXT(dst_wp, entry);
if (src_wp == NULL)
src_wp = TAILQ_FIRST(&dst_w->panes);
} else if (args_has(self->args, 'U')) {
- src_wl = dst_wl;
src_w = dst_w;
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
if (src_wp == NULL)
--
Michal Mazurek
Nicholas Marriott
2016-01-27 14:45:12 UTC
Permalink
Hi

tmux copy mode is not meant to work like vi, it is meant to work like
emacs, but emacs does do this so we can change it.

However, your diff is wrong. It prevents the cursor moving back when it
is at 0,0 _on screen_.

But if there is more than one screen worth of history, a left at 0,0 on
screen should scroll up one line in the history.

You can do something like "jot 1000" to generate plenty of history.
Post by Michal Mazurek
If the cursor is in position 0, 0 in copy mode, and the left arrow is
pressed, the cursor position is wrapped to the end of line. A similar
situation occurs at the last position and the right arrow. The following
patch prevents that, and makes the behaviour more consistent with other
Index: window-copy.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/window-copy.c,v
retrieving revision 1.144
diff -u -p -r1.144 window-copy.c
--- window-copy.c 19 Jan 2016 15:59:12 -0000 1.144
+++ window-copy.c 26 Jan 2016 11:43:38 -0000
@@ -1776,10 +1776,10 @@ window_copy_cursor_left(struct window_pa
{
struct window_copy_mode_data *data = wp->modedata;
- if (data->cx == 0) {
+ if (data->cx == 0 && data->cy > 0) {
window_copy_cursor_up(wp, 0);
window_copy_cursor_end_of_line(wp);
- } else {
+ } else if (data->cx > 0) {
window_copy_update_cursor(wp, data->cx - 1, data->cy);
if (window_copy_update_selection(wp, 1))
window_copy_redraw_lines(wp, data->cy, 1);
@@ -1799,10 +1799,10 @@ window_copy_cursor_right(struct window_p
px = window_copy_find_length(wp, py);
}
- if (data->cx >= px) {
+ if (data->cx >= px && data->cy < screen_size_y(&data->screen) - 1) {
window_copy_cursor_start_of_line(wp);
window_copy_cursor_down(wp, 0);
- } else {
+ } else if (data->cx < px) {
window_copy_update_cursor(wp, data->cx + 1, data->cy);
if (window_copy_update_selection(wp, 1))
window_copy_redraw_lines(wp, data->cy, 1);
Index: cmd-swap-pane.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cmd-swap-pane.c,v
retrieving revision 1.25
diff -u -p -r1.25 cmd-swap-pane.c
--- cmd-swap-pane.c 19 Jan 2016 15:59:12 -0000 1.25
+++ cmd-swap-pane.c 26 Jan 2016 15:26:14 -0000
@@ -45,28 +45,23 @@ const struct cmd_entry cmd_swap_pane_ent
enum cmd_retval
cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
- struct winlink *src_wl, *dst_wl;
struct window *src_w, *dst_w;
struct window_pane *tmp_wp, *src_wp, *dst_wp;
struct layout_cell *src_lc, *dst_lc;
u_int sx, sy, xoff, yoff;
- dst_wl = cmdq->state.tflag.wl;
- dst_w = dst_wl->window;
+ dst_w = cmdq->state.tflag.wl->window;
dst_wp = cmdq->state.tflag.wp;
- src_wl = cmdq->state.sflag.wl;
- src_w = src_wl->window;
+ src_w = cmdq->state.sflag.wl->window;
src_wp = cmdq->state.sflag.wp;
server_unzoom_window(dst_w);
if (args_has(self->args, 'D')) {
- src_wl = dst_wl;
src_w = dst_w;
src_wp = TAILQ_NEXT(dst_wp, entry);
if (src_wp == NULL)
src_wp = TAILQ_FIRST(&dst_w->panes);
} else if (args_has(self->args, 'U')) {
- src_wl = dst_wl;
src_w = dst_w;
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
if (src_wp == NULL)
--
Michal Mazurek
Michal Mazurek
2016-01-30 13:07:16 UTC
Permalink
Post by Nicholas Marriott
Hi
tmux copy mode is not meant to work like vi, it is meant to work like
emacs, but emacs does do this so we can change it.
However, your diff is wrong. It prevents the cursor moving back when it
is at 0,0 _on screen_.
Here is a fixed version:

Index: window-copy.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/window-copy.c,v
retrieving revision 1.144
diff -u -p -r1.144 window-copy.c
--- window-copy.c 19 Jan 2016 15:59:12 -0000 1.144
+++ window-copy.c 30 Jan 2016 13:00:40 -0000
@@ -1775,11 +1775,13 @@ void
window_copy_cursor_left(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
+ u_int py;

- if (data->cx == 0) {
+ py = screen_hsize(data->backing) + data->cy - data->oy;
+ if (data->cx == 0 && py > 0) {
window_copy_cursor_up(wp, 0);
window_copy_cursor_end_of_line(wp);
- } else {
+ } else if (data->cx > 0) {
window_copy_update_cursor(wp, data->cx - 1, data->cy);
if (window_copy_update_selection(wp, 1))
window_copy_redraw_lines(wp, data->cy, 1);
@@ -1790,19 +1792,20 @@ void
window_copy_cursor_right(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
- u_int px, py;
+ u_int px, py, yy;

+ py = screen_hsize(data->backing) + data->cy - data->oy;
+ yy = screen_hsize(data->backing) + screen_size_y(data->backing) - 1;
if (data->screen.sel.flag && data->rectflag)
px = screen_size_x(&data->screen);
else {
- py = screen_hsize(data->backing) + data->cy - data->oy;
px = window_copy_find_length(wp, py);
}

- if (data->cx >= px) {
+ if (data->cx >= px && py < yy) {
window_copy_cursor_start_of_line(wp);
window_copy_cursor_down(wp, 0);
- } else {
+ } else if (data->cx < px) {
window_copy_update_cursor(wp, data->cx + 1, data->cy);
if (window_copy_update_selection(wp, 1))
window_copy_redraw_lines(wp, data->cy, 1);
--
Michal Mazurek
Loading...