(-> % read write unlearn)

My writings on this area are my own delusion

~/.config/git/ignore や ~/.gitignore_global にフォルダ名を書くときは foo/* も検討する

例えば .vscode 内の設定は個人的な設定も含めて独自に色々いじるので基本的に常に ignore しておきたいとする。 そういうとき次のようなファイルにグローバルな設定を書いておくことがよくある。

  • ~/.config/git/ignore
  • ~/.gitignore_global

(ちなみに、 git はデフォルトで ~/.config/git/ignore を認識するそう。なので、~/.config/git/ignore を積極的に使おう。参考: ~/.gitignore_global を指定するのをやめ、デフォルトの置き場に置こう

ここで上記 ignore ファイルに

.vscode/

のように書くと、個別のワークスペースリポジトリ内で、部分的にその設定を打ち消す(つまり ignore しないようにする)ということができなくなる。

.vscode/*

としておくと、個別のワークスペースリポジトリ内の .gitignore 内で

!/.vscode/foo.json

とすることで foo.json だけはコミットできるように設定を上書きできる。

正確には、設定が上書きできること自体は Global 設定か否かには関係ない。 ただ、グローバルな設定をサブフォルダや個別リポジトリで上書き不可なのは厄介な場合がけっこうある気がする。

参考

Clojure 開発に VSCode の Code Spell Checker を使う

VSCodeClojure 開発を行っている人向け

背景

VSCodeClojure 開発をしているなら Calva を使っていると思う。 Calva は clojure-lsp も使っており、 clojure-lsp には clj-kondo が入っている。 cljstyle も同様なので、デフォルトで clj-kondo の Lint と cljstyle による Format の恩恵を受けている。

しかし、静的な型付けがない Clojure ではちょっとしたスペルミスや Typo によるエラーでそれに気づかず時間を使ってしまうということがある(自分だけだったらごめんなさい)。 もちろん、静的な型付けのある言語でも Typo ではまることはあるので Clojure や動的型付けの言語に限った話ではまったくない。 Spec や Schema を使えばいいというのもそのとおりで、それで解決する部分もある。 ただ、すべてにしっかり Spec 書いてるかというとそんなことないはず。(自分だけだったらごめんなさい)

というわけでスペルチェックを入れた。

インストール

まずは エクステンションを VSCode にインストール。

設定

1.Clojure に対する有効化とグローバルなユーザ辞書ファイル

settings.json

{
// ...省略...

  // Clojure にも有効にする
  "cSpell.enableFiletypes": [
    "clojure"
  ],
  // .clj だけでなく Clojurescript などのファイルも対象にする。 .clj と同じ扱いになる。
  "cSpell.overrides": [
    {
      "filename": "**/{*.cljs,*.cljc,*.edn}",
      "languageId": "clj"
    }
  ],
  // 「Spell: Add Words to User Settings」コマンドで辞書に単語を追加するとここに追加されていく
  "cSpell.userWords": [
  ],
  // この settings.json 内に単語直接追加していくと邪魔なので、辞書を独立したファイルに分離する設定。パスやファイル名は好きにどうぞ。
  "cSpell.customUserDictionaries": [
    {
      "name": "Custom",
      "description": "My custom user dictionary",
      "path": "~/.config/cSpell/cSpellCustomUserDictionary.txt",
      "addWords": true
    }
  ]
}

defn や defmethod など、普通にビルトインのマクロや関数も怒られるのでがんがん辞書追加する必要がある。 辞書への追加はコマンドパレットから

Spell: Add Words to User Settings

でできるが、その場合 settings.jsoncSpell.userWords にインラインで直接どんどん追加されていくので量が増えると邪魔。 なので cSpell.customUserDictionaries 設定を作って、

Spell: Add Words to User Dictionally

を使って単語の追加を行っていくことをおすすめします。

ここまでは、全ワークスペースに対して有効になるユーザ辞書の設定。

2.ワークスペース・オンリーの辞書ファイル

ワークスペース直下にワークスペース限定の設定を .vscode/settings.json として置くことができる。

.vscode/settings.json

{
  "cSpell.enableFiletypes": [
    "clojure"
  ],
  "cSpell.overrides": [
    {
      "filename": "**/{*.cljs,*.cljc,*.edn}",
      "languageId": "clj"
    }
  ],
  // Spell: Add Words to Workspace Settings」コマンドを使うとここに登録されていく。
  "cSpell.words": [
    "reitit" // <- 例
  ]
}

こんな感じにして、gitignore しないようにしておけば、チームで設定を共有することもできる。 さっきと同様にこの辞書を独立したファイルに分離することも設定可能。

