【问题标题】:Indenting SQL in another major mode in EmacsEmacs 中另一种主要模式下的 SQL 缩进
【发布时间】:2013-11-03 00:02:14
【问题描述】:

我经常在不同的主要模式下编写一些脚本来做一些事情,通常涉及 SQL。也许它看起来像这样:

sql = """
SELECT * FROM table WHERE row_awesomeness > 1000
"""

我希望能够正确缩进 SQL,所以它看起来像:

sql = """
SELECT *
  FROM table
 WHERE row_awesomeness > 1000
"""

我对所使用的 SQL 缩进算法并不挑剔,但我什么也做不了。我不是sql-indent.el 的忠实粉丝,但我什至无法在新缓冲区中使用它(函数sql-indent-buffer 并没有改变我的第一个描述,我绝对想要@ 987654326@、FROMWHERE 子句放在单独的行上,我认为这是非常标准的)。

理想情况下,我会突出显示包含 SQL 的区域并执行类似 Mx sql-indent-region RET 之类的操作 - 不需要在换行符上缩进。

【问题讨论】:

  • 您应该检查启用多个主要模式的 mumamo。由于我不使用,我不能给你更多的指导

标签: sql emacs elisp indentation


【解决方案1】:

这是一种方法(轻微测试,使用你提到的缩进函数——我不使用 SQL,但你应该能够插入任何函数作为只要它在整个缓冲区上运行):

(defun my-sql-indent-region (beg end)
  "Indent the SQL statement in the region."
  (interactive "*r")
  (save-excursion
    (save-restriction
      (narrow-to-region beg end)
      ;; http://www.emacswiki.org/emacs/download/sql-indent.el
      (sql-indent-buffer))))

如果我标记以下 sql 查询(从“SELECT”到“f2.PLAYERID”),嵌入到 elisp 字符串,然后执行 M-x my-sql-indent-region RET:

(defvar my-sql-query "
SELECT p1.PLAYERID, 
f1.PLAYERNAME, 
  p2.PLAYERID, 
f2.PLAYERNAME 
FROM PLAYER f1, 
                   PLAYER f2, 
    PLAYS p1 
    FULL OUTER JOIN PLAYS p2 
        ON p1.PLAYERID < p2.PLAYERID 
    AND p1.TEAMID = p2.TEAMID 
GROUP BY p1.PLAYERID, 
    f1.PLAYERID, 
   p2.PLAYERID, 
    f2.PLAYERID 
HAVING Count(p1.PLAYERID) = Count(*) 
  AND Count(p2.PLAYERID) = Count(*) 
    AND p1.PLAYERID = f1.PLAYERID 
AND p2.PLAYERID = f2.PLAYERID;
")

我最终得到:

(defvar my-sql-query "
SELECT p1.PLAYERID, 
    f1.PLAYERNAME, 
    p2.PLAYERID, 
    f2.PLAYERNAME 
FROM PLAYER f1, 
    PLAYER f2, 
    PLAYS p1 
    FULL OUTER JOIN PLAYS p2 
    ON p1.PLAYERID < p2.PLAYERID 
    AND p1.TEAMID = p2.TEAMID 
GROUP BY p1.PLAYERID, 
    f1.PLAYERID, 
    p2.PLAYERID, 
    f2.PLAYERID 
HAVING Count(p1.PLAYERID) = Count(*) 
    AND Count(p2.PLAYERID) = Count(*) 
    AND p1.PLAYERID = f1.PLAYERID 
    AND p2.PLAYERID = f2.PLAYERID;
")

【讨论】:

    【解决方案2】:

    我使用多模。

    (defun python/init-polymode ()
      (use-package polymode
        :ensure t
        :mode ("\.py$" . poly-python-sql-mode)
        :config
        (setq polymode-prefix-key (kbd "C-c n"))
        (define-hostmode poly-python-hostmode :mode 'python-mode)
        (add-hook 'python-mode-hook 'poly-python-sql-mode)
        (add-hook 'python-mode-hook 'define-python-keybindings))
    
      (define-innermode poly-sql-expr-python-innermode
        :mode 'sql-mode
        :head-matcher (rx "r" (= 3 (char "\"'")) (* (any space)))
        :tail-matcher (rx (= 3 (char "\"'")))
        :head-mode 'host
        :tail-mode 'host
        )
    

    然后我定义了几个可以应用于当前块的函数。

    (defun python-indent-sql-chunk ()
      (interactive)
      (let* ((chunk (pm-chunk-range))
             (beg (car chunk))
             (end (cdr chunk)))
        (sqlformat-region beg end)
        (indent-region-line-by-line beg end)
        (delete-trailing-whitespace beg end)
        (sqlup-capitalize-keywords-in-region beg end)))
    
    

    为了让我每次按回车时都会发生这种情况:

    defun sql-format-chunk ()
      (interactive)
      (newline-and-indent)
      (python-indent-sql-chunk)
    
    (define-key sql-mode-map (kbd "RET") 'sql-format-chunk)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-05
      • 1970-01-01
      相关资源
      最近更新 更多