今更ながら VS Code Auto Time Stamp について

昨日、溜まっていた Issue に対応して 0.0.5 をアップした。

GitHubVisual Studio Marketplace 以外に何も情報を上げないまま 5 年近く経ったが、今更ながら書いてみる。

これは何か

テキストファイルの内容に含まれる作成日時・更新日時を保存時に挿入/更新する、ごくシンプルな VS Code 拡張。

例:

// Created: 2018/02/04 12:24:41
// Last modified: 2018/02/09 11:41:41

更新日時はファイル保存時に毎回更新される。作成日時は空の場合のみ挿入する形とし、コピーされたファイルの作成日時が意図せず入らないようにしている。

想定している用途

ソースファイルのヘッダーコメントやドキュメントなどに記載した日時を作業に合わせて更新するような用途を想定している。

初版を作った2018年当時は仕様書を Markdown で書いていて、かつ私個人は Emacs から VS Code へ移行を試みているところだった。 Emacs では time-stamp で更新日時、autoinsert で作成日時を入れていて、それを VS Code でも再現しようとしてできたのが初版。

VS Code への移行はできたが仕様書は MS Word で書くようになり、自分で使うことはほぼなくなっていたりする。

使い方

デフォルトでは当時の私に合わせた設定になっているため、環境・プロジェクトに合わせて変更が必要。

設定項目:

設定項目名 デフォルト値
Birth Time End $
Birth Time Start [cC]reated *:
Filename Pattern ^(?!.*[/\\]\.vscode[/\\]settings.json$)
Line Limit 5
Modified Time End $
Modified Time Start [lL]ast[ -][mM]odified *:
Moment Format YYYY/MM/DD HH:mm:ss

私はユーザー設定でラフに使用したことしかないが、多くの言語・フォーマットで使用したい場合や複数人で共有したい場合はワークスペース設定がよいと思う。

README.md にも記載したように、よくある動かないケースは以下:

  • Line Limit が小さすぎる。
  • VS Code の Auto Save(自動保存)設定が afterDelay に設定されている。

デフォルトでは作成日時・更新日時ともに日時の後ろを文末$にしているが、適切にパターンを設定すれば文の途中を対象にすることもできる。

例:Issue #11より:

{{-- MODIFIED: [ 2022-04-20 02:51:45 PM ] --}}
{{-- some other comment --}}
{
    "lpubsppop01.autoTimeStamp.momentFormat": "YYYY/MM/DD HH:mm:ss A",
    "lpubsppop01.autoTimeStamp.modifiedTimeStart": "MODIFIED: \\[ ",
    "lpubsppop01.autoTimeStamp.modifiedTimeEnd": " \\]"
}

大抵のケースに対応できるだろうと思ってこういう仕様にしたが、 fork された方が TeX 向けの拡張をされていた。 何でもOKとはいかないようだ。

0.0.5の更新内容

以下の望ましくない挙動を修正した。

  • 自動保存が afterDelay のとき挙動がおかしい。正しい動きを決められなかったため、動作しないようにした。
  • ワークスペース設定(.vscode/settings.json)が対象となり内容を壊しやすい。デフォルトで対象外とした。

またアイコンを作成・設定した。

おわりに

先に書いた通り自分ではあまり使わなくなっているが、そのうちまた出番があるかもしれない。 よければお試しください。

お読みいただいた方、良いお年を。明けていたら、おめでとうございます。

外壁の補修塗装のために購入したもの

自宅は2階建の戸建で、風雨が強く当たる1面だけ外壁の劣化が速い。 少し延命して業者にお願いするタイミングを他の面と揃えられるといいなと思い、自分で塗装してみた。

9月末から始めて雨が降っていない休日に試行錯誤を繰り返し、3ヶ月弱で完了。 足りないものを買い足しながら進めたため、軌道に乗るまでが長かった。 振り返りつつ購入したものを挙げてみる。

掃除道具

高所壁面の洗浄をどうしようかあれこれ考えたが、最終的には塗装用のローラー軸をひとつ加工して洗車用スポンジを取り付け、延長柄で伸ばして擦るようにした。ローラー軸と延長柄は後で挙げる。

汚れを浮かせた後は普段使いの散水ホースで洗い流した。

剥げかけた塗膜もそれなりには落とせた。十分ではないと思うが妥協。

塗料(ペンキ)

アサヒペンの水性塗料とシーラーを使用。 補修目的のため、元の色にできるだけ近い色がほしかった。しかし塗って乾かしてみないと判断できず、近そうな色を少量ずつ購入して試した。 最終的にはサンドストーン、アイボリー、バーチブラウンを3:1:少々の割合で混ぜて使用した。

