日付入力して書式を選べるVSCode機能拡張をつくりました

この記事は「[Visual Studio Code Advent Calendar 2023](https://qiita.com/advent-calendar/2023/vscode)」に参加している記事です。

https://qiita.com/advent-calendar/2023/vscode

## はじめに
VSCodeの機能拡張作ったけど、ダウンロード数が全然いかないから、アドベントカレンダーで他の人に知らせなさい、という指令をいただいた気がしたので書かせていただきます。

こちらの機能拡張です。

Smart Insert Date - Visual Studio Marketplace

https://marketplace.visualstudio.com/items?itemName=SatoshiYamamoto.vscode-smart-insert-date

## 機能の説明

日付と時刻をテキストに追加することができます。

キーボードのショートカットキーで `	Ctrl + Alt + ; `を押すと
```
2023-12-15 Fri
```
このような文字が追加されて、この文字が選択されているので、そのまま、同じショートカットキーを押すと、
```
Fri, Dec 15, 2023
```
に変化しますので、ショートカットキー1つで、複数の日付時刻のフォーマットを切り替えることができます。

これで、1回ショートカットキーで機能拡張を呼び出したら、デフォルトの日付フォーマット。2回、3回と、ショートカットキー押すと別の日付フォーマットが出力されます。

選択を切り替えると、回数がリセットされる、という感じになります。

また、
`Smart Insert Date | Select Format`
のコマンドを選ぶと、フォーマットをプルダウンから選べます。

また、
`Smart Insert Date | Select Date`
このコマンドを選ぶと、日付を、週や月や年の単位でどこか選び、その日に対して、書式付きの日付を出力することができます。

リンク先に画像載せてるので雰囲気的にわかると思います。

## 機能が至らなかったところ

至らなかったので、将来作りたい、って思ってます。

1:
日本の曜日には対応しているのですが、日本の元号に対応するの忘れてました。いずれやりたいです。

2:
また、チャイニーズにも対応したいので、曜日設定を外部にもたせて、曜日定義を変えたら中国語/台湾語とかにも対応したいです。

国際交流感を感じたいと思っています。

参考
  星期天・星期日・禮拜天・禮拜日のなぜを解説【中国語の曜日】 | （株）台湾トーク日本中国語センターオフィシャルサイト
  https://taiwan-talk.co.jp/xingqitian-xingqiri/

3:
選択文字列が
YYYY-MM-DD ddd
とか書かれていたら、それに対応して現在時刻の値とかで出力したいところです。

4:
[3:]を発展させて、
YYYY-MM-DD+1 ddd
とか書かれてあれば、翌日の日付をフォーマット付きで出力したいです。

```
YYYY-MM
  DD ddd
  DD+1 ddd
  DD+2 ddd
```

こんなテキストを選択して実行したら、今日、明日、明後日、の日付が挿入されると、いいのではないかなと思ったりするのです。

実行すると、こんな感じのテキストに変換されるってことです。

```
2023-12
  20 Wed
  21 Thu
  22 Fri
```

5:
過去日付の文字列をフォーマット変えれたらいいかも。
2020/11/03
を、選択して実行したら、
03 Nov 2020 x曜日
みたいなのに変更できたら、ちょっといいかなと。

---

1,2,3は、難易度はたぶん高くないのですが、4は結構いろいろ考えることがあり、だいたい実装イメージできてきているのですが、実際作ってみないとできるかどうかわからずです。

5は、結構面倒かなあと思ったりしています。
読み取れたりしても、動作が、今も高速ではないのですが、読み取りフォーマットをいろいろやると、動作が遅いかもしれないかなと思ったりします。

3,4は、自分が使いたいので実装したい気持ちあるのですが、1はさほどでもなく、2も別にいらなくて、

5は、あったらいいかも、程度の思いつきだけですが、過去日付に対して、曜日を記入したいとか、そういう機能なんて誰も、自分ですら、求めていないのではないかと、そんな迷いもあります。

そもそも、実装できるかな...

そんな思いで日々過ごしています。

## コードのちょっとした説明

コードの中から、ちょっとこうやったらうまくいった、ということを書いておきます。

関数化していて、再利用バッチリ、読みやすさバッチリのコードになっている気がしているので、何か参考になる方は参考にしてください。

https://github.com/standard-software/vscode-smart-insert-date/blob/main/src/extension.js


insertText とか registerCommand とか getEditor とか commandQuickPick など、コードを読みやすくする工夫しています。日付系とか他ライブラリ系はそれなりにまとまっています。

肝というか、今回の機能拡張のコツの部分は、出力した文字列を選択し、次に機能拡張したときに、出力した文字と同じものが選択されていたら、別の文字列を出力する、というところ

```js
const insertBuffer = {
  text: ``,
  formatIndex: -1,
  dateType: ``,
  date: new Date(),
}
```

ここで、出力した文字列を保持し、その時に選択していたフォーマットのIndexとタイプ(日付か時刻か日時か)と
その時の時刻をバッファに保持しています。

それを次のコードで、判定していて
選択テキストが、前回出力内容と同じだったら、次のフォーマットを選んで出力してね

と書いています。

```js
  const insertDateTime = (dateType) => {
    if (!([`Date`, `DateTime`, `Time`].includes(dateType))) {
      throw new Error(`insertDateTimeCommand insertType`);
    }
    const editor = getEditor(); if (!editor) { return; }
    const dateFormatArray = getDateFormatArray(`${dateType}Format`);
    if (dateFormatArray.length === 0) { return; }

    const selectedText = getSelectedText(editor)[0] ?? ``;
    if (
      insertBuffer.dateType === dateType
      && insertBuffer.text === selectedText
    ) {
      insertBuffer.formatIndex += 1;
      if (dateFormatArray.length === insertBuffer.formatIndex) {
        insertBuffer.formatIndex = 0;
      }
    } else {
      insertBuffer.formatIndex = 0;
      insertBuffer.date = new Date();
    }

    _insertDateTime(
      dateType, insertBuffer.date, insertBuffer.formatIndex,
      dateFormatArray[insertBuffer.formatIndex]
    )
  }
```

function activate の外側に変数を持たせるだけで、前回機能拡張起動時の状態ってバッファできるんですね。いろいろ応用効きそう。

例えば、最近、よく紹介される、change-case の機能拡張とか、メニューでフォーマット選ぶタイプですが、これを、1ショートカットキーだけでどんどん切り替わるようにしておくと、ショートカットキーを複数設定しなくても、いろんな形式で文字列変換できるんじゃないかな、

そういう機能拡張つくるのもいいかもなあ、と、そんなことを思ったりしている日々を過ごしています。

## 終わりに

この機能拡張とか、別の機能拡張でもいいんですが、

「何かこういうのがあったら便利なのに、誰か作ってくれねーかな」と思ったら、要望ください。

ピンときたら作りますが、ピンとこなかったら作りません、😛

が、
ピンと来なくても、お金を十分にくれたら、遠慮なく作ります。😅

お金はないけど、要望がある人は、いろいろ学んで自分で機能拡張つくると楽しいですよ。