黄昏の迷宮

知的好奇心を刺激する冒険

思い立ったら

このブログの記事を書くにあたり、どうせならVS Codeで書こうと思ってはてなブログAtomPubを使ってみることにしました。

下書きディレクトリに作ったマークダウンファイルに記事を書いて、書き終わったらAPIで投稿するイメージです。

以下のツールを使わせていただいております。 x-motemen/blogsync: Push and pull blog entries from/to local filesystem

環境ができればどんどん書いていけばいいのですが、下書きのファイルの名称をどうしようかという部分で引っ掛かってしまいました。 そんなものは下書きなんだから「1.md」とかでいいじゃないかとも思うのですが、思い立ったら何かしないと気が済まない方なので自動で名前を生成して空のファイルを作成するスクリプトを作りました。

仕様は至って単純、実行時点のUNIX時間を62進数に変換してファイル名にして指定したディレクトリに作成するものです。マークダウンだったりテキストだったりするかもしれないので拡張子も指定するようにしました。

などと言っていますが、大枠はGeminiが作っています。

package main

import (
 "fmt"
 "os"
 "path/filepath"
 "strings"
 "time"
)

const base62Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

// int64をbase62文字列に変換する関数
func toBase62(num int64) string {
 if num == 0 {
  return string(base62Chars[0])
 }

 var result strings.Builder
 base := int64(len(base62Chars))

 for num > 0 {
  remainder := num % base
  result.WriteByte(base62Chars[remainder]) // 文字を追加
  num /= base
 }

 // 結果は逆順になっているため、元に戻す
 runes := []rune(result.String())
 for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
  runes[i], runes[j] = runes[j], runes[i]
 }
 return string(runes)
}

func main() {
 // 1. コマンドライン引数を確認
 if len(os.Args) != 3 {
  // os.Args[0] はプログラム名なので、引数は2つ必要
  fmt.Fprintf(os.Stderr, "使用法: %s [file extension] [dist directory]\n", filepath.Base(os.Args[0]))
  fmt.Fprintf(os.Stderr, "例: %s txt ./output\n", filepath.Base(os.Args[0]))
  os.Exit(1)
 }

 fileExt := os.Args[1]
 distDir := os.Args[2]

 // 拡張子の先頭にドットが付いている場合は削除 (例: ".txt" -> "txt")
 if strings.HasPrefix(fileExt, ".") {
  fileExt = fileExt[1:]
 }

 // 拡張子が空の場合はエラー
 if fileExt == "" {
  fmt.Fprintln(os.Stderr, "エラー: ファイル拡張子は空にできません。")
  os.Exit(1)
 }

 // 2. 現在のUNIX時間を取得
 unixTime := time.Now().Unix()

 // 3. UNIX時間をbase62に変換
 base62Name := toBase62(unixTime)

 // 4. ファイル名とパスを構築
 fileNameWithExt := fmt.Sprintf("%s.%s", base62Name, fileExt)
 fullPath := filepath.Join(distDir, fileNameWithExt)

 // 5. distディレクトリが存在しない場合は作成
 //    os.MkdirAll は親ディレクトリも必要に応じて作成し、ディレクトリが既に存在してもエラーにならない
 err := os.MkdirAll(distDir, 0755) // 0755: rwxr-xr-x
 if err != nil {
  fmt.Fprintf(os.Stderr, "エラー: ディレクトリ %s の作成に失敗しました: %v\n", distDir, err)
  os.Exit(1)
 }

 // 6. 空のファイルを作成
 file, err := os.Create(fullPath)
 if err != nil {
  fmt.Fprintf(os.Stderr, "エラー: ファイル %s の作成に失敗しました: %v\n", fullPath, err)
  os.Exit(1)
 }
 file.Close() // ファイルを作成するだけなので、すぐに閉じる

 fmt.Printf("ファイルが正常に作成されました: %s\n", fullPath)
}

このファイルをビルドしてEXE化した後、PATHの通った場所に移せば準備は完了です。 実行ファイル名を「base62file.exe」とすると以下のような感じで空のファイルを作ることができます。

base62file md ./drafts

まあ、正直無くても困らないものではありますが、思い立ったらとりあえず作ってみるのは正直楽しいものです。