DerivedMode

Instead of writing a new MajorMode 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)))
    )

CategoryCode