Prevent Emacs fontification failure w/ lots of classes - Fixes #248

What I've done to fix this:

- add a sclang-class-list variable in sclang-language.el, which is a
  list of all the classes known to sclang. this is populated when
  sclang starts.
- update sclang-font-lock-class-keyword-matcher in
  sclang-mode.el. since the sclang-class-name-regexp now will match
  all words that start with a capital letter (see next bullet point
  for that change), this function had to be updated to check to make
  sure that the word starting with a capital letter is in the list of
  classes. if it is, then we know it's a class and it gets
  highlighted. if it's not, then it's just something the user typed
  with a capital letter, so we don't highlight it.
- update sclang-update-font-lock in sclang-mode.el. instead of
  generating a huge regexp from a list of all the classes in
  SuperCollider, just run the normal fontification from that
  function. this avoids making the regexp too big and thus prevents
  fontification from failing.
This commit is contained in:
modula t. worm 2016-11-21 17:13:01 -06:00
parent 6d6ec77634
commit 16835a43e2
2 changed files with 18 additions and 16 deletions

View file

@ -207,6 +207,9 @@ low-resource systems."
(defvar sclang-symbol-table nil
"List of all defined symbols.")
(defvar sclang-class-list nil
"List of all defined classes.")
(defvar sclang-symbol-history nil
"List of recent symbols read from the minibuffer.")

View file

@ -244,10 +244,20 @@
'font-lock-comment-face)))
(defun sclang-font-lock-class-keyword-matcher (limit)
(let ((regexp (or sclang-font-lock-class-keywords
(concat "\\<" sclang-class-name-regexp "\\>")))
(case-fold-search nil))
(re-search-forward regexp limit t)))
(let ((regexp (concat "\\<" sclang-class-name-regexp "\\>"))
(case-fold-search nil)
(continue t)
(res nil))
(while continue
(setq res (re-search-forward regexp limit t))
(if (or (null res) (null sclang-class-list))
(setq continue nil)
(let ((thing (thing-at-point 'word)))
(if (null thing)
(setq res nil continue nil)
(when (position (substring-no-properties thing) sclang-class-list :test 'equal)
(setq continue nil))))))
res))
(defun sclang-set-font-lock-keywords ()
(setq
@ -255,7 +265,7 @@
sclang-font-lock-keywords-1
(list
;; keywords
(cons (regexp-opt sclang-font-lock-keyword-list'words)
(cons (regexp-opt sclang-font-lock-keyword-list 'words)
'font-lock-keyword-face)
;; builtins
(cons (regexp-opt sclang-font-lock-builtin-list 'words)
@ -302,17 +312,6 @@
(defun sclang-update-font-lock ()
"Update font-lock information in all sclang-mode buffers."
(setq sclang-font-lock-class-keywords
(and sclang-symbol-table
(let* ((list (remove-if
(lambda (x) (or (not (sclang-class-name-p x))
(sclang-string-match "^Meta_" x)))
sclang-symbol-table))
;; need to set this for large numbers of classes
(max-specpdl-size (* (length list) 2)))
(condition-case nil
(concat "\\<\\(?:Meta_\\)?\\(?:" (regexp-opt list) "\\)\\>")
(error nil)))))
;; too expensive
;; (dolist (buffer (buffer-list))
;; (with-current-buffer buffer