用Emacs编写mybatis
Table of Contents
- 1. 效果图
- 2. 配置
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的支持:
(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语句了。
然后,比较难的是对齐,因为两种语言混杂在一起,用其中任一一种都有问题。经过仔细的思考和试验之后,发现一种配置是相对合理,且实现简单的:
(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的话,再加上一些其他的小配置,比如更新之后自动刷新语法高亮等,就很简单了:
(setq mmm-parse-when-idle t) (setq mmm-global-classes nil) (setq mmm-classes-alist nil) (setq mmm-mode-ext-classes-alist nil)
总的配置,可以去我的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
Date: 2017-12-16 21:17
Created: 2017-12-16 Sat 22:02
Emacs 25.3.1 (Org mode 8.2.10)
Validate