おそらくはそれさえも平凡な日々

YAPC::Tokyo 2019で報恩謝徳の話をしてベストスピーカーを頂きました

http://songmu.github.io/slides/yapc-tokyo-2019/#0

「技術力が無い人間がエモに逃げてはいけない」という個人的ポリシーを持っていて、あまりエモい話は登壇ではしないようにしてきたんだけど、今回は「報恩謝徳」がテーマということで、思いっきりエモい話をしてやろうということで申し込んだ。このテーマならベストスピーカー狙えるだろうとも思っていました。

しかし、トーク採択していただいたものの、実は40分のところを20分にしてくれないかという打診があり承諾していました。僕は比較的運営から近い位置にいるのでそういう打診をしやすかったのかも知れず、そういう相談をしてもらえるのは嬉しいし、登壇者が増えるのも良いことだとも思い快諾しました。

とは言え20分にまとめるのは難儀でした。登壇は多少は慣れているつもりですが、今回はかなり難産で、資料作りに苦労しました。

プレゼン作る時は、話したいことをまずは書き出しまくって、アウトラインに収束させてからスライドに起こすのだけど、今回はテーマがテーマなので話したいことが多すぎて爆発してしまって、そもそもアウトラインに収束させられずに苦労した。ベストスピーカーを狙っていた気負いも合ったのでしょう。

もっと話したいとか、感謝を述べたいこと、面白いエピソードとかいろいろあったのですが泣く泣く削りました。

社内的には広報チェック通したほうがいいんですが、今回は事前に広報の担当者に「今回人生の話しようと思ってるんですけど、全然資料できなくて困ってるんで広報チェック回せそうにありません」と断っておいて「いいですよ」とは言われていました。本当は良くないんだけど!

スライドも当初はKeynoteに起こす予定だったけど、これは間に合わんな、ということでいつも使ってるMarkdonwからスライド生成する自作のプレゼンツール(Perl製!)を使うことに。だから逆に勢いよく話せたのかも知れない。

ベストスピーカーを狙ってるんだったら前日とかに宣伝エントリなりツイートなりしたほうがいいんだけど、最後の最後まで内容も収束させられないし全然自信も持てなかったのでそういうこともできなかった。

前夜祭後に @tokuhiromと@xaicronと飲みに行って全員が「スライドできてねー」って話してて、まあなんというかいつものYAPCの光景と言う感じで逆に落ち着いてプレゼンストーリーも見えてきた。この時「そんむーさん自分が意識高くないと思ってるなら相当重症ですよ」ってxaicronに言われたのが面白くて妙に印象に残っている。

xaicronはその後徹夜で資料作ったらしいけど、僕は早朝に起きて、会場で仕上げをしてなんとなく話せるかな、という手応えを感じたのは以下のツイート時点。

正直ベストスピーカーは諦めていて、資料は殴り書きみたいなアウトラインの域を超えてなかったので、まあこれを20分で話しきれたら御の字だろうと思っていた。

とは言え、トークの冒頭で「他のスピーカーの方は慎み深い方が多いか、言ってる人少ないんですけど、ベストスピーカー投票お願いしますね」という軽口を叩けるくらいには自信を持って話すことはできた。話し終わったあとも、少し時間オーバーしちゃったけど、話せてよかったという満足感はありました。

その時点でもベストスピーカーは取れるとは思ってなかったんだけど、YAPCの運営でもあり同僚でもあるpapixが悪くて、ベストスピーカーの発表前に社内のSlackでなにか良いことが起こったことを仄めかす発言をして「これはもしかしたらベストスピーカー取ったかも知れないぞ」とか頭によぎってしまった。

これでベストスピーカーだったら泣いてしまうかも知れないけど壇上で泣かないようにしないとな、とか思ったらその時点でなんだか泣けてきてしまって、いや仄めかしたのはベストスピーカーの話じゃないかも知れないし、別の同僚のスピーカーの話かもしれないからこれで泣いてたら馬鹿だな、とか色々思いを巡らせていたら、果たして本当にベストスピーカーであり、結局壇上でめちゃくちゃ泣いてしまった。人間揺さぶられると弱い。

ということで、多くの同僚やコミュニティの仲間達の前で泣いてしまったのだけど、温かく受け止めていただいたのは本当にありがたかったです。

