一直以来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.1emacs 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 | #!/bin/zsh |
不運行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模式。