用Emacs編寫mybatis
1 效果圖
2 配置
如今web開發,最流行的orm框架非mybatis莫屬了,它功能強大,編寫簡單靈活,能夠直接編寫SQL,也能夠添加條件控制。可是,正是由於mybatis採用xml做爲結構語言,因此,不免會有大量的xml和sql混雜在一塊兒的代碼,對這些代碼對語法高亮以及自動縮減就是一個問題。
在Emacs中對xml有web-mode對其提供了很是好的支持,不管是縮進、跳轉、剪切、拷貝、摺疊等等操做都很是簡單高效,遠超各類IDE。對SQL也有很好的支持。可是對於mybatis卻沒有任何支持,用web-mode則sql沒法高亮和縮進,用sql則基礎xml結構縮減有問題。網上關於Emacs中編寫mybatis的也甚少有涉及的,說明用Emacs來進行java開發的仍是不多的。因而,只能本人本身思考解決方案了。
我記得以前Purcell大神寫了一個mmm-mode,說是能夠把多個mode放到一塊兒,不知是做何用,說不定可讓web-mode支持sql語句。因而就在package管理中安裝了mmm-mode。而後,配置了web-mode中對sql-mode的支持:
css
(mmm-add-classes '((web-sql-select :submode sql-mode :front "<select[^>]*>[ \t]*\n" :back "[ \t]*</select>") (web-sql-insert :submode sql-mode :front "<insert[^>]*>[ \t]*\n" :back "[ \t]*</insert>") (web-sql-update :submode sql-mode :front "<update[^>]*>[ \t]*\n" :back "[ \t]*</update>") (web-sql-delete :submode sql-mode :front "<delete[^>]*>[ \t]*\n" :back "[ \t]*</delete>") )) (mmm-add-mode-ext-class 'web-mode nil 'web-sql-select) (mmm-add-mode-ext-class 'web-mode nil 'web-sql-insert) (mmm-add-mode-ext-class 'web-mode nil 'web-sql-update) (mmm-add-mode-ext-class 'web-mode nil 'web-sql-delete)
其實就是根據正則表達式來肯定哪些代碼是屬於指定的submode的,對於mybatis中的sql語句而言,很簡單就能夠找出哪些是sql語句了。
html
而後,比較難的是對齊,由於兩種語言混雜在一塊兒,用其中任一一種都有問題。通過仔細的思考和試驗以後,發現一種配置是相對合理,且實現簡單的:
java
(defun mmm-indent-line-web-sql-submode () (web-mode-propertize) (let (cur-type prev-type) (save-excursion (back-to-indentation) (setq cur-type (get-text-property (point) 'tag-type))) (save-excursion (previous-line) (back-to-indentation) (setq prev-type (get-text-property (point) 'tag-type))) (if (or (not (or prev-type cur-type)) ; both lines sql (and (not prev-type) (eq cur-type 'start)) ; sql -> xml ) (sql-indent-line) (web-mode-indent-line)))) (defun mmm-indent-line-web-sql () (interactive) (funcall (save-excursion (back-to-indentation) (mmm-update-submode-region) (if (and mmm-current-overlay (> (overlay-end mmm-current-overlay) (point))) 'mmm-indent-line-web-sql-submode 'web-mode-indent-line)))) (setq mmm-indent-line-function 'mmm-indent-line-web-sql)
如此,只使用mmm-mode用來支持mybatis的話,再加上一些其餘的小配置,好比更新以後自動刷新語法高亮等,就很簡單了:
git
(setq mmm-parse-when-idle t) (setq mmm-global-classes nil) (setq mmm-classes-alist nil) (setq mmm-mode-ext-classes-alist nil)
總的配置,能夠去個人github上查看,也能夠直接拷貝下面的代碼:
github
;;; init-mmm.el --- Summary ;;; Commentary: ;; comments ;;; Code: (use-package mmm-mode ;; :hook ((web-mode . mmm-mode)) :commands mmm-mode :config (defun mmm-indent-line-web-sql-submode () (web-mode-propertize) (let (cur-type prev-type) (save-excursion (back-to-indentation) (setq cur-type (get-text-property (point) 'tag-type))) (save-excursion (previous-line) (back-to-indentation) (setq prev-type (get-text-property (point) 'tag-type))) (if (or (not (or prev-type cur-type)) ; both lines sql (and (not prev-type) (eq cur-type 'start)) ; sql -> xml ) (sql-indent-line) (web-mode-indent-line)))) (defun mmm-indent-line-web-sql () (interactive) (funcall (save-excursion (back-to-indentation) (mmm-update-submode-region) (if (and mmm-current-overlay (> (overlay-end mmm-current-overlay) (point))) 'mmm-indent-line-web-sql-submode 'web-mode-indent-line)))) (setq mmm-parse-when-idle t) (setq mmm-global-classes nil) (setq mmm-classes-alist nil) (setq mmm-mode-ext-classes-alist nil) (setq mmm-indent-line-function 'mmm-indent-line-web-sql) (mmm-add-classes '((web-sql-select :submode sql-mode :front "<select[^>]*>[ \t]*\n" :back "[ \t]*</select>") (web-sql-insert :submode sql-mode :front "<insert[^>]*>[ \t]*\n" :back "[ \t]*</insert>") (web-sql-update :submode sql-mode :front "<update[^>]*>[ \t]*\n" :back "[ \t]*</update>") (web-sql-delete :submode sql-mode :front "<delete[^>]*>[ \t]*\n" :back "[ \t]*</delete>") )) (mmm-add-mode-ext-class 'web-mode nil 'web-sql-select) (mmm-add-mode-ext-class 'web-mode nil 'web-sql-insert) (mmm-add-mode-ext-class 'web-mode nil 'web-sql-update) (mmm-add-mode-ext-class 'web-mode nil 'web-sql-delete) ) (provide 'init-mmm) ;;; init-mmm.el ends here