Hatena::ブログ(Diary)

むしゃくしゃしてやった

2012-09-12

Shibuya.el#1でERTについて発表してきた

少し時間が経っておりますが、9/6にShibuya.el#1に参加&発表をしてきました。

関西Emacsでの顔見知りにも、一度会ってみたかった人にも会えてよかったです。

当日はど平日だったのと雨が降っていたのもあってか、キャンセルが結構出てしまっていたのが少し残念でしたが…

それではだらだらと思ったことなどを書いてゆきます。

ポジションペーパー

まずはポジションペーパーによる自己紹介

一応私の自己紹介はこんな感じ。

ついでにkey-combo.elとflex-autopair.elの宣伝もしてました。

他の皆さんは自己紹介だけで笑いが取れていてすごいです...私もなにかネタを仕込みたい。

ライトニングトーク

id:shigemk2 さんの

LT #shibuya_el - by shigemk2がよくまとまっていると思います。関西Emacsの時も思いましたが、相変わらず早くて正確で素敵です。

@さん:初めてのemacs lisp

hjkl-modeをmarmaladeに公開してみた話。

途中でmarmaladeの更新コマンドを出してくれていたのでありがたかったです。

資料の公開が楽しみですね。

hjkl-modeの方針はEvilまでは目指してなくて、view-mode的なものなのかなという印象でした。

Emacs Lispテスト

私の発表です。

テンパって内容を飛ばしたり、デモ想定外の動きをしたり、安定のグダグダっぷりです。

LTは初めてだったのでと言い訳しつつ…

スライドは

デモで使った資料は

です。