defn とかビルトインの関数やマクロはグローバルなユーザ辞書でいいけど、ライブラリの名前やその関数やマクロはワークスペースの辞書に入れて分けるというやり方も考えられる。 そうしておくと、リポジトリを初めてチェックアウトしてきたときに辞書内の単語一覧を見ればどういったライブラリや関数が使わているのか一気に分かって面白い( shadow-cljs.edn や project.clj を見ればだいたい同じだろ、というのはある)。 そこにはプロジェクトのユビキタス言語から Derive した特殊な英単語や変数名などが入ってくることもあり、そのプロジェクトの特徴をある側面から抽出した情報に見えて楽しい。

辞書の単語で1つづつループしてワークスペース内のソースコードすべてを grep し登場回数を数えて集計すると、さらに面白いよ。

また、辞書ファイルを git blame すると、このライブラリ(あるいは関数)を初めにこのリポジトリに導入したのは 〜〜 さんか、とかこの人はどんどん新しいものを取り入れているな、という傾向が分かってやっぱりなんだか楽しい。

Netlify CMS のマークダウンエディタの日本語入力がバグってるので雑に対応する

先に結論まとめ

public/admin/index.html

    <script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
    <!-- 以下を追加 -->
    <script>
      const schema = { properties: { sanitize_preview: { type: 'boolean' } } }
      CMS.registerWidget('md', CMS.getWidget("text").control, CMS.getWidget("markdown").preview, schema);
    </script>

Netlify とは

静的サイトホスティングSaaS/PaaS 。サービス名であり会社名。 Vercel や Firebase (Firebase Hosting) などと近い。

Netlify CMSとは

Netlify 社がメインでメンテする OSS の Headless CMS 。 Headless CMS のなかでも Git Based というタイプで、その他の大多数の API Based の Headless CMS と違い Database (RDB) を必要としないのが特徴。だけど、機能は豊富で拡張性も高い。

markdown Widget とは

Netlify CMS の執筆編集画面の各フォームは Widget というコンポーネントになっており、日付入力フォーム、ファイルアップロードフォーム、など多数の Widget がビルトインで存在する。マークダウンの WISWIG やプレビュー機能を持つ Widgetmarkdown Widget

markdown` Widget の日本語入力のバグとは

以下の Issues はたぶん全部同じ事象。各 Issue に動画や Gif が貼られているので見ると挙動はよく分かる。

原因

markdown Widget が内部で使っている Slate Editor の問題、あるいはSlate Editor との連携の問題のよう。

根本解決

使っている Slate Editor を最新に置き換える。そういった議論も存在する。

ただし、Issue 内では次のようにコメントされているので、中の人が積極的に修正に動く気配は今のところなさそう。

Hi @acomagu updating to the latest version of slate is not a simple task. See https://docs.slatejs.org/concepts/xx-migrating. We're open to a contribution for the upgrade if anyone if up to the challenge

妥協

妥協案1

markdown Widget ではなく text Widget を使う。この場合、単なる textarea タグが使われるので、

  1. マークダウンを書くためのサポートや WISWIG 機能がなくなる。
  2. マークダウンをレンダリングしたプレビューがされない。

妥協案2

markdown Widgetプレビュー機能text Widget のインプットフォーム機能を組み合わせた Custom Widget を使う。この場合、妥協案1の1つ目の課題は解決しないが、2つ目の課題は解決する。

  • [ ] マークダウンを書くためのサポートや WISWIG 機能がなくなる。
  • [x] マークダウンをレンダリングしたプレビューがされない。

方法

public/admin/index.html

    <script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
    <!-- この直下に custom widget を登録する処理を3行で追加 -->
    <script>
      CMS.registerWidget('md', CMS.getWidget("text").control, CMS.getWidget("markdown").preview, {});
    </script>

説明

widget をカスタムで自前開発する場合、パーツとしては入力欄機能とプレビュー機能をそれぞれ HTML (というか React Component) として作成する。そのため、入力機能は text widget から、プレビュー機能markdown widget から、それぞれ拝借するということが簡単にできる。できた。上記のコードでは md という名前で Widget を登録しているので config.yaml では以下のように参照し使用する。

    - { label: 本文), name: body, widget: md }

補足

markdown Widgetsanitize_preview オプションを解釈させたいなら次のように。

    <script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
    <script>
      const schema = { properties: { sanitize_preview: { type: 'boolean' } } }
      CMS.registerWidget('md', CMS.getWidget("text").control, CMS.getWidget("markdown").preview, schema);
    </script>

各ビルトイン Widget の実装

ここにある。モノリポ構成。

自前で作るなら上記のコードを参考にしつつドキュメンを参照。

感想

1年前はこんなバグなかった気がする。残念。時間ができたら Slate Editor をキャッチアップしたい。