YAPC自体は盛り上がっててよかった。若い人も結構話してたし、ベストLTもベストスピーカー賞も3位までPerlの話だったのも個人的には良かったと感じています。結構仕事が忙しかったのでフルで楽しめるか微妙だったんだけど、結局誘惑に負けて前夜祭からフルで楽しんでしまった。楽しめてよかった。YAPCが相変わらず僕にとってのモチベーションの源泉の場の一つでもあるのだなとも感じた日でした。あとはtokuhiromのキーノートの最後のスライドに写真を載せてもらえていたのは密かに結構嬉しかった。

Homebrewで自作ツールを簡単にインストール可能にする

まとめを先に

用語

これらは自前で簡単に作ることができます。公式リポジトリに頑張ってpull requestを送ることもできますが、個人的なものであれば気軽に自前で作ってしまうことがおすすめです。

tapリポジトリの作成

前項で書いたとおり"homebrew-"プレフィクスを付けて命名すればOKです。僕の場合homebrew-tapという名前で作っています。

https://github.com/Songmu/homebrew-tap/

このリポジトリ上のディレクトリ直下、もしくは Formula/ ディレクトリ配下にFormulaを配置します。上記のリポジトリの場合、Formula/ 以下に配置しています。現状7個のツールを登録しています。

このtapを利用したい場合は"homebrew-"プレフィクスを除いた形で以下のように登録します。

% brew tap Songmu/tap

また、以下の様にダイレクトにtapの登録とツールのインストールをおこなうことも可能です。

% brew install Songmu/tap/maltmill

Formulaの作成

FormulaはrubyのDSLファイルです。他のツールのFormulaを参考に見よう見まねで書くこともできますが、ここでは maltmill というツールの紹介をします。

https://github.com/Songmu/maltmill

実は1年以上前に作っていて、作りかけ気味なのですが、使い物にはなるし、実際活用しているので紹介することにしました。

コンセプトとしては、GitHub Releasesに登録しているアーカイブから簡単にFormulaを新規作成したり、更新したりすることができるものです。

インストール

# brew
% brew install Songmu/tap/maltmill
# go get
% go get github.com/Songmu/maltmill/cmd/maltmill

Formulaの新規作成

前提として、GitHub Releasesにアーカイブがアップロードされている必要があります。例えば、以下のようにすれば、ghqのFormulaが作成されます。

% maltmill new -w motemen/ghq

この場合、Formulaはghq.rbというファイル名で作成されます。適宜調整して、tapリポジトリにcommitしてください。

Formulaの更新

GitHub Releasesに新しいリリースが登録されている場合、以下のようにFormulaファイルを指定することで更新することができます。

% maltmill -w Formula/ghq.rb

これは、versionとアーカイブurlの取得と書き換え、アーカイブのsha256の再計算とその書き換えも自動でおこなってくれます。あとは更新内容を確認して、リポジトリにcommitするだけです。それで新しいバージョンをbrewでインストールすることが可能になります。

まとめ

まだ荒削りな部分もありますが、是非ご利用ください。mackerel-agentも以下でtapを公開していますが、maltmillに乗り換えていければいいな、と思っています。

https://github.com/mackerelio/homebrew-mackerel-agent

命名は、ビール醸造関連が良いなと思って、ビール製造工程の最初に麦芽を挽くのに使うMalt Millからつけました。

horenso v0.9.0でより便利になりました

https://github.com/Songmu/horenso

v0.9.0なので、version 1を出す前のRC的な気持ちでいます。アップデートは以下のとおりです。

設定ファイル(yaml形式)サポート

設定ファイルは環境変数 $HORENSO_CONFIG にファイルパスを指定します。設定項目は大体コマンドラインオプションに対応していて以下のような具合です。

noticer: /path/to/basic-noticer
reporter:
- /path/to/basic-reporter

こういうのを保存しておいて、crontabに以下のように記述します。

HORENSO_CONFIG=/path/to/horenso.yaml
11 * * * * horenso          -- /path/to/your-batch1 ...
23 2 * * * horenso -t daily -- /path/to/your-batch2 ...
23 2 1 * * horenso -t monthly -r 'additional-reporter' -- /path/to/your-batch3 ...

従来は、README.mdに書いてある通り、ラップするシェルスクリプトを書くのが一つのパターンでしたが、この設定ファイルの場合もっと見通しがよくなります。

またジョブによっては追加のレポーターを指定したいなどもあると思いますが、それに関して個別に追加することも可能です。上の additional-reporter と指定してある様な形です。個別指定した場合であっても、設定ファイルに記載のnoticer及びreporterは動作します。

