Function: define-combobulate-language
define-combobulate-language is a macro defined in
combobulate-setup.el.
Signature
(define-combobulate-language &key NAME MAJOR-MODES (CUSTOM nil) SETUP-FN (KEYMAP-VAR nil) (EXTRA-DEFCUSTOMS nil) (EXTRA-DEFVARS nil))
Documentation
Define a new language for Combobulate.
NAME is the name of the language as it'll be known to Combobulate and tree-sitter, and MAJOR-MODES is a list of major modes that should be set up for this language.
Source Code
;; Defined in /nix/store/b5fvrwzi3zvkabyzx0in6gw1cj963z46-emacs-packages-deps/share/emacs/site-lisp/combobulate-setup.el
(cl-defmacro define-combobulate-language (&key name
major-modes (custom nil)
setup-fn
(keymap-var nil)
(extra-defcustoms nil)
(extra-defvars nil))
"Define a new language for Combobulate.
NAME is the name of the language as it'll be known to
Combobulate and tree-sitter, and MAJOR-MODES is a list of major
modes that should be set up for this language."
(cl-assert (symbolp name) t "NAME must be a symbol")
(let ((group-name (intern (format "combobulate-language-%s" name))))
;; Create a customize group for the language
(let ((defvars
;; ((SHORTHAND DOCSTRING DEFAULT-VALUE) ... )
(append
combobulate-default-definitions
(and (boundp extra-defvars) (symbol-value extra-defvars))))
(defcustoms
(append
`((major-modes
"List of major modes where this language applies.
Combobulate will set up tree-sitter to use that language as the
primary buffer language if the major mode does not do this
itself. This is also useful for modes that lack tree-sitter
support where you still want to use Combobulate's features."
',major-modes
:type '(repeat symbol)))
(and (boundp extra-defcustoms) (symbol-value extra-defcustoms))))
(known-variable-shorthands)
(decls))
(cl-flet*
((intern-var (lang-name variable)
(combobulate-get variable lang-name))
(intern-lang-var (variable)
(push (if (stringp variable)
(intern variable)
variable)
known-variable-shorthands)
(intern-var name variable)))
(push `(custom-declare-group
',group-name nil ,(format "Language settings for `%s'" name)
:group 'combobulate)
decls)
;; Appease the byte compiler.
(push '(declare-function combobulate-baseline-indentation-default "combobulate-manipulation") decls)
(push '(defvar combobulate-key-map) decls)
(push '(defvar combobulate-options-key-map) decls)
;; Create the `defcustom' forms.
(pcase-dolist (`(,shorthand-var ,docstring ,default . ,rest) defcustoms)
;; (push shorthand-var known-variable-shorthands)
(push `(defcustom ,(intern-lang-var shorthand-var) ,default ,docstring
,@rest
:group ',group-name)
decls))
;; Create the `defvar' forms.
(pcase-dolist (`(,shorthand-var ,docstring ,default) defvars)
;; (push shorthand-var known-variable-shorthands)
(push `(defvar ,(intern-lang-var shorthand-var)
;; We must check that we have an association record
;; explicitly (and not just the value) as it could
;; be nil, which would then roll over to default,
;; which is not what we want.
,(if-let ((v (assoc shorthand-var (symbol-value custom))))
(cadr v)
default)
,docstring)
decls))
;; Create (or reuse) a key map and create a minor mode for
;; LANGUAGE.
(let ((language-keymap (or keymap-var (intern-lang-var "map")))
(envelope-keymap (or keymap-var (intern-lang-var "envelope-map")))
(minor-mode-fn (intern-lang-var "minor-mode")))
;; General key map for this language
(push `(makunbound ',language-keymap) decls)
(push `(defvar-keymap ,language-keymap
:doc ,(format "Keymap for Combobulate language for `%s'." name)
:full nil
:parent combobulate-key-map)
decls)
;; This is the envelope-specific keymap
(push `(defvar-keymap ,envelope-keymap
:doc ,(format "Keymap for Combobulate envelopes for `%s'." name)
:full nil)
decls)
;; This maps the `e' key to the envelope keymap.
(push `(define-key ,language-keymap (kbd ,(format "%s e" combobulate-key-prefix))
,envelope-keymap)
decls)
;; Create a minor mode for this language.
(push `(defvar-local ,minor-mode-fn nil
,(format "Combobulate minor mode for the `%s' tree-sitter language." name))
decls)
(push `(define-minor-mode ,minor-mode-fn
,(format "Combobulate minor mode for the `%s' tree-sitter language." name)
:init-value nil
:lighter "©"
:keymap ,language-keymap
;; Recycle `combobulate-mode' as the variable used
;; to store the toggle state of this minor mode
;; even though it is effectively 'shared' across
;; all the various minor modes we may create when
;; this macro is called. This has two beneficial
;; advantages:
;;
;; 1. `M-x combobulate-mode' is the default
;; entrypoint for the package, and people expect
;; the "mode" variable to match the command name.
;;
;; 2. It is not possible to engage more than one
;; minor mode in the same buffer.
:variable ,minor-mode-fn
;; Hm... leaving this to nil is probably for the
;; best. We do not want to encourage people to go
;; around experimenting with the minor mode as that
;; could circumvent other setup processes.
:interactive nil
;; This is the generic setup function that is
;; always run.
(combobulate-setup)
;; If a language has a custom setup function, we
;; run it with the language we are being
;; triggered in.
,(when setup-fn
`(,setup-fn ',name)))
decls)
(push `(combobulate-register-language ',name ',major-modes #',minor-mode-fn)
decls)
(push `(defconst ,(intern-lang-var "defined-variables")
',known-variable-shorthands
,(format "List of variable shorthands known to `%s'.
Each shorthand is a symbol referencing a variable belonging to
that language. They are best accessed with the `combobulate-read'
macro which optionally takes a language argument to retrieve that
language's setting." name))
decls)))
`(progn ,@(nreverse decls)))))