emacs sql indent heuristic
I was using sql mode recently and was not happy with the indentation. I wanted something similar to python-mode's indentation, wherein the cursor will at most indent to the current scope and then cycle through all of the previous scopes.
I decided that the quickest way to satisfy my requirements for sane indentation was to assign a custom function to emac's indent-line-function function in sql-mode.
Here's a link to the gist
Here's the source:
Here's a link to the gist
Here's the source:
(defun get-previous-indentation () "Get the column of the previous indented line" (interactive) (save-excursion (progn (move-beginning-of-line nil) (skip-chars-backward "\n \t") (back-to-indentation)) (current-column))) (defun get-current-indentation () "Return column at current indentation" (interactive) (save-excursion (progn (back-to-indentation) (current-column)))) (defun point-at-current-indentation () "Return point at current indentation" (interactive) (save-excursion (progn (move-to-column (get-current-indentation)) (point)))) (defun point-at-column-on-line (col) "Returns the point at `col` on the current line" (interactive) (save-excursion (progn (move-to-column col) (point)))) (defun ig-move-line-to-column (col) "Move the line to col; fill with all spaces if moveing forward" (interactive "p") (let ((point-at-cur-indent (point-at-current-indentation)) (col-at-cur-indent (get-current-indentation))) (cond ( (= col 0) ;; delete to beginning of line or do nothing (if (= col-at-cur-indent 0) nil (delete-region point-at-cur-indent (point-at-column-on-line 0)))) ( (< col col-at-cur-indent) ;; delete from our current point BACK to col (delete-region (point-at-column-on-line col) point-at-cur-indent)) ( (> col col-at-cur-indent) ;; delete all text from indent to beginning of line (progn (delete-region point-at-cur-indent (point-at-column-on-line 0)) (move-beginning-of-line nil) ;; add spaces forward (insert-string (make-string col ?\s))))))) (defun ig-indent-sql () "Indent by `tab-width` at most 1 time greater than the previously indented line otherwise go to the beginning of the line indent forward by `tab-width`" (let ((previous (get-previous-indentation)) (current (get-current-indentation))) (cond ( ;; exactly at previous line's indentation (= previous current) (ig-move-line-to-column (+ current tab-width))) ( ;; current is greater than previous (> current previous) ;; exactly at one indentation forward from previous lines indent (if (= tab-width (- current previous)) ;; move line to beginning (ig-move-line-to-column 0) ;; go back to previous indentation level (ig-move-line-to-column previous))) (t (ig-move-line-to-column (+ current tab-width)))))) (add-hook 'sql-mode-hook (function (lambda () (make-local-variable 'indent-line-function) (setq indent-line-function 'ig-indent-sql))))