このあたりドキュメントまだなのでversion 1までには書きます…。

ログファイル指定オプション(--log/-l)

ログをファイルに出力することが可能になりました。--log=%Y%m%d.log となど指定します。strftimeフォーマットが利用可能なのもポイントです。

verboseログを出せるように(--verbose/-v/-vv)

horensoは主体であるバッチコマンドの動作を妨げないように、標準出力や標準エラー出力にはそのバッチコマンド自体の出力のみ流し、horenso自体のログは一切出さない様になっています。

しかしそれでは、reporterやnoticerの動作確認時に困るという声もあり、それは分かるということで、--vebose オプションを追加しました。--verbose は重ねることができます。

という挙動となっています。

タイムスタンプのフォーマット変更

horenso--timestamp/-T オプションで出力への自動タイムスタンプ付与が可能ですが、このフォーマットがRFC3339の小数点以下6桁固定長に変更になりました。

この変更にあたって、Songmu/timestamper というライブラリを外に切り出しました。これは便利かつ実装も面白いので後日また別でブログを書こうと思います。

type Report struct の型情報の非互換修正

horenso コマンド自体は大きな非互換修正はありませんが、horenso.Reporter をライブラリ的に自前のreporterなどで利用している場合はビルドが通らなくなってしまうため、修正をお願いします。Reporterのフィールドからなるべくポインターを減らす対応をおこないました。

その他、コードの修正や効率化、リファクタリングも何点か実施しました。

より便利になったhorensoをぜひご利用ください。

オライリーの「入門 監視」の付録Cを執筆しました

入門 監視 ―モダンなモニタリングのためのデザインパターン

この本はPractical Monitoringの邦訳です。原著は持っており、良い本だと思っていたので、翻訳者の松浦さんが邦訳されている話を聞いたときには嬉しく思いましたし、そこで付録を執筆して欲しいという依頼もいただき、身に余る話でしたが、引き受けさせてもらいました。

そして「実践 監視SaaS」と言う内容を付録Cとして20ページほど書かせていただきました。原著が監視SaaSの活用を推奨してはいるのですが、内容的にはツールに偏らない、概念的で中立的な本であるため、監視SaaS活用に関してはもう少し具体的、実践的な話を補強して欲しいというオーダーを受け、書いたものです。

私は、Mackerel という監視SaaSのプロダクトマネージャーを務めており、それもあって依頼を頂いた形ですが、逆に、原著の中立的な良さを損なわないように公平さを心がけて執筆するのは苦労しました。とはいえ、私は、当たり前ですが、監視サービスの中ではMackerelが一番得意であるため、Mackerelも例示しながら付録を執筆する形となっています。

本書の推しポイント

付録を抜きにしても、本書は本当に良い本です。「監視はインフラエンジニアの担当領域である」や「監視は専門的な知識がない人には全くおこなうことができない」といった誤った固定概念を打ち砕いてくれる本です。私自身「アプリケーションの監視は、いわゆるインフラエンジニアより、アプリケーションを一番理解している人が監視を一番良くできる」と常々考えてきたため、この本はそれを伝えてくれている良い本です。

しかも、200ページ程度の本なのですぐ読めるでしょう。

筆者の主張が的確ながらも強めなのも面白ポイントで、個人的に良いと思った文言を以下に抜粋しておきます。

「メトリクスの履歴を保存していない(Nagios、お前のことだ) 」
「銀の弾丸はない。この本からこれだけは覚えておいてください。」
「お願いだから円グラフは使わないで」
「SLAとは、(ほとんどの場合) 願望や嘘である」
「多くのチームではアプリケーション監視が難しすぎるか、高い専門的なスキルセットを必要とすると考えているからだと私は思います。しかしありがたいことにどちらも真実ではありません」
「アプリケーションの計測を始めれば、もう病みつきになります」
「一般的に言って、何に対してであれロードアベレージに依存することは時間の無駄だと考えています。」
「ネットワークパフォーマンスの監視における最大の課題は、SNMPを使わなければならないという1点に尽きます」

その他の名言はぜひ皆様の方で見つけてください。

謝辞など

オライリーさんから報酬をいただけるような仕事ができたことは何よりの喜びです。翻訳者の松浦さんには良い機会を頂いて本当に感謝です。編集の高さんにもお世話になりました。

Practical Monitoringの原著を去年の頭に薦めてくれた、hayajoさんもありがとうございました。hayajoさんは僕が推薦して、この邦訳のレビュワーも担当されました。

