Instead of writing a new mode from scratch, you should derive your new mode from an existing mode. Deriving a new mode from fundamental mode (which does basically nothing) is better than writing a new mode from scratch. (Unless you know what you are doing, of course.)
Here’s an example of how to translate a very simple GenericMode code sample into a DerivedMode code sample. This would be the way to go if you think that GenericMode is too limiting for your needs.
Old GenericMode code:
(define-generic-mode `kk-mode
()
()
'(("\\(--.*\\)" 1 'font-lock-comment-face))
()
(list (lambda () (set (make-local-variable 'comment-start) "--")))
"Major mode to edit KK files.")New DerivedMode code:
(defvar mydsl-events
'("reservedword1"
"reservedword2"))
(defvar mydsl-keywords
'("other-keyword" "another-keyword"))
;; I'd probably put in a default that you want, as opposed to nil
(defvar mydsl-tab-width nil "Width of a tab for MYDSL mode")
;; Two small edits.
;; First is to put an extra set of parens () around the list
;; which is the format that font-lock-defaults wants
;; Second, you used ' (quote) at the outermost level where you wanted ` (backquote)
;; you were very close
(defvar mydsl-font-lock-defaults
`((
;; stuff between "
("\"\\.\\*\\?" . font-lock-string-face)
;; ; : , ; { } => @ $ = are all special elements
(":\\|,\\|;\\|{\\|}\\|=>\\|@\\|$\\|=" . font-lock-keyword-face)
( ,(regexp-opt mydsl-keywords 'words) . font-lock-builtin-face)
( ,(regexp-opt mydsl-events 'words) . font-lock-constant-face)
)))
(define-derived-mode mydsl-mode fundamental-mode "MYDSL script"
"MYDSL mode is a major mode for editing MYDSL files"
;; you again used quote when you had '((mydsl-hilite))
;; I just updated the variable to have the proper nesting (as noted above)
;; and use the value directly here
(setq font-lock-defaults mydsl-font-lock-defaults)
;; when there's an override, use it
;; otherwise it gets the default value
(when mydsl-tab-width
(setq tab-width mydsl-tab-width))
;; for comments
;; overriding these vars gets you what (I think) you want
;; they're made buffer local when you set them
(setq comment-start "#")
(setq comment-end "")
(modify-syntax-entry ?# "< b" mydsl-mode-syntax-table)
(modify-syntax-entry ?\n "> b" mydsl-mode-syntax-table)
;;A gnu-correct program will have some sort of hook call here.
)
(provide 'mydsl-mode)If you are are deriving your new mode from something other than fundamental-mode, you may want to add to that mode’s set of existing keywords.
(defface c3-face-1
'((t (:foreground "#FF0000")))
"red") ;;; c3-mode
(define-derived-mode c3-mode sgml-mode
"c3-mode"
"A variant of SGML mode. Numbers appear in red." (font-lock-add-keywords nil '(("[0-9]" . 'c3-face-1)))
)