summaryrefslogtreecommitdiff
path: root/lisp/newcomment.el
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2019-06-26 10:03:48 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2019-06-26 10:03:48 -0400
commit698ff554ac2699ec48fefc85a1307cbc4a183b0d (patch)
treea7b7592f7973f81cad4410366d313e790616907e /lisp/newcomment.el
parent9233865b7005831e63755eb84ae7da060f878a55 (diff)
downloademacs-698ff554ac2699ec48fefc85a1307cbc4a183b0d.tar.gz
* lisp/calc/calc-ext.el (math-scalarp): Fix typo
Diffstat (limited to 'lisp/newcomment.el')
-rw-r--r--lisp/newcomment.el99
1 files changed, 94 insertions, 5 deletions
diff --git a/lisp/newcomment.el b/lisp/newcomment.el
index ac706b949ba..f4ca6e77b46 100644
--- a/lisp/newcomment.el
+++ b/lisp/newcomment.el
@@ -334,6 +334,92 @@ terminated by the end of line (i.e., `comment-end' is empty)."
(const :tag "EOL-terminated" eol))
:group 'comment)
+;;;; Setup syntax from "high-level" description of comment syntax
+
+;; This defines `comment-set-syntax' so a major mode can just call
+;; this one function to setup the comment syntax both in the syntax-table
+;; and in the various comment-* variables.
+
+(defvar comment--set-table
+ ;; We want to associate extra properties with syntax-table, but syntax-tables
+ ;; don't have "properties", so we use an eq-hash-table indexed by
+ ;; syntax-tables instead.
+ (make-hash-table :test #'eq))
+
+(defun comment--set-comment-syntax (st comment-list)
+ "Set up comment functionality for generic mode."
+ (let ((chars nil)
+ (comstyles)
+ (comment-start nil))
+
+ ;; Go through all the comments.
+ (pcase-dolist (`(,start ,end . ,props) comment-list)
+ (let ((nested (if (plist-get props :nested) "n"))
+ (comstyle
+ ;; Reuse comstyles if necessary.
+ (or (cdr (assoc start comstyles))
+ (cdr (assoc end comstyles))
+ ;; Otherwise, use a style not yet in use.
+ (if (not (rassoc "" comstyles)) "")
+ (if (not (rassoc "b" comstyles)) "b")
+ "c")))
+ (push (cons start comstyle) comstyles)
+ (push (cons end comstyle) comstyles)
+
+ ;; Setup the syntax table.
+ (if (= (length start) 1)
+ (modify-syntax-entry (aref start 0)
+ (concat "< " comstyle nested) st)
+ (let ((c0 (aref start 0)) (c1 (aref start 1)))
+ ;; Store the relevant info but don't update yet.
+ (push (cons c0 (concat (cdr (assoc c0 chars)) "1")) chars)
+ (push (cons c1 (concat (cdr (assoc c1 chars))
+ (concat "2" comstyle)))
+ chars)))
+ (if (= (length end) 1)
+ (modify-syntax-entry (aref end 0)
+ (concat "> " comstyle nested) st)
+ (let ((c0 (aref end 0)) (c1 (aref end 1)))
+ ;; Store the relevant info but don't update yet.
+ (push (cons c0 (concat (cdr (assoc c0 chars))
+ (concat "3" comstyle)))
+ chars)
+ (push (cons c1 (concat (cdr (assoc c1 chars)) "4")) chars)))))
+
+ ;; Process the chars that were part of a 2-char comment marker
+ (with-syntax-table st ;For `char-syntax'.
+ (dolist (cs (nreverse chars))
+ (modify-syntax-entry (car cs)
+ (concat (char-to-string (char-syntax (car cs)))
+ " " (cdr cs))
+ st)))))
+
+(defun comment--set-comment-vars (comment-list)
+ (when comment-list
+ (let ((first (car comment-list)))
+ (setq-local comment-start (car first))
+ (setq-local comment-end
+ (let ((end (cadr first)))
+ (if (string-equal end "\n") "" end))))
+ (unless comment-start-skip ;Don't override manual setup.
+ (setq-local comment-start-skip
+ (concat (regexp-opt (mapcar #'car comment-list))
+ "+[ \t]*")))
+ (unless comment-end-skip ;Don't override manual setup.
+ (setq-local comment-end-skip
+ (concat "[ \t]*"
+ (regexp-opt (mapcar #'cadr comment-list)))))))
+
+(defun comment-set-syntax (st comment-list)
+ (comment--set-comment-syntax st comment-list)
+ (setf (gethash st comment--set-table) comment-list))
+
+(defun comment-get-syntax (&optional st)
+ (unless st (setq st (syntax-table)))
+ (or (gethash st comment--set-table)
+ (let ((parent (char-table-parent st)))
+ (when parent (comment-get-syntax parent)))))
+
;;;;
;;;; Helpers
;;;;
@@ -358,11 +444,14 @@ functions work correctly. Lisp callers of any other `comment-*'
function should first call this function explicitly."
(unless (and (not comment-start) noerror)
(unless comment-start
- (let ((cs (read-string "No comment syntax is defined. Use: ")))
- (if (zerop (length cs))
- (error "No comment syntax defined")
- (set (make-local-variable 'comment-start) cs)
- (set (make-local-variable 'comment-start-skip) cs))))
+ (let ((comment-list (comment-get-syntax)))
+ (if comment-list
+ (comment--set-comment-vars comment-list)
+ (let ((cs (read-string "No comment syntax is defined. Use: ")))
+ (if (zerop (length cs))
+ (error "No comment syntax defined")
+ (set (make-local-variable 'comment-start) cs)
+ (set (make-local-variable 'comment-start-skip) cs))))))
;; comment-use-syntax
(when (eq comment-use-syntax 'undecided)
(set (make-local-variable 'comment-use-syntax)