Emacs及扩展配置
Table of Contents
1 动机之反思
捣鼓了几天,总算把Emacs配置到基本正常使用的程度了。虽然有点迟,但还是尽量将能想起的细节都记录下来吧,否则以后要用到时都忘光了。
为什么会想转到Emacs上呢?多年以前,当我还在读大学时,就玩过Emacs,但是可能是觉得操作不方便,也可能是身边有朋友在用Vim了,捣鼓了一小段时间Emacs后,就转投向学习使用Vim了。 其实Vim作为编辑器而言非常好用,但是作为开发IDE而言,总是感觉欠缺;之前看过别人用Emacs,确实在代码调试上有其优势,可能就是因为这一点,一直耿耿于怀吧。 另外,在很早之前我就觉得在Emacs中显示中文很漂亮,比Vim中显示要漂亮些。恰好这次新买了MBP,换了OSX系统,就想在上面全新配置自己的环境。加上自己有一些任务管理、使用LaTex等的需求, 上网一搜,全都是将在Emacs上怎么实现的,于是就心痒痒想试试了。
本来想完全抛弃原先Vim的使用习惯,重新学习Emacs的各种操作的,但是每次用到Emacs那些复杂而且别扭的快捷键时,总是由心地希望用回Vim。我想,这就是Vim阵营的人鄙视Emacs的一大原因吧。 好在作为独缺好编辑器的操作系统,Emacs开发者已经为我这种两面派提供了终极解决方案:各种模仿Vi操作的扩展。最终,我使用了Evil,将ELPA中所有Evil开头的扩展都装了个遍,并将Emacs设 置为默认进入Evil模式,重启生效,顿时世界一片清静。其实我不太能理解为什么网上会有这么多Vim和Emacs之争,为什么不能站在相互取长补短的角度来使用它们?我觉得,只有真正去用一个工具, 才能真切体会它的好;同样,只有真正了解对手,才能发现自身的不足,也才有动力和方向去进一步完善它。当然,我只是一个纯粹的实用主义者,谁能解决我的问题,予我方便,我就用哪个,如果中 间遇到什么现在还没有的功能,而我有恰好有兴趣和时间去完善,那我才会去完善,回馈相应社区。
我不知道这次用Emacs会坚持多久,或者用了一段时间后发现不习惯了,还是用回Vim了。不过自从用了Evil,我感觉还是挺顺手了,现在环境也配置得七七八八了,应该够我用一阵的了。后续如果再 遇到问题,如果有时间,我想我还是会在Emacs上折腾的。
2 它山之石
刚开始我是从零开始配置Emacs的,所有的配置都写在~/.emacs中,基本也能工作,就是感觉自己要配置的东西太多,太繁琐。google了一番后,找到这篇文章:一年成为Emacs高手(像神一样使用编辑器), 里面的介绍蛮好的,作者力荐学Emacs要从使用研究大牛的配置开始,我刚刚开始学,不知道这样是否是最佳的学习方式,因此持谨慎的保留态度,但不可否认的是,大牛们的配置确实让我们省去了很多繁琐, 并且,给我们的后续配置提供了一个不同于原始Emacs配置方式的扩展框架(缺点是我们必须先搞清楚大牛的框架,否则出现问题时就不知道怎么办了)。老实说,相比Vim大牛们的配置,在网上能找到的 Emacs配置还是有点弱的,很多功能都没有,特别是编程方面的,基本就没有(purcell和prelude配置中对于C系的自动补全和自动缩进等都没有配置)。 从我google的结果来看,比较普遍使用的Emacs配置集基本有几个:purcell、prelude以及emacs-starter-kit。(注意,如果使用这些配置集,就不能添加自己的.emacs文件了,否则会导致这些配置集 失效;这些配置集内部都有机制可以让你定制自己的功能的)
- starter-kit:由于starter-kit的名字表明我太初级了,而我又自命不凡地觉得自己用了那么多年的Vim,不应该属于初级那类,因此我始终没有用starter-kit,也就无从知道它好不好用了。
- purcell:purcell是《一年成为Emacs高手》中推荐的,作者Purcell本身是从事Web开发的,从评论上看更新有点快,所以自己配置的话,可能经常会出现配置冲突。这个配置中有个比较好的功能, 就是可以保存桌面,保存的桌面可以在下一次打开时自动载入。purcell的版本默认装不了el-get,因为跟装在里面的scratch扩展有冲突,我的解决方案是在git clone el-get的过程中在终端通过 sed命令将el-get中冲突的部分替换掉,或者启动Emacs后,先将scratch卸载(在ELPA中卸载),然后执行el-get的下载脚本,安装成功后再重启Emacs;由于启动时purcell配置会自动检测更新配 置环境,因此在启动过程中会检测到scratch被删除,然后重新下载安装scratch。在purcell中,如果要加入自己的定制,则可以通过在Emacs中执行“M-x customize-variable”或者在 ~/.emacs.d/lisp/中增加init-local.el文件,这个文件相当于.emacs文件,只是记得文件最后要有一句:
(provide 'init-local)
- prelude:在网上乱搜的时候无意看到这个的,后来发现其实很多人都有推荐这个,比推荐purcell的多。它设置了一个较好的功能,就是保存“el”文件时自动编译。如果要添加自己的东西,则可以同样 通过“M-x customize-variable”,或者:在~/.emacs.d/personal/中添加后缀为“el”的文件,这样prelude便会自动载入这些配置了,这点感觉比purcell的实现要灵活一些。我大概花了一天左右的 时间在prelude上安装扩展和配置,弄得七七八八,基本能正常写代码了。不过后来头脑一热,又改成使用purcell了。现在回过头来看,purcell和prelude相比,并没有太多的孰优孰劣,要改成自己习 惯的环境也都得折腾一番,所以选择哪个完全是自己喜好了。
3 扩展的管理
目前Emacs主要有两种扩展管理器,一个是ELPA(package.el),另一个是el-get。其中ELPA是从Emacs24版本开始内置到Emacs中的,是官方的扩展管理器,但其仓库中的扩展比较少,需要配置其他仓库; 我加上网上搜到的几个仓库后,还是有些扩展找不到。el-get应该是比较老牌的扩展管理器了,安装(参见安装el-get )不算复杂,但是跟某些配置可能会有冲突(如在purcell的配置中,会跟其中的 scratch扩展有冲突,会提示void-variable el-get-sources);其仓库中的扩展比较完整,而且据称可以使用ELPA的仓库,但我没试过。从个人感觉而言,用el-get还是挺爽的,无奈大牛们的配置都是使用ELPA的,所以现在我也基本都是使用 ELPA了。比较讨厌的是el-get和ELPA相互不知道对方装了哪些东西,可能会造成重复安装;如果想在el-get中安装某个有依赖的包(如auto-complete-clang),则无论ELPA中是否已经安装了依赖,el-get都 会将依赖安装一遍,即浪费了空间,又可能导致不必要的冲突。
ELPA和el-get都有显示所有扩展的命令(pacakge-list-packages和el-get-list-packages),在列表界面中,“i”标记安装光标所在包,“d”表示删除,“U”表示更新,完成所有想要的动作后,输入“x”来 一次执行所有的操作。
如果要给ELPA添加其他仓库,则在配置文件中添加诸如以下语句(可以添加多句来实现添加多个仓库的目的):
(package-initialize)
(add-to-list 'package-archives
'("marmalade" . "http://marmalade-repo.org/packages/") t)
4 我额外安装的通用扩展(在purcell基础上)
- unicad:当打开文件时,自动猜测文件编码,启用后“妈妈再也不用担心我打开文件乱码了^_”。传说Emacs内置也有一个猜测编码的扩展,但我打开GBK编码的文件时始终会乱码,不知道是不是需要配置, 网上没有看到相关介绍。unicad不在ELPA的仓库中,需要通过el-get安装或者从网上搜索手动下载安装。配置相当简单:
;; allow unicad to guess file's encoding when open a file
(require 'unicad) - evil:我将ELPA仓库中所有evil开头的扩展都装了,基本啥都不用配置,用起来跟Vim差不了多少,相当给力!
(require 'evil)
;; enter evil-mode automatically
(evil-mode 1) - yasnippet:据说如果要跟auto-complete共同使用的话,需要在auto-complete前配置:
;; not yasnippet-bundle, and yasnippet is conflict with yasnippet-bundle now
(require 'yasnippet)
(yas-global-mode 1)
(yas-minor-mode-on) - auto-complete:蛮好用的自动补全工具。我的配置如下:
(require 'auto-complete-config)
;; change the path to where your dict fold locates,
;; and note that the trailing '/' must present.
(add-to-list 'ac-dictionary-directories "~/.emacs.d/elpa/auto-complete-20131128.233/dict/")
(ac-config-default) (setq ac-auto-start t)
(setq ac-quick-help-delay 0.5)
(define-key ac-mode-map [(control tab)] 'auto-complete) -
auto-complete-clang-async:使用clang来扫描生成文件的符号信息,以便用于自动补全等,非常爽的功能。修改自auto-complete-clang,不同的是采用了C/S方式,即使用一个二进制程序 clang-complete来进行源码分析,另外使用auto-complete-clang-aysnc.el来做前端,目的是提高自动补全的响应速度,避免卡顿。编译clang-complete时,需要系统安装有llvm(llvm-config) 和clang的头文件,在MacOX中,可以用以下命令安装:
# first install llvm
brew install llvm --with-clang --with-asan以上只是下载并编译了llvm,生成的二进制文件存放在/usr/local/Cellar/llvm/[版本号]中(/usr/local/opt/llvm会链接到/usr/local/Cellar/llvm/中最新版本的llvm)。在OSX中,由于系统自带有llvm,为了避免第三方的llvm替代系统默认的llvm而造成无法预测的问题,一般不建议在系统层面上替换llvm。如果为了省事,也可以强制安装替换:
# to link the binary to /usr/local/bin and /usr/local/lib/
# if we don't link, programs that use llvm's dylib will not run because
# they can't find the libs.
brew link llvm --force # we have to add '--force', or we can't link llvm如果不愿冒险替换,则比较繁琐:
(1) 在编译clang-complete时,不能直接make,而是需要指定llvm-config的位置:
make LLVM_CONFIG=/usr/local/opt/llvm/bin/llvm-config
(2) 编译出来的二进制是无法运行的,会出现如下错误:
$ ./clang-complete
dyld: Library not loaded: @rpath/libLLVM-3.4.dylib
Referenced from: /usr/local/opt/llvm/lib/libclang.dylib
Reason: image not found
Trace/BPT trap: 5(3) 采用如下方法修改:
sudo install_name_tool -add_rpath /usr/local/opt/llvm/lib/ /usr/local/opt/llvm/lib/libclang.dylib
(4) 在每次升级llvm后,clang-complete都会出现(2)的现象而无法运行,都需要使用(3)的方法进行修改。
ELPA中的auto-complete-clang-async.el与github仓库中完全一致,只是从ELPA下载的扩展包中不包含C代码,因此可以直接使用ELPA中的auto-complete-clang-async。 要让clang-complete能正常工作,还需要将编译好的clang-complete拷贝到~/.emacs.d/(或其他自定义的位置)中,并在.emacs或init-local.el(使用purcell的话)中进行以下设置:
(require 'auto-complete-clang-async) (defun ac-cc-mode-setup ()
;; you should change the server program's path here
(setq ac-clang-complete-executable "~/.emacs.d/clang-complete")
(setq ac-sources (append '(ac-source-clang-async) ac-sources))
(ac-clang-launch-completion-process)
) (defun my-ac-config ()
(add-hook 'c-mode-common-hook 'ac-cc-mode-setup)
(global-auto-complete-mode t)) (my-ac-config) - google-c-style:我不喜欢它的两字节缩进,但是既然要用,就习惯它吧,毕竟存在即合理。在其代码中,它将回车绑定为“newline-and-indent”,这样有个缺陷,就是无法实现回车后自动更正缩进 (比如回车后的大括号的位置),我修改它扩展中的源码,将其改为绑定到“reindent-then-newline-and-indent”,便能满足我的需求了。
- auto-indent-mode:在输入时实现自动缩进,有时很爽,有时很烦人,个人觉得有比没有好。有了这个,google-c-style中的修改应该可以不做了(但我没实测过)。配置如下:
;; note that auto-indent-mode might be conflict with yasnippet and autopair,
;; so we must load it first.
;; don't enable auto-indent-on-visit-file, or there will be error(conflict with yasnippet, maybe).
;(setq auto-indent-on-visit-file t) ;; If you want auto-indent on for files
(require 'auto-indent-mode)
;; make auto-indent work globally
(auto-indent-global-mode) - slime:运行lisp用的,我在系统中装的是clisp,默认它无法识别这个,因此需要在配置文件中指定:
(setq inferior-lisp-program "/usr/local/bin/clisp")
其他就没有什么需要配置的了。注意使用的lisp解析器是可以换其他的,之前我还试过另一个lisp解析器,忘了叫啥了,发现在使用slime时会无法使用方向键来调整输入,所以就换成clisp了。
- ecb:直接通过ELPA安装即可。我安装并启用了,但还没仔细用。
- cal-china-x:在calendar中显示农历的扩展。ELPA和el-get中的版本都是0.6的,在我的Emacs24中都是无法执行的,会有错误。从网上找到了2.1版本cal-china-xv2.1 。我先通过ELPA安装0.6版本, 然后将网上下载的新版本直接替换~/.emacs.d/elpa/cal-china-x-0.6目录中的cal-china-x.el就可以了。配置很简单:
(require 'cal-china-x)
;; mark holidays in calendar
(setq calendar-mark-holidays-flag t) - nav:比较简便的、类似于Vim的Nerdtree的文件树导航。输入“.”来转换是否显示隐藏文件。
- smartparens:自动输入匹配的括号等。网上查了一下,这个似乎是自动匹配的扩展中目标最宏伟的(实现其他几个扩展的功能),至于是不是最好用的就不知道了。purcell的配置也有自动输入匹配括号的功能, 对emacs-lisp有效,但是对C代码不生效,不知道为什么。smartparens简单配置一下就基本满足我的需求了,因此没有进一步研究其配置项:
;; use smartparens
(require 'smartparens-config)
;; global enabled, and use strict mode
(smartparens-global-strict-mode +1) - evernote-mode:可以通过Emacs登录查看evernote上的笔记,并可以进行管理(新增、修改等),我一直没有让它跑起来(跟其他扩展有冲突),而且看了下,这个扩展已经有几年没更新了。网上也说由于evernote新修改了登陆验证方法, 导致这个扩展无法正常使用了。搞了半天没搞定,最后把它卸载掉了。
- epic:在Mac OSX中,可以与Evernote.app通信,从而管理evernote中的笔记的扩展。简单地在配置文件中加入:
(require 'epic)
就可以正常使用了(如M-x epic-read-notebook),能获取到笔记本列表,但是进一步想查看里面的笔记时,就出错了,貌似又是与某些插件冲突了,在网上找了挺久也没解决方案,最后还是放弃了。
5 LaTex相关的问题和配置
- auctex:非常有名的LaTex编辑套件,直接通过ELPA安装即可。注意Emacs默认有latex支持的,默认的latex模式名为“latex-mode”,而AUCTeX也带了一个latex模式,名称为“LaTeX-mode”,其他 含有“TeX”字样的配置,应该都属于AUCTeX的。AUCTeX提供了很多的快捷输入方式,比如输入“C-c C-e”可以选择插入LaTeX环境等。以下是我目前的配置:
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq-default TeX-master nil)
;; set default tex engine to xetex, which has better support for chinese
(setq TeX-engine 'xetex)
;; generate pdf rather then dvi
(setq TeX-PDF-mode t)
(setq latex-run-command 'xetex)
(add-hook 'LaTeX-mode-hook 'auto-fill-mode)
(add-hook 'LaTeX-mode-hook 'flyspell-mode)
(add-hook 'LaTeX-mode-hook 'LaTeX-math-mode)
(add-hook 'LaTeX-mode-hook 'turn-on-reftex)
(add-hook 'LaTeX-mode-hook 'turn-on-cdlatex) ; auto enable cdlatex-mode when use auctex
(setq reftex-plug-into-AUCTeX t)
;; add "-shell-escape" option to LaTeX command, which is needed by packages like minted
(eval-after-load "tex"
'(setcdr (assoc "LaTeX" TeX-command-list)
'("%`%l%(mode) -shell-escape%' %t"
TeX-run-TeX nil (latex-mode doctex-mode) :help "Run LaTeX")
)
) - cdlatex:方便输入latex标记的扩展(如输入“it TAB”就输入\itemize组),确实省了很多输入的麻烦。
- auto-complete-auctex:利用auto-complete和yasnippet完成自动补全功能。刚装,还不知道好不好用。
(load "~/.emacs.d/3rd-party/auto-complete-auctex/auto-complete-auctex.el")
(require 'auto-complete-auctex) - 使用xetex作为引擎:xetex使得能够使用系统已安装的字体,并且默认处理Unicode,使得中文处理变得简单。
6 org模式相关的问题、扩展及配置
org模式提供了一种简易(纯文本)、方便以及美观的方式来记录,根据官方文档,主要适用于记录TODO、写项目计划等。网上看很多人用了后都觉得很爽,于是出现了基于org的各种应用,如导出成其他 格式(PDF、HTML等)、利用org模式来写博客等。当然,目前这篇文章也是使用org模式编写的(之前直接在Evernote中写,结果发现有很多排版问题,很烦),嘿嘿。之前也一直在想要使用LaTeX 来写文章,但是对于我这个初学者来说,要记忆LaTeX中的诸多格式和宏,实在太有难度了。org模式提供了比较简单的格式,又能导出为各种格式,还能在里面嵌入LaTeX片段,各种好用的功能,确实是 一个不错的选择。从我配置的结果来看,导出为HTML要比导出为PDF好看多了,可能是导出成LaTeX还需要更多、更细致的配置吧。
- org2blog:可以通过Emacs得org模式写博客,并提交到配置的博客上的扩展。依赖于metaweblog扩展,一个博客API协议。要能够正常使用这个扩展,需要目标博客(如wordpress)支持比较全的 metaweblog的API,而目前国内的博客(如博客园、CSDN以及新浪博客等)似乎都支持不是很全面,所以始终无法正常使用。配置如下:
(require 'org2blog-autoloads)
;; the blog account detail
(setq org2blog/wp-blog-alist
'(("cnblogs"
:url "http://www.cnblogs.com/[user]/services/metaWeblog.aspx"
:username "name"
:default-title "Hello World"
:default-categories ("org2blog" "emacs")
:tags-as-categories nil)
("another-blog"
:url "http://username.server.com/xmlrpc.php"
:username "admin"))) - org导出为pdf:
(require 'org-latex) ;; when export to latex, use minted, rather then listings
(setq org-latex-listings 'minted)
(add-to-list 'org-latex-packages-alist '("" "minted"))
;; add frame and line number for source code(using minted)
(setq org-latex-minted-options
'(("frame" "single")
("linenos" "true"))) ;; Originally taken from Bruno Tavernier: http://thread.gmane.org/gmane.emacs.orgmode/31150/focus=31432
;; but adapted to use latexmk 4.20 or higher.
(defun my-auto-tex-cmd (backend)
"When exporting from .org with latex, automatically run latex,
pdflatex, or xelatex as appropriate, using latexmk."
(let ((texcmd)))
;; default command: oldstyle latex via dvi
(setq texcmd "latexmk -dvi -pdfps -quiet %f")
;; pdflatex -> .pdf
(if (string-match "LATEX_CMD: pdflatex" (buffer-string))
(setq texcmd "latexmk -pdf -quiet %f"))
;; xelatex -> .pdf
(if (string-match "LATEX_CMD: xelatex" (buffer-string))
(setq texcmd "latexmk -pdflatex=xelatex -shell-escape -pdf -quiet %f"))
;; LaTeX compilation command
;; note that 'org-latex-to-pdf-process' now is renamed to 'org-latex-pdf-process'
(setq org-latex-pdf-process (list texcmd))) ;; org-export-latex-after-initial-vars-hook has been removed from org-v0.8
;(add-hook 'org-export-latex-after-initial-vars-hook 'my-auto-tex-cmd)
(add-hook 'org-export-before-parsing-hook 'my-auto-tex-cmd) ;; Specify default packages to be included in every tex file, whether pdflatex or xelatex
(setq org-latex-default-packages-alist
'(("" "graphicx" t)
("" "longtable" nil)
("" "float" nil))) (defun my-auto-tex-parameters (backend)
"Automatically select the tex packages to include."
;; default packages for ordinary latex or pdflatex export
(setq org-latex-default-packages-alist
'(("AUTO" "inputenc" t)
("T1" "fontenc" t)
("" "fixltx2e" nil)
("" "wrapfig" nil)
("" "soul" t)
("" "textcomp" t)
("" "marvosym" t)
("" "wasysym" t)
("" "latexsym" t)
("" "amssymb" t)
("" "hyperref" nil))) ;; Packages to include when xelatex is used
(if (string-match "LATEX_CMD: xelatex" (buffer-string))
(setq org-latex-default-packages-alist
'(("" "fontspec" t)
("" "xunicode" t)
("" "url" t)
("" "rotating" t)
("american" "babel" t)
("babel" "csquotes" t)
("" "soul" t)
("xetex" "hyperref" t)))) (if (string-match "LATEX_CMD: xelatex" (buffer-string))
(setq org-export-latex-classes
(cons '("article"
"\\documentclass[11pt,article,oneside]{memoir}"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
org-export-latex-classes)))) ;(add-hook 'org-export-latex-after-initial-vars-hook 'my-auto-tex-parameters)
(add-hook 'org-export-before-parsing-hook 'my-auto-tex-parameters)上述配置解决的问题主要有:
- 当org文档中含有“#+LATEXCMD: xelatex”的文件头时,使用xelatex作为编译程序,并使用额外的宏包,避免默认使用的inputenc包等导致xelatex无法编译通过。
- 从org导出成tex时,使用minted来替代listings。minted和listings都能提供代码美化功能,但是minted的格式更简单些。
- 由于minted需要用pygmentize程序来生成代码高亮的转化代码,因此在调用latex时要加入“-shell-escape”参数。
- 设置minted的显示格式为带边框,且显示行号。
7 其他遇到的问题及解决
- 找不到/usr/local/bin/中的二进制:
;; default path doesn't contain "/usr/local/bin", cause some "command not found"
;; issues, so I add the path here
(setq exec-path (append exec-path '("/usr/local/bin"))) - 默认显示行号:
(global-linum-mode t)
- 保存session等时总是提示文件编码问题。原因是默认情况下,Emacs保存文件都使用ASCII编码,这样在保存的文件中含有中文等多字节字符时,就会出现编码问题。解决方法:
;; set default encoding to utf-8
(setq-default buffer-file-coding-system 'utf-8)
;; set writing buffer default to utf-8, or emacs always show encoding
;; problem when saving files.
(setq save-buffer-coding-system 'utf-8)
(setq coding-system-for-write 'utf-8) - 在Emacs中显示斜体中文时,无法正常显示,只显示方块的问题。原因是因为Emacs没有为斜体设置中文字体,解决方法(Mac OSX中):
;; set Chinese font, or the when showing Italic Chinese characters, only rectangle block shown
(set-fontset-font
(frame-parameter nil 'font)
'han
(font-spec :family "Hiragino Sans GB" ))
8 总结
- 缺点/抱怨
- 在网上能找到的基础配置功能不齐全,仅提供了基础框架,且后续自定义配置中又诸多的坑,却在其配置说明中很少提及
- 很多问题能够在网上找到相近解决方案,但该解决方案往往是过时的(如:新版本中已采用新的变量名;解决方法中使用的hook已经失效等)。如果仔细查看问题扩展的源码的注释,会发现很多问题在注释中是有说明解决方法的。
- 启动速度着实不敢恭维,使用我目前的配置,在我I7的本子上要十来秒才完全载入。没
- 我比较习惯在Shell中查找并打开想打开的文件的(习惯了在终端中使用Vim),对于没有了GUI就少了很多功能的Emacs,感觉就少了些流畅。
- 与Vim相比的优势
- 字体渲染十分漂亮
- 与Vim不同,Emacs窗口可以显示的内容更丰富些,比如不同内容字体大小、格式不同,甚至还可以显示图片
- 更加方便的代码调试环境。相比VS、Eclipse等IDE还是要差一些,但是比Vim要好一些了。
- 更强大的auto-complete功能,相比Vim的代码自动补全也更容易配置一些,并且除了补全,还有补全内容的帮助信息同步提示。
- 可配置性更强。理论上是无所不能的(Emacs是一个操作系统,只是缺少好的编辑器~~)