付録執筆にあたっては、 kazuhoさんkyannyさんのblogから、一部文言を引用をさせてもらいました。ありがとうございます。

また、書籍「テスト駆動開発」からも引用させていただきました。t-wadaさんありがとうございました。そういえば、奇しくも、僕も付録C執筆クラスタになったことを愉快に思っています。(勝手に光栄だとも思っています)

入門 監視 ―モダンなモニタリングのためのデザインパターン
テスト駆動開発

Time Machineの容量削減のためにtmcleanというツールを作った

なんとPerl製で久々のCPANizeです。

% cpanm -vn App::tmclean

上記でインストール可能ですが、「Perlかよ」という声にお応えして、一つの実行ファイルにパックしたものを用意して、それをHomebrewで入れられるようにしておきました。(App::FatPack::Simple++)

% brew install Songmu/tap/tmclean

使い方は簡単で、

% sudo tmclean --days=300

とかやると、300日以前のバックアップを削除してくれます。root権が必要です。dry runにはroot権は必要無いので、以下のようにすれば事前にコマンドの実行計画を見ることもできます。

% tmclean --dry-run --days=300

環境にもよりますが、かなり時間がかかるので注意です。僕の場合、試しに最も古い2つのバックアップを削除したら、4時間程度かかりました。寝る前とかに仕込むのが良いと思います。何れにせよご利用の際は気をつけてお使いください。

やっていること

この「ターミナルからTimeMachineのバックアップを削除して使用可能領域を増やす」という記事に書かれていることをそのままスクリプトに起こしただけで、tmutil deletehdiutil compact コマンドを内部で実行しているだけです。tmutil delete だけではHDDの容量が空かないと言うのは罠い。

余談

Time Machineの容量がQNAPを圧迫していたので作った。正確に言うと、以前手作業でコマンド実行したのを後の作業では自動化したいためにツール化した。

上のエントリにも書いてあるとおり、以下のようにすれば、Time Machineのサイズも制限できるようなのでこれも実行しているが実際に有効に動いているかどうかはわからない。

% sudo defaults write /Library/Preferences/com.apple.TimeMachine MaxSize 109951162777

また、sparsebundle自体の容量制限をする手もあるらしいのだが、これはやっていない。

% hdiutil resize -size 1024g /Volumes/path/to/$machineName.sparsebundle

そもそも以下のQNAPの公式ヘルプにも書いてあるように、適切にクオータ設定をしておきましょうという話でもあった…。

https://www.qnap.com/ja-jp/how-to/tutorial/article/time-machine-%E3%82%92%E4%BD%BF%E3%81%84-mac-%E3%82%92-smb-%E7%B5%8C%E7%94%B1%E3%81%A7-qnap-nas-%E3%81%AB%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97%E3%81%99%E3%82%8B/

ということで、僕自身の個人向けの色が強いツールですが、もし必要な方がいれば、気をつけてご利用ください。

YAPC::Tokyo 2019で「多くのCPAN Authorに育てられ、息をするようにCPANモジュールを書けるようになり、そして分かったこと」というトークをします

https://yapcjapan.org/2019tokyo/

プロポーザル通ったので、テーマの「報恩謝徳」に即した、タイトルの通りのトークをさせてもらえることになりました。LT、キーノートの直前のメインホールでのセッションなので、キーノートの席確保がてらでも良いので、是非お越しください。あまりコードもでてこないのでカンファレンス終盤の疲れた頭にはちょうどよいトークになると思います.

https://yapcjapan.org/2019tokyo/timetable.html#/detail/15

内容は上記にも書いてあるとおりですが、僕自身Perlコミュニティーのおかげで一人前のプログラマーになれたという思いがあるので、そこに感謝を示すとともに、自分の行動を振り返り、行動して良かったことや、そこでの気付きをまとめたいと考えています。皆様の参考になる話になれば幸いです。

まだ、チケットの販売もしているようですので、まだの方は是非お買い求めください。

参考: 【YAPC::Tokyo】チケット購入必勝法

実行中のプロセスの終了を検知して通知をするpeepというのを作った

https://github.com/Songmu/peep

なにかコマンドを実行して、思ったより時間がかかりそうな場合、終了を通知して欲しくなること、あると思います。それをしてくれるのが peep です。言うなれば、 horenso の後付版です。

使い方はめちゃくちゃ簡単で、以下のようにpidと、その後に任意のコマンドを指定します。

% peep $pid -- /peth/to/notification-script

