Emacs 21時代の設定を捨ててEmacs 26に移行した

やっと時代に追いついた。なお、環境は macOS ( Terminal and Window ) なので、Windows や X Window のことは知らんです。

設定を全部捨てて作り直した

これまでの設定は Emacs 21 から設定を継ぎ足し継ぎ足した Emacs 21 - 24 まで対応するもので、mode 定義もそれぞれのバージョンでいい具合に動くように切り替えできるようにしてあった。

これは remote ( vagrant の向こうとかネットワークの向こうとか ) でも使えて、かつ手元の新し目の環境でも動くようにするために編み出した苦肉の策だったんだけど、もはや時代は Infra as Code で DevOps なので、これらの設定は完全に足枷でしかなくなっていた。そこで一気に捨てる機会を伺っていたんだけど、やっと実現できたというわけ。

予想はしていたけど、ほとんどコードを書かずに設定を終えることができた。いい時代になったもんだ。byte compile やら lazy load やら特に考えなくても起動速度も速くなってるみたいだし、よい環境だ。満足満足。

M-x customizeできなかったもの

今回はほとんどの設定を手書きの elisp ではなく M-x customize から行えた。例外は

  • keybind
  • font

くらい。それも以下くらいしかない。あれー Emacs のフォントの設定ってクソ面倒くさいイメージあったんだけど、あっさりしたもんだな。

