(require 'eieio) (require 'polymode-core) ;;; ROOT CLASS (if (fboundp 'eieio-named) (progn (defclass pm-root (eieio-instance-inheritor eieio-named) ((-props :initform '() :type list :documentation "Internal. Used to store various user history values. Use `pm--prop-get' and `pm--prop-put' to place key value pairs into this list.")) "Root polymode class.") ;; bug #22840 (defmethod clone ((obj eieio-named) &rest params) "Clone OBJ, initializing `:parent' to OBJ. All slots are unbound, except those initialized with PARAMS." (let* ((newname (and (stringp (car params)) (pop params))) (nobj (apply #'call-next-method obj params)) (nm (slot-value obj 'object-name))) (eieio-oset nobj 'object-name (or newname (save-match-data (if (and nm (string-match "-\\([0-9]+\\)" nm)) (let ((num (1+ (string-to-number (match-string 1 nm))))) (concat (substring nm 0 (match-beginning 0)) "-" (int-to-string num))) (concat nm "-1"))))) nobj))) (defclass pm-root (eieio-instance-inheritor) ((-props :initform '() :type list :documentation "Internal. Plist used to store various extra metadata such as user history. Use `pm--prop-get' and `pm--prop-put' to place key value pairs into this list.")) "Root polymode class.")) ;;; CONFIG (defclass pm-polymode (pm-root) ((hostmode :initarg :hostmode :initform 'pm-host/blank :type symbol :custom symbol :documentation "Symbol pointing to an object of class pm-chunkmode representing the host chunkmode.") (minor-mode :initarg :minor-mode :initform 'polymode-minor-mode :type symbol :custom symbol :documentation "Symbol pointing to minor-mode function that should be activated in all buffers (base and indirect). This is a \"glue\" mode and is `polymode-minor-mode' by default. You will rarely need to change this.") (lighter :initarg :lighter :initform " PM" :type string :custom string :documentation "Modline lighter.") (exporters :initarg :exporters :initform '(pm-exporter/pandoc) :type list :custom list :documentation "List of names of polymode exporters available for this polymode.") (exporter :initarg :exporter :initform nil :type (or null symbol) :custom symbol :documentation "Current exporter name. If non-nil should be the name of the default exporter for this polymode. Can be set with `polymode-set-exporter' command.") (weavers :initarg :weavers :initform '() :type list :custom list :documentation "List of names of polymode weavers available for this polymode.") (weaver :initarg :weaver :initform nil :type (or null symbol) :custom symbol :documentation "Current weaver name. If non-nil this is the default weaver for this polymode. Can be dynamically set with `polymode-set-weaver'") (map :initarg :map :initform 'polymode-mode-map :type (or symbol list) :documentation "Has a similar role as the :keymap argument in `define-polymode' with the difference that this argument is inherited through cloning, but :keymap argument is not. That is, child objects derived through clone will inherit the :map argument of its parents through the following scheme: if :map is nil or an alist of keys, the parent is inspected for :map argument and the keys are merged recursively from parent to parent till a symbol :map slot is met. If :map is a symbol, it must be a keymap, in which case this keymap is used and no parents are further inspected for :map slot. If :map is an alist it must be suitable for `easy-mmode-define-keymap'.") (init-functions :initarg :init-functions :initform '() :type list :documentation "List of functions to run at the initialization time. All init-functions in the inheritance chain are called. Parents hooks first. So, if current config object C inherits from object B, which in turn inherits from object A. Then A's init-functions are called first, then B's and then C's. Either customize this slot or use `object-add-to-list' function.") (switch-buffer-functions :initarg :switch-buffer-functions :initform '() :type list :documentation "List of functions to run at polymode buffer switch. Each function is run with two arguments, OLD-BUFFER and NEW-BUFFER.") (-hostmode :type (or null pm-chunkmode) :documentation "Dynamically populated `pm-chunkmode' object.") (-innermodes :type list :initform '() :documentation "Dynamically populated list of chunkmodes objects that inherit from `pm-hbtchunkmode'.") (-buffers :initform '() :type list :documentation "Holds all buffers associated with current buffer. Dynamically populated.")) "Configuration for a polymode. Each polymode buffer contains a local variable `pm/polymode' instantiated from this class or a subclass of this class.") (defclass pm-polymode-one (pm-polymode) ((innermode :initarg :innermode :type symbol :custom symbol :documentation "Symbol of the chunkmode. At run time this object is cloned and placed in -innermodes slot.")) "Configuration for a simple polymode that allows only one innermode. For example noweb.") (defclass pm-polymode-multi (pm-polymode) ((innermodes :initarg :innermodes :type list :custom list :initform nil :documentation "List of names of the chunkmode objects that are associated with this configuration. At initialization time, all of these are cloned and plased in -innermodes slot.")) "Configuration for a polymode that allows multiple (known in advance) innermodes.") (defclass pm-polymode-multi-auto (pm-polymode-multi) ((auto-innermode :initarg :auto-innermode :type symbol :custom symbol :documentation "Name of pm-hbtchunkmode-auto object (a symbol). At run time this object is cloned and placed in -auto-innermodes with coresponding :mode slot initialized at run time.") (-auto-innermodes :type list :initform '() :documentation "List of chunkmode objects that are auto-generated in `pm-get-span' method for this class.")) "Configuration for a polymode that allows multiple innermodes that are not known in advance. Examples are org-mode and markdown.") ;;; CHUNKMODE CLASSES (defclass pm-chunkmode (pm-root) ((mode :initarg :mode :type symbol :initform nil :custom symbol) (protect-indent-line :initarg :protect-indent-line :type boolean :initform t :custom boolean :documentation "Whether to modify local `indent-line-function' by narrowing to current span first") (indent-offset :initarg :indent-offset :type integer :initform 0 :documentation "Offset to add when indenting chunk's line. Takes effect only when :protect-indent-line is non-nil.") (font-lock-narrow :initarg :font-lock-narrow :type boolean :initform t :documentation "Whether to narrow to span during font lock") (adjust-face :initarg :adjust-face :type (or number face list) :custom (or number face list) :initform nil :documentation "Fontification adjustments chunk face. It should be either, nil, number, face or a list of text properties as in `put-text-property' specification. If nil no highlighting occurs. If a face, use that face. If a number, it is a percentage by which to lighten/darken the default chunk background. If positive - lighten the background on dark themes and darken on light thems. If negative - darken in dark thems and lighten in light thems.") (init-functions :initarg :init-functions :initform '() :type list :documentation "List of functions to called after the initialization of chunkmode has finished. Functions are called the buffer associated with this chunkmode. All init-functions in the inheritance chain are called. Parents hooks first. So, if current config object C inherits from object B, which in turn inherits from object A. Then A's init-functions are called first, then B's and then C's. Either customize this slot or use `object-add-to-list' function.") (switch-buffer-functions :initarg :switch-buffer-functions :initform '() :type list :documentation "List of functions to run at polymode buffer switch. Each function is run with two arguments, OLD-BUFFER and NEW-BUFFER. In contrast to identically named slot in `pm-polymode' class, these functions are run only when NEW-BUFFER is associated with this chunkmode.") (-buffer :type (or null buffer) :initform nil)) "Representatioin of a generic chunkmode object.") (defclass pm-bchunkmode (pm-chunkmode) () "Representation of the body-only chunkmodes. Body-only chunkmodes are commonly used as host modes. For example for a the web-mdoe the hostmode is `html-mode', for nowweb mode the host mode is usually `latex-mode', etc.") (defclass pm-hbtchunkmode (pm-chunkmode) ((head-mode :initarg :head-mode :type symbol :initform 'poly-head-tail-mode :custom symbol :documentation "Chunk's header mode. If set to 'body, the head is considered part of the chunk body. If set to 'host, head is considered part of the surrounding host mode.") (tail-mode :initarg :tail-mode :type symbol :initform nil :custom symbol :documentation "Chunk's tail mode. If nil, or 'head, the mode is picked from :HEAD-MODE slot. If set to 'body, the tail's mode is the same as chunk's body mode. If set to 'host, the mode will be of the parent host.") (head-reg :initarg :head-reg :initform "" :type (or string symbol) :custom (or string symbol) :documentation "Regexp for the chunk start (aka head), or a function returning the start and end positions of the head. See `pm--default-matcher' for an example function.") (tail-reg :initarg :tail-reg :initform "" :type (or string symbol) :custom (or string symbol) :documentation "Regexp for chunk end (aka tail), or a function returning the start and end positions of the tail. See `pm--default-matcher' for an example function.") (adjust-face :initform 2) (head-adjust-face :initarg :head-adjust-face :initform font-lock-type-face :type (or null number face list) :custom (or null number face list) :documentation "Can be a number, list or face.") (tail-adjust-face :initarg :tail-adjust-face :initform nil :type (or null number face list) :custom (or null number face list) :documentation "Can be a number, list or face. If nil, take the configuration from :head-adjust-face.") (-head-buffer :type (or null buffer) :initform nil :documentation "This buffer is set automatically to -buffer if :head-mode is 'body, and to base-buffer if :head-mode is 'host") (-tail-buffer :initform nil :type (or null buffer))) "Representation of an inner Head-Body-Tail chunkmode.") (defclass pm-hbtchunkmode-auto (pm-hbtchunkmode) ((retriever-regexp :initarg :retriever-regexp :type (or null string) :custom string :initform nil :documentation "Regexp that is used to retrive the modes symbol from the head of the chunkmode chunk. fixme: elaborate") (retriever-num :initarg :retriever-num :type integer :custom integer :initform 1 :documentation "Subexpression to be matched by :retriver-regexp") (retriever-function :initarg :retriever-function :type symbol :custom symbol :initform nil :documentation "Function symbol used to retrive the modes symbol from the head of the chunkmode chunk. It is called with no arguments with the point positioned at the beginning of the chunk header. It must return the mode name string or symbol (need not include '-mode' postfix).)")) "Representation of an inner chunkmode") (provide 'polymode-classes)