branch: elpa commit 40b351888936f8f80deabaddf34b32c6d130f8f8 Author: Arash Esbati <arash.esb...@gmail.com> Commit: Arash Esbati <arash.esb...@gmail.com>
Add new spell checking dictionary tex-ispell.el * doc/todo.texi (Wishlist): Remove spell checking of macros from wish list. * doc/changes.texi: Mention new file tex-ispell.el in news since 11.89. Fix typo. * Makefile.in (AUCSRC): Add tex-ispell.el. * latex.el (tex-ispell): Require tex-ispell.el. * tex.el (TeX-ispell-extend-skip-list): New customizable variable. (TeX-ispell-skip-setcar, TeX-ispell-skip-setcdr): New functions. (TeX-ispell-tex-arg-end): New function. * tex-ispell.el: Add new file. --- Makefile.in | 2 +- doc/changes.texi | 9 +- doc/todo.texi | 4 - latex.el | 1 + tex-ispell.el | 299 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tex.el | 80 +++++++++++++++ 6 files changed, 389 insertions(+), 6 deletions(-) diff --git a/Makefile.in b/Makefile.in index 23bf4a5..b79eaf4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -84,7 +84,7 @@ MULEELC = @MULEELC@ AUCSRC = tex.el tex-buf.el tex-style.el plain-tex.el latex.el tex-info.el \ texmathp.el multi-prompt.el tex-mik.el font-latex.el tex-font.el \ context.el context-en.el context-nl.el tex-fold.el \ - toolbar-x.el tex-bar.el bib-cite.el + toolbar-x.el tex-bar.el bib-cite.el tex-ispell.el AUCELC = $(AUCSRC:.el=.elc) STYLESRC = style/prosper.el \ diff --git a/doc/changes.texi b/doc/changes.texi index ed61b5f..a14ff2e 100644 --- a/doc/changes.texi +++ b/doc/changes.texi @@ -12,6 +12,13 @@ @itemize @bullet @item +@AUCTeX{} has a new Ispell dictionary @file{tex-ispell.el} for macros +and environments which will be skipped during spell checking. The +activiation of this feature is controlled by a new customize option +@code{TeX-ispell-extend-skip-list}, which is set to @code{t} and +activated by default. + +@item @AUCTeX{} has a new customize option @code{TeX-raise-frame-function} that is currently only used by Evince and Atril inverse search to raise the Emacs frame. @@ -46,7 +53,7 @@ A new option, @code{TeX-PDF-from-DVI}, controls if and how to produce a obsolete and may be removed in future releases. @item -Support for a number of external viewers has been addedd: +Support for a number of external viewers has been added: @itemize @item Atril viewer. Forward and inverse search requires version 1.9.1 or diff --git a/doc/todo.texi b/doc/todo.texi index 8025351..c21d816 100644 --- a/doc/todo.texi +++ b/doc/todo.texi @@ -76,10 +76,6 @@ used to insert an appropriate @samp{\usepackage} statement if the user tries to insert a macro for which the respective package has not been requested yet. -@item Spell checking of macros - -A special ispell dictionary for macros could be nice to have. - @item Improvements to error reporting Fringe indicators for errors in the main text would be nice. diff --git a/latex.el b/latex.el index babcd1a..c21699d 100644 --- a/latex.el +++ b/latex.el @@ -30,6 +30,7 @@ (require 'tex) (require 'tex-style) +(require 'tex-ispell) (eval-when-compile (require 'cl)) ;FIXME: Use cl-lib. ;;; Syntax diff --git a/tex-ispell.el b/tex-ispell.el new file mode 100644 index 0000000..f10d371 --- /dev/null +++ b/tex-ispell.el @@ -0,0 +1,299 @@ +;;; tex-ispell.el --- AUCTeX skip additions for Ispell + +;; Copyright (C) 2016 Free Software Foundation, Inc. + +;; Author: Arash Esbati <arash.esbati'at'gmail.com> +;; Maintainer: auctex-de...@gnu.org +;; Keywords: tex, wp, convenience + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; This file provides additions to skip list of Ispell (in this +;; context, Ispell is synonym for Ispell, Aspell and Hunspell spelling +;; checker programs). Macro arguments and environments skipped by +;; Ispell are stored in the car and/or cdr of +;; `ispell-tex-skip-alists'. This file uses two functions +;; `TeX-ispell-skip-setcar' and `TeX-ispell-skip-setcdr' defined in +;; `tex.el' to add new items to this variable. + +;; Ispell has a lot of LaTeX macros and environments already built-in. +;; E.g., check this link for Hunspell program: + +;; https://github.com/hunspell/hunspell/blob/master/src/parsers/latexparser.cxx + +;; Ispell does not check spelling in the preamble of a document. +;; Hence, only document macros and environments should be added here. +;; Currently, this file has support for the following macro packages: + +;; acro.sty +;; amsmath.sty +;; attachfile.sty +;; booktabs.sty +;; cleveref.sty +;; enumitem.sty +;; fancyref.sty +;; fancyvrb.sty +;; fontaxes.sty +;; fontspec.sty +;; listings.sty +;; mdframed.sty +;; minted.sty +;; nameref.sty +;; siunitx.sty +;; splitidx.sty +;; tabularx.sty +;; tabulary.sty +;; tikz.sty +;; varioref.sty + +;; If you have further additions, drop a line to <auctex-de...@gnu.org>. + +;;; Code: + +(require 'tex) + +;; Add new macros here: +(eval-when-compile + (defvar TeX-ispell-skip-cmds-list + '(;; acro.sty + ("ac" . 1) + ("ac*" . 1) + ("Ac" . 1) + ("Ac*" . 1) + ("acs" . 1) + ("acs*" . 1) + ("acl" . 1) + ("acl*" . 1) + ("Acl" . 1) + ("Acl*" . 1) + ("aca" . 1) + ("aca*" . 1) + ("acf" . 1) + ("acf*" . 1) + ("Acf" . 1) + ("Acf*" . 1) + ("acp" . 1) + ("acp*" . 1) + ("Acp" . 1) + ("Acp*" . 1) + ("acsp" . 1) + ("acsp*" . 1) + ("aclp" . 1) + ("aclp*" . 1) + ("Aclp" . 1) + ("Aclp*" . 1) + ("acap" . 1) + ("acap*" . 1) + ("acfp" . 1) + ("acfp*" . 1) + ("Acfp" . 1) + ("Acfp*" . 1) + ("Iac" . 1) + ("iacs" . 1) + ("iacl" . 1) + ("acflike" . 1) + ("acflike*" . 1) + ("acfplike" . 1) + ("acfplike*" . 1) + ("acsingle" . 1) + ("acsingle*" . 1) + ("Acsingle" . 1) + ("Acsingle*" . 1) + ("acreset" . 1) + ("acuse" . 1) + ("acsetup" . 1) + ;; attachfile.sty + ("attachfile" . 1) + ("attachfilesetup" . 1) + ("textattachfile" . 1) + ;; booktabs.sty + ("specialrule" . 3) + ;; cleveref.sty + ("cref" . 1) + ("Cref" . 1) + ("cref*" . 1) + ("Cref*" . 1) + ("cpageref" . 1) + ("Cpageref" . 1) + ("namecref" . 1) + ("nameCref" . 1) + ("lcnamecref" . 1) + ("labelcref" . 1) + ("crefrange" . 1) + ("Crefrange" . 1) + ("cpagerefrange" . 1) + ("Cpagerefrange" . 1) + ("crefrange*" . 1) + ("Crefrange*" . 1) + ("crefrange" . 2) + ("Crefrange" . 2) + ("cpagerefrange" . 2) + ("Cpagerefrange" . 2) + ("crefrange*" . 2) + ("Crefrange*" . 2) + ;; fancyref.sty + ("fref" . 1) + ("Fref" . 1) + ;; fancyvrb.sty + ("fvset" . 1) + ("VerbatimInput" . 1) + ;; fontaxes.sty + ("figureversion" . 1) + ;; fontspec.sty + ("addfontfeatures" . 1) + ;; listings.sty + ("lstinputlisting" . 1) + ("lstset" . 1) + ;; mdframed.sty + ("mdfsetup" . 1) + ("mdfapptodefinestyle" . 2) + ;; minted.sty + ("inputminted" . 2) + ("setminted" . 1) + ("setmintedinline" . 1) + ;; nameref.sty + ("nameref" . 1) + ("Nameref" . 1) + ;; siunitx.sty + ("num" . 1) + ("si" . 1) + ("sisetup" . 1) + ("SI" . 2) + ;; splitidx.sty + ("sindex" . 1) + ;; varioref.sty + ("vref" . 1) + ("Vref" . 1) + ("vref*" . 1) + ("Ref" . 1) + ("vpageref" . 1) + ("vpageref*" . 1) + ("fullref" . 1) + ("vrefrange" . 1) + ("vrefrange*" . 1) + ("vpagerefrange" . 1) + ("vpagerefrange*" . 1) + ("vrefrange" . 2) + ("vrefrange*" . 2) + ("vpagerefrange" . 2) + ("vpagerefrange*" . 2) ) + "List of commands with arguments to be skipped. +Each element of the list is a cons cell with command name +\(string) as car and the number of mandatory arguments to be +skipped as cdr.")) + + +;; Add new environments with one optional argument here: +(eval-when-compile + (defvar TeX-ispell-skip-envs-opt-arg-list + '(;; enumitem.sty + "description" + "description*" + "enumerate" + "enumerate*" + "itemize" + "itemize*" + ;; mdframed.sty + "mdframed") + "List of LaTeX environments with an opt argument to be skipped.")) + + +;; Add others delimited here: +(TeX-ispell-skip-setcar + '(;; LaTeX-base + ("\\\\raisebox" TeX-ispell-tex-arg-end 1 2 0) + ;; booktabs.sty + ("\\\\cmidrule" . "\\(([^)]*)\\)?{[-0-9]+}") + ;; fontspec.sty + ("\\\\fontspec" TeX-ispell-tex-arg-end 1 1 0) + ;; minted.sty + ("\\\\mint\\(inline\\)?\\(\\[[^]]*\\]\\)?{\\([^}]+\\)}{" . "}") + ("\\\\mint\\(inline\\)?\\(\\[[^]]*\\]\\)?{\\([^}]+\\)}|" . "|") + ("\\\\mint\\(inline\\)?\\(\\[[^]]*\\]\\)?{\\([^}]+\\)}#" . "#") + ("\\\\mint\\(inline\\)?\\(\\[[^]]*\\]\\)?{\\([^}]+\\)}\\+" . "\\+") + ("\\\\mint\\(inline\\)?\\(\\[[^]]*\\]\\)?{\\([^}]+\\)}\\*" . "\\*"))) + + +;; Add environments here: +(TeX-ispell-skip-setcdr + '(;; amsmath.sty + ("\\(align\\(\\*\\|at\\*?\\)?\\|flalign\\*?\\)" . + "\\\\end{\\(align\\(\\*\\|at\\*?\\)?\\|flalign\\*?\\)}") + ("gather\\*?" . "\\\\end{gather\\*?}") + ("multline\\*?" . "\\\\end{multline\\*?}") + ;; listings.sty + ("lstlisting" . "\\\\end{lstlisting}") + ;; minted.sty + ("minted" . "\\\\end{minted}") + ;; tabularx.sty, tabulary.sty, Standard LaTeX tabular*-env + ("tabular[*xy]" TeX-ispell-tex-arg-end) + ;; tikz.sty + ("tikzpicture" . "\\\\end{tikzpicture}") + ;; fancyvrb.sty: In practice, all verbatim environments have a * + ;; variant, which sets showspaces=true + ("\\(Save\\|[BL]\\)?Verbatim\\(\\*\\|Out\\)?" . + "\\\\end{\\(Save\\|[BL]\\)?Verbatim\\(\\*\\|Out\\)?}"))) + + +;; No customization below this line + +(eval-when-compile + (defun TeX-ispell-sort-skip-cmds-list (arg) + "Return elements from `TeX-ispell-skip-cmds-list' acc. to ARG." + (when (member arg '(1 2 3)) + (let (cmds) + (dolist (elt TeX-ispell-skip-cmds-list) + (when (= (cdr elt) arg) + (push (car elt) cmds))) + (symbol-value 'cmds))))) + +(defvar TeX-ispell-skip-cmds-one-arg-regexp + (eval-when-compile + (concat "\\\\" + (regexp-opt (TeX-ispell-sort-skip-cmds-list 1) t))) + "Regexp of LaTeX commands with one argument to be skipped.") + +(defvar TeX-ispell-skip-cmds-two-args-regexp + (eval-when-compile + (concat "\\\\" + (regexp-opt (TeX-ispell-sort-skip-cmds-list 2) t))) + "Regexp of LaTeX commands with two arguments to be skipped.") + +(defvar TeX-ispell-skip-cmds-three-args-regexp + (eval-when-compile + (concat "\\\\" + (regexp-opt (TeX-ispell-sort-skip-cmds-list 3) t))) + "Regexp of LaTeX commands with three arguments to be skipped.") + +(defvar TeX-ispell-skip-envs-opt-arg-regexp + (eval-when-compile + (regexp-opt TeX-ispell-skip-envs-opt-arg-list t)) + "Regexp of LaTeX environments with an opt argument to be skipped.") + +;; Make them available to Ispell: +(TeX-ispell-skip-setcar + `((,TeX-ispell-skip-cmds-one-arg-regexp ispell-tex-arg-end) + (,TeX-ispell-skip-cmds-two-args-regexp ispell-tex-arg-end 2) + (,TeX-ispell-skip-cmds-three-args-regexp ispell-tex-arg-end 3))) + +(TeX-ispell-skip-setcdr + `((,TeX-ispell-skip-envs-opt-arg-regexp ispell-tex-arg-end 0))) + +(provide 'tex-ispell) + +;;; tex-ispell.el ends here diff --git a/tex.el b/tex.el index 6c302bb..7e41738 100644 --- a/tex.el +++ b/tex.el @@ -6521,6 +6521,86 @@ NAME may be a package, a command, or a document." (append '(plain-tex-mode ams-tex-mode latex-mode doctex-mode) ispell-tex-major-modes)) +(defcustom TeX-ispell-extend-skip-list t + "Whether to extend regions selected for skipping during spell checking." + :group 'TeX-misc + :type 'boolean) + +;; These functions are used to add new items to +;; `ispell-tex-skip-alists' -- see tex-ispell.el: +(defun TeX-ispell-skip-setcar (skip) + "Add SKIP to car of `ispell-tex-skip-alists'. +SKIP is an alist with the format described in +`ispell-tex-skip-alists'. Each element in SKIP is added on top +of the car of `ispell-tex-skip-alists'. This only happens if +`TeX-ispell-extend-skip-list' is non-nil." + (when TeX-ispell-extend-skip-list + (let ((raws (car ispell-tex-skip-alists)) + (envs (cadr ispell-tex-skip-alists))) + (dolist (x skip) + (pushnew x raws :test #'equal)) + (setq ispell-tex-skip-alists (list raws envs))))) + +(defun TeX-ispell-skip-setcdr (skip) + "Add SKIP to cdr of `ispell-tex-skip-alists'. +SKIP is an alist with the format described in +`ispell-tex-skip-alists'. Each element in SKIP is added on top +of the cdr of `ispell-tex-skip-alists'. This only happens if +`TeX-ispell-extend-skip-list' is non-nil." + (when TeX-ispell-extend-skip-list + (let ((raws (car ispell-tex-skip-alists)) + (envs (cadr ispell-tex-skip-alists))) + (dolist (x skip) + (pushnew x envs :test #'equal)) + (setq ispell-tex-skip-alists (list raws envs))))) + +(defun TeX-ispell-tex-arg-end (&optional arg1 arg2 arg3) + "Skip across ARG1, ARG2 and ARG3 number of braces and brackets. +This function is a variation of `ispell-tex-arg-end'. It should +be used when adding skip regions to `ispell-tex-skip-alists' for +constructs like: + + \\begin{tabularx}{300pt}[t]{lrc} ... + or + \\fontspec{font name}[font features] + +where optional and/or mandatory argument(s) follow(s) a mandatory +one. ARG1 is the number of mandatory arguments before the +optional one, ARG2 the max. number of following optional +arguments, ARG3 is the max. number of mandatory arguments +following. Omitting argument means 1. + +Here some examples for additions to `ispell-tex-skip-alists': + + \\begin{tabularx}{300pt}[t]{lrc} ... + ARG 1 2 3 + (\"tabularx\" TeX-ispell-tex-arg-end) or equivalent + (\"tabularx\" TeX-ispell-tex-arg-end 1 1 1) + + \\fontspec{font name}[font features] + ARG1 ARG2 ARG3=0 + (\"\\\\\\\\fontspec\" TeX-ispell-tex-arg-end 1 1 0) + + \\raisebox{lift}[height][depth]{contents} + ARG1 ARG2 ARG3=0 (checked by Ispell) + (\"\\\\\\\\raisebox\" TeX-ispell-tex-arg-end 1 2 0) + +Optional arguments before the first mandatory one are all +skipped." + (condition-case nil + (progn + (while (looking-at "[ \t\n]*\\[") (forward-sexp)) + (forward-sexp (or arg1 1)) + (let ((num 0)) + (while (and (looking-at "[ \t\n]*\\[") + (< num (or arg2 1))) + (setq num (1+ num)) + (forward-sexp))) + (forward-sexp (or arg3 1))) + (error + (message "Error skipping s-expressions at point %d" (point)) + (sit-for 2)))) + ;;; Abbrev mode