branch: externals/sql-indent
commit 3a6275f20a362b9f2d507d50dd37c51d926a942d
Author: Alex Harsanyi <[email protected]>
Commit: Alex Harsanyi <[email protected]>

    Indent nested if statements correctly, fixes #4
    
    `sqlind-begining-of-block` and `sqlind-begining-of-statement` recognize IF
    statements and stop at the right point so that syntactic info is created
    correctly.
---
 sql-indent.el | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/sql-indent.el b/sql-indent.el
index fde9239..99d69c4 100644
--- a/sql-indent.el
+++ b/sql-indent.el
@@ -209,7 +209,7 @@ But don't go before LIMIT."
     (catch 'done
       (while (not (eq (point) (or limit (point-min))))
         (when (re-search-backward
-               ";\\|begin\\b\\|loop\\b\\|then\\b\\|else\\b\\|)"
+               ";\\|\\b\\(begin\\|loop\\|if\\|then\\|else\\|elsif\\)\\b\\|)"
                limit 'noerror)
           (let ((candidate-pos (match-end 0)))
             (cond ((looking-at ")")
@@ -217,12 +217,16 @@ But don't go before LIMIT."
                    ;; of the keywords inside one of them and think this is a
                    ;; statement start.
                    (progn (forward-char 1) (forward-sexp -1)))
-                  ((looking-at "\\bthen\\|else\\b")
+                  ((looking-at "\\b\\(then\\|else\\)\\b")
                    ;; then and else start statements when they are inside
                    ;; blocks, not expressions.
                    (sqlind-backward-syntactic-ws)
                    (when (looking-at ";")
+                     ;; Statement begins after the keyword
                      (throw 'done candidate-pos)))
+                  ((looking-at "\\b\\(if\\|elsif\\)\\b")
+                   ;; statement begins at the start of the keyword
+                   (throw 'done (point)))
                   ((not (sqlind-in-comment-or-string (point)))
                    (throw 'done candidate-pos)))))))))
 
@@ -354,6 +358,23 @@ See also `sqlind-beginning-of-block'"
           (when (null sqlind-end-stmt-stack)
             (throw 'finished (list 'in-block 'exception "")))))))))
 
+(defun sqlind-maybe-if-statement ()
+  "If (point) is on an IF statement, report its syntax."
+  (when (looking-at "if")
+    (save-excursion
+      (sqlind-backward-syntactic-ws)
+      (forward-word -1)
+      (unless (looking-at "end")        ; we don't want to match an "end if" 
here
+        (cond ((null sqlind-end-stmt-stack)
+               (throw 'finished (list 'in-block 'if "")))
+              (t
+               (destructuring-bind (pos kind _label)
+                   (pop sqlind-end-stmt-stack)
+                 (unless (eq kind 'if)
+                   (throw 'finshed
+                     (list 'syntax-error
+                           "bad closing for if block" (point) pos))))))))))
+
 (defun sqlind-maybe-else-statement ()
   "If (point) is on an ELSE statement, report its syntax.
 Only keywords in program code are matched, not the ones inside
@@ -408,7 +429,7 @@ See also `sqlind-beginning-of-block'"
                            (if (looking-at "<<\\([a-z0-9_]+\\)>>\\_>")
                                (sqlind-match-string 1) "")))
             (previous-block (save-excursion
-                              (forward-char -1)
+                              (ignore-errors (forward-char -1))
                               (cons (sqlind-beginning-of-block) (point))))
             (previous-block-kind (nth 0 previous-block)))
 
@@ -552,7 +573,7 @@ See also `sqlind-beginning-of-block'"
 
 (defconst sqlind-start-block-regexp
   (concat "\\(\\b"
-         (regexp-opt '("then" "else" "elsif" "loop"
+         (regexp-opt '("if" "then" "else" "elsif" "loop"
                        "begin" "declare" "create"
                        "procedure" "function" "end") t)
          "\\b\\)\\|)")
@@ -567,6 +588,7 @@ See also `sqlind-beginning-of-block'"
        (or (sqlind-in-comment-or-string (point))
            (when (looking-at ")") (forward-char 1) (forward-sexp -1) t)
            (sqlind-maybe-end-statement)
+            (sqlind-maybe-if-statement)
            (sqlind-maybe-then-statement)
            (sqlind-maybe-else-statement)
            (sqlind-maybe-loop-statement)

Reply via email to