emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: address@hidden: Re: comint's directory tracking doesn't understand \


From: Chong Yidong
Subject: Re: address@hidden: Re: comint's directory tracking doesn't understand \( or \)]
Date: Sat, 10 Mar 2007 15:18:31 -0500
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.95 (gnu/linux)

David Hansen <address@hidden> wrote:

> The string gets still splitted at members of
> `comint-delimiter-argument-list' (note that it's buffer local) no
> matter if they are escaped or not.
>
> I have to admit that it probably can be fixed with far less than a
> 200 line patch but I'm not willing to touch these regexps and i
> don't think it will result in anything "safer".

I think there is an easy way to get around this difficulty: once
backslash-escaped characters have been identified, put a text property
on the string saying that character is literal, then make
comint-delim-arg avoid splitting when such a text property is present.
Here is a patch to implement this.  I can verify that it solves the
original bug.

As far as safety goes, I think it is a little safer than the other
candidate patch, if only because it's simpler to read.

*** /home/cyd/emacs/lisp/comint.el.~1.358.~     2007-02-27 19:43:48.000000000 
-0500
--- /home/cyd/emacs/lisp/comint.el      2007-03-10 15:15:40.000000000 -0500
***************
*** 1356,1367 ****
        (while (< pos len)
        (let ((char (aref arg pos))
              (start pos))
!         (if (memq char comint-delimiter-argument-list)
              (while (and (< pos len) (eq (aref arg pos) char))
                (setq pos (1+ pos)))
            (while (and (< pos len)
!                       (not (memq (aref arg pos)
!                                  comint-delimiter-argument-list)))
              (setq pos (1+ pos))))
          (setq args (cons (substring arg start pos) args))))
        args)))
--- 1356,1371 ----
        (while (< pos len)
        (let ((char (aref arg pos))
              (start pos))
!         (if (and (memq char comint-delimiter-argument-list)
!                  ;; Ignore backslash-escaped characters.
!                  (not (get-text-property pos 'literal arg)))
              (while (and (< pos len) (eq (aref arg pos) char))
                (setq pos (1+ pos)))
            (while (and (< pos len)
!                       (not (and (memq (aref arg pos)
!                                       comint-delimiter-argument-list)
!                                 (not (get-text-property
!                                       pos 'literal arg)))))
              (setq pos (1+ pos))))
          (setq args (cons (substring arg start pos) args))))
        args)))
***************
*** 1381,1404 ****
    ;; The third matches '-quoted strings.
    ;; The fourth matches `-quoted strings.
    ;; This seems to fit the syntax of BASH 2.0.
!   (let* ((first (if (if (fboundp 'w32-shell-dos-semantics)
!                       (w32-shell-dos-semantics))
!                   "[^ \n\t\"'`]+\\|"
!                 "[^ \n\t\"'`\\]+\\|\\\\[\"'`\\ \t]+\\|"))
         (argpart (concat first
                          "\\(\"\\([^\"\\]\\|\\\\.\\)*\"\\|\
  '[^']*'\\|\
  `[^`]*`\\)"))
         (args ()) (pos 0)
         (count 0)
         beg str quotes)
      ;; Build a list of all the args until we have as many as we want.
      (while (and (or (null mth) (<= count mth))
                (string-match argpart string pos))
        (if (and beg (= pos (match-beginning 0)))
          ;; It's contiguous, part of the same arg.
          (setq pos (match-end 0)
!               quotes (or quotes (match-beginning 1)))
        ;; It's a new separate arg.
        (if beg
            ;; Put the previous arg, if there was one, onto ARGS.
--- 1385,1414 ----
    ;; The third matches '-quoted strings.
    ;; The fourth matches `-quoted strings.
    ;; This seems to fit the syntax of BASH 2.0.
!   (let* ((backslash-escape (not (and (fboundp 'w32-shell-dos-semantics)
!                                    (w32-shell-dos-semantics))))
!        (first (if backslash-escape
!                   "[^ \n\t\"'`\\]\\|\\(\\\\.\\)\\|"
!                 "[^ \n\t\"'`]+\\|"))
         (argpart (concat first
                          "\\(\"\\([^\"\\]\\|\\\\.\\)*\"\\|\
  '[^']*'\\|\
  `[^`]*`\\)"))
+        (quote-subexpr (if backslash-escape 2 1))
         (args ()) (pos 0)
         (count 0)
         beg str quotes)
      ;; Build a list of all the args until we have as many as we want.
      (while (and (or (null mth) (<= count mth))
                (string-match argpart string pos))
+       (and backslash-escape
+          (match-beginning 1)
+          (put-text-property (match-beginning 1) (match-end 1)
+                             'literal t string))
        (if (and beg (= pos (match-beginning 0)))
          ;; It's contiguous, part of the same arg.
          (setq pos (match-end 0)
!               quotes (or quotes (match-beginning quote-subexpr)))
        ;; It's a new separate arg.
        (if beg
            ;; Put the previous arg, if there was one, onto ARGS.
***************
*** 1406,1412 ****
                  args (if quotes (cons str args)
                         (nconc (comint-delim-arg str) args))))
        (setq count (length args))
!       (setq quotes (match-beginning 1))
        (setq beg (match-beginning 0))
        (setq pos (match-end 0))))
      (if beg
--- 1416,1422 ----
                  args (if quotes (cons str args)
                         (nconc (comint-delim-arg str) args))))
        (setq count (length args))
!       (setq quotes (match-beginning quote-subexpr))
        (setq beg (match-beginning 0))
        (setq pos (match-end 0))))
      (if beg




reply via email to

[Prev in Thread] Current Thread [Next in Thread]