]> git.bundesbrandschatzamt.de Git - emacsconfig.git/commitdiff
added sqlformat
authorAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Fri, 19 Aug 2016 14:32:08 +0000 (16:32 +0200)
committerAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Fri, 19 Aug 2016 14:32:08 +0000 (16:32 +0200)
- to make SQL more readable.

bba.org
lisp/sqlformat.el [new file with mode: 0644]

diff --git a/bba.org b/bba.org
index ab0d5693932797db503e64423e0f7079a9b0ffc7..8348ec8bae069b4ca53e0f1850975ad6a3075133 100644 (file)
--- a/bba.org
+++ b/bba.org
@@ -1702,6 +1702,24 @@ Combine abbrev with Ispell:
 
 #+END_SRC
 
+* [[https://github.com/steckerhalter/sqlformat.el][sqlformat]]
+[2016-08-19 Fri 16:20]
+
+Provides the sqlformat command, which uses the external Python tool
+sqlformat to format SQL in the current buffer.
+
+Be aware that if the buffer is mixed code/SQL then you need to select
+the SQL so that sqlformat only operates on the region, otherwise it
+acts on the whole buffer.
+
+On OS X you might want to run =sudo port install sqlparse= to have
+=sqlformat= available.
+
+#+BEGIN_SRC emacs-lisp
+  (load-file (expand-file-name "~/.emacs.d/lisp/sqlformat.el"))
+
+#+END_SRC
+
 * remove trailing whitespace
     [2014-09-24 Wed 16:56]
 
diff --git a/lisp/sqlformat.el b/lisp/sqlformat.el
new file mode 100644 (file)
index 0000000..bd058e3
--- /dev/null
@@ -0,0 +1,126 @@
+;;; sqlformat.el --- Use sqlformat to make SQL readable in Emacs
+
+;; Copyright 2015, steckerhalter
+;; Copyright 2015, Friedrich Paetzke <paetzkeNOSPAMfastmail.fm>
+
+;; Author: steckerhalter
+;; URL: https://github.com/steckerhalter/sqlformat.el
+;; Keywords: sql format region buffer
+
+;; This file is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;; <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides the `sqlformat' commmand, which use the external
+;; "sqlformat" tool to format SQL in the current region or buffer.
+
+;; it is based on `format-sql.el' by Friedrich Paetzke, see:
+;; https://github.com/paetzke/format-sql.el
+;; but uses the sqlformat command instead of format-sql
+
+;;; Code:
+
+(defgroup sqlformat nil
+  "Use sqlformat to sort the imports in a Python buffer."
+  :group 'convenience
+  :prefix "sqlformat-")
+
+(defcustom sqlformat-options '("--reindent"
+                               "--keywords" "upper"
+                               "--identifiers" "lower")
+  "Options used for sqlformat."
+  :group 'sqlformat
+  :type '(repeat (string :tag "option")))
+
+(defun sqlformat-apply-rcs-patch (patch-buffer)
+  "Apply an RCS-formatted diff from PATCH-BUFFER to the current buffer."
+  (let ((target-buffer (current-buffer))
+        (line-offset 0))
+    (save-excursion
+      (with-current-buffer patch-buffer
+        (goto-char (point-min))
+        (while (not (eobp))
+          (unless (looking-at "^\\([ad]\\)\\([0-9]+\\) \\([0-9]+\\)")
+            (error "invalid rcs patch or internal error in sqlformat-apply-rcs-patch"))
+          (forward-line)
+          (let ((action (match-string 1))
+                (from (string-to-number (match-string 2)))
+                (len  (string-to-number (match-string 3))))
+            (cond
+             ((equal action "a")
+              (let ((start (point)))
+                (forward-line len)
+                (let ((text (buffer-substring start (point))))
+                  (with-current-buffer target-buffer
+                    (setq line-offset (- line-offset len))
+                    (goto-char (point-min))
+                    (forward-line (- from len line-offset))
+                    (insert text)))))
+             ((equal action "d")
+              (with-current-buffer target-buffer
+                (goto-char (point-min))
+                (forward-line (- from line-offset 1))
+                (setq line-offset (+ line-offset len))
+                (kill-whole-line len)))
+             (t
+              (error "invalid rcs patch or internal error in sqlformat-apply-rcs-patch")))))))))
+
+(defun sqlformat-replace-region (filename)
+  (delete-region (region-beginning) (region-end))
+  (insert-file-contents filename))
+
+;;;###autoload
+(defun sqlformat (&optional start end)
+  "Uses the `sqlformat' tool to reformat the current buffer or region.
+If a region is active it operates on that, otherwise on the buffer."
+  (interactive "r")
+  (when (not (executable-find "sqlformat"))
+    (error "\"sqlformat\" command not found. Install sqlformat with \"pip install sqlparse\""))
+
+  (let* ((tmpfile (make-temp-file "sqlformat" nil ".sql"))
+         (patchbuf (get-buffer-create "*sqlformat patch*"))
+         (resultbuf (get-buffer-create "*sqlformat result*"))
+         (coding-system-for-read 'utf-8)
+         (coding-system-for-write 'utf-8))
+
+    (with-current-buffer resultbuf
+      (setq buffer-read-only nil)
+      (erase-buffer))
+    (with-current-buffer patchbuf
+      (erase-buffer))
+
+    (if (use-region-p)
+        (write-region start end tmpfile)
+      (write-region nil nil tmpfile))
+
+    (if (zerop (eval `(call-process "sqlformat" nil resultbuf nil ,@sqlformat-options tmpfile)))
+        (progn
+          (with-current-buffer resultbuf
+            (write-region nil nil tmpfile))
+          (if (zerop (call-process-region (point-min) (point-max) "diff" nil patchbuf nil "-n" "-" tmpfile))
+              (progn
+                (kill-buffer resultbuf)
+                (message "Buffer is already sqlformated"))
+            (if (use-region-p)
+                (progn
+                  (delete-region start end)
+                  (insert-file-contents tmpfile))
+              (sqlformat-apply-rcs-patch patchbuf))
+            (kill-buffer resultbuf)
+            (message "Applied sqlformat.")))
+      (error "Could not apply sqlformat. Check *sqlformat result* for details"))
+    (kill-buffer patchbuf)
+    (delete-file tmpfile)))
+
+(provide 'sqlformat)
+
+;;; sqlformat.el ends here