刷毛・ローラー

広いところはローラー、細かいところや試し塗りは刷毛を使用。初めは再利用できないか考えていたが、汚水の懸念があり使い捨てに落ち着いた。

延長柄を2種類と刷毛用のジョイントも購入。

塗料の取り出し・混色道具

缶から塗料を掬い出す用途でカンロ杓子を購入。モノタロウのレビューを見て決めた。

ChatGPTに「ペンキを塗料皿に移すとき、普通はどんな道具を使うのでしょうか?」と聞いたら「ペンキスクレーパーを使用することが一般的です。」とのこと。間違いだと思っているけど、何か職人技がある?

ローラーで塗るときはバケット+使い捨ての内容器、刷毛だけで塗るときは使い捨てのカップを使用した。 カップに付属していた混ぜ棒はバケットでも役に立った。

金属製のトレーも購入。塗料が事あるごとに垂れる&新聞紙は風でめくれ上がるため、これでだいぶ楽になった。

その他の購入物

幅広のマスキングテープを購入し、水切りを覆った。高所のエアコン配管には貼れなかったため、そちらはがんばって避けた。

凝固剤も1袋だけ購入しておき、最後に残った塗料の始末に使用した。

この他にビニール袋、ビニール手袋、古新聞、ウェットティッシュなどはストックを使用。 塗料が水性だったため、ウェットティッシュ(シルコットピュアウォーター)で拭けばだいたいリカバリーが効いた。

道具が足りない以外で気になったこと

題意からずれるが、せっかくなので印象に残ったことだけ。

  • 壁面に直接日光が当たると色の違いがわかりづらくなり、塗料の色や剥げた箇所の確認が難しくなる。
    • 晴天なら壁面が影になる時間帯、できれば曇天の方が作業しやすい。
  • 気のせいかもしれないが、虫が寄ってきやすい。溶剤の匂いが好きなのだろうか?
    • 赤とんぼ(アキアカネ)の群れが塗りたての壁面に次々くっついたときは焦ったが、力強く飛び立っていった。

以上。

Emacs の Python 開発環境見直し(続き)

前回コメントで教えてもらった emacs-jedi をインストールした。引き続き環境は Windows 8 + Cygwin + Emacs24。

前回と同様に一度マニュアルでインストールしたが、PyPI と MELPA にパッケージがあることに後から気づいて入れなおした。他もまた見直そう。

Python 側は jedi と epc を pip install(jedi から epc の依存は引っ張ってくれなかったので)。
Emacs 側は jedi を package-install。

~/.emacs.d/init.elはこんな感じになった。

;; ------------------------------------------------------------------------
;; emacs-epc

