From e91fd73dcb5e8fa57227160a27dbbd8faf6a52f3 Mon Sep 17 00:00:00 2001
From: Oleh Krehel <ohwoeowho@gmail.com>
Date: Fri, 11 Oct 2013 14:43:37 +0200
Subject: [PATCH] Add indentation for tabular environment.

* latex.el: add `LaTeX-indent-tabular' to `LaTeX-indent-environment-list'
* added `LaTeX-indent-environment-list--set' as a setter for
  `LaTeX-indent-environment-list'. It auto-sets `LaTeX-tabularlike--end',
  which should not be touched.
* tests/latex/latex-test.el: added an ERT test for `LaTeX-indent-tabular'
* tests/latex/tabular-in.tex: input to latex-test.el
* tests/latex/tabular-out.tex: input to latex-test.el
---
 latex.el                    | 66 ++++++++++++++++++++++++++++++++++++++++++---
 tests/latex/latex-test.el   | 15 +++++++++++
 tests/latex/tabular-in.tex  | 41 ++++++++++++++++++++++++++++
 tests/latex/tabular-out.tex | 41 ++++++++++++++++++++++++++++
 4 files changed, 160 insertions(+), 3 deletions(-)
 create mode 100644 tests/latex/latex-test.el
 create mode 100644 tests/latex/tabular-in.tex
 create mode 100644 tests/latex/tabular-out.tex

diff --git a/latex.el b/latex.el
index f59168f..2f264f5 100644
--- a/latex.el
+++ b/latex.el
@@ -2633,14 +2633,32 @@ consideration just as is in the non-commented source code."
     ("tabbing")
     ("table")
     ("table*")
-    ("tabular")
-    ("tabular*"))
+    ("tabular" LaTeX-indent-tabular)
+    ("tabular*" LaTeX-indent-tabular)
+    ("align" LaTeX-indent-tabular)
+    ("align*" LaTeX-indent-tabular))
     "Alist of environments with special indentation.
 The second element in each entry is the function to calculate the
 indentation level in columns."
     :group 'LaTeX-indentation
     :type '(repeat (list (string :tag "Environment")
-			 (option function))))
+			 (option function)))
+    :set (lambda (symbol value)
+           (setq LaTeX-tabularlike--end
+                 (format "\\\\end{%s}"
+                         (regexp-opt
+                          (cl-reduce (lambda (a b)
+                                       (when (eq (cadr b) 'LaTeX-indent-tabular)
+                                         (push (car b) a)))
+                                     value))))
+           (set-default symbol value)))
+
+(defvar LaTeX-tabularlike--end nil
+  "A regular expression that matches the ending of environments
+that will be aligned with `LaTeX-indent-tabular'.
+
+Do not set this variable. This variable is auto-set
+by customizing `LaTeX-indent-environment-list'.")
 
 (defcustom LaTeX-indent-environment-check t
   "*If non-nil, check for any special environments."
@@ -5996,6 +6014,48 @@ i.e. you do _not_ have to cater for this yourself by adding \\\\' or $."
       (replace-match "\\\\input{" nil nil)))))
   (TeX-normal-mode nil))
 
+(defun LaTeX-env-beginning-pos-col ()
+  (save-excursion
+    (LaTeX-find-matching-begin)
+    (cons (point) (current-column))))
+
+(defun LaTeX-hanging-ampersand-position ()
+  "Return indent position for a hanging (i.e. ^\\s-*&) ampersand
+in a tabular-like environment."
+  (destructuring-bind (beg-pos . beg-col)
+      (LaTeX-env-beginning-pos-col)
+    (let* ((cur-pos (point)))
+      (save-excursion
+        (if (re-search-backward "\\\\\\\\" beg-pos t)
+            (let ((cur-idx (how-many "&" (point) cur-pos)))
+              (goto-char beg-pos)
+              (re-search-forward "&" cur-pos t (+ 1 cur-idx))
+              (- (current-column) 1))
+          (+ 2 beg-col))))))
+
+(defun LaTeX-indent-tabular ()
+  "Return indent position for the current line
+in a tabular-like environment"
+  (destructuring-bind (beg-pos . beg-col)
+      (LaTeX-env-beginning-pos-col)
+    (cond ((looking-at LaTeX-tabularlike--end)
+           beg-col)
+
+          ((looking-at "\\\\\\\\")
+           (+ 2 beg-col))
+
+          ((looking-at "&")
+           (LaTeX-hanging-ampersand-position))
+
+          (t
+           (+ 2
+              (let ((any-col (save-excursion
+                               (when (re-search-backward "\\\\\\\\\\|&" beg-pos t)
+                                 (current-column)))))
+                (if (and any-col (string= "&" (match-string 0)))
+                    any-col
+                  beg-col)))))))
+
 (provide 'latex)
 
 ;;; latex.el ends here
diff --git a/tests/latex/latex-test.el b/tests/latex/latex-test.el
new file mode 100644
index 0000000..71a6450
--- /dev/null
+++ b/tests/latex/latex-test.el
@@ -0,0 +1,15 @@
+(defvar LaTeX-indent-tabular-test/in  (expand-file-name "tabular-in.tex"))
+(defvar LaTeX-indent-tabular-test/out (expand-file-name "tabular-out.tex"))
+
+(ert-deftest LaTeX-indent-tabular ()
+  (should (string=
+           (with-temp-buffer
+             (insert-file-contents LaTeX-indent-tabular-test/in)
+             (LaTeX-mode)
+             (indent-region (point-min) (point-max))
+             (buffer-string))
+           (with-temp-buffer
+             (insert-file-contents LaTeX-indent-tabular-test/out)
+             (buffer-string)))))
+
+
diff --git a/tests/latex/tabular-in.tex b/tests/latex/tabular-in.tex
new file mode 100644
index 0000000..a8be333
--- /dev/null
+++ b/tests/latex/tabular-in.tex
@@ -0,0 +1,41 @@
+\documentclass{article}
+\begin{document}
+\begin{tabular}{llll}
+Lorem ipsum dolor & sit amet, ei mei
+paulo tation honestatis,
+intellegam & accommodare ne vim, ut
+mel solum putant
+atomorum. Posse & dolores has ut,\\
+prompta           & disputando & ne mel, ne
+viderer ceteros
+vel.            & No petentium
+\\
+
+reformidans mel.  & Quo no sale
+natum, cu
+pericula   & deterruisset
+usu. Nec        & bonorum detracto\\
+detraxit          & no.        & Ne sea doming   & deserunt.
+\end{tabular}
+
+\begin{tabular}{ll}
+1 & 2 & 3
+\\
+& 4 & 5
+\\
+6 & 7
+& 8\\
+9 &
+10
+& 11
+\end{tabular}
+\begin{align}
+1 & 2
+3 & 4
+5\\
+6 &
+7
+8 &
+9
+\end{align}
+\end{document}
diff --git a/tests/latex/tabular-out.tex b/tests/latex/tabular-out.tex
new file mode 100644
index 0000000..cd5b708
--- /dev/null
+++ b/tests/latex/tabular-out.tex
@@ -0,0 +1,41 @@
+\documentclass{article}
+\begin{document}
+\begin{tabular}{llll}
+  Lorem ipsum dolor & sit amet, ei mei
+                      paulo tation honestatis,
+                      intellegam & accommodare ne vim, ut
+                                   mel solum putant
+                                   atomorum. Posse & dolores has ut,\\
+  prompta           & disputando & ne mel, ne
+                                   viderer ceteros
+                                   vel.            & No petentium
+  \\
+
+  reformidans mel.  & Quo no sale
+                      natum, cu
+                      pericula   & deterruisset
+                                   usu. Nec        & bonorum detracto\\
+  detraxit          & no.        & Ne sea doming   & deserunt.
+\end{tabular}
+
+\begin{tabular}{ll}
+  1 & 2 & 3
+  \\
+    & 4 & 5
+  \\
+  6 & 7
+        & 8\\
+  9 &
+      10
+        & 11
+\end{tabular}
+\begin{align}
+  1 & 2
+      3 & 4
+          5\\
+  6 &
+      7
+      8 &
+          9
+\end{align}
+\end{document}
-- 
1.8.4

