;;; listings.el --- AUCTeX style for `listings.sty'
-;; Copyright (C) 2004, 2005, 2009, 2013 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2005, 2009, 2013-2017 Free Software Foundation, Inc.
;; Author: Ralf Angeli <angeli@iwi.uni-sb.de>
;; Maintainer: auctex-devel@gnu.org
;; This file adds support for `listings.sty'.
;;
+;; May 2015: The style detects new environments defined with
+;; `\lstnewenvironment'. Users need to invoke `C-c C-n' for this.
+;;
+;; October 2015: The style detects new "styles" defined with
+;; `\lstdefinestyle' and offers them during key-value query.
+;;
+;; January 2017: Put label in opt. argument of environment.
+;;
;; FIXME: Please make me more sophisticated!
;;; Code:
+;; Needed for compiling `pushnew':
+(eval-when-compile (require 'cl))
+
;; The following are options taken from chapter 4 of the listings
;; manual (2007/02/22 Version 1.4).
(defvar LaTeX-listings-key-val-options
;; Captions
("title")
("caption") ; Insert braces?
- ("label")
+ ;; Label is inserted as part of environment insertion; see below
+ ;; for "lstlisting" in style hook
+ ;; ("label")
("nolol" ("true" "false"))
("numberbychapter" ("true" "false"))
("captionpos" ("t" "b")) ; Can be a subset of tb.
("indexstyle")
;; Column alignment
("columns" ("fixed" "flexible" "fullflexible" "spaceflexible")) ;
- ; Also supports an optional
- ; argument with {c,l,r}.
+ ; Also supports an optional
+ ; argument with {c,l,r}.
("flexiblecolumns" ("true" "false"))
("keepspaces" ("true" "false"))
("basewidth")
("multicolumn"))
"Key=value options for listings macros and environments.")
+(defvar LaTeX-listings-key-val-options-local nil
+ "Buffer-local Key=value options for listings macros and environments.")
+(make-variable-buffer-local 'LaTeX-listings-key-val-options-local)
+
+;; Setup for \lstnewenvironment:
+(defvar LaTeX-auto-listings-lstnewenvironment nil
+ "Temporary for parsing the arguments of `\\lstnewenvironment'
+from `listings' package.")
+
+(defvar LaTeX-listings-lstnewenvironment-regexp
+ `(,(concat "\\\\lstnewenvironment"
+ "[ \t\n\r]*{\\([A-Za-z0-9]+\\)}%?"
+ "[ \t\n\r]*\\[?\\([0-9]?\\)\\]?%?"
+ "[ \t\n\r]*\\(\\[\\)?")
+ (1 2 3) LaTeX-auto-listings-lstnewenvironment)
+ "Matches the argument of `\\lstnewenvironment' from `listings.sty'.")
+
+;; Setup for \lstdefinestyle:
+(TeX-auto-add-type "listings-lstdefinestyle" "LaTeX")
+
+(defvar LaTeX-listings-lstdefinestyle-regexp
+ '("\\\\lstdefinestyle{\\([^}]+\\)}"
+ 1 LaTeX-auto-listings-lstdefinestyle)
+ "Matches the argument of \"\\lstdefinestyle\" from
+\"listings\" package.")
+
+;; Setup for parsing the labels inside optional arguments:
+
+(defvar LaTeX-listings-key-val-label-extract
+ (concat
+ "\\(?:\\[[^][]*"
+ "\\(?:{[^}{]*"
+ "\\(?:{[^}{]*"
+ "\\(?:{[^}{]*}[^}{]*\\)*"
+ "}[^}{]*\\)*"
+ "}[^][]*\\)*"
+ "label[ \t]*=[ \t]*{\\([^}]+\\)}"
+ "\\(?:[^]]*\\)*"
+ "\\]\\)")
+ "Helper regexp to extract the label out of optional argument.")
+
+(defvar LaTeX-listings-key-val-label-regexp
+ `(,(concat
+ "\\\\begin{lstlisting}" LaTeX-listings-key-val-label-extract)
+ 1 LaTeX-auto-label)
+ "Matches the label inside an optional argument after \\begin{lstlisting}.")
+
+(defun LaTeX-listings-update-style-key ()
+ "Update the \"style\" key from `LaTeX-listings-key-val-options-local'
+with user-defined values via the \"lstdefinestyle\" macro."
+ (let* ((elt (assoc "style" LaTeX-listings-key-val-options-local))
+ (key (car elt))
+ (temp (copy-alist LaTeX-listings-key-val-options-local))
+ (opts (assq-delete-all (car (assoc key temp)) temp)))
+ (pushnew (list key (TeX-delete-duplicate-strings
+ (mapcar #'car (LaTeX-listings-lstdefinestyle-list))))
+ opts :test #'equal)
+ (setq LaTeX-listings-key-val-options-local
+ (copy-alist opts))))
+
+(defun LaTeX-listings-auto-prepare ()
+ "Clear temporary variable from `listings.sty' before parsing."
+ (setq LaTeX-auto-listings-lstnewenvironment nil)
+ (setq LaTeX-auto-listings-lstdefinestyle nil))
+
+(defun LaTeX-listings-auto-cleanup ()
+ "Process the parsed results of \"\\lstnewenvironment\" and
+\"\\lstdefinestyle\"."
+ (dolist (env-args LaTeX-auto-listings-lstnewenvironment)
+ (let ((env (car env-args))
+ (args (cadr env-args))
+ (opt (nth 2 env-args)))
+ (cond (;; opt. 1st argument and mandatory argument(s)
+ (and args (not (string-equal args ""))
+ opt (not (string-equal opt "")))
+ (LaTeX-add-environments
+ `(,env
+ LaTeX-env-args
+ [TeX-arg-key-val LaTeX-listings-key-val-options-local]
+ (LaTeX-env-label-as-keyval "caption")
+ ,(1- (string-to-number args)))))
+ (;; mandatory argument(s) only
+ (and args (not (string-equal args ""))
+ (string-equal opt ""))
+ (LaTeX-add-environments
+ (list env (string-to-number args))))
+ (t ; No args
+ (LaTeX-add-environments (list env))))
+ (add-to-list 'LaTeX-indent-environment-list `(,env current-indentation) t)
+ (add-to-list 'LaTeX-verbatim-environments-local env t)
+ (add-to-list 'LaTeX-label-alist `(,env . LaTeX-listing-label) t)
+ ;; Add new env to parser for labels in opt. argument:
+ (TeX-auto-add-regexp `(,(concat "\\\\begin{" env "}"
+ LaTeX-listings-key-val-label-extract)
+ 1 LaTeX-auto-label))
+ ;; Tell RefTeX
+ (when (fboundp 'reftex-add-label-environments)
+ (reftex-add-label-environments
+ `((,env ?l "lst:" "~\\ref{%s}" nil (regexp "[Ll]isting")))))
+ ;; Fontification
+ (when (and (fboundp 'font-latex-add-keywords)
+ (fboundp 'font-latex-update-font-lock)
+ (eq TeX-install-font-lock 'font-latex-setup))
+ ;; Tell font-lock about the update.
+ (font-latex-update-font-lock t))
+ ;; Add new env's to `ispell-tex-skip-alist': skip the entire env
+ (TeX-ispell-skip-setcdr `(,(cons env (concat "\\\\end{" env "}"))))))
+ (when (LaTeX-listings-lstdefinestyle-list)
+ (LaTeX-listings-update-style-key)))
+
+(add-hook 'TeX-auto-prepare-hook #'LaTeX-listings-auto-prepare t)
+(add-hook 'TeX-auto-cleanup-hook #'LaTeX-listings-auto-cleanup t)
+(add-hook 'TeX-update-style-hook #'TeX-auto-parse t)
+
(TeX-add-style-hook
"listings"
(lambda ()
+
+ ;; Add to parser:
+ (TeX-auto-add-regexp LaTeX-listings-lstnewenvironment-regexp)
+ (TeX-auto-add-regexp LaTeX-listings-lstdefinestyle-regexp)
+ (TeX-auto-add-regexp LaTeX-listings-key-val-label-regexp)
+
+ ;; Local version of key-val options:
+ (setq LaTeX-listings-key-val-options-local
+ (copy-alist LaTeX-listings-key-val-options))
+
;; New symbols
(TeX-add-symbols
'("lstalias" ["Alias dialect"] "Alias" ["Dialect"] "Language")
- '("lstdefinestyle" "Style name"
- (TeX-arg-key-val LaTeX-listings-key-val-options))
+ '("lstdefinestyle"
+ (TeX-arg-eval
+ (lambda ()
+ (let ((name (TeX-read-string "Style name: ")))
+ (LaTeX-add-listings-lstdefinestyles name)
+ (LaTeX-listings-update-style-key)
+ (format "%s" name))))
+ (TeX-arg-key-val LaTeX-listings-key-val-options-local))
'("lstinline" TeX-arg-verb)
- '("lstinputlisting" [TeX-arg-key-val LaTeX-listings-key-val-options]
+ '("lstinputlisting" [TeX-arg-key-val LaTeX-listings-key-val-options-local]
TeX-arg-file)
"lstlistoflistings"
'("lstnewenvironment" "Name" ["Number or arguments"] ["Default argument"]
"Starting code" "Ending code")
- '("lstset" (TeX-arg-key-val LaTeX-listings-key-val-options))
+ '("lstset" (TeX-arg-key-val LaTeX-listings-key-val-options-local))
'("lstloadlanguages" t)
;; 4.17 Short Inline Listing Commands
'("lstMakeShortInline" [ "Options" ] "Character")
'("lstDeleteShortInline" "Character")
-
+
"lstgrinddeffile" "lstaspectfiles" "lstlanguagefiles"
"lstlistingname" "lstlistlistingname")
-
+
;; New environments
(LaTeX-add-environments
'("lstlisting" LaTeX-env-args
- [TeX-arg-key-val LaTeX-listings-key-val-options]))
+ [TeX-arg-key-val LaTeX-listings-key-val-options-local]
+ (LaTeX-env-label-as-keyval "caption")))
+
+ ;; Append "lstlisting" to `LaTeX-label-alist':
+ (add-to-list 'LaTeX-label-alist '("lstlisting" . LaTeX-listing-label) t)
+
;; Filling
- (make-local-variable 'LaTeX-indent-environment-list)
- (add-to-list 'LaTeX-indent-environment-list
- '("lstlisting" current-indentation))
- (make-local-variable 'LaTeX-verbatim-regexp)
- (setq LaTeX-verbatim-regexp (concat LaTeX-verbatim-regexp "\\|lstlisting"))
+ (add-to-list (make-local-variable 'LaTeX-indent-environment-list)
+ '("lstlisting" current-indentation) t)
(add-to-list 'LaTeX-verbatim-environments-local "lstlisting")
(add-to-list 'LaTeX-verbatim-macros-with-delims-local "lstinline")
(add-to-list 'LaTeX-verbatim-macros-with-braces-local "lstinline")
;; Fontification
(when (and (fboundp 'font-latex-add-keywords)
- (fboundp 'font-latex-set-syntactic-keywords)
+ (fboundp 'font-latex-update-font-lock)
(eq TeX-install-font-lock 'font-latex-setup))
(font-latex-add-keywords '(("lstnewenvironment" "{[[{{")) 'function)
(font-latex-add-keywords '(("lstinputlisting" "[{")) 'reference)
- (font-latex-add-keywords '(("lstinline" "[{") ; The second argument should
- ; actually be verbatim.
+ (font-latex-add-keywords '(("lstinline" "[")
("lstlistoflistings" ""))
'textual)
(font-latex-add-keywords '(("lstalias" "{{")
("lstdefinestyle" "{{")
("lstset" "{"))
'variable)
- ;; For syntactic fontification, e.g. verbatim constructs.
- (font-latex-set-syntactic-keywords)
;; Tell font-lock about the update.
- (setq font-lock-set-defaults nil)
- (font-lock-set-defaults)))
+ (font-latex-update-font-lock t)))
LaTeX-dialect)
-(defvar LaTeX-listings-package-options '("draft" "final" "savemem"
+(defvar LaTeX-listings-package-options '("draft" "final" "savemem"
"noaspects"
- ;; procnames is mentioned in
- ;; Section 5.2
- "procnames")
+ ;; procnames is mentioned in
+ ;; Section 5.2
+ "procnames")
"Package options for the listings package.")
;;; listings.el ends here