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 ()