emacs-pretest-bug
[Top][All Lists]
Advanced

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

Re: perl-mode confused whith split(/,/,$var);


From: Stefan Monnier
Subject: Re: perl-mode confused whith split(/,/,$var);
Date: Fri, 02 Dec 2005 12:55:38 -0500
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux)

>> This code below confuses perl-mode. The comma in split /,/, ...  causes
>> everything after it to be indented and hi-lighted wrong.

> The best I could come up with so far is the patch below.  Please try it.
> It's a real pain in the rear to have to do so much effort just for this one
> special case.

> But it's really non trivial since I have to be able to tell the difference
> between

>         $tmp = split / $foo /
> and
>         $tmp = $ split / $foo /
> or
>         $tmp = $# split /$ foo /

It turns out the problem is not just with `split'.
It can also occur with `grep', or with pretty much any function.
E.g. it's perfectly valid to do:

     print /regexp/;

and there's also things like

     print 2 + /regexp/;
or
     print "toto" if /regexp/;

I believe the patch below should work better.  Can people try it?
Please watch out for performance differences when you try it out.


        Stefan


Index: perl-mode.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/progmodes/perl-mode.el,v
retrieving revision 1.63
diff -u -u -b -r1.63 perl-mode.el
--- perl-mode.el        17 Nov 2005 07:36:41 -0000      1.63
+++ perl-mode.el        2 Dec 2005 17:52:39 -0000
@@ -267,8 +267,8 @@
     ("^[ \t]*format.*=[ \t]*\\(\n\\)" (1 '(7)))
     ;; Funny things in sub arg specifications like `sub myfunc ($$)'
     ("\\<sub\\s-+\\S-+\\s-*(\\([^)]+\\))" 1 '(1))
-    ;; regexp and funny quotes
-    ("[?:.,;=!~({[][ \t\n]*\\(/\\)" (1 '(7)))
+    ;; Regexp and funny quotes.
+    ("\\(/\\)" (0 (perl-font-lock-slash)))
     ("\\(^\\|[?:.,;=!~({[ \t]\\)\\([msy]\\|q[qxrw]?\\|tr\\)\\>\\s-*\\([^])}> 
\n\t]\\)"
      ;; Nasty cases:
      ;; /foo/m  $a->m  $#m $m @m %m
@@ -297,6 +297,36 @@
       (modify-syntax-entry char "(" st)
       (modify-syntax-entry close ")" st))
     st))
+
+(defun perl-font-lock-slash ()
+  "Tell whether the / is used for division or for regexp matching.
+Expect to be called with point right after a slash char.
+Returns a syntax-table property to be placed on the char, or nil."
+  ;; This is very tricky.  Some nasty cases:
+  ;;   $foo = split / $bar          vs     $foo = $ split / $bar
+  ;; Also if the line starts with a / we have to look at the previous line
+  ;; to figure out what's going on, which can misbehave when font-locking
+  ;; only part of the buffer.  We could instead simply say that such a / is
+  ;; always a division operator, based on 2 observations:
+  ;; - /foo/ regexp matches normally occur within instructions.
+  ;; - the GNU coding convention recommends to split a line before rather
+  ;;   than after infix operators.
+  (save-excursion
+    ;; This regexp should *always* match, and preferably quickly.
+    (re-search-backward (concat "\\(?:"
+                                ;; The / is not preceded by a word.
+                                "\\(?:\\([^[:alpha:] \t\n]\\)\\|\\`\\)" "\\|"
+                                ;; The / is preceded by a word.
+                                "\\(?:\\([^ \t\n]\\)\\|\\`\\)[ 
\t\n]*\\<[[:alpha:]]+"
+                                "\\)" "[ \t\n]*/"))
+    ;; The / is a regexp operator in the following cases
+    (if (cond
+         ((match-end 1)                 ; The / is preceded by a non-word.
+          (memq (char-syntax (char-after)) '(?\( ?.)))
+         ((match-end 2)                 ; The / is preceded by a word.
+          (not (memq (char-after) '(?$ ?# ?% ?@))))
+         (t))                           ; We hit the beginning of buffer.
+        '(7))))
 
 (defun perl-font-lock-special-syntactic-constructs (limit)
   ;; We used to do all this in a font-lock-syntactic-face-function, which




reply via email to

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