[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [AUCTeX-devel] Adding key/vals to predefined ones

From: Arash Esbati
Subject: Re: [AUCTeX-devel] Adding key/vals to predefined ones
Date: Thu, 12 Feb 2015 17:11:32 +0000 (UTC)
User-agent: Loom/3.14 (

Tassilo Horn <tsdh <at>> writes:

Hi Tassilo,

> Arash Esbati <esbati <at>> writes:

> > Is there any blueprint how this can be implemented on AUCTeX side?  The
> > following excerpt for an `enumitem.el' works for commands mentioned
> > above, but I have still no clear idea about how to build a bridge
> > between AUCTeX auto-parser and key-vals defined when a file is loaded,
> > i.e. how to add items from `LaTeX-enumitem-SetEnumitem*-list' to
> > `LaTeX-enumitem-key-val-options'.
> You could also use two separate variables, e.g.,
> `LaTeX-enumitem-key-val-options' and an automatically buffer-local
> `LaTeX-enumitem-key-val-options-local', and then your argument functions
> you use in `TeX-add-symbols' and `LaTeX-add-environments' in your style
> hook would append the values of the two variables to build the complete
> list of keyval options available for a macro/environment.

Thanks for your suggestion, will do so.  But I am still struggling with one
other issue.  Consider this example (say filename.tex):

--8<---------------cut here---------------start------------->8---



--8<---------------cut here---------------end--------------->8---

When I insert all above, everything works and
`LaTeX-enumitem-key-val-options' gets updated.  After hitting `C-c C-n',
AUCTeX writes this into `filename.el'

--8<---------------cut here---------------start------------->8---
(TeX-add-style-hook ...
    '("label" "numeric")
    '("leftmargin" "standard"))
--8<---------------cut here---------------end--------------->8---

Now I close the file and re-open it.  My question is: What is the best way
to get the key/vals back into `LaTeX-enumitem-key-val-options[-local]'?  My
simple approach below returns always nil for `TEST'. 

  (setq TEST LaTeX-enumitem-SetEnumitemValue-list))

This time, I am attaching the current state of my `enumitem.el'; as always,
looking forward to your comments.

TIA, Arash

--8<---------------cut here---------------start------------->8---
(defvar LaTeX-enumitem-key-val-options
  '(;; Vertical Spacing
    ;; Horizontal Spacing
    ("leftmargin"  ("*" "!"))
    ("itemindent"  ("*" "!"))
    ("labelsep"    ("*" "!"))
    ("labelwidth"  ("*" "!"))
    ("labelindent" ("*" "!"))
    ;; Labels and cross reference format
    ("align" ("left" "right" "parleft"))
    ;; Numbering, stopping, resuming
    ;; Series
    ;; Penalties
    ;; Description styles
    ("style" ("standard" "multiline" "nextline" "sameline" "unboxed"))
    ;; Compact lists
    ;; Wide lists
    ;; Inline lists
    ("mode" ("boxed" "unboxed")))
  "Key=value options for enumitem macros and environments.")

;; (defvar LaTeX-enumitem-key-val-options-local nil
;;   "List of key=val options defined by `enumitem' and by user per file.")

(make-variable-buffer-local 'LaTeX-enumitem-key-val-options)

;; Needed for auto-parsing.
(require 'tex)

;; Variables needed for \newlist: This command is not hooked into the
;; parser via `TeX-auto-add-type'

(defvar LaTeX-enumitem-newlist-list nil
  "List of environments defined by command `\\newlist' from
`enumitem' package.")

(defvar LaTeX-enumitem-newlist-list-local nil
  "Local list of all environments definded with `\\newlist'
plus available through `enumitem' package.")
(make-variable-buffer-local 'LaTeX-enumitem-newlist-list-local)

(defvar LaTeX-enumitem-newlist-list-item-arg nil
  "List of description like environments defined by command
`\\newlist' from `enumitem' package.")

(defvar LaTeX-enumitem-newlist-list-item-arg-local nil
  "Local list of all description like environments defined by command
`\\newlist' plus available through `enumitem' package.")
(make-variable-buffer-local 'LaTeX-enumitem-newlist-list-item-arg-local)

(defvar LaTeX-enumitem-newlist-auto nil
  "Temporary for parsing the arguments of `\\newlist' from
`enumitem' package.")

(defvar LaTeX-enumitem-newlist-regexp
    (1 2) LaTeX-enumitem-newlist-auto)
  "Matches the arguments of `\\newlist' from `enumitem'

;; Setup for \SetEnumitemKey:

(TeX-auto-add-type "enumitem-SetEnumitemKey" "LaTeX")

(defvar LaTeX-enumitem-SetEnumitemKey-regexp
    1 LaTeX-auto-enumitem-SetEnumitemKey)
  "Matches the arguments of `\\SetEnumitemKey' from `enumitem'

;; Setup for \SetEnumitemValue:

(TeX-auto-add-type "enumitem-SetEnumitemValue" "LaTeX")

(defvar LaTeX-enumitem-SetEnumitemValue-regexp
    (1 2) LaTeX-auto-enumitem-SetEnumitemValue)
  "Matches the arguments of `\\SetEnumitemValue' from `enumitem'

;; Plug them into the machinery.
(defun LaTeX-enumitem-auto-prepare ()
  "Clear various `LaTeX-enumitem-*' before parsing."
  (setq LaTeX-enumitem-newlist-auto          nil
        LaTeX-enumitem-newlist-list          nil
        LaTeX-enumitem-newlist-list-item-arg nil
        LaTeX-auto-enumitem-SetEnumitemKey   nil
        LaTeX-auto-enumitem-SetEnumitemValue nil))

(defun LaTeX-enumitem-auto-cleanup ()
  "Move parsing results into right places for further usage."
  ;; \newlist{<name>}{<type>}{<max-depth>}
  ;; env=<name>, type=<type>, ignored=<max-depth>
  (dolist (env-type LaTeX-enumitem-newlist-auto)
    (let* ((env  (car env-type))
           (type (cadr env-type)))
      (add-to-list 'LaTeX-auto-environment
                   (list env 'LaTeX-enumitem-env-with-opts))
      (add-to-list 'LaTeX-enumitem-newlist-list
                   (list env))
      (when (or (string-equal type "description")
                (string-equal type "description*"))
        (add-to-list 'LaTeX-enumitem-newlist-list-item-arg
                     (list env)))))
  ;; \SetEnumitemKey{<key>}{<replacement>}
  (dolist (key LaTeX-auto-enumitem-SetEnumitemKey)
    (add-to-list 'LaTeX-enumitem-SetEnumitemKey-list
                 (list key)))
  ;; \SetEnumitemValue{<key>}{<string>}{<replacement>}
  (dolist (key-val LaTeX-auto-enumitem-SetEnumitemValue)
    (let* ((key (car key-val))
           (val (cdr key-val)))
      (list key val))))

(add-hook 'TeX-auto-prepare-hook #'LaTeX-enumitem-auto-prepare t)
(add-hook 'TeX-auto-cleanup-hook #'LaTeX-enumitem-auto-cleanup t)

;; Again, thanks to Tassilo Horn for his comments on this one.
(defun LaTeX-enumitem-env-with-opts (env)
  "Insert ENV and optional key-val and the first item."
   (let ((opts (TeX-read-key-val t LaTeX-enumitem-key-val-options)))
     (when (and opts (not (string-equal opts "")))
       (format "[%s]" opts))))
  (if (TeX-active-mark)
        (end-of-line 1))
    (end-of-line 0))
  (delete-char 1)
  (when (looking-at (concat "^[ \t]+$\\|"
                            "^[ \t]*" TeX-comment-start-regexp "+[ \t]*$"))
    (delete-region (point) (line-end-position)))
  ;; Deactivate the mark here in order to prevent `TeX-parse-macro'
  ;; from swapping point and mark and the \item ending up right after
  ;; \begin{...}.
  ;; The inserted \item may have outdented the first line to the
  ;; right.  Fill it, if appropriate.
  (when (and (not (looking-at "$"))
             (not (assoc environment LaTeX-indent-environment-list))
             (> (- (line-end-position) (line-beginning-position))
    (LaTeX-fill-paragraph nil)))
(defun LaTeX-arg-SetEnumitemKey (optional &optional prompt)
  "Ask for a new key to be defined and add it to
  (let ((key     (read-string "New Key: "))
        (replace (TeX-read-key-val optional
    (TeX-argument-insert key     optional)
    (TeX-argument-insert replace optional)
    (add-to-list 'LaTeX-enumitem-key-val-options (list key))
    (LaTeX-add-enumitem-SetEnumitemKeys key)))

(defun LaTeX-arg-SetEnumitemValue (optional &optional prompt)
  "Ask for a new value added to an existing key incl. the final
replacement of value."
  (let* ((key (TeX-read-key-val optional LaTeX-enumitem-key-val-options "Key"))
         (val (read-string "String value: "))
         (key-match (car (assoc key LaTeX-enumitem-key-val-options)))
         (val-match (cdr (assoc key LaTeX-enumitem-key-val-options))))
    (setq LaTeX-enumitem-key-val-options
          (assq-delete-all (car (assoc key LaTeX-enumitem-key-val-options))
    (if (null val-match)
        (add-to-list 'LaTeX-enumitem-key-val-options (list key (list val)))
      (add-to-list 'LaTeX-enumitem-key-val-options
                   (list key (delete-dups (apply 'append (list val) 
    (TeX-argument-insert key optional)
    (TeX-argument-insert val optional)))

 (lambda ()

   ;; Add enumitem to the parser.
   (TeX-auto-add-regexp LaTeX-enumitem-newlist-regexp)
   (TeX-auto-add-regexp LaTeX-enumitem-SetEnumitemKey-regexp)
   (TeX-auto-add-regexp LaTeX-enumitem-SetEnumitemValue-regexp)

   ;; Set the standard env's to the local list.
   (setq LaTeX-enumitem-newlist-list-local
         '(("itemize") ("enumerate") ("description")))

   ;; Add the starred versions to the local list.
   (when (LaTeX-provided-package-options-member "enumitem" "inline")
     (setq LaTeX-enumitem-newlist-list-local
           (append '(("itemize*") ("enumerate*") ("description*"))

   ;; Now add the parsed env's to the local list.
   (setq LaTeX-enumitem-newlist-list-local
         (append LaTeX-enumitem-newlist-list

   ;; Move parsed description like env's into a local variable.
   (setq LaTeX-enumitem-newlist-list-item-arg-local
   ;; Tell AUCTeX about special items parsed
   (dolist (env LaTeX-enumitem-newlist-list-item-arg-local)
    (add-to-list 'LaTeX-item-list `(,(car env) . LaTeX-item-argument)))

   ;; Standard env's take key-val as optional argument.
    '("itemize"      LaTeX-enumitem-env-with-opts)
    '("enumerate"    LaTeX-enumitem-env-with-opts)
    '("description"  LaTeX-enumitem-env-with-opts))

   ;; Make inline env's available with package option "inline"
   (when (LaTeX-provided-package-options-member "enumitem" "inline")
      '("itemize*"     LaTeX-enumitem-env-with-opts)
      '("enumerate*"   LaTeX-enumitem-env-with-opts)
      '("description*" LaTeX-enumitem-env-with-opts))
     (add-to-list 'LaTeX-item-list '("description*" . LaTeX-item-argument)))

   ;; Cloning lists
    ;; The easy way would be:
    ;; '("newlist"
    ;;   "Name" (TeX-arg-eval
    ;;           completing-read "Type: "
    ;;                 '(("itemize")  ("enumerate")  ("description")
    ;;                   ("itemize*") ("enumerate*") ("description*")))
    ;;  "Max-depth")
    ;; But we go the extra mile to improve the user experience and add
    ;; the arguments directly to appropriate lists.
    ;; \newlist{<name>}{<type>}{<max-depth>}
       (lambda ()
         (let ((name (read-string "Name: "))
               (type (completing-read
                      "Type: "
                      '(("itemize")  ("enumerate")  ("description")
                        ("itemize*") ("enumerate*") ("description*"))))
               (depth (read-string "Max-depth: ")))
           (setq LaTeX-enumitem-newlist-list-local
                 (append `(,(list name)) LaTeX-enumitem-newlist-list-local))
           (when (or (string-equal type "description")
                     (string-equal type "description*"))
             (add-to-list 'LaTeX-item-list `(,name . LaTeX-item-argument)))
           (LaTeX-add-environments `(,name LaTeX-enumitem-env-with-opts))
           (insert (format "{%s}" name)
                   (format "{%s}" type))
           (format "%s" depth)))))

    ;; \renewlist{<name>}{<type>}{<max-depth>}
      (TeX-arg-eval completing-read "Name: "
      (TeX-arg-eval completing-read "Type: "
                    '(("itemize")  ("enumerate")  ("description")
                      ("itemize*") ("enumerate*") ("description*")))

    ;; \setlist{<names,levels>}{<key-vals>}
      [TeX-arg-eval mapconcat 'identity
                     "Environment(s), level(s): "
                       ("1") ("2") ("3") ("4"))) ","]
      (TeX-arg-key-val LaTeX-enumitem-key-val-options))

    ;; \setlist*{<names,levels>}{<key-vals>}
      [TeX-arg-eval mapconcat 'identity
                     "Environment, level: "
                       ("1") ("2") ("3") ("4"))) ","]
      (TeX-arg-key-val LaTeX-enumitem-key-val-options)))

   ;; General commands:

    ;; Ask for an Integer and insert it.
    '("setlistdepth" "Integer")

    ;; Just add the braces and let the user do the rest.
    '("AddEnumerateCounter" 3)

    ;; This command only makes sense for enumerate type environments.
    ;; Currently, we offer all defined env's -- to be improved
    ;; sometimes.
      (TeX-arg-eval completing-read "List name: "

    ;; "Key" will be parsed and added to key-val list.
    '("SetEnumitemKey" LaTeX-arg-SetEnumitemKey)

    ;; "Key" and "Value" are added to our key-val list
    '("SetEnumitemValue" LaTeX-arg-SetEnumitemValue "Replacement")

    ) ; This terminates `TeX-add-symbols'
   ;; Setting enumerate short label
   (when (LaTeX-provided-package-options-member "enumitem" "shortlabels")
        (TeX-arg-eval completing-read "Key: "
                      '(("A") ("a") ("I") ("i") ("1")))

   ;; Fontification
   (when (and (featurep 'font-latex)
              (eq TeX-install-font-lock 'font-latex-setup))
     (font-latex-add-keywords '(("newlist"             "{{{")
                                ("renewlist"           "{{{")
                                ("setlist"             "*[{")
                                ("AddEnumerateCounter" "{{{")
                                ("SetEnumitemKey"      "{{" )
                                ("SetEnumitemValue"    "{{{"))
     (font-latex-add-keywords '(("restartlist"            "{" )
                                ("setlistdepth"           "{" )
                                ("SetEnumerateShortLabel" "{{"))

(defvar LaTeX-enumitem-package-options
  '("inline" "ignoredisplayed" "shortlabels" "loadonly")
  "Package options for the enumitem package.")
--8<---------------cut here---------------end--------------->8---

reply via email to

[Prev in Thread] Current Thread [Next in Thread]