一直以来Haskell没有好用的工具支持goto-references,hasktags
、fast-tags
等能提供ctags风格的goto-definition,但不支持goto-references。最近Google开源的一个工具https://github.com/google/haskell-indexer(主要作者为Robin
Palotai)提供了基于Kythe的交叉引用实现。
haskell-indexer
依赖
- stack,Arch
Linux的话可以使用felixonmars打包的
community/stack
(感谢肥猫辛勤劳作,喵!)。 - Google Kythe。把https://github.com/google/kythe/releases下载的压缩包装到
/opt/kythe
之类的地方。如果不想成为Bazel工程师的话,不要从源码编译,编译需要一大堆编译时依赖。
索引Hackage
1 | git clone https://github.com/google/haskell-indexer |
打开http://127.0.0.1:8080能看到Kythe的简陋网页前端。
注意事项:
- Kythe
v0.0.26里的
/opt/kythe/tools/http_server --listen localhost
不会监听IPv6 ::1。 - haskell-indexer使用GHC
API,需要ghc编译的命令行。当前找到所需源码及编译选项、依赖的方式是让
build-stack.sh
修改PATH
环境变量,让stack build --system-ghc
时使用自己指定的ghc wrapper。但有些时候stack build
会复制~/.stack/precompiled/
下的包而不是重新构建。需要一个更加可靠的获取ghc命令行的方式。目前如果发现某个包mtl-2.2.1: using precompiled package
的话,可以删除~/.stack/precompiled/x86_64-linux/ghc-8.0.2/1.24.2.0/mtl-2.2.1/
目录后再执行build-stack.sh
。
helm-kythe.el
我写了一个Emacs Helm扩展,调用tools/http_server
的HTTP
API实现交叉引用。
安装
建议用某个Emacs包管理器加载https://github.com/MaskRay/emacs-helm-kythe到load-path
。helm-kythe
依赖dash
和helm
。
如果只有一个vanilla
Emacs的话,可以执行下面代码,添加melpa-stable
源并安装这两个包。
1 | (add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/")) |
使用
1 | (require 'helm-kythe) |
假设./build-stack.sh /tmp/logs mtl
时安装了mtl-2.2.1
。
cabal get mtl-2.2.1
emacs mtl-2.2.1/Control/Monad/Cont/Class.hs
可以在mode
line看到Kythe
字样,如果显示为Kythe的话说明helm-kythe-apply-decorations
没有执行成功,无法访问http://127.0.0.1:8080
或者没有索引。
- 设置了
eldoc-documentation-function
,把point移动到标识符上可以在minibuffer看到其定义的snippet
helm-kythe-find-definitions
,默认绑定到C-c k d
,跳转到定义helm-kythe-find-references
,默认绑定到C-c k r
,跳转到引用helm-kythe-imenu
,默认绑定到C-c k i
,显示当前文件顶层定义helm-kythe-resume
,默认绑定到C-c k l
,打开最近访问的一个helm-kythe buffer
假设当前文件为/tmp/kan-extensions-5.0.2/src/Data/Functor/Contravariant/Coyoneda.hs
,如果要跳转到的文件在当前Cabal包外,比如要跳到contravariant-1.4/
目录,会尝试找kan-extensions-5.0.2/
的兄弟目录,不存在的话再考虑helm-kythe-filesystem-path-to-corpus-root
。如果你把Cabal
.tar.gz
解压到其他地方了,请设置这个变量。
效果
C/C++
helm-kythe
对于C/C++也适用。Emacs做如下配置:
1 | (add-hook 'c-mode-hook 'helm-kythe-mode) |
目前Kythe
0.0.26的命令行工具非常难用,下面是索引/tmp/c/proj/a.c
的例子。
1 |
|
不运行tools/http_server
,用命令行客户端tools/kythe
检查生成得到的kythe/serving
目录可用:
1 | % /opt/kythe/tools/kythe -api serving ls 'kythe:?' |
可以参考我的Emacs配置https://github.com/MaskRay/Config/blob/master/home/.emacs.d。
1 | ;; spacemacs|define-reference-handlers 是仿照 spacemacs|define-jump-handlers 写的 |
一晃到七月了,不能再堕落了,开启CTF模式。