diff --git a/Makefile.in b/Makefile.in --- a/Makefile.in +++ b/Makefile.in @@ -134,7 +134,7 @@ style/acronym.el style/xparse.el style/fancyvrb.el \ style/tabulary.el style/fontspec.el style/unicode-math.el \ style/luacode.el style/metalogo.el style/english.el \ - style/exercise.el + style/exercise.el style/plext.el STYLEELC = $(STYLESRC:.el=.elc) CLEANFILES = $(AUCELC) $(STYLEELC) $(MULEELC) diff --git a/latex.el b/latex.el --- a/latex.el +++ b/latex.el @@ -1028,7 +1028,8 @@ (concat (unless (zerop (length pos)) (concat LaTeX-optop pos LaTeX-optcl)) - (concat TeX-grop fmt TeX-grcl))))) + (concat TeX-grop fmt TeX-grcl))) + (LaTeX-item-array t))) (defun LaTeX-env-label (environment) "Insert ENVIRONMENT and prompt for label." @@ -1076,7 +1077,8 @@ (concat TeX-grop width TeX-grcl) ;; not optional! (unless (zerop (length pos)) (concat LaTeX-optop pos LaTeX-optcl)) - (concat TeX-grop fmt TeX-grcl))))) + (concat TeX-grop fmt TeX-grcl))) + (LaTeX-item-tabular* t))) (defun LaTeX-env-picture (environment) "Insert ENVIRONMENT with width, height specifications." @@ -1154,6 +1156,126 @@ "Insert a new bibitem." (TeX-insert-macro "bibitem")) +(defun LaTeX-item-array (&optional suppress) + "Insert line break macro on the last line and suitable number of &'s. +For array and tabular environments. + +If SUPPRESS is non-nil, do not insert line break macro." + (unless suppress + (save-excursion + (end-of-line 0) + (just-one-space) + (TeX-insert-macro "\\"))) + (LaTeX-insert-ampersands + LaTeX-array-skipping-regexp 'LaTeX-array-count-columns)) + +(defun LaTeX-item-tabular* (&optional suppress) + "Insert line break macro on the last line and suitable number of &'s. +For tabular* environment. + +If SUPPRESS is non-nil, do not insert line break macro." + (unless suppress + (save-excursion + (end-of-line 0) + (just-one-space) + (TeX-insert-macro "\\"))) + (LaTeX-insert-ampersands + LaTeX-tabular*-skipping-regexp 'LaTeX-array-count-columns)) + +(defvar LaTeX-array-skipping-regexp (regexp-opt '("[t]" "[b]" "")) + "Regexp matching between \\begin{xxx} and column specification. +For array and tabular environments. See `LaTeX-insert-ampersands' for +detail.") + +(defvar LaTeX-tabular*-skipping-regexp + ;; Assume width specification contains neither nested curly brace + ;; pair nor escaped "}". + (concat "{[^}]*}[ \t]*" (regexp-opt '("[t]" "[b]" ""))) + "Regexp matching between \\begin{tabular*} and column specification. +For tabular* environment only. See `LaTeX-insert-ampersands' for detail.") + +(defun LaTeX-insert-ampersands (regexp func) + "Insert suitable number of ampersands for the current environment. +The number is calculated from REGEXP and FUNC. + +Example 1: +Consider the case that the current environment begins with +\\begin{array}[t]{|lcr|} +. REGEXP must be chosen to match \"[t]\", i.e., the text between just +after \"\\begin{array}\" and just before \"{|lcr|}\", which encloses +the column specification. FUNC must return the number of ampersands to +be inserted, which is 2 since this example specifies three columns. +FUNC is called with two arguments START and END, which spans the column +specification (without enclosing braces.) REGEXP is used to determine +these START and END. + +Example 2: +This time the environment begins with address@hidden,}p{5ex}} +. REGEXP must match \"{1.0\\linewidth}[b]\" and FUNC must return 1 from +the text \"address@hidden,}p{5ex}\" between START and END specified two columns. + +FUNC should return nil if it cannot determine the number of ampersands." + (let* ((cur (point)) + (num + (save-excursion + (ignore-errors + (LaTeX-find-matching-begin) + ;; Skip over "\begin{xxx}" and possible whitespaces. + (forward-list 1) + (skip-chars-forward " \t") + ;; Skip over the text specified by REGEXP and whitespaces. + (when (let ((case-fold-search nil)) + (re-search-forward regexp cur)) + (skip-chars-forward " \t") + (when (eq (following-char) ?{) + ;; We have reached the target "{yyy}" part. + (forward-char 1) + ;; The next line doesn't move point, so point + ;; is left just after the opening brace. + (let ((pos (TeX-find-closing-brace))) + (if pos + ;; Calculate number of ampersands to be inserted. + (funcall func (point) (1- pos)))))))))) + (if (natnump num) + (save-excursion (insert (make-string num ?&)))))) + +(defvar LaTeX-array-column-letters "clrp" + "Column letters for array-like environments. +See `LaTeX-array-count-columns' for detail.") + +(defun LaTeX-array-count-columns (start end) + "Count number of ampersands to be inserted. +The columns are specified by the letters found in the string +`LaTeX-array-column-letters' and the number of those letters within the +text between START and END is basically considered to be the number of +columns. The arguments surrounded between braces such as p{30pt} do not +interfere the count of columns. + +Return one less number than the column, or nil on failing to count the +right number." + (save-excursion + (let (p (cols 0)) + (goto-char start) + (while (< (setq p (point)) end) + + ;; The below block accounts for one unit of move for + ;; one column. + (setq cols (+ cols (skip-chars-forward + LaTeX-array-column-letters end))) + (skip-chars-forward (concat + "^" LaTeX-array-column-letters + TeX-grop) end) + (if (eq (following-char) ?{) (forward-list 1)) + + ;; Not sure whether this is really necessary or not, but + ;; prepare for possible infinite loop anyway. + (when (eq p (point)) + (setq cols nil) + (goto-char end))) + ;; The number of ampersands is one less than column. + (if cols (1- cols))))) + ;;; Parser (defvar LaTeX-auto-style nil) @@ -5678,7 +5800,10 @@ (make-local-variable 'LaTeX-item-list) (setq LaTeX-item-list '(("description" . LaTeX-item-argument) - ("thebibliography" . LaTeX-item-bib))) + ("thebibliography" . LaTeX-item-bib) + ("array" . LaTeX-item-array) + ("tabular" . LaTeX-item-array) + ("tabular*" . LaTeX-item-tabular*))) (setq TeX-complete-list (append '(("\\\\cite\\[[^]\n\r\\%]*\\]{\\([^{}\n\r\\%,]*\\)" diff --git a/style/amsmath.el b/style/amsmath.el --- a/style/amsmath.el +++ b/style/amsmath.el @@ -43,8 +43,8 @@ '("xalignat" LaTeX-amsmath-env-alignat) '("xalignat*" LaTeX-amsmath-env-alignat) '("xxalignat" LaTeX-amsmath-env-alignat) - '("aligned" LaTeX-amsmath-env-aligned) - '("gathered" LaTeX-amsmath-env-aligned) + '("aligned" ["Vertical position (t or b)"]) + '("gathered" ["Vertical position (t or b)"]) '("alignedat" LaTeX-amsmath-env-alignedat) "align*" "gather*" "flalign*" "multline*" "equation*" "split" @@ -104,19 +104,19 @@ (append '(("split" . LaTeX-item-equation) ("multline" . LaTeX-item-equation) ("multline*" . LaTeX-item-equation) - ("gather" . LaTeX-item-equations) + ("gather" . LaTeX-item-equation) ("gather*" . LaTeX-item-equation) ("gathered" . LaTeX-item-equation) - ("align" . LaTeX-item-equations) + ("align" . LaTeX-item-equation) ("align*" . LaTeX-item-equation) ("aligned" . LaTeX-item-equation) - ("alignat" . LaTeX-item-equations) - ("alignat*" . LaTeX-item-equation) - ("xalignat" . LaTeX-item-equations) - ("xalignat*" . LaTeX-item-equation) - ("xxalignat" . LaTeX-item-equation) - ("alignedat" . LaTeX-item-equation) - ("flalign" . LaTeX-item-equations) + ("alignat" . LaTeX-item-equation-alignat) + ("alignat*" . LaTeX-item-equation-alignat) + ("xalignat" . LaTeX-item-equation-alignat) + ("xalignat*" . LaTeX-item-equation-alignat) + ("xxalignat" . LaTeX-item-equation-alignat) + ("alignedat" . LaTeX-item-equation-alignat) + ("flalign" . LaTeX-item-equation) ("flalign*" . LaTeX-item-equation) ("matrix" . LaTeX-item-equation) ("pmatrix" . LaTeX-item-equation) @@ -136,7 +136,7 @@ (append '(("align" . LaTeX-amsmath-label) ("alignat" . LaTeX-amsmath-label) ("xalignat" . LaTeX-amsmath-label) - ("multline" . LaTeX-amsmath-label) + ("multline" . LaTeX-amsmath-label) ("flalign" . LaTeX-amsmath-label) ("gather" . LaTeX-amsmath-label)) LaTeX-label-alist)) @@ -160,38 +160,43 @@ (defun LaTeX-amsmath-env-alignat (env) (let ((ncols (read-string "Number of columns: "))) (LaTeX-insert-environment env (concat TeX-grop ncols TeX-grcl)) - (and (not (string= "xxalignat" env)) - (not (string= "*" (substring env -1))) - (LaTeX-label env) - (newline-and-indent)))) - -(defun LaTeX-amsmath-env-aligned (env) - (let ((where (read-string "(optional) Vertical position (t or b): "))) - (if (string= where "") - (setq where "") - (setq where (concat "[" where "]"))) - (LaTeX-insert-environment env where))) + (LaTeX-item-equation-alignat t))) (defun LaTeX-amsmath-env-alignedat (env) - (let ((where (read-string "(optional) Vertical position (t or b): ")) - (ncols (read-string "Number of columns: "))) - (if (string= where "") - (setq where "") - (setq where (concat "[" where "]"))) - (LaTeX-insert-environment env (concat where TeX-grop ncols TeX-grcl)))) + (let ((where (read-string "(Optional) Vertical position (t or b): ")) + (ncols (read-string "Number of columns: "))) + (unless (string= where "") + (setq where (concat LaTeX-optop where LaTeX-optcl))) + (LaTeX-insert-environment env (concat where TeX-grop ncols TeX-grcl)) + (LaTeX-item-equation-alignat t))) -(defun LaTeX-item-equation () - (end-of-line 0) - (just-one-space) - (insert "\\\\") - (forward-line 1) - (indent-according-to-mode)) +(defun LaTeX-item-equation (&optional suppress) + (unless suppress + (end-of-line 0) + (just-one-space) + (TeX-insert-macro "\\") + (forward-line 1) + (indent-according-to-mode)) + (let ((env (LaTeX-current-environment))) + (when (and (assoc env LaTeX-label-alist) + (LaTeX-label env)) + (LaTeX-newline) + (indent-according-to-mode)))) -(defun LaTeX-item-equations () - (LaTeX-item-equation) - (let ((environment (LaTeX-current-environment 1))) - (and (LaTeX-label environment) - (newline-and-indent)))) +(defun LaTeX-item-equation-alignat (&optional suppress) + (LaTeX-item-equation suppress) + (LaTeX-insert-ampersands + (concat "\\(?:" + (regexp-quote LaTeX-optop) "[tb]" (regexp-quote LaTeX-optcl) + "\\)?") + 'LaTeX-amsmath-alignat-number-of-ampersands)) + +(defun LaTeX-amsmath-alignat-number-of-ampersands (start end) + "Return the number of ampersands to insert. +The number is 2N-1 where N is the number taken from the text between +START and END." + (let ((num (string-to-number (buffer-substring-no-properties start end)))) + (if (integerp num) (+ num num -1)))) (defvar LaTeX-amsmath-package-options '("intlimits" "nointlimits" "sumlimits" "nosumlimits" diff --git a/style/array.el b/style/array.el --- a/style/array.el +++ b/style/array.el @@ -40,7 +40,10 @@ ;; `array.sty' adds a couple of new lengths. They're added here, rather than ;; in the `TeX-add-symbols' block. - (LaTeX-add-lengths "extratabsurround" "extrarowheight"))) + (LaTeX-add-lengths "extratabsurround" "extrarowheight") + + ;; `array.sty' adds some new column specification letters. + (set (make-local-variable 'LaTeX-array-column-letters) "clrpmb"))) (defvar LaTeX-array-package-options nil "Package options for array.") diff --git a/style/plext.el b/style/plext.el new file mode 100644 --- /dev/null +++ b/style/plext.el @@ -0,0 +1,49 @@ +;;; plext.el --- Style hook for the pLaTeX plext package. + +;;; Code: + +(TeX-add-style-hook + "plext" + (lambda () + ;; plext.sty extends some environments to accept option, e.g. , + ;; for vertical typesetting. + (LaTeX-add-environments + ;; TODO: Add support for minipage and picture + ;; environments extension. + '("array" LaTeX-plext-env-array) + '("tabular" LaTeX-plext-env-array) + '("tabular*" LaTeX-plext-env-array)) + + (set (make-local-variable 'LaTeX-array-skipping-regexp) + (concat "\\(?:<[tyz]>\\)?[ \t]*" (regexp-opt '("[t]" "[b]" "")))) + (set (make-local-variable 'LaTeX-tabular*-skipping-regexp) + (concat "\\(?:<[tyz]>\\)?[ \t]*{[^}]*}[ \t]*" + (regexp-opt '("[t]" "[b]" "")))))) + +(defun LaTeX-plext-env-array (env) + (let ((dir (read-string "(Optional) Direction (t or y or z): ")) + (width (if (string= env "tabular*") + (read-string "Width: " LaTeX-default-width))) + (pos (and LaTeX-default-position ; LaTeX-default-position can + ; be nil, i.e. do not prompt + (read-string "(Optional) Position: " LaTeX-default-position))) + (fmt (read-string "Format: " LaTeX-default-format))) + (unless (zerop (length dir)) + (setq dir (concat "<" dir ">"))) + (if (string= env "tabular*") + (setq LaTeX-default-width width)) + (setq LaTeX-default-position pos) + (setq LaTeX-default-format fmt) + (LaTeX-insert-environment env + (concat + dir + (if (string= env "tabular*") + (concat TeX-grop width TeX-grcl)) + (unless (zerop (length pos)) + (concat LaTeX-optop pos LaTeX-optcl)) + (concat TeX-grop fmt TeX-grcl))) + (if (string= env "tabular*") + (LaTeX-item-tabular* t) + (LaTeX-item-array t)))) + +;;; plext.el ends here.