• 作成:

HaskellでGTKの最近開いたファイルに項目を追加する

問題

以前、スクリーンショット環境をimport(ImageMagick)からgnome-screenshotに移行できなかったので, PyGObjectで「最近開いたファイル」を追加するスクリプトを書きました - ncaq に書いたとおり、 xmonadでスクリーンショットを取るとGnome(GTK(GObject))の「最近開いたファイル」にファイルを追加するようにしていました。

しかし、この方法には問題がありました。

それは、 Pythonがシステムのライブラリを参照しているので、型チェッカなどが偽のエラーを吐くことです。

Pyrightがエラーを出している様子

pipenvなどを使ってライブラリのパスを通せばおそらく解決するのでしょうが、実際に読み込むのはシステムにインストールされたライブラリなので、二重に管理するのは汚くて嫌です。

また、 Pythonのシステムバージョンを変更すると動かなくなったりすることが以前ありました。

解決策

HaskellにGtkのバインディングが存在するので、 Haskellで記述すれば問題が解決すると考えました。

GI.Gtk.Objects.RecentManager

結果

色々使い方を調べて出来た関数がこちらです。

https://github.com/ncaq/.xmonad/blob/e6d19f769af0ae63b0e21df183b46042f198c485/src/Main.hs#L146

-- | GTKの最近使ったファイルリストにファイルを追加します
recentAddItem :: FilePath -> IO ThreadId
recentAddItem filePath = forkIO $ do -- `forkIO`しないとxmonad自体が終了してしまいます。
  _ <- Gtk.init Nothing              -- Gtk.initしないとアプリケーション名が存在しないと言う警告が出ます
  recentManager <- G.recentManagerGetDefault
  _ <- G.recentManagerAddItem recentManager $ toTextStrict $ "file://" <> filePath
  _ <- G.idleAdd G.PRIORITY_DEFAULT_IDLE $ do
    Gtk.mainQuit
    return True
  Gtk.main

普段あまりGTKなどを弄らないので試行錯誤がありました。単に項目追加するためだけにGtk.mainを呼び出したり軽量とは言えスレッドを作ったりするのは本当に必要か? と言う疑問は無くはないです。

まあさほど呼び出さないので動いてリソースリークが無ければ問題ないでしょう。