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

    Add a handful if indentation helpers
    
    They are not used directly, but they can be used to construct custom
    indentation tables.
---
 customize-indentation.md |  37 ++++++++++++++++-
 sql-indent.el            | 101 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 137 insertions(+), 1 deletion(-)

diff --git a/customize-indentation.md b/customize-indentation.md
index 188b39d..be986b8 100644
--- a/customize-indentation.md
+++ b/customize-indentation.md
@@ -27,7 +27,7 @@ them up in your init.el file before loading the package.  For 
example:
         (update-clause 0)
         ,@sqlind-default-indentation-offsets-alist))
         
-    (add-hoook 'sql-mode-hook 
+    (add-hook 'sql-mode-hook 
         (lambda () 
            (setq sqlind-indentation-offsets-alist
                my-sql-indentation-offsets-alist)))
@@ -100,6 +100,39 @@ The following functions are available as part of the 
package:
 
 * `sqlind-use-previous-line-indentation` -- discards the current offset and
   returns the indentation column of the previous line
+  
+* `sqlind-lineup-to-anchor` -- discards the current offset and returns the
+  column of the anchor point, which may be different than the indentation
+  column
+  
+* `sqlind-lineup-open-paren-to-anchor` -- if the line starts with an open
+  paren, discard the current offset and return the column of the anchor point.
+  
+* `sqlind-lineup-close-paren-to-open` -- if the line starts with a close
+  paren, discard the current offset and return the column of the corresponding
+  open paren.
+  
+* `sqlind-adjust-comma` -- if the line starts with a comma, adjust the current
+  offset so that the line is indented to the first word character.  For
+  example, if added to a 'select-column' syntax indentation rule, it will
+  indent as follows:
+  
+```sql
+select col1
+   ,   col2 -- align "col2" to "col1"
+from my_table;
+```
+
+* `sqlind-lineup-into-nested-statement` -- discard the current offset and
+  return the column of the first word inside a nested statement.  This rule
+  makes sense only for 'nested-statement-continuation' syntax indentation
+  rule, it will indent as follows:
+  
+```sql
+(    a,
+     b  -- b is aligned with a
+)
+```
 
 * `sqlind-indent-comment-start`, `sqlind-indent-comment-continuation` -- used
   to indent comments
@@ -115,6 +148,8 @@ statements.  Have a look at their doc strings for what they 
do:
 
 * `sqlind-right-justify-clause`
 
+* `sqlind-lineup-joins-to-anchor`
+
 ## Syntactic symbols
 
 The the SQL parsing code returns a syntax definition (either a symbol or a
diff --git a/sql-indent.el b/sql-indent.el
index e0a9edf..e0ef9d3 100644
--- a/sql-indent.el
+++ b/sql-indent.el
@@ -1207,6 +1207,8 @@ Indentation is usually done in multiples of this amount, 
but
 special indentation functions can do other types of indentation
 such as aligning.  See also `sqlind-indentation-offsets-alist'.")
 
+(make-variable-buffer-local 'sqlind-basic-offset)
+
 (defvar sqlind-indentation-syntax-symbols '()
   "This variable exists just for its documentation.
 
@@ -1500,6 +1502,21 @@ returned."
          (setq indent-info (cdr indent-info)))
        new-indentation)))
 
+(defun sqlind-find-syntax (syntax-symbol syntax)
+  "Find the SYNTAX-SYMBOL in the SYNTAX chain.
+SYNTAX chain is a list of (SYNTAX-SYMBOL . ANCHOR), as returned
+by `sqlind-syntax-of-line'.  The function finds the fist element
+which matches the specified syntax symbol.
+
+See `sqlind-indentation-syntax-symbols' for the possible syntax
+symbols and their meaning."
+  (if (null syntax)
+      nil
+    (let ((stx (car (car syntax))))
+      (if (if (atom stx) (eq stx syntax-symbol) (eq (car stx) syntax-symbol))
+          (car syntax)
+        (sqlind-find-syntax syntax-symbol (cdr syntax))))))
+
 (defun sqlind-report-sytax-error (syntax _base-indentation)
   (destructuring-bind (_sym msg start end) (caar syntax)
     (message "%s (%d %d)" msg start end))
@@ -1519,6 +1536,15 @@ indentation of the anchor as the base indentation."
       (goto-char anchor)
       (current-indentation))))
 
+(defun sqlind-lineup-to-anchor (syntax _base-indentation)
+  "Return the column of the anchor point of SYNTAX.
+This need not be the indentation of the actual line that contains
+anchor."
+  (let ((anchor (cdar syntax)))
+    (save-excursion
+      (goto-char anchor)
+      (current-column))))
+
 (defun sqlind-use-previous-line-indentation (syntax _base-indentation)
   "Return the indentation of the previous line.
 If the start of the previous line is before the ANCHOR, use the
@@ -1674,6 +1700,81 @@ syntaxes"
          (+ base-indentation offset)
          base-indentation))))
 
+(defun sqlind-lineup-joins-to-anchor (syntax base-indentation)
+  "Align JOIN keywords with the anchor point of SYNTAX.
+If the line starts with an INNER,OUTER or CROSS JOIN keyword,
+return the column of the anchor point, otherwise return
+BASE-INDENTATION.
+
+If this rule is added to `select-table-continuation' indentation,
+it will indent lines starting with JOIN keywords to line up with
+the FROM keyword."
+  (if (looking-at "\\b\\(\\(inner\\|outer\\|cross\\)\\s-+\\)?join\\b")
+      (sqlind-lineup-to-anchor syntax base-indentation)
+    base-indentation))
+
+(defun sqlind-lineup-open-paren-to-anchor (syntax base-indentation)
+  "Align an open paranthesis with the anchor point of SYNTAX.
+If the line starts with an open paren '(', return the column of
+the anchor point.  If line does not start with an open paren, the
+function returns BASE-INDENTATION, acting as a no-op."
+  (save-excursion
+    (back-to-indentation)
+    (if (looking-at "(")
+        (sqlind-lineup-to-anchor syntax base-indentation)
+      base-indentation)))
+
+(defun sqlind-lineup-close-paren-to-open (syntax base-indentation)
+  "Align a closing paren with the corresponding open paren.
+If line starts with a closing paren ')', the corresponding
+'nested-statement-continuation syntax is found in SYNTAX and the
+column of the anchor point is returned. BASE-INDENTATION is
+ignored in that case.
+
+If line does not start with a closing paren, the function return
+BASE-INDENTATION, acting as a no-op."
+  (save-excursion
+    (back-to-indentation)
+    (if (looking-at ")")
+        (let ((stx (sqlind-find-syntax 'nested-statement-continuation syntax)))
+          (if stx
+              (let ((anchor (cdr stx)))
+                (goto-char anchor)
+                (current-column))
+            base-indentation))
+      base-indentation)))
+
+(defun sqlind-adjust-comma (_syntax base-indentation)
+  "Lineup lines starting with a comma ',' to the word start.
+Adjust BASE-INDENTATION so that the actual word is lined up. For
+example:
+
+  SELECT col1
+     ,   col2 -- ignore the comma and align the actual word.
+"
+  (save-excursion
+    (back-to-indentation)
+    (let ((ofs (if (looking-at ",\\s-*") (length (match-string 0)) 0)))
+      (max 0 (- base-indentation ofs)))))
+
+(defun sqlind-lineup-into-nested-statement (syntax _base-indentation)
+  "Align the line to the first word inside a nested statement.
+Return the column of the first non-witespace char in a nested
+statement.  For example:
+
+  (    a,
+       b, -- b is always aligned with 'a'
+  )
+
+This function only makes sense in a
+'nested-statement-continuation sytnax indentation rule.
+"
+  (save-excursion
+    (let ((anchor (cdr (car syntax))))
+      (goto-char anchor)
+      (forward-char 1)
+      (sqlind-forward-syntactic-ws)
+      (current-column))))
 
 
 (defun sqlind-indent-line ()

Reply via email to