当該 $pid のプロセスが終了したら、指定したコマンドが動くという仕組みです。なんと、リモートプロセスの終了も検知できます。

インストール

go get

% go get github.com/Songmu/peep/cmd/peep
% go get github.com/Songmu/peep/cmd/peep-notify

Homebrew

% brew install Songmu/tap/peep

ghg

% ghg get Songmu/peep

GitHub releases

https://github.com/Songmu/peep/releases

使いかた

peep を簡単に使うために peep-notify というコマンドを用意しており、最初はそれを使うのが楽です。

% peep $pid -- peep-notify mac

サブコマンドに mac を指定すると、デスクトップ通知をしてくれます。perl -E 'say $$; sleep 20 などとして、出力されたpidを $pid 部分に入れて試してみると良いでしょう。

peep-notify は他には slackpushbullet に対応しています。slackを利用する場合、SLACK_WEBHOOK_URL、pushbulletの場合、PUSHBULLET_TOKEN という環境変数が必要です。Slack通知は以下のような表示になります。

リモートプロセスをpeepする

これも簡単で、以下のように、 -H オプションにsshターゲットを指定するだけです。

% peep -H user@hostname $pid -- /path/to/notify

カスタム通知コマンドを作る

通知コマンドは簡単に自作できます。単なるコマンドなので好きに書いて構いませんが、監視していたコマンドの実行結果を取得したい場合には、horensoのreporter同様に、通知コマンドの標準入力に監視していたコマンドの実行結果がJSON形式で書き込まれるため、そこから取得すると良いでしょう。JSONは以下のようなフォーマットです。

{
  "user": "Songmu",
  "command": "perl -E say $$; sleep 10",
  "startAt": "2018-12-31T17:29:56+09:00",
  "endAt": "2018-12-31T17:30:07+09:00",
  "host": "localhost",
  "pid":20028
}

と言う感じで簡単に使えて便利なのでぜひご利用ください。

仕組み

内部実装は、なんのことはなく、非常に素朴で、 ps コマンドを毎秒実行しているだけです。リモートの場合は5秒おきです。

できたきっかけ

年末年始でデータの整理をしていて、自宅のmacから仕事用のmacに音楽データをrsyncしたら思ってたより時間がかかってしまったので、こういうのが欲しいなーと思って作ったのでした。

Homebrewのdaemontoolsでsvscanを自動起動できるようになりました

やった~、homebrew-coreのcontributorになったよー。

macでdaemontoolsを使ってる人もあまりいないだろうけど(僕は開発中のmackerel-agentとかその他適当なデーモンを飼うのに便利に使ってます)、pull request送って、以下で自動起動いけるようになりました。

% brew install daemontools
% sudo mkdir /service
% sudo brew services start daemontools

これでmacでも簡単にデーモンを飼うことができるようになりました。便利なのでご利用ください。plist使えって話はあると思うんだけど、plist作るのめんどいので…。

macでdaemontoolsを自動起動させるにあたって、これまでは自前でplistこさえて配置してたんだけど、最近マシンのセットアップしてるときにめんどかったので、pull request送った次第。

とか思ったら結構やり取りがいろいろあって40日くらいのやり取りとなりました。レビューワーも入れ代わり立ち代わりだった。他のissueは進んでたりするのに何度も放置されたので、めちゃくちゃしつこくメンションしまくった。詳しくはissue見てもらうとなかなかおもしろいと思います。

当たり前だけど、メンテナの人たちもあまりdaemontoolsわかってなくて

みたいなことを聞かれて説明のやりとりの往復をした。他にもHomebrewメンテナ同士のやり取りで、

MikeMcQuaid: We should consider patching the need for this directory. Arguably it's not fully ported to macOS if it requires it.
fxcoudert: We don't want to patch djb software. It really does not follow the Unix norms, so if we start it will be endless

「これdaemontoolsにパッチ送った方がいいんじゃないの?」
「djb wareにパッチを送るなんてとんでもない!」(意訳)

みたいなやり取りがあったのが面白かった。

という感じで、pull request放置されたらめげずにping送るのが吉です。

sh -cで呼び出したコマンドがbashだと孫プロセスにならないことがある

前提として、/bin/sh は、デフォルトでは、RHEL系の場合bashシェル、Debian系の場合dashシェルへのsymlinkになっています。この2つのシェルの挙動は細かいところで結構異なります。そもそもの思想として、dashシェルはPOSIX互換を目指す軽量なシェルであり、bashは拡張された高機能なシェル。なのでbash前提で書かれたシェルスクリプトがdashでは動かない、みたいなことはよくあります。そういう感じで困ることがままありますが今回もそういう話。

