>From a0e7bfb791703f140fdbe3aee5c24f490945228c Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 7 Sep 2015 17:10:03 +0000 Subject: [PATCH 3/3] accept-line, accept-and-hold, accept-and-infer-next-history: Strip trailing newline after paste. --- Src/Zle/zle_hist.c | 4 ++++ Src/Zle/zle_misc.c | 25 +++++++++++++++++++++++++ Src/utils.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index c61b4ef..c3d7c1a 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -1728,12 +1728,16 @@ infernexthist(Histent he, UNUSED(char **args)) return NULL; } +/* Defined in zle_misc.c */ +void zle_strip_trailing_newline_if_after_paste(void); + /**/ int acceptandinfernexthistory(char **args) { Histent he; + zle_strip_trailing_newline_if_after_paste(); if (!(he = infernexthist(hist_ring, args))) return 1; zpushnode(bufstack, ztrdup(he->node.nam)); diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index c1005dc..dac31bf 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -395,10 +395,34 @@ poundinsert(UNUSED(char **args)) return 0; } +/* Declare non-static so zle_hist.c can use it */ +void zle_strip_trailing_newline_if_after_paste(void); + +/* If the last widget is a paste, and the last byte is a newline, strip it. + * + * If it was syntactically whitespace, that's cleaner; and if it was + * significant, it will be re-added latre. + */ +void zle_strip_trailing_newline_if_after_paste(void) +{ + if (lbindk == Th(z_bracketedpaste)) { + if (zlemetaline ? zlemetall : zlell) { + char last = zlemetaline ? ztr_last(zlemetaline) : zleline[zlell-1]; + if (last == ZWC('\n')) { + /* backwarddeletechar() doesn't use ARGS, but be conservative + * and pass them empty. */ + static char *empty_args[] = { NULL }; + backwarddeletechar(empty_args); + } + } + } +} + /**/ int acceptline(UNUSED(char **args)) { + zle_strip_trailing_newline_if_after_paste(); done = 1; return 0; } @@ -407,6 +431,7 @@ acceptline(UNUSED(char **args)) int acceptandhold(UNUSED(char **args)) { + zle_strip_trailing_newline_if_after_paste(); zpushnode(bufstack, zlelineasstring(zleline, zlell, 0, NULL, NULL, 0)); stackcs = zlecs; done = 1; diff --git a/Src/utils.c b/Src/utils.c index ca68eae..325997a 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -4483,6 +4483,38 @@ unmeta(const char *file_name) return fn; } +/* Return the last character of a metafied non-empty string */ + +/**/ +mod_export char +ztr_last(char const *s) +{ + char last; + + if (!*s) { + DPUTS(1, "BUG: ztr_last() called on empty string\n"); + + /* We must return some value. Hopefully NUL is good enough. */ + return '\0'; + } + + while (*s) { + if (*s == Meta) { + ++s; + if (! *s) { + DPUTS(1, "BUG: unexpected end of string in ztr_last()\n"); + + /* We must return some value. Hopefully NUL is good enough. */ + return '\0'; + } + last = *s++ ^ 32; + } + else + last = *s++; + } + return last; +} + /* * Unmetafy and compare two strings, comparing unsigned character values. * "a\0" sorts after "a". -- 2.1.4