ねこみみすと工房 👋

某メーカーの組み込みソフト屋。昔はマイコンでモーター動かしたりしてたけど、最近はLinuxばかり。
最近の興味範囲は 自作PC・自作キーボード・3Dプリンタ(SnakeOilXY-3S/VORON V0.739/VORON VT.496/QIDI PLUS 4)と艦これ。

刷新前のコンテンツは Hello あたりを参照すれば辿れます。

Hello

現コンテンツ 上の search / archives / categories / tags あたりを参照のこと 古いコンテンツ 2017年あたりまでのWeb日記 古いえろ小説 連絡先 bluesky https://bsky.app/profile/nekomimist.org Fedibird https://fedibird.com/@nekomimist misskey.io https://misskey.io/@nekomimist X(Twitter) https://x.com/nekomimist github http://github.com/nekomimist

August 13, 2023 · 1 min · 24 words · nekomimist

2024年Emacsふりかえり

私自身のEmacsの使い方 AIの活用 今年はEmacsの設定やらなんやらにやたらとAIを活用するようになったという点で変革の年だった。 気軽に質問できて、まあまあ正しい回答が返ってくるのは実によい。 実装の案出しだったりリファクタだったりをだいぶGPT-4oやclaude-3.5-sonnetに助けてもらった。 EmacsのAI系パッケージも充実してきた。gptelは当初はopenaiのAPIを使えるだけのシンプルなパッケージだったのに、いろんなLLM backendに対応したり、gptel-rewriteが実装されたりして、リファクタやらなんやらやりやすくなった。elysiumもregionに対する指示をチャットバッファでできて、変更はsmergeで表示できたりできてよい。まだ使いこなせていないがevedelにも期待したい。 magit-gptcommitもまあまあ便利に使っている。前はgpt-commitだったけど、毎回生成したいわけじゃないし、明示的に呼べるmagit-gptcommitはそこそこ具合がよい。 その他使うようになったパッケージ(と、使うのを止めたパッケージ) perspective 去年からプロジェクト毎に作業環境を分けるためにtabを活用できないか?と思って、 しばらくtabspacesやらactivitesやら試行してきたけれど、結局tab-barの表示を消して、tabspacesやactivitiesを使うのを止めて、perspective.elで作業空間を明示的に分けるようにした。やはり昔からあって今もメンテされているパッケージは強いなと思った次第。 perspectiveの状態をファイルに保存するpersp-state-save/loadも使うけれど、起動時にpersp-state-loadをすると遅いので、最初にユーザー操作でpersp-switchしようとした時に読み込むようにした。あとpersp-state-loadしてないのにsaveされるとイマイチなので、loadしてた後だけemacs終了時にsaveするようにしている。 (defvar my/perspctive-state-already-loaded nil) (defvar my/persp-switch-commands '(persp-switch persp-switch-by-number)) (defun my/perspective-state-load (&rest _options) (when (memq this-command my/persp-switch-commands) (unless my/perspctive-state-already-loaded (setq my/perspctive-state-already-loaded t) (persp-state-load persp-state-default-file)))) (defun my/perspective-state-save-if-loaded (&rest _options) (when my/perspctive-state-already-loaded (persp-kill persp-initial-frame-name) ; depotは毎回きれいにして終わる (persp-state-save))) (dolist (cmd my/persp-switch-commands) (advice-add cmd :before #'my/perspective-state-load)) (add-hook 'persp-state-after-load-hook (lambda () (setq my/perspctive-state-already-loaded t))) (add-hook 'kill-emacs-hook #'my/perspective-state-save-if-loaded) treemacs tab-barの表示自体を止めるより前に、sidebarとしてtreemacsを常時表示するのを止めた。 プロジェクト内のファイルを開くならproject-find-fileを使うし、gitの状態はmagit-statusで確認するので、ファイルツリーなんか見ないのである。表示してると遅くなるし幅も食うし、見た目だけならないほうがよいやんということでデフォルトでは表示しないようにした。 tab-barも消してtreemacsも消した今、Emacsの表示はえらいすっきりとした。古くさい見た目かもしれないがそれでいい。俺は風になりたいんだ。 olivetti sidebar表示は止めたのだが、横が広すぎるのも好みじゃないので、今、Emacsの表示幅は130文字くらいにしている。 l横80文字程度だとソース編集するのにあからさまに狭く感じるからね……。 しかし、org-modeで文章を書くときなんかは130文字だと幅が広すぎて書きづらいで見辛い。そこでolivettiを使うようにした。幅をいい感じに制限してくれてよい。 empx カーソルがあった所に戻ったりまた進んだりするのに長いことdogearsを使っていた。 ただ、案外必要なタイミングで保存されてなかったりしたために、いろいろhookやadviceで仕込みを入れる必要があって面倒だったり、キーバインドが専用になるのがどうもすっきりしなかったので、Redditで見かけたempxにしてみた。 作者がredditで紹介している通り、「専用の*-back/*-forward関数じゃなくてemacsで標準で持っているxref-go-back/xref-go-forwardを使いたい!」という目的のパッケージで、xref-find-definitionで定義元に飛んだ後に戻る操作と同じで前カーソルがあった所にも戻れるので、覚える操作が減ってすっきりする。 xrefの履歴にカーソル履歴が入るのはどうかな?と思ったが今のところ特に問題は感じない。前述のperspective.elが、xrefの履歴をperspective毎に分けるようにしているので、意図せず他のperspectiveに移動したりしないのもわかりやすい。 avy / ace-window これは前ブログに書いた通り 、Avyならなんでもできるを読んだので使うようにした。ace-windowによるwindow移動は慣れたけど、avyは単純な用途以外にはあまり活用できてない。活用が来年の課題かな。 embark これは一応以前から設定はしていたが活用できていなかった。Embarkを使う15の方法を見て、少しは使えるようになったかもしれないが、より一層の活用は来年の課題かな。 Emacsの展望 emacs-30.1はそろそろ出る。わりと地味なリリースだが、native-compileがデフォルト有効になったり、tree-sitter関連の組み込みが進んだり、jsonが独自パーサに変わって高速化したり、いろいろ着実な進歩はあるはずだ。 ...

December 29, 2024 · 1 min · 99 words · nekomimist

Emacsのgrepバッファの行末が省略されて困った話

EmacsでM-x grepでgrepした結果をwgrepで編集したりする事がたまにある。 で、ふとgrepで出た行が長いとき、終端が[…]のように省略されていることに気付いた。昔はこんなんじゃなかったはずだが、いつからこうなっていたのだろう? カーソルを […] に持っていってEnterとかすると開くが、grepバッファをwgrepで編集したりする時など、省略されていては嬉しくない局面もあるわけで、オフする方法を探してみた。 ChatGPTもClaude 3.5 Sonnetもロクな回答は返さなかったので、素直にgrep.elからcompile.elを辿って変数 compilation-max-output-line-length を見付けた。 で事後的に確認するととNEWS.29に変数の記載があった。とはいえgrepとは書いてないので案外気付きづらい。 Emacs 29から入った機能ならば歴史が浅くてAIも知識として持っていなかったのだろう。 というわけで、未来のAIのため、そして自分の備忘録として「grepの結果の行末端が[…]のように省略されるのを止めさせるには、 compilation-max-output-line-length を nil にすればよい」とここに記しておく。

December 1, 2024 · 1 min · 19 words · nekomimist

Emacsのpgtkビルド版でのcopy&paste

WSL上でEmacs使ってるんで、pure Waylandのほうが性能よいのかなあ?と思ってnixでemacs30-pgtkを入れて動かしてみている。まあ、そこそこX用と遜色ないくらいに動く。たまに落ちるけど。 問題点としてすぐに気付くのはWindows側との相互のコピペができないこと。 で、これはEmacsWikiのCopyAndPasteに対応策が書いてある。 ;; credit: yorickvP on Github (setq wl-copy-process nil) (defun wl-copy (text) (setq wl-copy-process (make-process :name "wl-copy" :buffer nil :command '("wl-copy" "-f" "-n") :connection-type 'pipe :noquery t)) (process-send-string wl-copy-process text) (process-send-eof wl-copy-process)) (defun wl-paste () (if (and wl-copy-process (process-live-p wl-copy-process)) nil ; should return nil if we're the current paste owner (shell-command-to-string "wl-paste -n | tr -d \r"))) (setq interprogram-cut-function 'wl-copy) (setq interprogram-paste-function 'wl-paste) これでコピペができるようになって助かった……という話だけならわざわざこんなarticleは書かない。 これだとTRAMPでssh先のファイルを編集している時はうまく動かないのである。 shell-commandはfile-name-handler-alistをチェックして現在対象のバッファのそこにヒットするなら、そこにあるhandler経由でshell-commandを実行する。grepとかはfindとかはリモートで実行しないとダメだから。 それはわかる、わかるが、でもwl-pasteがremoteが実行されても何も得られないのである。 問題に気付いてしまえば対策は簡単で↓とでもすればよい。 (let ((default-directory (getenv "TEMP"))) (shell-command-to-string "wl-paste -n | tr -d \r"))

November 28, 2024 · 1 min · 83 words · nekomimist

Emacsとフォント設定の話

注意 必要があって自分で調べた事を書き散らしたのみで、あまり真剣に裏は取っていない。 Emacsとフォント設定 昔々のEmacsは、フォント設定をフォントをXFLDで書かないといけなかったりして面倒だったが、最近のEmacsはわりと楽にフォント設定ができる。 Emacsが受けつけるフォント名のパターンは下記の3つがある。 fontconfig pattern FONTNAME[-FONTSIZE][:NAME1=VALUES1][:NAME2=VALUES2]… Monospace Monospace-12 Monospace-12:bold DejaVu Sans Mono:bold:italic Monospace-12:weight=bold:slant=italic Infoによれば、WindowsだとFONTNAME[-FONTSIZE]しか食わないと書いてあるが、とりあえずboldとitalicは食ってくれるようだ。 GTK font pattern FONTNAME [PROPERTIES] [FONTSIZE] Monospace 12 Monospace Bold Italic 12 InfoによればやはりWindowsはフル記述を受けつけないと書いてあるが、これもBoldとItalicは食ってくれるようだ。 XFLD pattern 古くからのX Windows System使いならば馴染み(?)のあるXLFDも受けつける。まあ現代においては手で書くものじゃない気もする……。 -MAKER-FAMILY-WEIGHT-SLANT-WIDTHTYPE-STYLE... ...-PIXELS-HEIGHT-HORIZ-VERT-SPACING-WIDTH-REGISTRY-ENCODING EmacsのInfoにはWindowsでは未対応と書いてあるが、少なくともEmacs-29以降ではこのフォント指定方法も食ってくれない事はないような挙動をしている。 fontとfontset ところでEmacsは文字コード毎に別のフォントを与えることができるので、実際にEmacsが内部で取り扱うの は文字毎のフォント設定を持つfontsetである。 フォントを指定するところで、前述のフォント指定パターンでフォント名を指定した時、 実際にそれが表示に使われるタイミングで内部的にfontsetが自動的に生成される。 例を挙げる。例えば、 (set-frame-font "UDEV Gothic JPDOC 13") とした後に、M-x list-fontsetを実行すると、こんなのがfontset一覧に現れる。 Fontset: -TWR-UDEV Gothic JPDOC-regular-normal-normal-*-18-*-*-*-d-0-fontset-auto1 この末端の"fontset-auto1"が自動生成されたfontsetの名前である。 このfontset名はフォント名と同じように使える。 (set-frame-font "fontset-auto1") 自動生成だと名前を好きにつけられないので、fontsetを指定して後からいろいろ設定したいならば、 自分で明示的にfontsetを生成したくなるだろう。 create-fontset-from-ascii-fontの沼 明示的なfontsetの作り方でよく見るのはcreate-fontset-from-ascii-fontを使う方法だ。 create-fontset-from-ascii-fontにASCII範囲を含むフォント名を与えると、そこからfontsetが作ってくれる。 ...

November 27, 2024 · 1 min · 168 words · nekomimist

xeftの表示をカスタマイズする

メモの取り方の話 思考のメモなどを取る時、昔々はhowmで書いていて、ある時からorgで書くようになって、最近はdenoteをorgフォーマットで使っている。いずれの形式でも1メモ1ファイルになるので、メモが大量になると管理が大変になる。 howmは自前の検索機構でよいが、orgにした時はdeftを使っていた。deftの仕様はたいへんよいのだが、ピュアEmacs Lispなので、ファイル数が増えるとむちゃくちゃgcが走ってとても反応が悪くなる。 で、xeft で、2023年の1月から検索にxeftを使っている。これはバックエンドにXapianを使っていて、高速な検索がウリである。正規表現が使えないためmigemoが使えないという欠点はあるが、migemoがないと日本語の検索ができないdeftと違って、日本語を直接入力できるのでそこまで困らない。 ……のだが、xeftは一覧表示がそっけない上に、あまりカスタマイズの余地もなく、そこにちょっと不満がある。deftに慣れていたので、ファイルの最終更新日付も一緒に出したいのだ。 で、確認すると、タイトルを抜き出すための関数は登録できるようになっていたので、下記のようなファイル名の前に日付をつけるような関数を作ってxeft-title-functionに設定してみた。 ;; 一覧にファイルの最終更新日時を入れる (defun my/xeft-title-and-date (file) "Return the title of FILE with its last modification date." (let ((last-mod-date (format-time-string "%Y-%m-%d " (nth 5 (file-attributes file))))) (re-search-forward (rx "#+TITLE:" (* whitespace)) nil t) (let ((bol (point)) title) (end-of-line) (setq title (buffer-substring-no-properties bol (point))) (if (eq title "") (concat last-mod-date (file-name-base file)) (concat last-mod-date title))))) (setopt xeft-title-function #'my/xeft-title-and-date) これでファイル名の前に日付が出るようになった。 あと、検索画面でexcerptが出るのはいいが、2.7行分も出る上にそこにdenoteのfront matterやらorgのoptionsやらが含まれてしまって邪魔臭い1。行数を減らしてかつ不要な情報は出さないようにしたいなと思って、元のxeft–file-excerptをちょっと書きかえて、advice-addでoverrideしてみた。 (defun my/xeft--file-excerpt (file search-phrase) "Return an excerpt for FILE. Return (TITLE EXCERPT FILE). FILE should be an absolute path. SEARCH-PHRASE is the search phrase the user typed." (let ((excerpt-len (floor (* 0.7 (1- (window-width))))) (last-search-term (car (last (split-string search-phrase)))) title excerpt) (with-current-buffer (xeft--work-buffer) (widen) (erase-buffer) (setq buffer-undo-list t) (insert-file-contents file nil nil nil t) (goto-char (point-min)) (setq title (funcall xeft-title-function file)) (narrow-to-region (point) (point-max)) ;; denoteのfront matterとorgのoptions/startupの最後の行の ;; 次の行からexcerptに入るようにする (when (string-equal (file-name-extension file) "org") (let ((case-fold-search t) (options "\\(OPTIONS\\|STARTUP\\|DATE\\|IDENTIFIER\\|FILETAGS\\)")) (goto-char (point-max)) (when (re-search-backward (concat "^#\\+" options ":.*$") nil t) (forward-line) (narrow-to-region (point) (point-max))))) ;; Grab excerpt (setq excerpt (string-trim (replace-regexp-in-string "[[:space:]]+" " " (if (and last-search-term (search-forward last-search-term nil t)) (buffer-substring-no-properties (max (- (point) (/ excerpt-len 2)) (point-min)) (min (+ (point) (/ excerpt-len 2)) (point-max))) (buffer-substring-no-properties (point) (min (+ (point) excerpt-len) (point-max))))))) ;; Return result (list title excerpt file)))) (advice-add 'xeft--file-excerpt :override #'my/xeft--file-excerpt) 適当なわりに自分の用途ではそれらしくは動いているので、まあよし。 ...

October 21, 2024 · 1 min · 213 words · nekomimist

avyでmigemoろう

avyでmigemoりたいのに…… Qiitaのavyならなんでもできるを読んで、「そういえばavyって真剣に試してみたことないなあ」と思い、 書いてある通りにやってみたらわりとよい感じだった。 だが、日本語が多い局面だとavyで飛べない事が多い。こういう時はmigemoが使いたくなる。で、調べてみると avy-migemoがあるのだが、どうもissueなど見ていると最近はメンテされてない様子。 別にそんな凝ったことをしたいわけじゃないんだよ、ということで再度調べると avy で migemo る (avy-migemo を使わずに)が見つかる。これこそ欲しかったものだ。そのままいただこう。 ……しかしavy-goto-migemo-timerを実行して何か1文字入力するとout of range(だったと思う)が出てうまく動かなかった。 原因 migemo-get-patternが、入力長さがmigemo-isearch-min-length未満の時に""を返すのが原因である。私の設定だとmigemo-isearch-min-lengthが2なので、1文字入れると""を食らってavy–read-candidatesがエラーを返すのである。 じゃあこの時だけ1にしてあげようと、avy-goto-migemo-timerの中のletでmigemo-isearch-min-lengthを1にしてみると、だいたい問題ないのだが、ふとcを入力すると"too long ほげほげ"1とか言われしまって幸せになれなかった。2 そもそも、本来のmigemoの動作だってmigemo-isearch-min-lengthが未満の時は、引数をそのまま返したほうが幸せになるんじゃないの?とふとと思ったので、下記のようなadviceを入れて対策とした。 (defun my/migemo-get-pattern-advice (func word) (let ((ret (funcall func word))) (if (string-equal ret "") word ret))) (advice-add 'migemo-get-pattern :around #'my/migemo-get-pattern-advice) migemo-isearchとavy-goto-migemo-char以外の用途で何か副作用があるかもしれないが、まあ、そう悪い挙動にはならない気もする。 1 何が出たのかメモってなかった。 2 そもそも1文字の時にmigemoが動いてもいらんものがひっかかってあまり嬉しくなかったからmigemo-isearch-min-lengthを1にしているわけで、まあ当然といえば当然である。

October 14, 2024 · 1 min · 45 words · nekomimist

Emacsの起動高速化の話

はじめに Emacsの起動高速化については、とても定評がある記事がある。 Emacsの起動時間を""詰める"" Emacsを世界最速級で起動する方法 これを参考にすれば誰でも起動速度を"詰める"ことはできるはずで、あまり俺ごときが追加で書くような 話はないのだが、自分なりのメモを残しておこうと思う。 leaf.elとpackage.elでの起動高速化を目指す 本件はleafでパッケージ設定を書き、パッケージ管理をpackage.elにまかせつつ高速化する話で、 実のところ最速を狙う手法ではない。まあ最速じゃなくてきっと意味はあるよね……ということで。 遅延初期化 通常Emacsでの遅延初期化は、他の.elを読んだら評価する(with-eval-after-load)や、 書かれた関数・変数が使われたら呼ぶ(autoload)に頼ることになるのだが、 package.elを使いつつemacs-init-timeを100ms未満にしようとするなら、もう一歩踏み込む必要がある。 遅延実行 まず、Emacsを起動した後、あまり使わないパッケージの初期化が全部終わってなくてもエディットは 始めていいはずだ。よって、よくある例と同様にEmacs起動後に遅延評価させるようにする。 ;; after-init-hookで順次登録された関数を実行する (defvar my/delayed-configs nil) (defvar my/delayed-config-timer nil) (defvar my/delayed-config-done nil) (eval-and-compile (defconst my/prio-low 1) (defconst my/prio-normal 10) (defconst my/prio-urgent 100)) (defun my/add-to-delayed-configs (priority config) "Add CONFIG with PRIORITY to delayed configs." (if my/delayed-config-done (condition-case err (eval config) (error (message "my/delayed-config exection error: %s" err))) (push (cons priority config) my/delayed-configs) ;; sort the configs by priority (setq my/delayed-configs (sort my/delayed-configs (lambda (a b) (> (car a) (car b))))))) (defun my/execute-config (config) "Execute a single delayed CONFIG safely." (let ((inhibit-message t)) (condition-case err (eval config) (error (message "my/delayed-config execution error: %s" err))))) (defun my/execute-delayed-configs () "Execute delayed configs using timer for urgent priority and idle timer for others." (if my/delayed-configs (let* ((config-pair (pop my/delayed-configs)) (priority (car config-pair)) (config (cdr config-pair))) (if (>= priority my/prio-urgent) ;; For urgent priority, use run-with-timer (run-with-timer 0.1 nil (lambda () (my/execute-config config) (my/execute-delayed-configs))) ;; For normal and low priority, use run-with-idle-timer (run-with-idle-timer (if (>= priority my/prio-normal) 0.5 1.0) nil (lambda () (my/execute-config config) (my/execute-delayed-configs))))) (setq my/delayed-config-done t))) (add-hook 'after-init-hook 'my/execute-delayed-configs) (defmacro with-delayed-startup-exec (priority &rest body) "Execute BODY after init with delay, according to PRIORITY." (declare (indent 1)) `(my/add-to-delayed-configs ,priority ',(cons 'progn body))) priorityをつけたので先例より実装がちょっとだけ大きくなったが、見ての通り大した事はしてない。 ...

October 11, 2024 · 2 min · 406 words · nekomimist

2023年の振り返り(その他編)

自作キーボード これが2022年末ということは、ほぼ1年進捗なしということになる。 ネジ用のスペースのなさがつらかったが、まあなんとか完成。ちょっと使ってみてキー配置に問題なさそうなら基板を作ろうかな pic.twitter.com/dbhMtvyk9j — いずみたすく (@nekomimist) December 10, 2022 2023/1に当時最新のqmkに合わせて自分のキーボードのソースを書きかえたりしたけれど、それも1年前なので、また追随しなければいけないが、qmk側の都合による変更であって、自分のキーボードの機能が不足しているわけではないので、どうもやる気が出ない。 2024年は2つくらいキーボードのネタがある。 nekonos1の改版 上のpostはSU120で作ったものだが、同じレイアウトで自分に設計した基板に変えたい。Adafruit KB2040が2つ手元にあるのでこれを使う。まあ、あまりピン配置はPro Microと変わらんので、Pro Microでも作れるようにはする。 3Dプリンタケースと合わせて設計したいので、やる事が多くてやる元気がでるかどうかは不明。 nekonote1 昔te96で作った nekonote0の改版。18x16ピッチを18x17ピッチに変える。BLE Micro Proで作るくらいな感じで。 薄さと丈夫さを兼ねそろえたいと思うとケースは悩ましいが、基板サンドイッチ構造でいいのかも。 3Dプリンタ KP3S 1.0をSnakeOilXY-3Sに改造した。 これが、 VORON 0.1を作ってからほぼ使ってない、わりと素に近いKP3S 1.0。のんびりSnakeOilXY-3Sにしていく予定 pic.twitter.com/A8RBoa29Dc — いずみたすく (@nekomimist) January 28, 2023 こうなった。 SnakeOilXY-3S、もうちょい調整はいるけど動くようにはなったな pic.twitter.com/SLrjZQ0fVJ — いずみたすく (@nekomimist) September 9, 2023 カッコいいし、安定度も高く満足度は高い。 VORON 0.1 VORON 0.1はSherpa Miniの部品破損トラブルがあったのを直したのみ。 構成がシンプルなのでExtruderまわりの断線とパーツ破断以外はほぼトラブらないよい子。 さらに調べると今までももよく割れてたShelpa miniのIdler armの根本がまた割れてた。なんとかしたいなこれ…… — いずみたすく (@nekomimist) September 20, 2023 VORON Trident 2022年末にCAN toolheadてそこに由来するトラブルは1年間特に発生しなかった。 ...

January 4, 2024 · 1 min · 96 words · nekomimist

2023年の振り返り(Emacs編)

起動速度のこと init.elの初期化処理で時間がかかる事は起動後にやるようにした。 参考文書は定番とも言える下記2点。 Emacs の起動時間を""詰める"" Emacsを世界最速級で起動する方法 (defvar my/delayed-configs nil) (defvar my/delayed-config-timer nil) (eval-and-compile (defconst my/prio-low 1) (defconst my/prio-normal 10) (defconst my/prio-urgent 100)) (defun my/add-to-delayed-configs (priority config) "Add CONFIG with PRIORITY to delayed configs." (push (cons priority config) my/delayed-configs) ;; sort the configs by priority (setq my/delayed-configs (sort my/delayed-configs (lambda (a b) (> (car a) (car b)))))) (defun my/start-delayed-configs () "Execute `my/delayed-configs` list using a timer. Start a timer to run each config in the list with a default interval of 10ms. The timer runs until all configs are executed, then it stops. Customize interval with `my/delayed-config-interval`. Delayed configs can impact your Emacs environment." (setq my/delayed-config-timer (run-with-timer 0.0 0.01 ; start after 0ms with 10ms interval (lambda () (let ((inhibit-message t)) ;; if there is a config, execute it (if-let (config (cdr (pop my/delayed-configs))) (eval config) ;; if there is no config, cancel the timer (cancel-timer my/delayed-config-timer))))))) (add-hook 'after-init-hook 'my/start-delayed-configs) こんなのを書いて、 ...

December 30, 2023 · 2 min · 385 words · nekomimist