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 15:44:59 -0800 Message-ID: <87608l6t50.fsf@gmail.com> References: <87fu8272h6.fsf@gmail.com> <87shbqto33.fsf@users.sourceforge.net> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: blaine.gmane.org 1514850267 1545 195.159.176.226 (1 Jan 2018 23:44:27 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 1 Jan 2018 23:44:27 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.0.90 (gnu/linux) Cc: 29821@debbugs.gnu.org To: Noam Postavsky Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Tue Jan 02 00:44: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 1eW9kc-00088a-DY for geb-bug-gnu-emacs@m.gmane.org; Tue, 02 Jan 2018 00:44:14 +0100 Original-Received: from localhost ([::1]:48358 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eW9mb-0007Jv-FV for geb-bug-gnu-emacs@m.gmane.org; Mon, 01 Jan 2018 18:46:17 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:51569) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eW9mP-0007JM-Pt for bug-gnu-emacs@gnu.org; Mon, 01 Jan 2018 18:46:07 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eW9mM-0001vE-Kd for bug-gnu-emacs@gnu.org; Mon, 01 Jan 2018 18:46:05 -0500 Original-Received: from debbugs.gnu.org ([208.118.235.43]:51614) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eW9mM-0001uw-F3 for bug-gnu-emacs@gnu.org; Mon, 01 Jan 2018 18:46:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1eW9mM-0001Ib-2Q for bug-gnu-emacs@gnu.org; Mon, 01 Jan 2018 18:46: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: Mon, 01 Jan 2018 23:46:02 +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.15148503124937 (code B ref 29821); Mon, 01 Jan 2018 23:46:02 +0000 Original-Received: (at 29821) by debbugs.gnu.org; 1 Jan 2018 23:45:12 +0000 Original-Received: from localhost ([127.0.0.1]:60295 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eW9lW-0001HX-BV for submit@debbugs.gnu.org; Mon, 01 Jan 2018 18:45:10 -0500 Original-Received: from mail-pg0-f49.google.com ([74.125.83.49]:38998) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eW9lT-0001HJ-Q1 for 29821@debbugs.gnu.org; Mon, 01 Jan 2018 18:45:08 -0500 Original-Received: by mail-pg0-f49.google.com with SMTP id 81so4177719pgf.6 for <29821@debbugs.gnu.org>; Mon, 01 Jan 2018 15:45:07 -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=Okrz+2aX5a+J4qJUPryPZ0lJvMmoLD5ch/9agNI+Am0=; b=TO7+ok3fAIDD3Odlj10xU4WBozSXb2kctBMP7rAd84+UHrsGA+vXZ/rZunOzLHgGW/ OtnHleHTcVCjj9ZNGeUCs7h32+vlVKNgJ/nxB5FWlnXWjYQV/YbfZOIj0aiHgkEn6Rq3 hp8DT19aEy7BL9FoW2FZq9r4nkYJJFGnv8i/20ZUYlwrIgnBxNYwqIIiCxwurb8G9JJi HySpIPcWKxgjSrgVfnChjKhJ7M9P9bPTBny0XkWPDqzHEn7OS67ESBvmSaRFo9WvZtNJ H0+gZS+M0Y4jyBef+NAeqmxQ4sbL2e3zFqQXJgVVWEhO5JXpDUMEfldZ80rjeFCg0T8Q RI7w== 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=Okrz+2aX5a+J4qJUPryPZ0lJvMmoLD5ch/9agNI+Am0=; b=eVsZEGZMUmBOZnh1EKj6Gx/1BDUNsiQiuiM4kO4tMctBL0C32LRLl/e6GxMZqy0bQu OFXyiuc3I07wrvUCX+fgpfEB8ggUBzPP9kJPeWbgaIX9qo4nVIBwevx+DwaCcQRTGZnX TzxW/kjOiAj7wqtTtPnBsyFFSFC1otB2thBGS+W8BQvnDHqTn6My6Qe+XZtHj7DhInsD ZdxavHcOP3WeZ8uNBAuy6okvhKn2sugr/ijRhwf1iBrpvNKJbsNlHMMjgVuOmbccLUrJ njyjLWxvwIOZlZjF2vi85epVodNWsFiqLp5Or7uSdouoXq4Bgh3QotgoddSIvqu9sOhv l/Sw== X-Gm-Message-State: AKGB3mKYPkDN5/zD+KpjfVs9zpVpnKWsHB5dQQEulcojMkkKZeOZGlvU zEqdx75VlBZMfDOCVbHxQPqNIdIa X-Google-Smtp-Source: ACJfBosQa4qyfJ+OUONHz502TvGJSBkHilZHCTkHwuDPhS4xnNu1HmspePRLYMspowWyIbEYTcJhRg== X-Received: by 10.98.39.68 with SMTP id n65mr43636481pfn.175.1514850301564; Mon, 01 Jan 2018 15:45:01 -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 f15sm2422023pgv.38.2018.01.01.15.44.59 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 01 Jan 2018 15:45:00 -0800 (PST) In-Reply-To: <87shbqto33.fsf@users.sourceforge.net> (Noam Postavsky's message of "Sun, 31 Dec 2017 19:33: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:141704 Archived-At: --=-=-= Content-Type: text/plain Noam Postavsky writes: > Hmm, using history expansion would mean typing > > M-p DEL C-a M-f M-d M-d ! ! : $ > > to get > > mv !!:$ two.txt > > vs > > M-p C-a M-f M-d M-d C-k C-y C-y DEL > > to get > > mv two.txtt two.txt > > Hardly seems worth the trouble of learning this syntax (and occasionally > triggering accidentally, which is why I disable it in bash too). Is > having history expansion enabled by default very important? You can > still enable it in your config. I do suppose that is true, but I still find myself preferring history substitution in some cases, such as typing a new command but preserving the last argument. I don't think it's too important that history expansion is enabled by default, but I do think it's important to have it available as an option. I think that turning it off would startle some users, especially because it's featured in some popular 'getting started' articles for eshell (such as this one: https://masteringemacs.org/article/complete-guide-mastering-eshell), but the decision is up to you. I would much prefer a variable (perhaps defaulting to off) to tweak this setting on or of rather than adding/removing a function to the hook. Removing it in the current way makes it feel more 'deprecated' to me, rather than 'disabled by default'. Would you mind if I submitted a patch to add a new `eshell-history-expansion-enabled' variable (or similar)? > I guess it's an improvement on what we have currently (the feature is > rather underspecified). Should we consider also handling spaces like > bash does? In bash I can do this: > > ~/tmp$ echo foo bar > foo bar > ~/tmp$ ^foo bar^blah^ > echo blah > blah > > In eshell (with and without your patch) I get: > > ~/src/emacs $ echo foo bar > ("foo" "bar") > ~/src/emacs $ ^foo bar^blah^ > ^foo: command not found I've attached a new patch which attempts to solve this as well. I'm unfamiliar with eshell internals though, so I'm not sure if it's done properly. Let me know if anyone sees any issues with it! Thanks, -Jay --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0001-Prevent-expansion-of-quick-substitutions-when-not-at.patch >From 573b03a76798496b3bcfcada1557f1a9d83cc987 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 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 20 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 (. -- 2.11.0 --=-=-=--