10

When writing a major mode, it's often useful to know 'is point in a string?' 'is point in a comment?'.

Most major modes seem to attempt to parse the programming language. For example:

  • python-syntax-content calls syntax-ppss
  • haskell-fill-paragraph calls syntax-ppss and re-search-forward
  • c-in-comment-line-prefix-p moves point around and calls looking-at
  • sp-point-in-comment calls syntax-ppss but also checks if it's on a comment delimeter

However, this doesn't work in some cases. In org-mode buffers, comments in source blocks are not correctly detected by these approaches.

It also seems pointless, since the buffer is already showing comments highlighted.

Instead, you could simply inspect the faces at point:

(defun wh--get-faces (pos)
  "Get all the font faces at POS."
  (remq nil
        (list
         (get-char-property pos 'read-face-name)
         (get-char-property pos 'face)
         (plist-get (text-properties-at pos) 'face))))

(defun wh-string-p (pos)
  "Return non-nil if POS is inside a string."
  (memq 'font-lock-string-face (wh--get-faces pos)))

Why don't major modes do this? The buffer is already fontified, so I would expect this to be faster, more robust, and require less code.

Wilfred Hughes
  • 6,890
  • 2
  • 29
  • 59
  • 1
    I like this question. However, what if you don't use `font-lock-mode`? (Not that I think you should.) – mbork Nov 08 '14 at 09:58

2 Answers2

12

The problem is that it is not more robust.

Firstly, the major modes are precisely the ones responsible for deciding what's a comment or a string. If they were able to successfully define them for the purpose of font-locking, they should be able to do the same for other purposes.

Secondly, reading the syntax to determine the context that point is inside is the more robust way of doing it if it is done right. If you have found instances where that fails, it's worth submitting a bug report to the major-mode author.


The reason why inspecting the faces is less robust is because it can fail in some situations.

  1. For starters, the user could have disabled font-lock-mode (maybe it's a huge buffer), but even with font-lock-mode enabled, faces are somewhat unstable.

  2. Also, the user could have a minor-mode that adds some font-lock-keywords (like highlighting TODO in comments). Or there might be a minor mode that dynamically applies some faces after font-lock has fontified the buffer.

In summary, the major mode has no guarantee that the faces defined by it are the faces currently applied.

Wilfred Hughes
  • 6,890
  • 2
  • 29
  • 59
Malabarba
  • 22,878
  • 6
  • 78
  • 163
2

I guess the main reason is because font-lock uses syntax-ppss.

Stefan
  • 26,154
  • 3
  • 46
  • 84