(require 'epc)

;; ------------------------------------------------------------------------
;; emacs-jedi

(autoload 'jedi:setup "jedi" nil t)
(add-hook 'python-mode-hook 'jedi:setup)

;; jedi:complete-on-dot はこちらでは動作しない
;; (autoload 'jedi:ac-setup "jedi" nil t)
;; (add-hook 'python-mode-hook 'jedi:ac-setup)

;; ドットの後で補完候補表示
(setq jedi:complete-on-dot t)

;; 推奨キーバインドを適用
;; (setq jedi:setup-keys t)

レスポンスは ac-python と同程度だが、表示・補完される情報量は断然こちらの方がよい。精度はまだよくわからない。

Emacs の Python 開発環境見直し

EmacsPython 開発環境を見直した。これまでは python-mode で pycomplete は動かすの諦めていたので、補完が動けばいいなと。

試行した結果、編集は python.el + ac-python で行い ropemacs もリファクタリングツールとして入れておく形に落ち着いた。Windows 8 + Cygwin 環境だが Emacs からは Windows 用の Python 2.7 系を使用。

以下インストール手順。インストール先は全部 ~/.emacs.d の下。gnupack の Emacs 24 にパスが通っている状態で作業。

auto-complete をインストール。http://cx4a.org/software/auto-complete/index.ja.html よりパッケージをダウンロード。

$ cd auto-complete-1.3.1
$ mkdir ~/.emacs.d/site-lisp/auto-complete-1.3.1
$ make install DIR='c:/opt/cygwin/home/lpubsppop01/.emacs.d/site-lisp/auto-complete-1.3.1'

Pymacs をインストール。

$ git clone https://github.com/pinard/Pymacs.git
$ cd Pymacs
$ make PYTHON="/cygdrive/c/Program\ Files/Python27/python.exe"
$ PYTHONPATH=c:/opt/cygwin/home/lpubsppop01/.emacs.d/lib/python/ \
/cygdrive/c/Program\ Files/Python27/python.exe setup.py install --home=~/.emacs.d

rope をインストール。

$ hg clone http://bitbucket.org/agr/rope/
$ cd rope
$ PYTHONPATH=c:/opt/cygwin/home/lpubsppop01/.emacs.d/lib/python/ \
/cygdrive/c/Program\ Files/Python27/python.exe setup.py install --home=~/.emacs.d

ropemacs をインストール。

$ hg clone http://bitbucket.org/agr/ropemacs/
$ cd ropemacs
$ PYTHONPATH=c:/opt/cygwin/home/lpubsppop01/.emacs.d/lib/python/ \
/cygdrive/c/Program\ Files/Python27/python.exe setup.py install --home=~/.emacs.d

ropemode をインストール。

$ hg clone http://bitbucket.org/agr/ropemode/
$ cd ropemode
$ PYTHONPATH=c:/opt/cygwin/home/lpubsppop01/.emacs.d/lib/python/ \
/cygdrive/c/Program\ Files/Python27/python.exe setup.py install --home=~/.emacs.d

yasnippet をインストール。

$ cd ~/.emacs.d/site-lisp
$ git clone https://github.com/capitaomorte/yasnippet

ac-python.el を http://chrispoole.com/project/ac-python/ からダウンロードして ~/.emacs.d/site-lisp に配置。

~/.emacs.d/init.el を以下のような感じに。

;; ------------------------------------------------------------------------
;; パス

;; (略)

;; exec-path に Windows 版 Python のインストールフォルダパスを追加
;; Cygwin の /bin よりも先に検索される必要あり
(when (and windows-nt-p (file-exists-p "C:/Program Files/Python27/python.exe"))
  (setq exec-path (cons "C:/Program Files/Python27" exec-path)))

;; (略)

;; exec-path を環境変数 PATH に反映
(setenv "PATH" (mapconcat 'identity exec-path ";"))

;; (略)

;; 環境変数 PYTHONPATH に ~/.emacs.d/lib/python を追加
;; Windows 環境では Windows 版を利用する想定(not Cygwin 版)
(let ((pythonpath (getenv "PYTHONPATH"))
      (additinal-directory (expand-file-name "~/.emacs.d/lib/python")))
  (setenv "PYTHONPATH" (if pythonpath (concat additinal-directory ":" pythonpath) additinal-directory)))

;; (略)

;; ------------------------------------------------------------------------
;; auto-complete

(require 'auto-complete-config)
(ac-config-default)
(setq ac-use-menu-map t) ; 補完ウィンドウで C-p, C-n で候補選択

;; ------------------------------------------------------------------------
;; Pymacs

(autoload 'pymacs-apply "pymacs")
(autoload 'pymacs-call "pymacs")
(autoload 'pymacs-eval "pymacs" nil t)
(autoload 'pymacs-exec "pymacs" nil t)
(autoload 'pymacs-load "pymacs" nil t)
(eval-after-load "pymacs"
  '(add-to-list 'pymacs-load-path "~/.emacs.d/my-pymacs"))

;; Cygwin 版 Python の python は Cygwin スタイルのシンボリックリンクのため
;; NTEmacs からは実行できない。
;; 参照先の python2.6.exe を使用するようにする。
;; (when windows-p
;;   ;; (setq pymacs-python-command "python2.6") ; 環境変数 PYMACS_PYTHON がないとき使用
;;   (setenv "PYMACS_PYTHON" "python2.6"))

;; ------------------------------------------------------------------------
;; yasnippet

(require 'yasnippet)
(yas-global-mode 1)

;; ------------------------------------------------------------------------
;; ac-python

(require 'ac-python)

;; ------------------------------------------------------------------------
;; roopemacs

;; auto-complete による補完
;; (ac-ropemacs-initialize)
;; (add-hook 'python-mode-hook
;;           '(lambda ()
;;              (add-to-list 'ac-sources 'ac-source-ropemacs)))

;; ac-ropemacs-initialize を呼び出す場合はこちらは不要
;; 補完は ac-python で行う場合はこちらで
(add-hook 'python-mode-hook
          '(lambda () (ac-ropemacs-require)))

;; python-mode 開始時点でプロジェクトファイルが存在すれば開く
(add-hook 'python-mode-hook
          '(lambda ()
             ;; ロードのタイミングがいまいちわからないため単に存在チェック
             (when (fboundp 'rope-open-project)
               (cond ((file-exists-p ".ropeproject")
                      (rope-open-project "."))
                      ((file-exists-p "../.ropeproject")
                       (rope-open-project ".."))))))

試行錯誤中に気づいた点など。

  • CygwinPython でも補完までは何とかうまくいった(python-mode + pycomplete, python-mode + ropemacs で確認)が、ropemacs の rope-rename を試したら WindowsCygwin の混ざったパスを表示してファイルがない!とか怒られて折れた。/bin/pythonCygwin 方式のシンボリックリンクなのが今後も引っかかりそうなのもあり、諦めた。
  • python-mode だと ac-python がうまく動作しなかった。python-symbol-completions がない、というエラーは py-symbol-completions へのラッパーを定義すれば回避できた?が、妙に補完の動きがにぶく実用できそうになかった。
  • ropemacs の補完も上記のコメントアウトしてある設定で動きはしたが、補完の開始がスムーズでなかったり、ドットの後に補完が始まらなかったり。正しく動いているのかよくわからないが、ac-python がたいへん快適なのでそちらを使うようにした。
  • rope はファイルの先頭の coding 表記を読むようだが、それをそのまま Pythonunicode.encode に渡すため、utf-8 は OK だが utf-8-unix だとエラーになる。base/fscommands.py を確認したところ 2 行目までしか見てないようなので今後は 3 行目に書くようにして回避Python の処理系も 2 行目までしか見ないみたい。やりづらい。
  • PySmel と py-mode-ext というのもあるようだけど試していない。
  • flymake + pyflakes は試してみたい。

参考 URL:

sjsonで再帰構造を扱うとき

sjsonでProtocolを定義するときにはFormatを簡単に書けるasProduct?なメソッドが使えるが、再帰構造のときは単純に書くとシリアライズで例外が出るようだ(デシリアライズは試してない)。
lazyFormatを使うとうまくやってくれるみたい。

case class DirectoryItem(name: String, files: List[FileItem], directories: List[DirectoryItem])

implicit val DirectoryItemFormat: Format[DirectoryItem] =
  lazyFormat(asProduct3("name", "files", "directories")(DirectoryItem)(DirectoryItem.unapply(_).get))

https://github.com/debasishg/sjson/blob/master/src/test/scala/sjson/json/Protocols.scala

sbt 0.11でSWTを使う

sbt 0.11でSWTを使う方法(たぶん0.10系も同じ)。ググって出てきたのが0.7系の情報ばかりではまった…。

とりあえずlibの下にswt.jarを配置。

build.sbtに以下を記述。これがないと2回目のrunでこける。

fork in run := true

Macの場合はjava起動時に"-XstartOnFirstThread"が必要となる。Macでだけ動けばいいならbuild.sbtに以下を記述。(0.7系の場合はrunJVMOptionsらしい。)

javaOptions in run += "-XstartOnFirstThread"

"-XstartOnFirstThread"は非Mac環境ではエラーになるので、他環境でも動かしたい場合はproject/Build.scalaなどでMacの場合だけオプションが足されるように記述。

import sbt._
import Keys._

object HogeBuild extends Build {

  lazy val root = Project(
    id = "", // set in build.sbt
    base = file("."),
    settings = rootSettings
  )

  def rootSettings = {
      if (isMacOSX)
        Defaults.defaultSettings ++ Seq (javaOptions in run += "-XstartOnFirstThread")
      else
        Defaults.defaultSettings
  }

  def isMacOSX: Boolean = {
    val name = System.getProperty("os.name")
    name != null && name.contains("Mac")
  }

}

たぶん妥当な書き方ではないのだろうけど、とりあえず手元のUbuntuMacで動いた。

ubuntu 11.10

Ubuntu 11.04から11.10にアップグレードした後、gtk_key_theme=Emacsの設定が効かなくなってた。
単にデフォルト設定に戻されたのかと思ったが、gconf-editorで見るとEmacsになっている。
以下でバグとして報告されている現象と同じ?
Bug #872936 “gconf-editor does not set (some/all?) values if cha...” : Bugs : gconf-editor package : Ubuntu

gsettingsで設定し直すと問題なく反映された。

$ gsettings get org.gnome.desktop.interface gtk-key-theme
'Default'
$ gsettings set org.gnome.desktop.interface gtk-key-theme Emacs
$ gsettings get org.gnome.desktop.interface gtk-key-theme
'Emacs'