From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Jay Kamat Newsgroups: gmane.emacs.bugs Subject: bug#29821: Ensure quick substitution only occurs at start of line Date: Thu, 04 Jan 2018 12:26:11 -0800 Message-ID: <877esxid5o.fsf@gmail.com> References: <87fu8272h6.fsf@gmail.com> <87shbqto33.fsf@users.sourceforge.net> <87wp11rqtr.fsf@users.sourceforge.net> <871sj96lgu.fsf@gmail.com> <87tvw4syi9.fsf@users.sourceforge.net> <87wp105ezz.fsf@gmail.com> <87o9mbso9j.fsf@users.sourceforge.net> <87po6q5sns.fsf@gmail.com> <87a7xus4hr.fsf@users.sourceforge.net> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: blaine.gmane.org 1515097521 16641 195.159.176.226 (4 Jan 2018 20:25:21 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Thu, 4 Jan 2018 20:25:21 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.0.90 (gnu/linux) Cc: 29821@debbugs.gnu.org, Andreas Schwab To: Noam Postavsky Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Thu Jan 04 21:25:16 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eXC4e-0003gs-Aj for geb-bug-gnu-emacs@m.gmane.org; Thu, 04 Jan 2018 21:25:12 +0100 Original-Received: from localhost ([::1]:39490 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eXC6d-0004sk-50 for geb-bug-gnu-emacs@m.gmane.org; Thu, 04 Jan 2018 15:27:15 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:57495) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eXC6U-0004r4-Kx for bug-gnu-emacs@gnu.org; Thu, 04 Jan 2018 15:27:08 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eXC6Q-0007Jb-GC for bug-gnu-emacs@gnu.org; Thu, 04 Jan 2018 15:27:06 -0500 Original-Received: from debbugs.gnu.org ([208.118.235.43]:55590) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eXC6Q-0007JL-AE for bug-gnu-emacs@gnu.org; Thu, 04 Jan 2018 15:27:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1eXC6P-0000Ph-UU for bug-gnu-emacs@gnu.org; Thu, 04 Jan 2018 15:27:01 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Jay Kamat Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 04 Jan 2018 20:27:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 29821 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 29821-submit@debbugs.gnu.org id=B29821.15150975811524 (code B ref 29821); Thu, 04 Jan 2018 20:27:01 +0000 Original-Received: (at 29821) by debbugs.gnu.org; 4 Jan 2018 20:26:21 +0000 Original-Received: from localhost ([127.0.0.1]:36038 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eXC5k-0000OW-Vt for submit@debbugs.gnu.org; Thu, 04 Jan 2018 15:26:21 -0500 Original-Received: from mail-pl0-f45.google.com ([209.85.160.45]:44597) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eXC5k-0000OJ-0c for 29821@debbugs.gnu.org; Thu, 04 Jan 2018 15:26:20 -0500 Original-Received: by mail-pl0-f45.google.com with SMTP id n13so1677335plp.11 for <29821@debbugs.gnu.org>; Thu, 04 Jan 2018 12:26:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=og+UJj9hcww1+vaSaeEsxDqBzFORY3F7GniEisKPAng=; b=gzYaRMFgAP3aZBZ88sUG+wbvKKzBD6VmlNZny9Ubt4R8PcijCPZPE6CfrMPJ7gNRNg O20JKcceFqej/rgfMEKHPYdv0TvWq4EdY+hKj2jddGz6ACPLMEY0J/a2VAPqOGs8XFbu 2daguT5ACJ3U54Vs2lxKx4yPdQbjtqVlPhlqR95JCEXgoB1+fXI0qmisl/pFGgFmjV9B 6ApJuaiSQlLvGdkftdKhHc/h26Nfd0KqR0jnwUkI65ep+vWdkjbjhHtdngHPThNhMfJk 6UNUbxj9sgogEL8Ko/4yAWsJ4jBF8zJhvXOVicQ5qoyJFGGBT1NOkFjm+d/eNdNtPu2j oSIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=og+UJj9hcww1+vaSaeEsxDqBzFORY3F7GniEisKPAng=; b=av2IznT+DCmr9S7B3DVmIAEbi6lqMpavX1PyyS0pwm9QHu5Ynk5C33duiD6fDOtvZ3 oM17c1En3JNM8wBR0YKUSa2pJ7WMORM6YE1ei8NoQVOxWGOxMhYpGVWn98yBnJtA3E4i j4unRX3F70ww61her8iEwyL18hhOe5E7lh9IWgjjOaQiZBxvk2N84DgVtI7CTEtt17++ MX96stuX6FpfP4/L2ICDCPHIeaaboYVQ7dENcQO06aKCY00JGyqiX0MgD73MVeHZ7hB+ tZ9lUcHNl9jTQ0AxIE6FvS4qgsMOQ5FDRlenZ4qZNdbs7HPodA0qgO6yNUYbQomI+w+7 Fnhw== X-Gm-Message-State: AKGB3mK9lw814vJ2ZL0BVHPed7JsP6con6uKL9IXzVhxHb6rl3nXwWYD KEW2I3BJnwyNJk+tsh4KzFk= X-Google-Smtp-Source: ACJfBotpGx8VTjpK3c5+2igqYnNQGjCCs3AUUuqITvHJTXMt9kWRvb9cKw31ElO37Btt02yQpREKbw== X-Received: by 10.84.252.142 with SMTP id y14mr700899pll.275.1515097574005; Thu, 04 Jan 2018 12:26:14 -0800 (PST) Original-Received: from laythe (c-67-161-9-47.hsd1.ca.comcast.net. [67.161.9.47]) by smtp.gmail.com with ESMTPSA id h81sm10905072pfh.119.2018.01.04.12.26.12 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 04 Jan 2018 12:26:12 -0800 (PST) In-Reply-To: <87a7xus4hr.fsf@users.sourceforge.net> (Noam Postavsky's message of "Wed, 03 Jan 2018 22:10:56 -0500") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:141781 Archived-At: --=-=-= Content-Type: text/plain Noam Postavsky writes: > I almost regret to prolong this, but I found another mismatch with bash. > It seems the quick substitution does not need to take up the entire > line: > > ~/tmp$ echo foo bar > foo bar > ~/tmp$ ^foo^blah^ etc > echo blah bar etc > blah bar etc > > Whereas, with your patch: > > ~/src/emacs $ echo foo bar > ("foo" "bar") > ~/src/emacs $ ^foo^blah^ etc > ^foo^blah^: command not found Ah, nice catch! I've updated the patch to handle that case as well. I've tested it as well as I could and it seems good to me, but in order to fix that case, I had to mess with the regexes a bit, so It's possible I might have missed a few cases. *[j@laythe emacs]$ echo one two three ("one" "two" "three") *[j@laythe emacs]$ ^one two^five six^ seven eight *[j@laythe emacs]$ echo five six three seven eight ("five" "six" "three" "seven" "eight") *[j@laythe emacs]$ Thanks, -Jay --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0001-Prevent-expansion-of-quick-substitutions-when-not-at.patch >From 729a73af7352b2870e65f8366c97cde49e5b1e78 Mon Sep 17 00:00:00 2001 From: Jay Kamat Date: Fri, 22 Dec 2017 15:34:44 -0800 Subject: [PATCH] Prevent expansion of quick substitutions when not at start of line See bug #29157 for an initial report In Addition: - Allow spaces inside substitutions, so ^foo bar^baz works. - Allow trailing characters after substitution, so ^foo^bar^ trailing works. - Throw an error when substitution does not match. * lisp/eshell/em-hist.el (eshell-expand-history-references): Expand history substitution before other types of expansions, and expand them with the whole line. (eshell-history-substitution): New function to expand only substitutions, taking in the entire typed line rather than individual arguments. --- lisp/eshell/em-hist.el | 60 +++++++++++++++++++++++++++++++++----------------- lisp/eshell/em-pred.el | 3 ++- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/lisp/eshell/em-hist.el b/lisp/eshell/em-hist.el index df462a7058..f77b831b56 100644 --- a/lisp/eshell/em-hist.el +++ b/lisp/eshell/em-hist.el @@ -581,21 +581,30 @@ eshell-hist-parse-arguments (defun eshell-expand-history-references (beg end) "Parse and expand any history references in current input." - (let ((result (eshell-hist-parse-arguments beg end))) + (let ((result (eshell-hist-parse-arguments beg end)) + (full-line (buffer-substring-no-properties beg end))) (when result (let ((textargs (nreverse (nth 0 result))) (posb (nreverse (nth 1 result))) - (pose (nreverse (nth 2 result)))) + (pose (nreverse (nth 2 result))) + (full-line-subst (eshell-history-substitution full-line))) (save-excursion - (while textargs - (let ((str (eshell-history-reference (car textargs)))) - (unless (eq str (car textargs)) - (goto-char (car posb)) - (insert-and-inherit str) - (delete-char (- (car pose) (car posb))))) - (setq textargs (cdr textargs) - posb (cdr posb) - pose (cdr pose)))))))) + (if full-line-subst + ;; Found a ^foo^bar substitution + (progn + (goto-char beg) + (insert-and-inherit full-line-subst) + (delete-char (- end beg))) + ;; Try to expand other substitutions + (while textargs + (let ((str (eshell-history-reference (car textargs)))) + (unless (eq str (car textargs)) + (goto-char (car posb)) + (insert-and-inherit str) + (delete-char (- (car pose) (car posb))))) + (setq textargs (cdr textargs) + posb (cdr posb) + pose (cdr pose))))))))) (defvar pcomplete-stub) (defvar pcomplete-last-completion-raw) @@ -630,20 +639,31 @@ eshell-complete-history-reference (setq history (cdr history))) (cdr fhist))))))) +(defun eshell-history-substitution (line) + "Expand quick hist substitutions formatted as ^foo^bar^. +Returns nil if string does not match quick substitution format, +and acts like !!:s/foo/bar/ otherwise." + ;; `^string1^string2^' + ;; Quick Substitution. Repeat the last command, replacing + ;; STRING1 with STRING2. Equivalent to `!!:s/string1/string2/' + (when (and (eshell-using-module 'eshell-pred) + (string-match + "^\\^\\([^^]+\\)\\^\\([^^]+\\)\\(\\^\\(\\s-+.*\\)?\\)?\\s-*$" + line)) + ;; Save trailing match as `eshell-history-reference' runs string-match. + (let ((matched-end (match-string 4 line))) + (concat + (eshell-history-reference + (format "!!:s/%s/%s/" + (match-string 1 line) + (match-string 2 line))) + matched-end)))) + (defun eshell-history-reference (reference) "Expand directory stack REFERENCE. The syntax used here was taken from the Bash info manual. Returns the resultant reference, or the same string REFERENCE if none matched." - ;; `^string1^string2^' - ;; Quick Substitution. Repeat the last command, replacing - ;; STRING1 with STRING2. Equivalent to `!!:s/string1/string2/' - (if (and (eshell-using-module 'eshell-pred) - (string-match "\\^\\([^^]+\\)\\^\\([^^]+\\)\\^?\\s-*$" - reference)) - (setq reference (format "!!:s/%s/%s/" - (match-string 1 reference) - (match-string 2 reference)))) ;; `!' ;; Start a history substitution, except when followed by a ;; space, tab, the end of the line, = or (. diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el index 72a7bc4afc..86a9d4262a 100644 --- a/lisp/eshell/em-pred.el +++ b/lisp/eshell/em-pred.el @@ -545,7 +545,8 @@ eshell-pred-substitute (function (lambda (str) (if (string-match ,match str) - (setq str (replace-match ,replace t nil str))) + (setq str (replace-match ,replace t nil str)) + (error (concat str ": substitution failed"))) str)) lst))))) (defun eshell-include-members (&optional invert-p) -- 2.11.0 --=-=-=--