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: Mon, 01 Jan 2018 18:30:41 -0800 Message-ID: <871sj96lgu.fsf@gmail.com> References: <87fu8272h6.fsf@gmail.com> <87shbqto33.fsf@users.sourceforge.net> <87wp11rqtr.fsf@users.sourceforge.net> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: blaine.gmane.org 1514860167 1108 195.159.176.226 (2 Jan 2018 02:29:27 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Tue, 2 Jan 2018 02:29:27 +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 Tue Jan 02 03:29:22 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 1eWCKG-0007pS-3n for geb-bug-gnu-emacs@m.gmane.org; Tue, 02 Jan 2018 03:29:12 +0100 Original-Received: from localhost ([::1]:53059 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eWCMF-0003v7-3i for geb-bug-gnu-emacs@m.gmane.org; Mon, 01 Jan 2018 21:31:15 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:51291) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eWCM7-0003uR-Lp for bug-gnu-emacs@gnu.org; Mon, 01 Jan 2018 21:31:09 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eWCM2-00079Q-KC for bug-gnu-emacs@gnu.org; Mon, 01 Jan 2018 21:31:07 -0500 Original-Received: from debbugs.gnu.org ([208.118.235.43]:51675) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eWCM2-00079F-Ej for bug-gnu-emacs@gnu.org; Mon, 01 Jan 2018 21:31:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1eWCM1-00056e-W1 for bug-gnu-emacs@gnu.org; Mon, 01 Jan 2018 21:31:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Jay Kamat Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 02 Jan 2018 02:31: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.151486025319609 (code B ref 29821); Tue, 02 Jan 2018 02:31:01 +0000 Original-Received: (at 29821) by debbugs.gnu.org; 2 Jan 2018 02:30:53 +0000 Original-Received: from localhost ([127.0.0.1]:60356 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eWCLt-00056C-05 for submit@debbugs.gnu.org; Mon, 01 Jan 2018 21:30:53 -0500 Original-Received: from mail-pg0-f41.google.com ([74.125.83.41]:46944) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eWCLr-00055x-Fr for 29821@debbugs.gnu.org; Mon, 01 Jan 2018 21:30:51 -0500 Original-Received: by mail-pg0-f41.google.com with SMTP id r2so8436603pgq.13 for <29821@debbugs.gnu.org>; Mon, 01 Jan 2018 18:30:51 -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=iNXn6j9KF3SELNgYFwp5O37rwC76RNsrjWH350Xa+xk=; b=tKAiQcVE+C9Jn5fEAG9DJEvarZPpx5LOSxstNlbFNAvLMPByk+DnETXqh2xkCqrHby oDl1HqoS7+Wp6Twg380cva3KSKSTITJE2uoLk5Aabebw6maHEysv0V3tpsgDc3C9TuG8 sz3JNAEpX8vB9j7Q0342gYytjNbkvwEcaeuE2lxehgvEaCVlb/4XyVcF/f5pmgb3CCrL dPMYDWIeYviKVZkDlKB3kw7mQJIfKLLBIimda5mdqwmYItEJXrqzG5Ty1HGr/uK2Dia4 DousPQy3yXTiB8vQJ7UnTOSuO3o1aYe3deduhIsTCZcDsfwS5vkA16WnYwj1MDo7FFIQ EnrQ== 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=iNXn6j9KF3SELNgYFwp5O37rwC76RNsrjWH350Xa+xk=; b=AQ8TSjGH1V+woLIJQOFx7zAJ0Z5knnCYhz2+DVh09eW8dSftZpw3mAYizLzMb3Oazr PSzoxsW3PR6Cs3sB4G4WR38OrbS0XqYX+RuuIQM6dZoZyGZ6jkBD0214sqGCsnqVtD3h S2bP6MQFATbT2ylSRlsS0hpTjXtRpg7R4BdWurXOQFBcMgzY/KYlAdZ8SglTXwy/4+9J 4WA5Ef+mttYdMc6rqUcS/zKYigfoEOCzBe9a0Y/xf3cSS/PZZIb84ZSUimOn4wsafizw 1b01ZMe+ciwJr8N8MO8jRMe9IhTtEmzcdfLfisxQOwxCJecCa/+j/gemuHvsIDNqLZod u0yw== X-Gm-Message-State: AKGB3mL8G2X8+aXNUHX98ITQOTL2DH/OmTnLjjpaLkPGGa7Ea9cZUtci AQqo/e4XaAMdYMHcMEp0PZ6Pz1YC X-Google-Smtp-Source: ACJfBotcx/d5mXOt7psgPXSjiv9SUnKDVlTITFJGimyXoPQgO8s12FAH7D+7oYXzUhR54wgqL1CJHg== X-Received: by 10.98.8.202 with SMTP id 71mr35395013pfi.204.1514860245478; Mon, 01 Jan 2018 18:30:45 -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 e8sm20509312pgs.44.2018.01.01.18.30.42 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 01 Jan 2018 18:30:43 -0800 (PST) In-Reply-To: <87wp11rqtr.fsf@users.sourceforge.net> (Noam Postavsky's message of "Mon, 01 Jan 2018 20:29:20 -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:141706 Archived-At: --=-=-= Content-Type: text/plain Noam Postavsky writes: > With your patch, if I do > > ~/src/emacs $ ^this string not present in history^blah^ > > I get the latest entry in the history substituted and re-executed. In > bash I get > > ~/tmp$ ^this string not present in history^blah^ > bash: :s^this string not present in history^blah^: substitution failed > > (if it's easier, I think it would be okay if eshell prints an error > using the !!:s/foo/bar/ syntax, but this case must be an error) Ah, I did notice that, but I was not sure whether it was a bug or desired behavior (as it seemed to occur for me even before this patch). I've added a tiny change to the patch to fix that, but it has the side effect of doing: > *[j@laythe emacs-bisect]$ echo "foo"(:s/bar/baz/) > foo: substitution failed But I think that's an OK change, especially if we want to error out on ^bar^baz when no search is found. I also discovered another issue (which existed before as well): > *[j@laythe emacs-bisect]$ echo one one one > ("one" "one" "one") > *[j@laythe emacs-bisect]$ !!:sg/one/two > :sg/one/two > Wrong type argument: integer-or-marker-p, nil but I'd rather take a look at that later on to avoid cluttering this changeset. (and I'm not sure if I'm just using the feature incorrectly). Thanks, -Jay --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0001-Prevent-expansion-of-quick-substitutions-when-not-at.patch >From d4ba97c7b15c48d3394b8567b05fae31874220a7 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 Also, allow spaces inside substitutions, so ^foo bar^baz works. * 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 | 57 ++++++++++++++++++++++++++++++++------------------ lisp/eshell/em-pred.el | 3 ++- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/lisp/eshell/em-hist.el b/lisp/eshell/em-hist.el index df462a7058..d4d4b93b81 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,28 @@ eshell-complete-history-reference (setq history (cdr history))) (cdr fhist))))))) +(defun eshell-history-substitution (line) + "Expand whole-line history substitutions by converting them to +!!:s/a/b/ syntax. +Returns nil if no match found." + ;; `^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-*$" + line)) + (let* ((reference (format "!!:s/%s/%s/" + (match-string 1 line) + (match-string 2 line))) + (result (eshell-history-reference reference))) + (unless (eq result reference) + result)))) + (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 --=-=-=--