2

I'm trying to make a font lock hook to replace strings of text for a mathmatical notation plugin.

So I'm thinking " / " (note the spaces) will turn into " ÷ ", but "/" won't. (It's a package mainly for R statistical language.)

I'm playing with the examples from the manual and I can't even get that to work lol. I was trying to get the word FIXIT to change font color.

(add-hook 'emacs-lisp-mode-hook
        (lambda ()
        (font-lock-add-keywords nil
            '(("\\<\\(FIXIT\\):" 1
            font-lock-warning-face t)))))

I don't even fully understand the syntax since I'm just getting used to lisp. Does it use a RegEx to identify strings? and if so, what RegEx engine.

I was hoping it would change the font color, but it didnt... but again, that was just me playing with it trying to understand it, not the end goal. The end result would be the first thing I mentioned to change math symbols (" / " into " ÷ ")

Drew
  • 75,699
  • 9
  • 109
  • 225
Chris
  • 23
  • 2
  • 2
    You might want to take a look at `prettify-symbols-mode`. –  Feb 17 '19 at 22:04
  • Re: "if so, what RegEx engine", see https://www.gnu.org/software/emacs/manual/html_node/elisp/Regular-Expressions.html . Emacs regexp syntax is similar to BRE syntax, along with various custom features. – phils Feb 17 '19 at 22:28
  • https://www.emacswiki.org/emacs/CategoryRegexp and https://emacs.stackexchange.com/q/5568 might be useful. – phils Feb 17 '19 at 22:33
  • @DoMiNeLa10 , yes, I'm primarily using `prettify-symbols-mode` for this but for certain items I need something more powerful, as `prettify-symbols-mode` only allows one symbol. So if I need to replace a string of symbols, `p-s` mode only allows one (as far as i know.) I also would like to italicize variables as is generally done in mathematical notation (ie: _x_ ) – Chris Feb 18 '19 at 16:41

1 Answers1

4

Here's a code snippet that will make all occurrences of " / " appear as " ÷ " in the current buffer:

(add-to-list 'font-lock-extra-managed-props 'display)
(font-lock-add-keywords nil
 '((" \\(/\\) " 1 '(face nil display "÷"))))

The first line makes font-lock manage the display property of text, so that it removes the property when a piece of text no longer matches the keyword.

Let's break down what (" \\(/\\) " 1 '(face nil display "÷")) means:

  • " \\(/\\) " is an emacs regex that matches only the sequence  /  (space-slash-space), and captures the / -- that's what the escaped parentheses (\\( and \\)) are for.

  • 1 says that we want to modify the properties of text captured in the first group. In our case, we want to change the display property of only the / character, not the surrounding spaces. That's why we capture it in the regex. If we wanted to change the properties of the entire matched text, we would put 0 in place of 1.

  • '(face nil display "÷") specifies the properties that we want applied to the / character. We only want to set the display property, not the face property, but the function requires us to specify face, so we specify it as nil. The effect is that font-lock won't change the face property of matching text. We then set the display property to "÷", so the / character will be displayed as ÷.

More about font-lock keywords: https://www.gnu.org/software/emacs/manual/html_node/elisp/Search_002dbased-Fontification.html

More about the display property: https://www.gnu.org/software/emacs/manual/html_node/elisp/Display-Property.html#Display-Property (the code above uses a replacing spec)

jpi
  • 116
  • 1
  • 5
  • Oh I'm sorry, the " wasn't part of the String... I just put that there because StackExcange collapses the whitespace around the symbols when they're in code brackets. See: ` / ` (i just typed that with 10 white space characters surrounding) Anyway the string is " / " -> " ÷ " all spaces as is. What's the emacs regex for that? But besides that this answer is exactly what I needed. Thanks! – Chris Feb 19 '19 at 00:12
  • The regex `" \\(/\\) "` matches the sequence space-slash-space. The escaped parentheses (`\\(` and `\\)`) are used to capture the `/` character, as this is the only character in the regex that we want to change the display of. – jpi Feb 19 '19 at 07:28
  • So the code you posted would find " / " or "" / "" (ignore the first set of parentheses in both cases.) – Chris Feb 19 '19 at 18:23
  • It will find " / ". – jpi Feb 19 '19 at 18:55