From 16835a43e2a14742d2b3e4f73ab90415613089f3 Mon Sep 17 00:00:00 2001 From: "modula t. worm" Date: Mon, 21 Nov 2016 17:13:01 -0600 Subject: [PATCH] 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. --- el/sclang-language.el | 3 +++ el/sclang-mode.el | 31 +++++++++++++++---------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/el/sclang-language.el b/el/sclang-language.el index b0bc1a6..2f03b32 100644 --- a/el/sclang-language.el +++ b/el/sclang-language.el @@ -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.") diff --git a/el/sclang-mode.el b/el/sclang-mode.el index 999162f..e90396c 100644 --- a/el/sclang-mode.el +++ b/el/sclang-mode.el @@ -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