個人的にはorg-tree-slideを使えばモテると聞いていたのに、だれも触れてくれなかったのが悲しいです( ´・ω・` )

@さん:emacsdvorak配列について

dvorakをさらにカスタマイズしましたというお話。

かな配列ですら覚えられない私のようなヘタレにはアナザーワールドですね。

すごいです、キーボード渡されても全く使える気がしないです。

@さん:tokyo-emacs という歴史上の出来事

すごく発表がうまく、会場が盛り上がってました。

私は小指が短いので、選ばれしホモイーマックスではないようです。残念。

話の本筋は勉強会の運営のお話。やはり大変ですよね…shibuya.elは末長く続いていって欲しいなぁと思います。

@さん:最近作った拡張(popwin.elなど)について

最近github上でやり取りしてたので、お会いできるのを楽しみにしてました。

内容はpopwin,direx,emux,yascrollなどなどデモが盛りだくさん。

意外だったのが、見た目上はデフォルトから激しく変更している感じがしなかったことです(実際は色々変えていると思いますが)。

バッファの切り替えにもanything/helmではなくiswitchb(?)を使ってるみたいでした。

個人的には、gsocでのnative profilerの話も詳しく聞いてみたいところです。

@さん:clgrep.el について

まずはkinesisの話題。

他人が使えないキーボードを使うと、セキュリティ対策にもなるとの話で笑いました。

本題はgrep系のお話。メモを取ってる時には前後関係が分かるように行単位ではなくメモ単位grepできるといいでしょう(context grep)。

clgrep(というかバックエンドのblgrep)は汎用的な作りになっていて、clmemo以外にも色々(2ch,outline-modeなど)扱えるようになっている。org-modeで使えるとうれしいかもと思ったけど、元々の機能のorg-occurというので似たようなことができそうな感じ。

@さん:Vimmerから見たEmacs

VimEmacsとの比較

完全に客観的な比較はできないので、偏りはまぁ想定範囲内といったところですかね。

Emacsデフォルト設定が使いづらいのは同意です。とは言ってもどうしても無理なのは「C-h」のキーバインドぐらいですが。

デフォルトの設定をそのまま使うかカスタマイズして使うかは文化の違いだと思います。詰めVimの話にもその違いが表れていると思っていて、もしテキスト操作の機能Vimと同様だとしてもキーバインドが人によって違っていたら成り立たないよなぁとか思ってました。

お互いを理解するには、機能の点取り表では出てこない文化や思想の違いも重要な気がしますがいかがでしょうか?

その他

懇親会では@さん,at_akaさん,@さんと「ブラウザOperaがいい」「Macがいろいろ楽だ」という話になったり。

m2ymさん,ShougoMatsuさん,Hayamizさんと「拡張機能メンテナンス(特にドキュメントテストまわり)が大変」などなどの話をしてました。

m2ymさんからは(popwinのテストと同様に)auto-completeのテストもお願いされてしまいました…時間確保できるといいんですが…

他にもr_takaishiさんからorg-syncの話が聞けたり、楽しかったです。

主催のainameさん、会場の準備などしていただいたmixiの方々、発表者、参加者の皆様、本当にありがとうございました

2012-07-20

el-spec v0.2リリース:テスト結果からテスト定義へのジャンプ。個別のテスト実行をサポート

el-spec v0.2 をリリースします。変更点は以下です

  1. テスト結果からテスト定義ジャンプ可能に
  2. 個別のテスト実行をサポート

https://github.com/uk-ar/el-spec

変更詳細

1つ目はテスト結果からテスト定義へのジャンプです。テスト(example)が失敗した際にはテスト内容を詳しくみれると便利ですね。ertにもともと備わっている機能ですが、ertの関数ラップして使ってるのでv0.1では対応できてませんでした。今回、遅れて対応です。

使い方はertバッファ上の失敗/成功したテスト名の上で「RET」を押すことでテスト定義した場所へ飛ぶことができます。

ただし一つ制限があり、現時点ではshered-examples(include-examples)された定義には飛べません。実装を頑張らないとshared-examplesへの対応は難しそうです。

2つ目は個別のテスト実行です。テストが増えてくると全部を実行するには時間がかかるようになります。その場合、一部のテストだけを実行できると便利ですね。v0.1ではcontext単位テスト実行をサポートしていましたが、これを拡張してexample単位で実行できるようにしました。M-x el-spec:eval-and-execute-examplesでカーソル付近のexample/contextだけを実行することができます。

挙動が分かりづらいので、スクリーンショットで説明します。

f:id:uk-ar:20120716054729j:image

カーソル位置により実行範囲が変わり、

  • 灰色部分にあるときdescribe以下(3つのexample)が実行される
  • 青色部分にあるときit以下(各々1つのexample)が実行される
  • 黄色部分にあるときcontext以下(2つのexample)が実行される

ことになってます。shared-examplesやinclude-examplesの内部で実行しても上位のcontextなどを実行するだけなので、注意して下さい。

逆にM-x el-spec:eval-and-execute-allでdescribe以下のコンテキストを実行できます。M-C-x でevalした時の挙動も切り替えが可能で、M-x el-spec:toggle-selectionするたびにallとexamplesが切り替わります。

インストール方法

el-specはertに依存しています。

Emacs23以下の場合はert自体のインストールが必要です。

rspecのように前処理などを構造化できるEmacs Lisp用テストフレームワーク(el-spec)をリリース - むしゃくしゃしてやったを参考にしてください。

el-specインストール

(auto-install-from-url "https://raw.github.com/uk-ar/el-spec/52dc72aa71ddfa1dba87ba93703f1328b1496ed3/el-spec.el")

を評価するか、

marmaladeから

M-x package-install el-spec

でOKです。

感想

今回はv0.1をリリースした後すぐに対応しようと思っていた機能です。当初考えていたよりも時間がかかりました。

一つの理由はfind-functionの実装が正規表現関数定義を探すようになっていたので、そのままでは対応が難しかったこと。もう一つはitマクロ呼び出し時に(C言語の__LINE__的なもので)呼び出し行数を記録していけばタグファイル的なものを作れると思っていたけど、似た機能がなさそうだったことです。

結局、力技ですがdescribe以下のS式を自前でパースすることで対応しました。

その際readを使うことでメインのロジックと一部の処理を共通化することができました*1

扱いが難しいのがshared-examplesですね。サクッと対応したいところですが、泥臭い実装しか浮かびません。アイデアが欲しいところです。本家のrspecを見てみようか...

2012-07-05

rspecのように前処理などを構造化できるEmacs Lisp用テストフレームワーク(el-spec)をリリース

[http://d.hatena.ne.jp/uk-ar/20120720/p1:title]にて機能追加をおこないました。そちらも参照ください。

Emacs Lisprspec*1のように前処理などをネストして定義できるテストフレームワーク(el-spec)が欲しくて作ってみました。

https://github.com/uk-ar/el-spec

実用になりそうなレベルになったのでリリースします。

きっかけ、が欲しいです。

Emacs Lispにもいくつかテストフレームワークがあり、今まではid:rubikitch さんのel-expectation*2を使ってました。使い勝手が良くてテスト数の少ないうちは満足していたのですが、テストが多くなると複数のテストで同じような前処理をしているのが目立ってきました。

このような場合マクロ関数で対応するのが常套手段です。しかし、前処理の内容も全く同じわけではなく少しずつ違っているので、マクロ関数が増えて管理が辛くなります。

そこでEmacs 24から添付されたert*3を利用して、テストフレームワーク(fixture?)を作ってみました。

特徴

テストを書くのに今回リリースするel-specを使用すると

  • 前処理や後処理を簡単に追加できる
  • テストが整理できる(同じようなテストが近い場所に固まる)
  • 個々のテストに対して、名前をつけなくてよい
  • 似たようなテストを増やしやすい(shared-contextやshared-examples)

というメリットがあります

逆にデメリットもありますが、最後に書きます。

準備

el-specEmacs 24から標準添付されたertに依存しています。Emacs 23以下の場合は

(auto-install-from-url "https://raw.github.com/ohler/ert/c619b56c5bc6a866e33787489545b87d79973205/lisp/emacs-lisp/ert.el")

としておきましょう。

インストール方法

el-spec自体のインストール

(auto-install-from-url "https://raw.github.com/uk-ar/el-spec/144c053a5303101378d6e3b981d10b715a6c8775/el-spec.el")

を評価するか、

marmaladeから

M-x package-install el-spec

でOKです。

インストール後に

(require 'el-spec)

とすると使えます。

お品書き

使い方をチュートリアル風に解説します。内容はこんな感じです。

基本的な構造(前処理/後処理の設定)

基本的にdescriptionブロックの中にテストケース(example)を書いていきます。descriptionの中でitブロックに囲われた部分が独立したexampleになります。

具体的には

(describe "description"
  (it "test 1"
    (should ...)
    )
  (it "test 2"
    (should ...)
    )
  ...
  )

のような形になります。

前処理/後処理を設定するにはbefore/afterマクロを使用します。

(require 'el-spec)

(describe "description"
  (before
    (message "before common")
    )
  (after
    (message "after common\n")
    )
  (it "test 1"
    (message "test 1")
    )
  (it "test 2"
    (message "test 2")
    )
  )

を実行すれば、

before common
test 1
after common

before common
test 2
after common

のように実行されます。

実行するには M-x el-spec:eval-buffer を使用するか、describeのS式を M-C-x とかでevalすればオッケーです(この方法はel-expectationを参考にしました)。実行するとertのテスト結果が出ますが、ここでは気にせずmessageバッファをみてみましょう。

前処理/後処理の階層化(コンテキストの使用)

さらに前処理/後処理はcontextマクロにより階層化することができて

(describe "description"
  (before
    (message "before common"))
  (after
    (message "after common\n"))
  (context "when 1"
    (before
      (message "before 1"))
    (after
      (message "after 1"))
    (it "test 1"
      (message "test 1")))
  (context "when 2"
    (before
      (message "before 2"))
    (after
      (message "after 2"))
    (it "test 2"
      (message "test 2")))
  )

のように書けば、

before common
before 1
test 1
after 1
after common

before common
before 2
test 2
after 2
after common

のように実行されます。

describe,context,itに与える(第一引数の)説明文字列は結合してテスト名となります(例えばtest 1は"description\nwhen 1\ntest 1"のようなテスト名になります)。ですので、説明文字列コンテキスト内でユニークであることと、改行"\n"を使わないことを気をつけて下さい(重複した場合は、定義時に警告が出ます)。

before/afterの他にaroundマクロも使用することができるので、上のテスト

(describe "description"
  (around
    (message "before common")
    (funcall el-spec:example)
    (message "after common\n")
    )
  (context "when 1"
    (around
      (message "before 1")
      (funcall el-spec:example)
      (message "after 1")
      )
    (it "test 1"
      (message "test 1")))
  (context "when 2"
    (around
      (message "before 2")
      (funcall el-spec:example)
      (message "after 2")
      )
    (it "test 2"
      (message "test 2")))
  )

と書き直すことができます。

aroundを使えば、it節を囲うような使い方(with-temp-bufferやletなど)が可能です。

実用

上で挙げた機能も含めて、実際の例で説明します。

題材として括弧の自動挿入を取り上げます。

ここでは

  • 開き括弧を入力すると括弧のペアを挿入
  • 閉じ括弧を入力すると閉じ括弧のみ挿入
  • 開き括弧かどうかは文脈やモードに依存

という仕様を確かめるため以下の3つのテストを書きます。

(with-temp-buffer
  (switch-to-buffer (current-buffer))
  (c-mode)
  (execute-kbd-macro "'")
  (should (string= (buffer-string) "''"))
  )

(with-temp-buffer
  (switch-to-buffer (current-buffer))
  (c-mode)
  (insert "'")
  (execute-kbd-macro "'")
  (should (string= (buffer-string) "''"))
  )

(with-temp-buffer
  (switch-to-buffer (current-buffer))
  (emacs-lisp-mode)
  (execute-kbd-macro "'")
  (should (string= (buffer-string) "'"))
  )

明らかにwith-temp-bufferとswitch-to-bufferの部分が冗長なのでaroundで共通化します。

(describe "auto-pair"
  (around
    (with-temp-buffer
      (switch-to-buffer (current-buffer))
      (funcall el-spec:example)))

  (it ()
    (c-mode)
    (execute-kbd-macro "'")
    (should (string= (buffer-string) "''")))
  (it ()
    (c-mode)
    (insert "'")
    (execute-kbd-macro "'")
    (should (string= (buffer-string) "''")))
  (it ()
    (emacs-lisp-mode)
    (execute-kbd-macro "'")
    (should (string= (buffer-string) "'")))
  )

itへの説明文字列nilを渡すことで省略可能で、省略時にはブロック内容が説明文字列になります。

なおこれ以降は実行時にテストが失敗することがあると思います。その場合、ertバッファ上の失敗したテスト名の場所で「b」を入力すると実行時のバックトレースを表示することができます。また、本来ならテスト名の上で「RET」とすることでテスト定義した場所へ飛ぶことができるはずですが、el-specでは現状使えません。

変数の使用

次はわかりやすいようモードごとにテストをグループ化しましましょう。

(describe "auto-pair"
  (around
    (with-temp-buffer
      (switch-to-buffer (current-buffer))
      (funcall el-spec:example)))

  (context "in c-mode"
    (before
     (c-mode))

    (it ()
      (execute-kbd-macro "'")
      (should (string= (buffer-string) "''")))
    (it ()
      (insert "'")
      (execute-kbd-macro "'")
      (should (string= (buffer-string) "''"))))

  (context "in emacs-lisp-mode"
    (before
      (emacs-lisp-mode))

    (it ()
      (execute-kbd-macro "'")
      (should (string= (buffer-string) "'"))))
  )

モード切り替え部分(before)が冗長ですね。モード名を変数にできたらスッキリします。

(describe ("auto-pair" :vars (mode))
  (around
    (with-temp-buffer
      (switch-to-buffer (current-buffer))
      (funcall mode)
      (funcall el-spec:example)))

  (context ("in c-mode" :vars ((mode 'c-mode)))
    (it ()
      (execute-kbd-macro "'")
      (should (string= (buffer-string) "''")))
    (it ()
      (insert "'")
      (execute-kbd-macro "'")
      (should (string= (buffer-string) "''"))))

  (context "in emacs-lisp-mode"
    (let ((mode 'emacs-lisp-mode))
      (it ()
        (execute-kbd-macro "'")
        (should (string= (buffer-string) "'")))))
  )

定義時の変数はそのままでは実行時に参照できません。なので、自前でlexical-letを使うか、describe,context,itに:varsというキーワード引数変数宣言をしてあげるとうまいことしてくれます(:varsはletと同じ形式で変数を受け付けます)。

一度:varsで変数宣言をすれば、変数への代入はletやsetq、:varsで可能です。

コンテキストの共有(shared_context)

テスト(example)が増えてくると、beforeやafterをまとめたcontextを複数の場所で使いたいことがあります。

例えば、上記の2つ目のexampleのように文字を挿入するexampleを追加すると次のようになります

(describe ("auto-pair" :vars (mode))
  (around
    ...)

  (context ("in c-mode" :vars ((mode 'c-mode)))
    (it ()
      ...)

    (context ("buffer-string before" :vars (string-of-buffer))
      (before
        (insert string-of-buffer))
      (it (:vars ((string-of-buffer "'")))
        (execute-kbd-macro "'")
        (should (string= (buffer-string) "''")))))

  (context "in emacs-lisp-mode"
    (let ((mode 'emacs-lisp-mode))
      (it ()
        ...)

      (context ("buffer-string before" :vars (string-of-buffer))
        (before
          (insert string-of-buffer))
        (it (:vars ((string-of-buffer "\"")))
          (execute-kbd-macro "\"")
          (should (string= (buffer-string) "\"\"")))
        )))
  )

この例では(before (insert string-of-buffer))の部分を共有したいところですが、c-modeとemacs-lisp-modeでコンテキストを分けているので難しいです。

このような場合はshared-contextとinclude-contextを使います。

(describe ("auto-pair" :vars (mode))
  (around
    (with-temp-buffer
      (switch-to-buffer (current-buffer))
      (funcall mode)
      (funcall el-spec:example)))
  (shared-context ("insert string" :vars (string-of-buffer))
    (before
      (insert string-of-buffer)))

  (context ("in c-mode" :vars ((mode 'c-mode)))
    (it ()
      (execute-kbd-macro "'")
      (should (string= (buffer-string) "''")))

    (context "buffer-string before"
      (include-context "insert string")
      (it (:vars ((string-of-buffer "'")))
        (execute-kbd-macro "'")
        (should (string= (buffer-string) "''")))))

  (context "in emacs-lisp-mode"
    (let ((mode 'emacs-lisp-mode))
      (it ()
        (execute-kbd-macro "'")
        (should (string= (buffer-string) "'")))

      (context "buffer-string before"
        (include-context "insert string")
        (it (:vars ((string-of-buffer "\"")))
          (execute-kbd-macro "\"")
          (should (string= (buffer-string) "\"\"")))
        )))
  )

shared-contextはcontextマクロと同じような使い方で定義します。定義したshared-contextをinclude-contextすれば、その場所で使えるようになります。

exampleの共有(shared_example)

テスト(example)が増えてくると、あるテストを違うコンテキスト(違う前提条件)で実行したいことがあります。

例えば、上記4つ目の「"」を入力するexampleはc-modeでもemacs-lisp-modeでも動作します。

このような場合はshared-examplesとinclude-examplesを使います。

(describe ("auto-pair" :vars (mode))
  (around
    (with-temp-buffer
      (switch-to-buffer (current-buffer))
      (funcall mode)
      (funcall el-spec:example)))
  (shared-context ("insert string" :vars (string-of-buffer))
    (before
      (insert string-of-buffer)))
  (shared-examples "examples for \""
    (it ()
      (execute-kbd-macro "\"")
      (should (string= (buffer-string) "\"\""))))

  (context ("in c-mode" :vars ((mode 'c-mode)))
    (it ()
      (execute-kbd-macro "'")
      (should (string= (buffer-string) "''")))
    (include-examples "examples for \"")
    (context "buffer-string before"
      (include-context "insert string")
      (it (:vars ((string-of-buffer "'")))
        (execute-kbd-macro "'")
        (should (string= (buffer-string) "''")))))

  (context "in emacs-lisp-mode"
    (let ((mode 'emacs-lisp-mode))
      (it ()
        (execute-kbd-macro "'")
        (should (string= (buffer-string) "'")))
      (include-examples "examples for \"")
      ))
  )

簡単にするため、上記の例とは少しテスト内容を変更しています。

最後にテストコードと実装コード一つにまとめるケースも考えて、dont-compileで囲むと

(dont-compile
  (when (fboundp 'describe)
    (describe ("auto-pair" :vars (mode))
      (around
        (with-temp-buffer
          (switch-to-buffer (current-buffer))
          (funcall mode)
          (funcall el-spec:example)))
      (shared-examples "examples for quote"
        (it ()
          (execute-kbd-macro quote)
          (should (string= (buffer-string) (concat quote quote))))
        (context ("buffer-string before" :vars (string-of-buffer))
          (before
            (insert string-of-buffer))
          (it (:vars ((string-of-buffer quote)))
            (execute-kbd-macro quote)
            (should (string= (buffer-string) (concat quote quote))))))

      (context ("in c-mode" :vars ((mode 'c-mode)))
        (context ("examples for \"" :vars ((quote "\"")))
          (include-examples ("examples for quote" )))
        (context ("examples for '" :vars ((quote "'")))
          (include-examples ("examples for quote"))))
      (context ("in emacs-lisp-mode" :vars ((mode 'emacs-lisp-mode)))
        (it ()
          (execute-kbd-macro "'")
          (should (string= (buffer-string) "'")))
        (context ("examples for \"" :vars ((quote "\"")))
          (include-examples ("examples for quote" :vars ((quote "\""))))))
      )))

といった感じで完成です。

テスト実行範囲の変更

テストが増えてくると、すべてのテストを実行した場合に時間がかかるようになります。普段は一部分のテストだけ実行して、区切りがついたら全部をテストできると便利ですね。

M-x el-spec:eval-and-execute-contextでカーソル付近コンテキストだけを実行することができます。逆にM-x el-spec:eval-and-execute-allでdescribe以下のコンテキストを実行できます。M-C-x でevalした時の挙動も切り替えが可能で、M-x el-spec:toggle-selectionするたびにallとcontextが切り替わります。

課題と対応

現在判明してるデメリットとして、

  1. テストの失敗時にexampleに飛べない
  2. 個々のテスト実行ができない
  3. 変数定義が分かりづらい(:varsを忘れる)
  4. (無名関数を多用してるので)バックトレースが追いづらい

という4つは認識しています。

で、今後の対応予定/回避策は以下の通りです。

1. に関してはかなりだるい&対応策があるような気がするので次回対応します。

2. に関しても浅い階層のexampleを実行する際には欲しくなりますが、実装をがんばらないといけない感じです。とりあえずはcontextを作ることで回避可能なので、気力があれば対応します。

3. に関しては自分で使っていても:varsをつけ忘れてエラーがよく出ます。describe以下のletをlexical-letに置き換える技もありますが副作用心配です。もう少し使い込んでから対応を決めます。

4. 設計的に対応が厳しいです。私は慣れてきました。アイデアがあれば下さい。

あとがき

最低限の動くものはすぐにできたのですが、使っているうちにいろいろと機能が欲しくなって時間がかかってしまいました。

マクロを使いまくったおかげでマクロに詳しくなった気がします。

実装のコンセプトは単純なので、クロージャが使える言語なら移植は可能です。最低限の実装は

https://github.com/uk-ar/el-spec/tree/a7b548271ae0cb996e5c201712f1e658c075c65c

にあるので興味があればのぞいてみて下さい。

もちろん要望フィードバック、pull requestもウェルカムです!

2012-06-13

flex-autopair v0.3:Emacs 24対応。指定したモードで無効化。モードごとの設定を強化など。

flex-autopair v0.3 をリリースします。変更点は以下です

  1. Emacs 24に対応しました
  2. モードを指定して無効にできるようにしました
  3. モードごとの設定を強化しました

変更詳細

1つめはEmacs 24への対応です。関西Emacsで@さんから報告を受けて気づきました。Emacs 24の新しいAPIを使おうとして、使い方が間違っていたため動かなくなっていたのを修正しました。

2つ目は無効にするモードの指定についてです。@さんからの

提案を受けて、特定のモードで無効化することができるようにしました。

例えばlisp系のモードで無効にするには

(setq flex-autopair-disable-modes
        '(emacs-lisp-mode lisp-interaction-mode lisp-mode ilem-mode))

とします。これに関連して、v0.2までは

M-x flex-autopair-mode ですべてのバッファに対してトグルできましたが、

v0.3からは

M-x flex-autopair-mode で現在のバッファに対してトグル

M-x global-flex-autopair-mode で新規のバッファに対してトグル

となります。

3つめはモードごとの設定の強化です。v0.2までは条件設定(flex-autopair-conditions)をグローバルで持っていましたが、v0.3ではバッファごとに切り替えができるようになりました。これにより、

  • 設定が増えてもそれほど重くならない
  • 他のモードを気にせず書き換えられる

などのメリットがあります。

これに関連して各種モード用の設定を追加しました。

  • haskell-mode(')とcoffee-mode(`)の設定を追加しました。haskell-modeの方は(')がシンボル名としても使えるように、空白の後ろだけペアにするようになってます。@さんからのpull requestでした。
  • c系のモードで中括弧「{」を入れると自動で改行するようにしました。実際の動きは
{
    !! //←!!の場所にカーソルがインデントした状態で配置
}

みたいな感じです。こちらは第5回関西Emacs勉強会での id:lurdan さんからの要望を反映しました。

インストール方法

ソースgithubにおいてあるので

(auto-install-from-url "https://raw.github.com/uk-ar/flex-autopair/0184a539b874e20938418e4dbeaec0665129bf46/flex-autopair.el")

を評価するか、

marmaladeから

M-x package-install flex-autopair

インストール可能です。

その他

個人的に一番大きな変更点はモードごとの設定切り替えです。これで、設定が書きやすくなって実用的な使い方ができるかと思います。使ってみて設定の公開もしくはpull requestをしてみて下さい。

2012-06-06

key-combo v1.5.1:文字列境界でのバグ修正。デフォルト設定の強化(特にrubyやc)。

key-combo v1.5.1をリリースします。変更点は以下です

  1. 文字列境界の判定に関するバグを修正しました
  2. デフォルト設定を強化しました(特にrubyやc)
  3. 誤ってflex-autopairの関数を呼び出していたのを修正

変更詳細

1つめは文字列境界の判定に関するバグ修正です。文字列コメントのなかでkey-comboが動くとイラっとするので、判定して動かないようにしてるつもりでした。ですが、判定ロジックに穴があったので行末やら境界で誤判定してました。@さんからのhttps://github.com/uk-ar/key-combo/issues/20:バグ報告]があり、修正も@tomy_kairaさんがしてくれました。やっほい!

2つめはデフォルト設定に関してです。またまた@tomy_kairaさんのpull requestによる"!=="演算子を入れて、ruby演算子関連を

コーディング規約をまとめてみた (Ruby編) - bojovs::blog

を参考に追加、後はc言語も。

3つめは@さんからのバグ報告に感する修正です。間違ってflex-autopairの関数を呼び出していたため、flex-autopairを入れてないと動かなくなる(これはひどい…)のを修正しました。

インストール方法

ソースgithubにおいてあるので

(auto-install-from-url "https://raw.github.com/uk-ar/key-combo/36cc9bc85868cea9c32b18031850b1f5d9633e31/key-combo.el")

を評価するか、

marmaladeから

M-x package-install key-combo

インストール可能です。

その他

大きな機能追加はなく、デフォルト設定の強化とバグ修正がメインでした。