unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Filipp Gunbin <fgunbin@fastmail.fm>
To: Stefan Monnier <monnier@IRO.UMontreal.CA>
Cc: emacs-devel@gnu.org
Subject: Re: Small fix in `shell--unquote&requote-argument' - please review
Date: Thu, 08 Sep 2016 22:22:21 +0300	[thread overview]
Message-ID: <m2d1keurgy.fsf@fgunbin.local> (raw)
In-Reply-To: <m2twdzofh5.fsf@fastmail.fm> (Filipp Gunbin's message of "Thu, 01 Sep 2016 17:35:18 +0300")

Hi Stefan & list,

On 01/09/2016 17:35 +0300, Filipp Gunbin wrote:

> Stefan,
>
> On 01/09/2016 09:39 -0400, Stefan Monnier wrote:
>
>>>>> 1. match is always less than (length str), so I guess they meant
>>>>> `((< (1+ match) (length qstr))'.
>>>>> 2. If `string-match' searching for ending single quote failed,
>>>>> `(match-string 0)' is still called - be careful not to do this.
>>>> Do you have corresponding recipes to trigger the corresponding errors
>>>> (so we could write tests)?  This part of my code is in dire need of
>>>> tests, otherwise it's much too easy to introduce regressions.
>>> Honestly, no, I found this when studying the code.
>>
>> Hmm... would you be able to artificially construct or describe a failing
>> case, then?  Part of the issue is that I don't remember the code well
>> enough, so while your description makes some sense, I'm having
>> difficulty understanding really what the change does.
>
> Yep, I'll try.
>
> Filipp

I didn't find a way how to produce an error in an interactive command,
because `comint-word' won't eat single/double quote characters (see
`comint--match-partial-filename')

But if invoked directly:

1. (shell--unquote&requote-argument "te'st" 2)

This produces `("testst" 2 comint-quote-filename)'.

Having found first `'', `string-match' cannot find closing quote.
Then (match-end 0) is used, it's value is "undefined", but happens to
be 3, so we duplicate last 2 chars and that's wrong.

2. (shell--unquote&requote-argument "test'" 2)

This produces `("test" 2 comint-quote-filename)'.

First `'' happens to be at the end of line.  The condition

`(< match (1+ (length qstr)))'

returns t (it always does so), so we are trying to find closing quote
when there are no characters left.  Again, `(match-end 0)' is called
after a failed search.  The result is correct, because we are already at
the end of string, but the logic is wrong.

I've modified my patch to be quite about missing closing quote, it's
below.


I looked into shell.el/comint.el a bit.  There's a FIXME in
`comint-word' which points at missing single/double-quote parsing in
shell.el.  Do we have a planned strategy for how that should work?

Something like that:

- Parse backwards up to some stop char, like it is done now.  We cannot
  know the context (whether we are in quotes) in this case, so it's
  reasonable to stop at the first non-filename char and complete what we
  have.  What is and what is not a filename character cannot be known,
  too, because we don't know whether we are in quotes.

or

- Determine the position of the current shell pipeline start.  Then,
  from it, we can determine the quoting context and use correct filename
  chars set.

Filipp

diff --git a/lisp/shell.el b/lisp/shell.el
index 1f019f2..20a5350 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -384,11 +384,15 @@ shell--unquote&requote-argument
        ((eq (aref qstr match) ?\") (setq dquotes (not dquotes)))
        ((eq (aref qstr match) ?\')
         (cond
+         ;; treat single quote as text if inside double quotes
          (dquotes (funcall push "'" (match-end 0)))
-         ((< match (1+ (length qstr)))
+         ((< (1+ match) (length qstr))
           (let ((end (string-match "'" qstr (1+ match))))
-            (funcall push (substring qstr (1+ match) end)
-                     (or end (length qstr)))))
+            (unless end
+              (setq end (length qstr))
+              (set-match-data (list match (length qstr))))
+            (funcall push (substring qstr (1+ match) end) end)))
+         ;; ignore if at the end of string
          (t nil)))
        (t (error "Unexpected case in shell--unquote&requote-argument!")))
       (setq qpos (match-end 0)))



  reply	other threads:[~2016-09-08 19:22 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-30 23:24 Small fix in `shell--unquote&requote-argument' - please review Filipp Gunbin
2016-08-31 13:27 ` Stefan Monnier
2016-09-01 13:15   ` Filipp Gunbin
2016-09-01 13:39     ` Stefan Monnier
2016-09-01 14:35       ` Filipp Gunbin
2016-09-08 19:22         ` Filipp Gunbin [this message]
2016-09-08 20:23           ` Stefan Monnier
2016-10-26 18:32           ` Stefan Monnier
2016-10-27 12:41             ` Filipp Gunbin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m2d1keurgy.fsf@fgunbin.local \
    --to=fgunbin@fastmail.fm \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@IRO.UMontreal.CA \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).