;; keybindings
; buffer-menu -> bs-show
(global-set-key "\C-x\C-b" 'bs-show)
(global-set-key "\C-h" (quote delete-backward-char))

(when window-system
  ;; font
  (setq default-frame-alist
        (append (list
                 '(font . "Migu 1M 13")
                 )
                default-frame-alist)
        )
     (define-key global-map [?\] "\\")
     )

Terminal では相変わらず Monaco + ヒラギノなんだけど、一部の文字の大きさが揃わないので Window System くらいは完全な等幅にしておこうと思って Migu の設定を足してみた。

Miguフォント : M+とIPAの合成フォント

package.el便利

Emacs 23 も 24 も使っていたけど、ELPA についてはバージョン切り替え用の設定が悪さするのが分かっていたので使っていなかった。これで知らない elisp とか探しやすくなったし、簡単便利。

一応標準だと物足りなかったので melpa を足して、

(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)

mode を少々。追加したのは

  • csv-mode
  • yaml-mode
  • markdown-mode
  • php-mode
  • rhtml-mode
  • feature-mode
  • vue-mode
  • editorconfig
  • company

くらいかな。apache-mode とか昔は使ってたけど、必要になってから入れればいいや。

editorconfig

やっと時代に(ry

t にしないと動かないので

(custom-set-variables
 '(editorconfig-mode t)

が必要ですね。

mmm-mode

もともとあんまり好きじゃなくて使ってなかったんだけど、Single File Component な .vue とかあると対応できなきゃいけないので向き合うことにした。

inverse-videoが邪魔

(custom-set-faces
 '(menu ((t (:inverse-video t))))
 '(mmm-comment-submode-face ((t nil)))
 '(mmm-declaration-submode-face ((t nil)))
 '(mmm-default-submode-face ((t nil))))

editorconfigの設定が反映されない

editorconfig 側で追加設定が必要だった。今回できた .emacs ではこの部分がいちばんでかい。

..vue でいい具合に適用させるためには

(custom-set-variables
 '(editorconfig-indentation-alist
   (quote
    ((vue-mode js-indent-level css-indent-offset)
    ..

みたいな感じの設定が必要だった。なるほどなぁ。ちょっと不便。

Webpacker環境へのJest + Power-Assertの導入が本当に簡単だった話

まとめ

  • Jest は確かに設定減ってる。でも zero config は言いすぎ1
  • Webpack の設定をテスト用に書き足す必要はなかったが、Jest 用の transform を追加するが必要あり、Webpack の再発明感はある2
  • Power-Assert が Babel に対応してて設定が楽になってきてる
  • Jest よりも Webpacker のクセが強い(これはまた別に書く)

背景

以前 Rails 4.2にWebpacker入れた - あーありがち(2018-01-19) で Webpacker を導入したわけだが、やはりテストがなくてつらかったので3、今回はテストの環境を Jest で作った話。

実は最近も Nuxtを利用したVueアプリのユニットテストに関するメモ - あーありがち(2018-04-24) で似たような話をやっているんだけど、その時は

  • mocha-webpack
  • テスト環境用のwebpack.config.js
  • jsdom-global
  • power-assert

をちまちまと準備していった。勉強にはなったけど、またアレやるのはちょっとイヤだなと思っていたので、最近評判のよい Jest を試してみることにした。

Jest · Delightful JavaScript Testing

参考までに今回動かしたのはそれぞれ以下のバージョン。

  • jest 23.2
  • power-assert 1.6.0
  • @vue/test-utils 1.0.0-beta.20
  • babel-jest 23.2.0
  • vue-jest 2.6.0

まず最小限で動かす

yarn add –dev jest とか npm install –save-dev jest とかでインストール。

で、 package.json に

"test": "jest --config <config-path>"

を書く。Rails + RSpec 環境なので、場所は

spec/javascripts/jest.conf.js

がよいだろう。

で、jest.conf.js の中身だが、基本的には

module.exports = {
  rootDir: ".",
  modulePaths: <webpacker-path>
  ..

で動く。

rootDir ( または roots ) や modulePaths はこの jest.conf.js からの相対パスで指定するようだ。conf を独立させずに package.json の中に書く場合は package.json からの相対パスになる。

これでテストコード側からは modulePaths で指定したパス以下のプロダクトコードを気軽に読み込むことができる。はずだ。ただし Jest は Node.js で動いており、2018-07 時点では当たり前だがそのままでは import は使えないので、Babel の登場を待つ必要がある。

Mochaの追加とjsdom-globalの設定は不要

自分が Mocha にこだわっていたのは Jasmine では power-assert を使うのが難しいと思っていたためだったのだが、Jest では Jasmine2 + jsdom-global の環境が最初からできあがっており、またこの状態で describe / it 形式でテストコードは書けるので、ここは本当によかった。いきなり

describe('', () => {
  it('', () => {
    console.log('foo')
  })
})

が動く。

jsdom-global はここまでの流れでは関係ないが、Vue component のテストを書く際に jsdom 関係の設定は一切不要だった。

余談だけど Jest では assert を呼ばなくても true が返ってなければエラーになるっぽい。こういうの、いいな。

やはりimportは解釈できないのでtransformの追加が必要

Vue.jsでアプリを書いている場合、基本的にはこれでいける。

transform: {
  "\\.js$": "babel-jest",
  "\\.vue$": "vue-jest",

もちろん babel-jest, vue-jest はインストールしておくこと。

この辺が非常に Webpack の再発明っぽくてどうなんだと思のだが、babel-jest, vue-jest については特に設定は不要なので助かる4。babel-jest は Jest本家が、vue-jest は Vue本家がサポートしているので安心。

YAML でデータを食わせている場合にも yaml-jest を追加設定すればよいだけ。

以前は JavaScript のテストでは fixture をどうするのかが課題の一つだったが、イマドキはもうこれでよいような気がする。違う? 適当にテストデータを YAML で用意すればいいんじゃないかなぁ。

Webpacker環境独自の課題

ここまでは順調だが、Webpacker 環境の場合はまだ注意が必要。

まず、Webpacker の作った .babelrc の presets env が modules: false になっているので、babel-jest を設定しているにも関わらず import できない。そこでこれを消そうかと思うのだが、影響がよく分からないのと、ついでにやることがあるので、 .babelrc で

"env": {
  "test": {
    ..
  }
}

を用意して環境を切り替えることにする。いちばんシンプルには以下のようになる。

"env": {
  "test": {
    "presets": ["env"]
  }
}

Power-Assertの導入

実は Webpacker の課題を解決するのと同時に Power-Assert を使うために上では .babelrc で env を追加してある。

yarn add --dev power-assert babel-preset-power-assert

しておいて、先ほどの env.test の中に以下のように追加する。

"env": {
  "test": {
    "presets": ["env", "power-assert"]
  }
}

これでテストコードの中で

import assert from 'power-assert'

して使うことができる。

よーしこれでバンバンTDDできるってもんだ。

  1. jsdom-global は確かに zero config 

  2. でも出力しなくて済むので、Webpack と Jest は load と transform 周りを切り離すと本当はいいんだろうなぁ 

  3. どーして毎回こういう話になるのかというと、自分が新規案件をゼロから書く機会を奪われている(集中すると他に手が回らなくなって困る)ので、こういう話が増えるのです。とは言え今回は 2016年にやっていたことに比べればへなちょこ級に楽ちんです。 http://aligach.net/diary/20161228.html#p01 

  4. 特に vue-jest が Webpack にも Babel にも依存していなくてどちらにも何も設定しなくて済むのは助かる。Webpacker 側も無設定なので本当に助かる。 

メガネのレンズを注文した

今使っているメガネのレンズのコーティングがところどころはげてきていて、白っぽく見える場所が多くなってきた。気づいてはいたが先日 J!NS PC カスタムを購入して以来、この白っぽくなっているのがすごく気になるようになってしまったので、常用メガネのレンズも換えることにした。

とりあえずフレームには満足しているので、レンズだけ換えるために買ったお店へ。伝票によると今のメガネを買って5年経っているらしい。その前のメガネは5年でレンズ交換1回したうえで今のメガネに換えているので、以前のものよりはだいぶ保ちがいいみたいだ。ただ、もう部品がないので、壊れたらもう無理ですよとは念押しされた。

まぁ物保ちはいい方だと思うので、もうしばらくはこれでいけるんじゃないかな。どれくらいが平均的な寿命なのかよく分かってないけど。

一応簡単に検査したけど作ったときと変わらず(もしかしたらよりクリアに)見えているので、同じ数字のレンズで、1ランクコーティングなどが丈夫な新製品をお願いしてきた。

というわけで1週間程度でクリアな世界が手に入るので楽しみ。

rst2odt.py 用の stylesheet を作る準備

rst2odt.py の変換結果がイロイロまずい

先日、docutils を使った OOo Writer (.odt ) 形式への変換 を試してからサクっと一ヶ月が経ったわけだけど、あれは実はあのままでは面白くない。というのも

フォントなどのスタイル情報が自分の好みに合わない。

結果として手作業で一つ一つスタイルを合わせ直さないといけないんだとすると、全然省力化になっていない。そもそもこの「マウスを握ってポチポチやらなきゃいけない感」がきらいだからこそ Office がきらいだと言っても過言ではないのに、そこが改善されないままではいくらスタートが reST であってもダメダメである。

スタイルシートを与えて変換する

ではどうしたらいいのかというと、ちゃんと方法がある。help を見ると

$ rst2odt.py --help
Usage
=====
  rst2odt.py [options] [<source> [<destination>]]

Generates OpenDocument/OpenOffice/ODF documents from standalone
reStructuredText sources.  Reads from <source> (default is stdin) and writes
to <destination> (default is stdout).  See
<http://docutils.sf.net/docs/user/config.html> for the full reference.

Options
=======
(snip)
ODF-Specific Options
--------------------
--stylesheet=STYLESHEET
                        Specify a stylesheet.  Default: "/opt/local/Library/Fr
                        ameworks/Python.framework/Versions/2.6/lib/python2.6
                        /site-packages/docutils-0.6-py2.6.egg/docutils/writers
                        /odf_odt/styles.odt"

と書かれているので、

--stylesheet=STYLESHEET

を与えればよいことが分かる。また、このときデフォルトで与えられる stylesheet のファイルが分かる1ので、次にこれを cp して中身を確認してみる。

ODTWriter の stylesheet の中身を見る

最初に引っかかったのが

stylesheet として与えるものが .odt であるということは、これは Writer のファイルそのものであって、テンプレート ( .ott ) ではない

ということだった。というのも、GUI で文書を作るときにはテンプレートを作ってそれが見た目の基準になるのが基本的な流れだから。どうも docutils の ODTWriter の考え方は違うらしい。

話がそれたが、OOo のファイルフォーマットである ODF ( Open Document Format ) は XML でかつ ZIP アーカイブだということは知っていたので、まずは styles.odt を展開してみる。

$ unzip styles.odt -d styles
Archive: styles.odt
extracting: styles/mimetype
inflating: styles/content.xml
inflating: styles/styles.xml  <- コレ
extracting: styles/meta.xml
inflating: styles/Thumbnails/thumbnail.png
inflating: styles/Configurations2/accelerator/current.xml
creating: styles/Configurations2/progressbar/
creating: styles/Configurations2/floater/
creating: styles/Configurations2/popupmenu/
creating: styles/Configurations2/menubar/
creating: styles/Configurations2/toolbar/
creating: styles/Configurations2/images/Bitmaps/
creating: styles/Configurations2/statusbar/
inflating: styles/settings.xml
inflating: styles/META-INF/manifest.xml

もう正解は書いちゃったけど、それっぽい名前のファイルが見つかった。まずは font の設定を変更したいので font 関連の記述のあるファイルを探そう。

$ grep -rl font *
content.xml
settings.xml
styles.xml

※ ここで役に立つのが(実際には同日の作業なんだけど)昨日のエントリとして書いたxml-modeのindentとそれを活かすための改行の挿入である。

content.xml は内容っぽいのであやしいのは settings.xml と styles.xml かな。このうち settings.xml は font の設定はないっぽい。となると styles.xml か。

ということで styles.xml をいじっていけばよいらしいことが分かった。

該当スタイルを見ておく

最初何も考えずに styles.xml をいじり始めて「反映されない!」と騒いでいたんだけど、よくよく見れば当たり前。変換後の文書を注意深く見てみると分かるんだけど、rst2odt.py で生成した文書は通常の「見出し」などの書式ではなく

"rststyle-heading1" のような書式が割り当てられている。

そうか、これをいじるのか。ということは 'rststyle-*' を対象にスタイルを考えていけばいいのか。

とりあえず今日はここまで。

参考

ざっと手順を追ってみたけど、後で調べたらちゃんと資料があった。まぁ当たり前か。

関連エントリ

  1. 上の場所は MacPorts で入れた Python 2.6 の docutils 0.6 の場合 

MacPorts の正しいアンインストール

上の話とは別に以下のような問題にハマっていました。以下はハマりから解決するまでの twitter のログ。

> python25 を activate できない
> activate できないので python製ツールが port install できない
> MacPorts で Python がインストールできないっていう症状はそんなポピュラー
  じゃないのかな。なんか、以前は普通にインストールしたような気もするし
  なぁ。
> 意味が分からん。install されてるからダメって言うくせに uninstall しよ
  うとすると install されてないって言うし。
> pkgdb みたいなのってあるんだっけ
> あー uninstall できた。+macosx まで全部要るのか。
> uninstall したがやはりダメ。
> install できてないのに install できてるとして registered ってなんなん
  だ
>  /Application/MacPorts の中の Python てなんだ
> 以前一度 MacPorts 全部消して入れ直したときに残ったのかな、これ。
> それっぽい。macports.conf の中に applications_dir として定義されてる。
  そういうことか。
> あーやっと通った。MacPorts 消すときは /opt だけ消せばいいんじゃないの
  かぁーーーー。

数日前に MacPorts を一度全部消して入れ直していたのですが、そのとき /opt しか消していなかったのです。どうやら Python はそれだけでは完全に削除されないらしい。という話でした。

linkchecker を OSX w/ py25 で使う

複数の人間で Web を作る場合、最後にリソースが適切に揃っているのか統一的にチェックする手法が必要になると思います。1

その際、どういうツール使うのがいいのかなーと去年調べまして、今のところ

Check websites for broken links — LinkChecker

がいいのかな、と考えています。Python を使ってて Windows でも Linux でも動くし、結果が見やすいのも気に入っています。

しかしこれ、OSX で動かそうとしたときにハマります。2

 File "/sw/lib/python2.5/site-packages/linkcheck/director/console.py", line 30,
in <module>
   stderr = codecs.getwriter(_encoding)(sys.stderr, errors="ignore")
 File "/sw/lib/python2.5/codecs.py", line 930, in getwriter
   return lookup(encoding).streamwriter
LookupError: unknown encoding: X-MAC-JAPANESE

はいはい、ぐぐる先生ぐぐる先生。

……。

ねぇ。どんだけ調べても linkchecker でこの現象にハマっている事例は見つかりません。見つかるのは Django とか Trac とか。くそー、linkchecker はマイナーだったか。

で、どうもこれは Mac で Python のツールを動かすときには必ずハマる道らしい。うへー。ばかばかしくね? ばかばかしくね?

というわけで今回は以下のように修正しました。

こう直すべきなのかどうかは分からないです。

Python 2.6 で直ってるとかいう話もあるようですが、すべてのツールが 2.6 で動くように書かれてるわけでもないでしょうし、なかなか面倒な話ですね。

※ たぶん Python 2.6 を入れた状態で、fink も macports も使わずに野良で、あるいは自分でそれ用のパッケージを作って linkchecker を入れればいいんじゃないかなという気がしますが、やってみていません。

  1. 個々人のレベルでは Dreamweaver だけで完結するチェックとかはもちろんやるんでしょうけど。 

  2. 以下は Fink で入れた linkchecker を動かそうとした結果 

金沢ビーンズ明文堂書店行ってきた

恐ろしく混んでた。周りの他の店の駐車場まで臨時に解放してた。さすが金沢の人はとりあえず新しいものは一応チェックしますな。すぐ引いちゃうんだけど、この波は。

日本最大級っていう表現はどうなんだーと思ったけれど、まぁ田舎らしく、それなりにレイアウト的にも余裕があっていいかもしんない。富山や野々市とは違って TSUTAYA とは組んでなかった。まぁ8号線挟んですぐのところに TSUTAYA があるわけで、逆に本に集中してくれているのが個人的には高評価。むしろ本屋としてはその TSUTAYA と一緒にやってる文苑堂がちょっとピンチなんじゃないかという感じ。イオン示野の方が力入ってるだろうし。個人的にはあこの文苑堂のラインナップには不満だらけなので、競合が出て来てくれてとても嬉しいというのが本音ですが。

でまぁ、コンピュータ関係は意外とあるんだけど、なんか新書系の本もかなり混ざってて、ディープな方向としてはちょっと微妙。世の中にはエクセル本てこんなにあるのね、という驚きを感じることはできたが。ワインバーグ先生なんかもあって、一応全般的に揃えてますよ的な印象は保てているんだけど、「全般」の方向がちょっと王様の本ぽいと思った。古典もそれなりにあるので若い人にいいかも。

※ ふらふらと On Lisp と Ruby クックブックを買いそうになったが、とりあえず未読消化を優先して我慢我慢。

Un*x 系はイオン示野の文苑堂の方が揃ってるなーって感じ。店舗の雰囲気は野々市店やイオン示野の文苑堂の方がよい。ビーンズは全体に白すぎてまぶしい。

なんか、アート系が思ったよりなかったような気がしたんだけど、根本的な見落としをしている可能性アリ。最近は住宅とかインテリアとかちょっと毛色の違う料理本とか多いねぇ。

640MB MO を Mac で読む

Giga は知らないけど、OSX て Windows フォーマットの 640MB の MO も読めるのね。Classic は 230MB までしかいけないけど。

知らなかった。230MB の時代で自分の頭は止まってたよ。

+DESIGNING 気合い入ってるなぁ

Unicode 面倒くせぇ

放置プレイになっていた NAS をやっといじり始めている。で、Classic Mac やら Win98 やら有象無象が未だ夢覚めやらぬ状況なので、ファイル名に使っちゃいけない文字をチェックしようとしている。

NAS 上では utf-8 でファイル名が保存されているようなので、nfs でマウントして Ruby で -Ku でやればいいかーと思って作業を始めた。(こういう用途を想定して nfs に対応した NAS にしたのだ。)

  1. mule-ucs を入れて動かす → 起動が死ぬほど重くなる
  2. terminal が euc だと本来表示させたい文字が出ないのは当然として、utf-8 にしてもフォントが対応してなきゃ同じ → なんだか徒労の気配orz
  3. 読めない文字についてチェックするために hexl-mode 大活躍。でも hexl-mode にしたらなぜか日本語読めない(utf-8 のときは出ないのか?)ので、どれがダメな文字なのか特定するのに四苦八苦。
  4. VirtualPC on OSX, BasiliskII on Win, SheepShaver on Linux 大活躍。

重たいわ。うざいわ。

つーかこの辺のノウハウってどこかで共有されてないのだろうか。Samba も netatalk も WebDAV も日本語周りで必ず悩みが出てくるわけだけど、こうしたサービスの開発チームだけでなく、運用のノウハウ共有ってのが必要なような気がするなぁ。

nkf for win32 の最新版発見 orz

nkf Windows版 (vector.co.jp)

nkf Win32 版という呼び方はやめたらしい。なんでそんなややこしいことしやがんだ。

select option の謎

Namazu の設定をいじっていて気づいたのだが、

<select name="idxname">
  <option selected>↓ 選べ ↓
  <option value="develop/php4.3.4">PHP 4.3.4
  <option value="develop/pear200406">Pear
  <option value="develop/ruby1.6.8">Ruby 1.6.8

の場合は検索後も選択したインデックスが select ボックスの中で selected になる。しかし

<select name="idxname">
  <option selected>↓ 選べ ↓</option>
  <option value="develop/php4.3.4">PHP 4.3.4</option>
  <option value="develop/pear200406">Pear</option>
  <option value="develop/ruby1.6.8">Ruby 1.6.8</option>

こうした場合は必ず先頭の「選べ」が selected になる。つまり再検索の際に必ず idxname を選び直さないといけない。これは「選べ」に明示的に selected を書いていてもいなくても同じ。

Mozilla でも IE でも同じ動きをする。この辺の動作って、本当は JavaScript や cookie 使ってちゃんと制御すべきなのかな。DOCTYPE はこうなっている。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
       "http://www.w3.org/TR/html4/strict.dtd">

これが Transitional だとまた違うのかもしれない。

IT業界、中間管理職の給与が減少--米調査

特にシステム管理者が減っているとな。誰かが管理してるから無事なのにね。。。

いつまで経っても人間は失ってからしか健康のありがたさが分からないままですか? 学習はできないのですか?

情報流出事故続出の日本でこれやったらほんとにただのアホやな。

外来語言い換え

スラドのストーリーを見て一言。

お前ら、「自分だけは永久に年を取らない。取っても 40歳まで。」とかわけの分からない妄想を抱いてるだろ。

中にはちゃんと読んでる人もいる けど、ごく少数だね。

その後。

ものすごくコメント伸びてると思ったら Ryo.F 台風とか発生してますよ。。。

nkf for Win32

  • cygwin で gcc -mno-cygwin すれば nkf.exe は作れる
  • NKF.pm は NKF.dll と NKF.bs が必要で、これらはプラットフォーム依存。具体的には cygwin で make perl して NKF.pm 用の Makefile を作成する段階で cygwin 依存の情報が入ってしまうので、やるんなら pure mingw か Borland C などの処理系が必要。(フリー限定なら。)

実際には NKF.pm を利用するスクリプトは多くないし、Perl 5.6 以降は unicode を標準のモジュールだけで処理できるんだから、必要ないっちゃ必要ないし、これ以上深追いするのは面倒なんでやらない。

普段は euc-jp に統一して作業した方が楽だし。

とりあえず単独で動く nkf.exe は簡単に作れた。lv は cygwin 用の patch が必要だから、今後は個人的には nkf 標準で行こうかな。mime の decode もできるし、文字コード変換ツール以上の価値が nkf にはあると思う。

Apple Remote Desktop 2 が VNC 対応

おまけに Windows の RemoteDesktop にも対応。

ということはこれさえあればすべてのプラットフォームが管理できるってことじゃん。いいじゃん。安いしね。

7月下旬発売予定。

About

例によって個人のなんちゃらです