Sublime REPL上のghciで確認しながらコード書いているときに、変更後に:loadするのが面倒なので保存後に自動で:loadしてくれるプラグインを書いてみた。
import sublime, sublime_plugin, os, re
class ZanelicativeGhciAutoLoadEventListener(sublime_plugin.EventListener):
def on_post_save(self, view):
filename = view.file_name()
path, ext = os.path.splitext(filename)
if ext != ".hs" and ext != ".lhs":
return
replView = Util.get_ghci_view(view.window().views())
if replView is None:
return
Util.put_ghci_command(replView, "l", filename)
class ZanelicativeGhciTypeCommand(sublime_plugin.TextCommand):
def run(self, edit):
replView = Util.get_ghci_view(self.view.window().views())
if replView is None:
return
sels = self.view.sel()
for sel in sels:
word = self.view.substr(self.view.word(sel))
if not re.match(r"^\w+$", word) and not re.match(r"^\(.*\)$", word):
word = "(" + word + ")"
Util.put_ghci_command(replView, "t", word)
class Util:
@staticmethod
def get_ghci_view(views):
for view in views:
if view.name() == "*REPL* [haskell]":
return view
return None
@staticmethod
def put_ghci_command(view, command, param):
edit = view.begin_edit()
view.insert(edit, view.size(), ":" + command + " " + param)
view.run_command("repl_enter")
view.end_edit(edit)
ZanelicativeGhciAutoLoadEventListener の on_post_save メソッドで、保存後に発火するリスナーを作成している。
ファイル名を取得して、タイトルが「REPL [haskell]」のタブを探してそこに「:l <ファイルパス>」を出力して
Enterキーを送ることで実現している。
少しハマったのが、Enterキーと認識されるキーを出力してコマンドを決定させるところ。
最初はコマンドの末尾に改行文字や os.linesep を付与していたが改行文字そのものがghciに出力されて
コマンド決定扱いとみなされなかった。
これは「view.run_command("repl_enter")」を実行することで解決した。
上のタブ「test.hs」でソース編集後、Ctrl + s で保存した際、自動で下のタブにロードされている。
オマケ(?)でカーソルの当たっている関数を ghci の:typeで調べるようにしたのが
ZanelicativeGhciTypeCommand。
こちらはリスナー発火ではなく、コマンド実行時にフォーカスの当たっている単語を取得し、
「REPL [haskell]」タブに「:t <関数>」と repl_enter を出力することで実現している。
Default (Linux).sublime-keymap
[
{ "keys": ["ctrl+shift+t"], "command": "zanelicative_ghci_type" }
]
このようにキーを割り当てると、関数にカーソルが置かれた状態で Ctrl + Shift + T を押下すると ghci で型を調べることができる。
putStrLnにカーソルが置かれた状態で Ctrl + Shift + T を押下し、:t putStrLn している。