From f803d706dc6158001f1fa0bc4abe4915990cc2f6 Mon Sep 17 00:00:00 2001
From: Benno Schulenberg <bensberg@telfort.nl>
Date: Sun, 28 Oct 2018 17:20:18 +0100
Subject: [PATCH] possible feature: the ability to set an anchor to which one
 can jump back

A first press of the anchor key (M-' by default) will place the anchor
on the current line.  When M-' is pressed again later, the cursor will
jump back to the start of the line where the anchor was placed, and
then the anchor is cleared.

The anchor is thus like an ephemeral bookmark: it disappears as soon
as you return to it.  This is done so that it can be managed with a
single key.

The line number of the anchor line is adjusted when lines are added or
deleted before it.

The anchor is not visible in any way.
---
 src/cut.c    | 19 ++++++++++++++++++-
 src/files.c  |  1 +
 src/global.c |  5 +++++
 src/nano.h   |  2 ++
 src/proto.h  |  1 +
 src/text.c   | 20 ++++++++++++++++++++
 6 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/src/cut.c b/src/cut.c
index 13ed91a4..4fdad5d0 100644
--- a/src/cut.c
+++ b/src/cut.c
@@ -87,6 +87,10 @@ void do_deletion(undo_type action)
 			openfile->mark = openfile->current;
 			openfile->mark_x += openfile->current_x;
 		}
+
+		/* When there's an anchor after the current line, adjust it. */
+		if (openfile->anchored > openfile->current->lineno)
+			openfile->anchored--;
 #endif
 		unlink_node(joining);
 		renumber_from(openfile->current);
@@ -226,6 +230,12 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
 
 	if (top == bot && top_x == bot_x)
 		return;
+
+	/* When an anchor is after or in the cut piece, adjust it. */
+	if (openfile->anchored > bot->lineno)
+		openfile->anchored -= (bot->lineno - top->lineno);
+	else if (openfile->anchored > top->lineno)
+		openfile->anchored = top->lineno;
 #endif
 
 	/* Reduce the buffer to cover just the text that needs to be extracted. */
@@ -299,6 +309,7 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
  * at the current cursor position. */
 void ingraft_buffer(linestruct *topline)
 {
+	size_t was_lineno = openfile->current->lineno;
 	size_t current_x_save = openfile->current_x;
 	/* Remember whether the current line is at the top of the edit window. */
 	bool edittop_inside = (openfile->edittop == openfile->current);
@@ -318,8 +329,10 @@ void ingraft_buffer(linestruct *topline)
 	/* Replace the current buffer with the passed buffer. */
 	openfile->filetop = topline;
 	openfile->filebot = topline;
-	while (openfile->filebot->next != NULL)
+	while (openfile->filebot->next != NULL) {
 		openfile->filebot = openfile->filebot->next;
+		openfile->filebot->lineno = openfile->filebot->prev->lineno + 1;
+	}
 
 	/* Put the cursor at the end of the pasted text. */
 	openfile->current = openfile->filebot;
@@ -340,6 +353,10 @@ void ingraft_buffer(linestruct *topline)
 		} else
 			openfile->mark = openfile->filetop;
 	}
+
+	/* When an anchor is after the grafting point, adjust it. */
+	if (openfile->anchored > was_lineno)
+		openfile->anchored += (openfile->filebot->lineno - openfile->filetop->lineno);
 #endif
 
 	/* Add the number of characters in the copied text to the file size. */
diff --git a/src/files.c b/src/files.c
index beffa263..19d63bc7 100644
--- a/src/files.c
+++ b/src/files.c
@@ -107,6 +107,7 @@ void make_new_buffer(void)
 #endif
 #ifndef NANO_TINY
 	openfile->mark = NULL;
+	openfile->anchored = 0;
 
 	openfile->fmt = NIX_FILE;
 
