3

My company uses a version of Perl where you can define by binary number using something like my $var = 'b010110110; etc. Problem is both perl-mode and cperl-mode interpret ' as the start of the string and will apply a string font lock to everything until the next '. This causes large sections of code are to appear as a string when they are not.

I have looked into how Emacs defines strings, and it does not have a string start or string end syntax class. Rather it just has a string quote character syntax class of which both " and ' are members of in Perl modes.

I have modified the syntax table to changed the ' character from the string quote character class to the punctuation character class. This fixes the problems of stringifying blocks of code but normal strings quoted with ' are no longer recognized.

I need a really smart person who can show me some code to modify the syntax highlighting of Perl so that strings are recognized as strings and binary notation is recognized as binary notation. How can I accomplish this?

Prgrm.celeritas
  • 849
  • 6
  • 15
  • 2
    `syntax-propertize-function` is a way to set up custom rules for applying text properties. – wasamasa Nov 17 '16 at 19:00
  • In perl you define a binary number using `0b` as a prefix, see [`perldoc perlnumber`](http://perldoc.perl.org/perlnumber.html). I am not sure why you need to use a single quote instead of `0b`? – Håkon Hægland Nov 17 '16 at 20:12
  • HåkonHægland I know that is how binary numbers are defined in Perl. But my companies Perl interpreter accepts `'b` as well (probably because it is really old) and all of our Perl files use `'b`. So I have to find someone to correct for this. I can't go through all our repo's and change it. – Prgrm.celeritas Nov 17 '16 at 20:36
  • @wasamasa I did some digging based on you mentioning `syntax-propertize-function` and I was able to add addition rule to `syntax-propertize-rules` that makes things work correctly. Now the question is, how do I add it to my `perl-mode`? (I was hacking the source file directly) Is there a hook or something? – Prgrm.celeritas Nov 17 '16 at 21:02
  • `perl-mode-hook`. Generally, every properly defined mode (read: via `define-derived-mode`) offers a variable named as the mode with `-hook` appended to it after its definition. Feel free to self-answer this question with the code involved! – wasamasa Nov 17 '16 at 21:58
  • I got it to work changing the source code directly but can't seem create a hook that works. I will probably open a new question and then apply the answer here. – Prgrm.celeritas Nov 17 '16 at 22:43

1 Answers1

2

So I did some more digging and I was able to find a solution, but not a very clean one. I copied the perl-syntax-propertize-function from perl-mode.el. I then added this to my .emacs and changed the name to my/perl-syntax-propertize-function and added the following code after syntax-propertize-rules

("\\('\\)b[^'a-z]" (1 "."))

I then added a perl-mode-hook after my function redefinition

(add-hook 'perl-mode-hook
        (lambda () (setq-local syntax-propertize-function #'my/perl-syntax-propertize-function)))

I reloaded my Emacs and everything worked like I wanted. I still hope that someone can come up with a cleaner solution.

Prgrm.celeritas
  • 849
  • 6
  • 15
  • I think this is the right solution. Of course, a minor tweak you can do is to call the original perl syntax propertize function, instead of copy-pasting it. Also, if this is proper perl, you could report this as a bug in Emacs and ask them to fix it centrally. Finally, I think your regexp might match too many things. Try to only match `'b[01]`. – Lindydancer Nov 18 '16 at 09:35
  • @Lindydancer, How can I call the original when I need to change it? I was trying to find some way to advise the function but no luck. Perhaps you know of a way? Because you're right, copy and pasting the original function seems like a waste since I only need to add one line. – Prgrm.celeritas Nov 18 '16 at 14:53
  • In classic perl-mode, it is function named `perl-syntax-propertize-function`. You can call it from you function before (or after) you do your work. (In cperl-mode it is a lambda bound to the variable. You can save it for later and call it using `funcall`. In fact, this technique can be used for plain perl mode as well.) – Lindydancer Nov 18 '16 at 16:13
  • This works because you can have multiple calls to `syntax-propertize-rules`. After all, it is only a macro that expands to a lambda that applies the `syntax-table` text properties to the buffer. In fact, your function doesn't even have to use it, it can apply the text property manually, if that would make sense. – Lindydancer Nov 18 '16 at 16:18
  • so you are suggesting I define an advice that surrounds the original function so that I can make a call to `syntax-propertize-rules`, add my rules, then call the original function? – Prgrm.celeritas Nov 18 '16 at 16:48
  • No, I dont think you will need to advice the original function. It should work if you define your own function that call the original, and add your function to `syntax-propertize-function`, – Lindydancer Nov 18 '16 at 19:45