threads / patch / 27381

patchadd -i: ignore terminal escape sequences

Subject: [PATCH] add -i: ignore terminal escape sequences

## tl;dr

6 messages between May 17, 2011 and May 18, 2011. Diffs are folded; open one to read it.

replies: 5people: 4as markdown or json

trast@student.ethz.ch· May 17, 2011, 15:19 UTC · lore
From: Thomas Rast <trast@student.ethz.ch>

On the author's terminal, the up-arrow input sequence is ^[[A, and thus fat-fingering an up-arrow into 'git checkout -p' is quite dangerous: git-add--interactive.perl will ignore the ^[ and [ characters and happily treat A as "discard everything".

As a band-aid fix, use Term::Cap to get all terminal capabilities. Then use the heuristic that any capability value that starts with ^[ (i.e., \e in perl) must be a key input sequence. Finally, given an input that starts with ^[, read more characters until we have read a full escape sequence, then return that to the caller. We use a timeout of 0.5 seconds on the subsequent reads to avoid getting stuck if the user actually input a lone ^[.

Since none of the currently recognized keys start with ^[, the net result is that the sequence as a whole will be ignored and the help displayed.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---

I nearly managed to lose a bunch of uncommitted work today, but could salvage most of it from the pieces of diffs in the terminal scrollback. Sigh.

Future work might include mapping such sequences to the keys they represent, so that (shift) up-arrow can be k (K) and (shift) down-arrow j (J), or some such.

Oh yeah, PS: I'm alive ;-)
 git-add--interactive.perl |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)
Show changes to git-add--interactive.perl +19 −0
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 4f08fe7..8f0839d 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -45,6 +45,9 @@
 my $normal_color = $repo->get_color("", "reset");
 
 my $use_readkey = 0;
+my $use_termcap = 0;
+my %term_escapes;
+
 sub ReadMode;
 sub ReadKey;
 if ($repo->config_bool("interactive.singlekey")) {
@@ -53,6 +56,14 @@
 		Term::ReadKey->import;
 		$use_readkey = 1;
 	};
+	eval {
+		require Term::Cap;
+		my $termcap = Term::Cap->Tgetent;
+		foreach (values %$termcap) {
+			$term_escapes{$_} = 1 if /^\e/;
+		}
+		$use_termcap = 1;
+	};
 }
 
 sub colored {
@@ -1067,6 +1078,14 @@ sub prompt_single_character {
 		ReadMode 'cbreak';
 		my $key = ReadKey 0;
 		ReadMode 'restore';
+		if ($use_termcap and $key eq "\e") {
+			while (!defined $term_escapes{$key}) {
+				my $next = ReadKey 0.5;
+				last if (!defined $next);
+				$key .= $next;
+			}
+			$key =~ s/\e/^[/;
+		}
 		print "$key" if defined $key;
 		print "\n";
 		return $key;
-- 
1.7.5.1.520.g98107.dirty
Junio C Hamano· May 18, 2011, 03:52 UTC · re: trast@student.ethz.ch · lore

Re: [PATCH] add -i: ignore terminal escape sequences

<trast@student.ethz.ch> writes:
> I nearly managed to lose a bunch of uncommitted work today, but could
> salvage most of it from the pieces of diffs in the terminal
> scrollback.  Sigh.

I think the take-home lesson is that confirmation offered in the default mode is valuable. The "single-key" mode is another long rope that I would not use myself, but the users can choose to hang themselves with.

Jokes aside, it may make sense to offer an extra confirmation for "a" and possibly "s" in single-key mode. Unlike others, they are destructive when the changes you are splitting from the working tree is large-ish.

> Oh yeah, PS: I'm alive ;-)
Good to hear.
Sverre Rabbelier· May 18, 2011, 04:37 UTC · re: Junio C Hamano · lore

Re: [PATCH] add -i: ignore terminal escape sequences

Heya,
On Tue, May 17, 2011 at 20:52, Junio C Hamano <gitster@pobox.com> wrote:
> Jokes aside, it may make sense to offer an extra confirmation for "a" and
> possibly "s" in single-key mode. Unlike others, they are destructive when
> the changes you are splitting from the working tree is large-ish.

I don't understand why/how 's' is destructive? Doesn't it just ask you again for each of the split hunks?

-- 
Cheers,

Sverre Rabbelier
Junio C Hamano· May 18, 2011, 05:03 UTC · re: Sverre Rabbelier · lore

Re: [PATCH] add -i: ignore terminal escape sequences

Sverre Rabbelier <srabbelier@gmail.com> writes:
Show 7 quoted lines
> On Tue, May 17, 2011 at 20:52, Junio C Hamano <gitster@pobox.com> wrote:
>> Jokes aside, it may make sense to offer an extra confirmation for "a" and
>> possibly "s" in single-key mode. Unlike others, they are destructive when
>> the changes you are splitting from the working tree is large-ish.
>
> I don't understand why/how 's' is destructive? Doesn't it just ask you
> again for each of the split hunks?

I think "add -p" used to have an internal mechanism to merge the adjacent split hunks back to a single hunk, so if we wanted to we could have given users a way to recover from a mistaken "s"plit, but I don't think we kept that code, so there is no way to properly "recover" from such a mistake.

Yes, it may be just the matter of two easy keystrokes, either yy or nn, to recover from such a mistake, and that is why I said "possibly". It is nevertheless destructive in the sense that you cannot recover without quitting the current session and restarting.

Of course Thomas could have simply done "reset" and started from scratch, so in that sense nothing is destructive, but we are not talking about the kind of destructive operations you cannot possibly recover without typing everything again.

Jeff King· May 18, 2011, 05:54 UTC · re: Junio C Hamano · lore

Re: [PATCH] add -i: ignore terminal escape sequences

On Tue, May 17, 2011 at 10:03:03PM -0700, Junio C Hamano wrote:
Show 14 quoted lines
> I think "add -p" used to have an internal mechanism to merge the adjacent
> split hunks back to a single hunk, so if we wanted to we could have given
> users a way to recover from a mistaken "s"plit, but I don't think we kept
> that code, so there is no way to properly "recover" from such a mistake.
> 
> Yes, it may be just the matter of two easy keystrokes, either yy or nn, to
> recover from such a mistake, and that is why I said "possibly". It is
> nevertheless destructive in the sense that you cannot recover without
> quitting the current session and restarting.
> 
> Of course Thomas could have simply done "reset" and started from scratch,
> so in that sense nothing is destructive, but we are not talking about the
> kind of destructive operations you cannot possibly recover without typing
> everything again.

I'm not that concerned about these type of destructive operations, which might waste a few seconds or a minute of your time. But Thomas' original email indicated he was using "git checkout -p", which _is_ destructive in a much bigger way, because a "y" overwrites worktree files which do not otherwise have a backup (even "reset -p" leaves unreferenced blobs that used to be in the index).

-Peff
Thomas Rast· May 18, 2011, 07:33 UTC · re: Jeff King · lore

Re: [PATCH] add -i: ignore terminal escape sequences

Jeff King wrote:
Show 13 quoted lines
> On Tue, May 17, 2011 at 10:03:03PM -0700, Junio C Hamano wrote:
> 
> > Of course Thomas could have simply done "reset" and started from scratch,
> > so in that sense nothing is destructive, but we are not talking about the
> > kind of destructive operations you cannot possibly recover without typing
> > everything again.
> 
> I'm not that concerned about these type of destructive operations, which
> might waste a few seconds or a minute of your time. But Thomas' original
> email indicated he was using "git checkout -p", which _is_ destructive
> in a much bigger way, because a "y" overwrites worktree files which do
> not otherwise have a backup (even "reset -p" leaves unreferenced blobs
> that used to be in the index).

Indeed. I wouldn't be complaining if I typed "a" or "y", but 'checkout -p' trashed all my changes to a file because it treated the up-arrow as an "a". We should not accidentally "bind" things to extra keys, much less dangerous ones. The fact that up-arrow is ^[[A is an implementation detail.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

← back to recent threads