見出し画像

Obsidian でファイルを作ったときに自動的にテンプレートを適用するプラグイン

ファイルの作成日付を本文に YFM で入れるプラグインを作ってみた。

---
date: 2021-04-27T17:03
aliases: []
---

ファイル作成時に、ファイルの中身が空っぽだったら、その日の日付と aliases 予定地を含む YFM を自動的に挿入します。

これにより、いつ作ったファイルかがすぐわかって便利だし、alias はろうと思ったときもすぐにはれます。

このプラグインは、広く使ってもらおうと思って実装したというよりは、自分がほしいから作ってみたというだけで、plugin repository に公開する予定はありません(特殊なユースケースだとわかっているので)。

ファイル名に日付入れればいいんじゃないの?

Zettelkasten 風にファイル名に入れてしまうと、日付が毎回リンクはるときに出てくるのが好みじゃないのです。

コード

https://github.com/tokuhirom/obsidian-new-file-template

ここで MIT ライセンスで公開しています。気になる方はどうぞ。

実装の解説

プラグインの実装の仕方の解説は今後、別エントリで細かくしていこうと思いますので、今回はこのプラグインのコアの部分の実装についてのみ解説したいと思います。

export default class NewFileTemplatePlugin extends Plugin {
 settings: NewFileTemplatePluginSettings;

 async onload() {
   console.log("loading new-file-template plugin");

   await this.loadSettings();

   this.addSettingTab(new NewFileTemplatePluginSettingTab(this.app, this));

   this.app.workspace.on("file-open", this.onFileOpen.bind(this))
 }

  async onFileOpen(file: TFile) {
   if (file == null) {
     return;
   }

   const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView);
   if (markdownView == null) {
     return;
   }

   const content = await file.vault.read(file)
   if (content == "" && markdownView.getMode() == "source") {
     const content = this.renderTemplate(this.settings.template)
     await markdownView.sourceMode.set(content, false)

     await markdownView.editor.focus()
     await markdownView.editor.setCursor({line: content.split(/\n/).length, ch: 1})
     // same as `workspace:edit-file-title`
     await this.app.workspace.getActiveViewOfType(MarkdownView)?.leaf?.setEphemeralState({rename:"all"})
   }
 }

 renderTemplate(v: string) {
   return v.replace(/{{\s*date\s*:\s*(.*?)}}/gi, (_, fmt) => {
     return moment().format(fmt);
   });
 }

 onunload() {
   console.log("unloading new-file-templatte plugin");
 }

 async loadSettings() {
   this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
 }

 async saveSettings() {
   await this.saveData(this.settings);
 }
}

このプラグインのコアは以下の部分です。ファイルのオープンイベントをフックしています。

this.app.workspace.on("file-open", this.onFileOpen.bind(this))  

onFileOpen の中では以下のような流れになります。

- 現在表示中の markdown view を取得します。
- view に紐付いたファイルが、サイズがゼロかどうかを確認
- サイズがゼロなら、テンプレートをレンダリングして挿入する
- いったんフォーカスをエディターにあてる
- エディターの末尾にカーソルを動かす
-フォーカスをタイトルに戻す

ということをしています。

このプラグインの難しいところは、フォーカスをどう扱うかというところとカーソルの位置をどう制御するかというところです。ここを丁寧に実装しないと、体験が非常に悪くなります(長らく体験が悪いプラグインを使っていたのですが、Obsidian Dicord の #plugins で pjeby 氏に色々教えてもらってついにやりたいことができました)

コミュニティに助けられ、たぶん僕しか求めてない挙動が実現されて、大変快適に Obsidian を使えるようになりましたとさ。

このプラグインは、求めてる人とくにいなさそうなので、OSSとして github にひっそり公開しておきますが、特に公式プラグインレポジトリへの公開予定はありません。

まとめ

Obsidian では TypeScript が書ければ、細かいところまで Emacs を elisp で制御するような感覚で、自分好みの挙動に変更することができます。Hacker 気質のあなたにもオススメです(本当は Obsidian 本体のソースコードを公開してほしいところではあります。VIP tier の人のみ対象でもいいので。。)。

今後、Obsidian plugin の開発方法の解説などもしていこうと思っていますのでよろしければフォローお願いします。

Discord の #日本語 も、直近は3人ぐらいが話しているだけで過疎ってるので、興味ある方はぜひ JOIN してください。最近は「使ってるプラグインどんなの?」って話をしています。

この記事が気に入ったらサポートをしてみませんか?