Incremental Search + Multiple Cursors
「複数カーソル」というものが便利だと教わった。調べてみたところ multiple-cursors.el と smartrep.el を使えば Emacs でも似たようなことができそうだったので、真似をしつつ設定を追加してみた。
まずは isearch-forward
した状態から mc/mark-next-like-this
したい。
(define-key isearch-mode-map (kbd prefix) #'(lambda () (interactive) (push-mark isearch-other-end t 'activate) (isearch-exit))) (smartrep-define-key global-map prefix ...)
これだと prefix
を押さなければいけない回数が多くて嬉しくないのだけど、さしあたり良い案を思いつけなかった。
あとは選択状態に合わせてスクロールさせたい。これは mc/cycle-forward
や mc/cycle-backward
を呼ぶだけなので易しい。
(defun mc/mark-next-like-this-and-cycle-forward () (interactive) (mc/mark-next-like-this 1) (mc/cycle-forward)) (smartrep-define-key global-map prefix '(("C-v" . 'mc/cycle-forward) ("M-v" . 'mc/cycle-backward) ("n" . 'mc/mark-next-like-this-and-cycle-forward) ...))
ついでにsmartrepによるコマンド実行中はキー入力をエコーしないようにしたら快適だった。
First Step of Customizing Magit
主に magit-status
, magit-show-level-4
, magit-commit
を快適に使うべく、いくつかのサイトを参考に設定してみた。
;; http://d.hatena.ne.jp/syohex/20130904/1378310201 (defadvice magit-status (around magit-fullscreen activate) (window-configuration-to-register :magit-fullscreen) ad-do-it (delete-other-windows)) (defun my/magit-quit-session () (interactive) (kill-buffer) (jump-to-register :magit-fullscreen)) (define-key magit-status-mode-map (kbd "q") 'my/magit-quit-session) (defadvice git-commit-commit (after move-to-magit-buffer activate) (delete-window)) ;; http://qiita.com/dtan4/items/658a8a7ca06aa8c2da4c (set-variable 'magit-emacsclient-executable "/usr/local/Cellar/emacs/24.3/bin/emacsclient") ;; http://www.clear-code.com/blog/2012/4/3.html (set-face-background 'magit-diff-file-header "gray15") (set-face-background 'magit-diff-hunk-header "gray18") (set-face-background 'magit-diff-none (face-background 'default)) (set-face-foreground 'magit-diff-none (face-foreground 'diff-context)) (set-face-background 'magit-diff-add (face-background 'diff-added)) (set-face-foreground 'magit-diff-add (face-foreground 'diff-added)) (set-face-background 'magit-diff-del (face-background 'diff-removed)) (set-face-foreground 'magit-diff-del (face-foreground 'diff-removed)) (set-face-background 'magit-item-highlight (face-background 'helm-selection)) (setq magit-diff-refine-hunk 'all)
S3 File Resource for Chef
Chef で S3 からファイルをコピーするのに gist:DavidAllison/5288249 を使うと「S3の認証にIAM Roleを使うことができ、各EC2インスタンスにアクセスキーなどを配布する必要がありません」。これは嬉しい、と思ったら使われているメソッドが deprecated になってしまっていたり AWS SDK for Ruby の新しいメジャーリリースが近づいていたりしていたので少し手を入れてみました。
test-kitchen + kitchen-docker on Mac OS X
追記(2014-10-30): 少しだけ手順が変わった
実は簡単に使える状態になっているのではないか。
まず 公式ドキュメントを参考にしつつ Docker の設定をし、さらに test-kitchen や kitchen-docker をインストールする。
$ export DOCKER_HOST=tcp://127.0.0.1:4243 $ brew install boot2docker $ boot2docker init $ for i in {49000..49900}; do VBoxManage modifyvm "boot2docker-vm" --natpf1 "tcp-port$i,tcp,,$i,,$i"; VBoxManage modifyvm "boot2docker-vm" --natpf1 "udp-port$i,udp,,$i,,$i"; done $ boot2docker up $ gem install test-kitchen $ gem install kitchen-docker
次に .kitchen.yml を書く。
--- driver_plugin: docker driver_config: use_sudo: false provisioner: name: chef_solo platforms: - name: ubuntu-12.04 suites: - name: foobar run_list: - "recipe[foo]" - "recipe[bar]" attributes:
そしてテストする。必要に応じて serverspec なども組み合わせる。
$ kitchen test
追記: ところで kitchen login
したいのにパスワードが分からんと思っていたのだけど、どうやら kitchen だったらしい。
Json4s and Enumeration
json4s の EnumSerializer
がちょっと使いづらい。何となれば二つの Enumeration を同時に扱えない。
import org.json4s.DefaultFormats import org.json4s.ext.EnumSerializer import org.json4s.native.JsonMethods.parse import org.json4s.native.Serialization.write object E1 extends Enumeration { val v1 = Value } object E2 extends Enumeration { val v2 = Value } case class C(e1: E1.Value, e2: E2.Value) implicit val f = DefaultFormats + new EnumSerializer(E1) + new EnumSerializer(E2) val c = C(E1.v1, E2.v2) println(c) // C(v1,v2) println(parse(write(c)).extract[C]) // C(v2,v2)
EnumSerializer の実装を見ると EnumerationClass で他のクラスと区別をつけているようだが、残念なことに classOf[E1.Value]
と classOf[E2.Value]
は区別がつかない。
println(classOf[E1.Value]) // class scala.Enumeration$Value println(classOf[E2.Value]) // class scala.Enumeration$Value
さてどうしたものか。
追記: ScalaType や TypeInfo を拡張して Type なり TypeTag なりを持たせるようにしていけば何とかできなくもなさそうだけど、コンストラクタを読み取る部分なども変えないといけないし割に合わなさそうなので当面はあきらめることにした。
$in MongoDB
MongoDB の $in
の実装がどうなっているのかと思ってソースをちょっと覗いてみた。
まず、ライセンスは AGPL 3.0 らしい。
とりあえず Matcher::matches の中で処理をしているに違いない、と当たりをつけてみる。そこには normal non-regex cases があって matchesDotted が呼ばれている。多分 $in
を処理するときは、この中の compareOp == BSONObj::opIN が真になって valuesMatch が呼ばれるんでしょう。そうすると op == BSONObj::opIN なんていうそれっぽい式があって、ここの if
文の中で $in
を処理しているように見える。bm
の型は ElementMatcher らしいので bm._myset
の型である set
は pch.h で include してる set
っぽい。じゃあ count
の時間計算量は要素数 n に対して O(log(n)) とかかなあ。知らんけど。ところで ElementMatcher
には _myregex なるものが定義されていて、実際に使われているみたいだけど何かしらん。多分 $regex とかいうやつだなあ。多分 { $in: [ "foo", /bar/i ] }
みたいに正規表現を混ぜられたときに使うんだろう。
上記はバージョン 2.4.1 の話ですが、このあたりのコードはどうも大幅に書き直しているらしく、master を見てみると src/mongo/db の下に matcher というディレクトリが出来ていて、$in
は InMatchExpression という分かりやすい名前のクラスに収まっていた。ちなみに処理そのものは変わっていないみたい。
インデックスが張られていたときのことを考えていなかった。findOne を見ると NamespaceDetailsTransient::getCursor を呼んでいるようなので、そのあたりから読めば良いのかもしれない。
nscala-time and salat
case class と JSON (や BSON) の相互変換は意外と面倒らしい。
salat は JSON をデシリアライズするとき TypeMatchers というクラスを使って場合分けしているようなのだけど、このあたり に com.github.nscala_time.time.Imports.DateTime が入っていないせいか、nscala-time と併せて使おうとすると少し困ることに気づいた。入れると直るのか、直るとしてそんな修正で良いのかは知らない。