Hi, AUCTeX developpers,

The attatched patch enhances the support for array and tabular(*)
environments in LaTeX mode of AUCTeX.  With this change, the right
number of ampersands are inserted automatically in the buffer at the
following situations:
(1) After inserting a new environment with C-c C-e.
(2) After terminating a row with C-c C-j (or M-RET).

For example, C-c C-e tabular RET t RET |l|c|r RET yields
\begin{tabular}[t]{|l|c|r}
  &&
\end{tabular}
.  Note that two &'s are inserted according to the column specification
"|l|c|r".  The number of &'s is determined from the column specification
on the fly.  It is robust enough not to be confused with the presence
of bars("|") and construcs such as "@{,}" and "p{30pt}".
In addition, C-c C-j (or M-RET) at the end of line of the &'s asks for
optional argument for the line breaking macro "\\" and supplies two &'s
in the next line.
You will get similar experience with array and tabular* environments,
too.

The patch includes:
1. support for alignat environment and its friends in amsmath.el
2. support for enhancement of array.sty in array.el
3. support for enhancement of plext.sty (pLaTeX only) in plext.el, a
   newly created file

This feature is inspired from YaTeX(http://www.yatex.org/).  If you like
this change, please include it into AUCTeX.

I confirmed the change works with emacs 24.3 and 22.3.  I believe it
also works with emacs 23.  Confirmations with emacs 21 and xemacs are
omitted, because AUCTeX in the current git repository does not seem to
be compatible with them.  (Errors occur during byte compilation.)

Regards,
Ikumi Keita

P.S. I'm not on the list [email protected], so please include me on
Cc: when replying.

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
+\\begin{tabular*}{1.0\\linewidth}[b]{c@{,}p{5ex}}
+.  REGEXP must match \"{1.0\\linewidth}[b]\" and FUNC must return 1 from
+the text \"c@{,}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. <t>,
+   ;; 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.
_______________________________________________
auctex-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/auctex-devel

Reply via email to