例えば % sh -c "sleep 100" のようなコマンドを実行した場合、呼び出し元の子プロセスが sh になり、その更に子プロセスが sleep になると直感的には思うでしょう。つまり以下のような具合。

.
 \_ sh -c sleep 100
     \_ sleep 100

しかし、 sh の実体が bash である場合なんとそうならず、sleep が直の子プロセスになります。

.
 \_ sleep 100

dashシェルでは期待通り、 sleep は呼び出し元の孫プロセスになります。

どうやら、bashは sh -c に渡された文字列が、単独コマンドとして実行できる場合は、exec してくれるような挙動となるようです。この場合 exec sleep 100 してくれる。実際bashのソースコードを見に行くと以下の記述が見られます。

Define ONESHOT if you want sh -c 'command' to avoid forking to execute 'command' whenever possible. This is a big efficiency improvement.

http://git.savannah.gnu.org/cgit/bash.git/tree/config-top.h?h=bash-4.4#n39

「可能な限りforkなしでコマンドを実行する」と書かれています。単独コマンドじゃない場合、例えば、 sh -c "sleep 10; sleep 5;" だと、当然ですがexecすることはありません。

これはなかなかbashは攻めた挙動で少しやりすぎなのではないかとも感じます。

この挙動が嬉しい場合

ただ、確かにこの挙動が嬉しい局面もあります。例えば、プログラムからシェル経由でコマンドを呼び出したときに、呼び出した子プロセスにシグナルを送ってそのコマンドを停止させようとしても、通常のdashの挙動だと、呼び出し元の子プロセスは sh -c になるため、孫プロセスのコマンドにまではシグナルが届きません。逆にbashの挙動だと、子プロセスが直接実行コマンドになるため、そのコマンドを停止させられます。

mackerel-agentの場合

実は、mackerel-agentがそれで困ったことがありました。mackerel-agentはプラグインの実行をコマンド呼び出しでおこなっていますが、その多くはシェル経由で実行されています。また、プラグインの実行時間が長くなった場合にシグナルを送ってタイムアウトさせる機構も持っています。

しかし、前述の通り、素朴に子プロセスにシグナルを送っても、プラグイン実行が孫プロセスになっている場合にはプラグインを直接停止させることができません。昔は素朴に、子プロセスにシグナルを送っていたため、bash環境ではタイムアウトが動くのに、dash環境ではタイムアウトが動かないという問題がありました。

現在は、プラグイン実行時にプロセスグループを作り、プロセスグループに対してシグナルを送ることでその問題を解決しています。具体的には、コマンドタイムアウト用のライブラリである、github.com/Songmu/timeout に以下の変更を加えたことでそれが可能になりました。

https://github.com/Songmu/timeout/pull/6

github.com/Songmu/timeout はだいぶ良いライブラリで、内部的にも面白いことをやっているので、そのうち解説記事を書くなり、Go Conferenceなどで登壇して説明したいと思っています。

mattn/memoでmemoのテンプレートが使えるようになったので便利

最近メモソリューションを見直していて、glidenote/memolist.vimmattn/memoを相互運用する、メモはDropboxに放り込んでおくのが良かろうという結論になった。

相互運用する上で少し困ったのが、glidenote/memolist.vimには、メモを作る際のテンプレート機能があるのだが、mattn/memoにはその機能が無かった。

なので、pull requestを送って 取り込んでもらった。

使い方としては、以下のように設定ファイルにテンプレートファイルを指定します。

memotemplate = "/path/to/template.txt" # default: '~/.config/memo/template.txt'

テンプレート自体は以下のようなGoのtext/template形式です。

---
title: {{.Title}}
date: {{.Date}}
---

{{.Title}}
===========

このようにすれば、 memo new でYAML Frontmatter付きのMarkdownを出力してくれます。

ちなみに、テンプレートファイルには、上記のtext/template形式の他にも、以下のような glidenote/memolist.vim の形式も直接利用が可能(!)です。

title: {{_title_}}
==========
date: {{_date_}}
tags: [{{_tags_}}]
categories: [{{_categories_}}]
----------

これは、相互運用上は便利なのですが、やりすぎ感があるなーとか思ったのですが、これもmattnさんにシュッと取り込んでもらえたので助かりました。

ぜひご利用ください。