auto-complete配置sass失败

###1.问题 我准备配置sass的auto-complete,已经做了如下配置,却依然失败。 配置:

  • (add-hook 'sass-mode-hook 'auto-complete-mode) ;; 启动auto-complete
  • 在C-h v中找到ac-modes,把sass-mode添加到ac-modes列表中 以上两项配置都确定是ok的。 但是*.sass文件下 auto-complete依然不起效果,*.scss的倒是有。

2.我的尝试

经过近一步谷歌,我发现这个配置,它作了4件事情:

  • 配置electric(不是很清楚这个东西是什么,应该是缩减,与自动补全无关,跳过)
  • 配置ac-sources
  • 配置ac-modes,把sass-mode加入ac-modes
  • 启动rainbow-mode (与补全无关) 对比一下,我想应该是ac-sources没有配置,但是我把它的ac-sources 复制到spacemacsd的用户自定义配置,重启后报错:File mode specification error: (void-variable ac-sources) ;; ac-sources这个变量非法

###3.我的猜想、疑惑、问题:

  • emacs的auto-complete 是不是没有天然支持sass?不然scss都不用配置ac-sources,为什么sass需要配置ac-sources?
  • ac-sources这个变量是什么含义?C-h v里面没有说明这个变量的含义,官方也没具体说明
  • 为什么我复制了那段配置ac-sources的配置之后,会报ac-sources 不存在?并且这时候C-h v里面也找不到ac-sources这个变量了

4.我的配置:

;; 在custom-set-variables中(spacemacs自动生成的):这里配置了ac-modes,添加了sass-mode
 '(ac-modes
   (quote
    (sass-mode emacs-lisp-mode lisp-mode lisp-interaction-mode slime-repl-mode nim-mode c-mode cc-mode c++-mode objc-mode swift-mode go-mode java-mode malabar-mode clojure-mode clojurescript-mode scala-mode scheme-mode ocaml-mode tuareg-mode coq-mode haskell-mode agda-mode agda2-mode perl-mode cperl-mode python-mode ruby-mode lua-mode tcl-mode ecmascript-mode javascript-mode js-mode js-jsx-mode js2-mode js2-jsx-mode coffee-mode php-mode css-mode scss-mode less-css-mode elixir-mode makefile-mode sh-mode fortran-mode f90-mode ada-mode xml-mode sgml-mode web-mode ts-mode sclang-mode verilog-mode qml-mode apples-mode)))

;; 在dotspacemacs/user-config 中: 配置启动auto-complete-mode,配置ac-sources
  (add-hook 'sass-mode-hook 'auto-complete-mode)
  (defun configure-auto-complete-for-sass ()
    (add-to-list 'ac-sources 'ac-source-css-property))
  (add-hook 'sass-mode-hook 'configure-auto-complete-for-sass)
1 个赞

我找到问题所在了。

  • 什么是ac-sources? 官方其实有,我漏了。链接
  • 为什么之前的配置不work? 因为 启动auto-complete配置ac-sources 这两个hook是有顺序要求的。 必须先 启动auto-complete 然后才会有 ac-sources 这个变量供我们配置。所以把两个add-hook的顺序对调:
  (defun configure-auto-complete-for-sass ()
    (add-to-list 'ac-sources 'ac-source-css-property))
  (add-hook 'sass-mode-hook 'configure-auto-complete-for-sass) ;; 此时hook为:(configure-auto-complete-for-sass)
  (add-hook 'sass-mode-hook 'auto-complete-mode) ;; 此时hook为:(auto-complete-mode configure-auto-complete-for-sass)

hook在被调用的时候,是 按列表的顺序 来的,而不是 添加的顺序 , add-hook 这个函数是往目标hook的头部添加,而不是一个push操作。

其它hook 是不是也是这种类似栈的机制?“后入先出”的执行顺序?


以上方案并不完美。

  • ac-source-css-property 这个ac-source 只能补全css的value, 不能补全key。可以再自定义一个key的ac-sources,如下的:ac-source-css-property-names
  (defvar ac-source-css-property-names       ;; refer to http://d.hatena.ne.jp/sugyan/20120107
    '((candidates . (loop for property in ac-css-property-alist
                          collect (car property)))))
  (defun configure-auto-complete-for-sass ()
    (add-to-list 'ac-sources 'ac-source-css-property)
    (add-to-list 'ac-sources 'ac-source-css-property-names))
  • 我发现ac一个不完美的地方,用来生成css相关ac-sources的变量:ac-css-property-alist比较老旧,没有box-sizing属性。。。估计很多css3的属性都没有。一会提个rq。
  • 这种auto-complete貌似意义不大,不智能。比如: position这个css属性,会弹出 “red”跟“relative”这两个选项,“red”明显就是一个非法值。

全过程我都在骂爹骂娘:“为什么emacs界对*.sass的支持这么少?” 最后才去细查了一下.sass与.scss的区别,*.sass这种格式有被遗弃之嫌,所以支持得就少一点。回头再来看看这个问题,我觉得直接选择*.scss这种格式的sass语法就好了,有scss-mode直接支持补全。虽然它自带的补全方式不像auto-complete那样弹出所有候选项,但是补全的值都是合法的,而且我觉得已经够用了。

(add-hook 'sass-mode-hook 'configure-auto-complete-for-sass 'append) 可以确保所要 hook 的函数被添加到 hook 列表的末端而不是相反。

1 个赞

非常感谢。 细看C-h f中关于add-hook的介绍,确实有append这个可选参数。