diff --git a/src/global.c b/src/global.c
index d73bdcd0..979d3704 100644
--- a/src/global.c
+++ b/src/global.c
@@ -624,6 +624,7 @@ void shortcut_init(void)
 		N_("Comment/uncomment the current line (or marked lines)");
 #endif
 	const char *savefile_gist = N_("Save file without prompting");
+	const char *anchor_gist = N_("Place an anchor, or jump to it and clear it");
 	const char *findprev_gist = N_("Search next occurrence backward");
 	const char *findnext_gist = N_("Search next occurrence forward");
 #ifndef NANO_TINY
@@ -984,6 +985,9 @@ void shortcut_init(void)
 	add_to_funcs(run_macro, MMAIN,
 		N_("Run Macro"), WITHORSANS(runmacro_gist), BLANKAFTER, VIEW);
 
+	add_to_funcs(do_anchor, MMAIN,
+		N_("Anchor"), WITHORSANS(anchor_gist), BLANKAFTER, VIEW);
+
 	add_to_funcs(zap_text, MMAIN,
 		N_("Zap Text"), WITHORSANS(zap_gist), BLANKAFTER, NOVIEW);
 
@@ -1141,6 +1145,7 @@ void shortcut_init(void)
 	add_to_sclist(MMAIN, "M-A", 0, do_mark, 0);
 	add_to_sclist(MMAIN, "^6", 0, do_mark, 0);
 	add_to_sclist(MMAIN, "^^", 0, do_mark, 0);
+	add_to_sclist(MMAIN, "M-'", 0, do_anchor, 0);
 	add_to_sclist(MMAIN, "M-6", 0, copy_text, 0);
 	add_to_sclist(MMAIN, "M-^", 0, copy_text, 0);
 	add_to_sclist(MMAIN, "M-}", 0, do_indent, 0);
diff --git a/src/nano.h b/src/nano.h
index ba05501c..299c6e31 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -381,6 +381,8 @@ typedef struct openfilestruct {
 		/* The mark's x position in the above line. */
 	mark_type kind_of_mark;
 		/* Whether it is a soft (with Shift) or a hard mark. */
+	size_t anchored;
+		/* The line number of the line where the "anchor" was dropped. */
 	format_type fmt;
 		/* The file's format -- Unix or DOS or Mac or mixed. */
 	char *lock_filename;
diff --git a/src/proto.h b/src/proto.h
index 8850c735..9d63c19e 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -507,6 +507,7 @@ void do_find_bracket(void);
 /* Most functions in text.c. */
 #ifndef NANO_TINY
 void do_mark(void);
+void do_anchor(void);
 #endif
 void do_tab(void);
 #ifndef NANO_TINY
diff --git a/src/text.c b/src/text.c
index 78af48f0..02ed5a7d 100644
--- a/src/text.c
+++ b/src/text.c
@@ -61,6 +61,22 @@ void do_mark(void)
 		refresh_needed = TRUE;
 	}
 }
+
+/* Place an anchor when none exists, otherwise jump to it and clear it. */
+void do_anchor(void)
+{
+	if (openfile->anchored == 0) {
+		openfile->anchored = openfile->current->lineno;
+		statusbar(_("Placed anchor"));
+	} else {
+		openfile->current = line_from_number(openfile->anchored);
+		openfile->current_x = 0;
+		openfile->placewewant = 0;
+		statusbar(_("Jumped to anchor and cleared it"));
+		openfile->anchored = 0;
+		refresh_needed = TRUE;
+	}
+}
 #endif /* !NANO_TINY */
 
 /* Insert a tab.  If the TABS_TO_SPACES flag is set, insert the number
@@ -896,6 +912,10 @@ void do_enter(void)
 		openfile->mark = newnode;
 		openfile->mark_x += extra - openfile->current_x;
 	}
+
+	/* When an anchor is after the current line, adjust it. */
+	if (openfile->anchored > openfile->current->lineno)
+		openfile->anchored++;
 #endif
 
 	/* Insert the newly created line after the current one and renumber. */
-- 
2.24.1

