neocompleteのomniソースからneosnippetのスニペットを生成する

前回のTokyoVimで作ったアレプラグイン化しました。

github.com

プラグイン名は語感と強引なこじつけです。
クーポンなんかはありません。

を実装したかったところだけど、とりあえず公開してOmniSharp対応*1を優先させることにしました。

*1:thincaさんのPR

TokyoVim#24に行ってきた

tokyovim.connpass.com

今日のTokyoVimではneocompleteのomniソースから関数のシグネチャスニペットを生成するVim scriptを作ってみました。

今のところ対応しているのは

のみです。

使い方は以下のソースをvimrcにでも貼り付けて適当にマッピングするだけです。

imap <C-]> <Plug>(neosnippet_autogen_signature)

プラグイン化の予定は未定です。

vital-smtpを作った

Vim Advent Calendar 2014の7日目の記事です。 昨日は@katono123さんのVim script + Lua で rogue.vim を作った話でした。

以前unite-notmuchというメールを閲覧するプラグインを作ったのですが、 メールを送信する機能がないため、これと組み合わせて使うメール送信プラグインが欲しいと思っていました。

探してみると

などが見つかりましたが、これらは単体で使用するためのプラグインなので他のプラグインと組み合わせて使うには向いていないようです。
やはりVimでメールを送りたいという人がいないからなのか、これといったものが見つからなかったので自作してみることにしました。

他のプラグインと組み合わせて使うというと真っ先に思いつくのがvital.vimです。
少し前から気にはなっていたのですが(vital-overなど)、vital.vimは独自に外部モジュール作ることができるようなので今回はそれを試してみます。

1. vital外部モジュールの作成

作成するのはSMTPでメールを送信するvitalモジュールなのでプラグイン名は vital-smtp とします。
まずはプラグイン用のディレクトリ、 vital-smtp を作成します。
中身は本家vital.vimと同じでautoload配下に vital/__latest__ を配置すれば良いようです。
プラグイン本体はその配下に配置することになるので SMTP.vim を作成します。

vital-smtp
└── autoload
     └── vital
         └── __latest__
             └── SMTP.vim

完成したプラグインこちらです。
pythonのsmtplibを利用してメールを送信する s:sendmail という関数があるだけの簡単なプラグインになりました。

function! s:sendmail(addr, user, password, from_addr, to_addrs, msg)
    " 省略
endfunction

2. vital外部モジュールの使い方

vitalの外部モジュールを作成したら次は実際にプラグインに組み込んでみることにします。
とりあえず確認用なので適当なディレクトリにサンプルプラグインを作ります。

$ mkdir vim-sendmail-example
$ cd vim-sendmail-example/
$ mkdir autoload plugin
$ vim plugin/sendmail_example.vim

組み込み方はvital-smtpVimのruntimepathに通っていれば通常のvitalモジュールと同じようにVitalizeコマンドを実行するだけです。

:Vitalize --name=sendmail_example . SMTP

プラグイン内での呼び出し方も同様で、 import するだけで先ほど作成した関数を使うことができるようになります。

let s:SMTP = vital#of('sendmail_example').import('SMTP')
" call s:SMTP.sendmail()が使えるようになる

完成したサンプルプラグインこちらです。
:Sendmail コマンドを実行するとプロンプトに入力した内容でメールを送信します。

3. メール送信の確認

手っ取り早く使えそうなSMTPサーバが思いつかなかったのでローカルのメールサーバでサンプルプラグインの確認をします。

# pythonに付属しているデバッグ用サーバを起動する
$ sudo python -m smtpd -c DebuggingServer localhost:10025

サーバが起動したらVimを立ち上げてサンプルプラグインの:Sendmailコマンドを実行します。

:Sendmail
host: localhost<Enter>
port: 10025<Enter>
user: <Enter><Enter>
password: <Enter>
from: test@example.com<Enter>
to: test@example.com<Enter>
msg: test<Enter>

msgにtestと入力してEnterを押すとメールサーバのコンソールにVimから送ったメールが表示されました。

---------- MESSAGE FOLLOWS ----------
From: test@example.com
To: test@example.com
X-Peer: 127.0.0.1

test
------------ END MESSAGE ------------

4. テストの追加

順番は置いておいて、せっかくプラグインを作ったのでthincaさんのvim-themisを使ったテストを追加しておきます。

vital-smtp
├── autoload
│   └── vital
│       └── __latest__
│           └── SMTP.vim
└── test
    └── SMTP.vim

テストはthemisコマンドに --runtimepath でvital-smtpに必要なプラグインを指定して実行します。

$ themis --runtimepath /tmp/vital.vim
1..9
ok 1 - SMTP test_import
ok 2 - SMTP test_sendmail_success
ok 3 - SMTP test_sendmail_success_without_starttls
ok 4 - SMTP test_sendmail_success_without_login
ok 5 - SMTP test_sendmail_failed_to_connect
ok 6 - SMTP test_sendmail_failed_to_starttls
ok 7 - SMTP test_sendmail_failed_to_login
ok 8 - SMTP test_sendmail_failed_to_send
ok 9 - SMTP test_sendmail_failed_to_quit

# tests 9
# passes 9

5. ハマったところ

if_pyの例外

pythonで例外が発生するとコマンドラインにはpythonのTraceが表示されますが、 v:exception が常に 'Vim(python):Traceback (most recent call last):' になってしまうため、 Vim script内ではcatchできなくて困りました。
これが仕様なのかはよくわかりませんが、今回はif_py側で例外を捕捉したら文字列にしてVim script側に返す作りにしました。

if_pyを使った関数のテスト

pythonのsmtplib周りのテストにはメールサーバが必要なのですが、 例外を発生させるためのメールサーバを用意するのが面倒だったので mockを使うことにしました。
ただテストが

  1. Vim script: テスト関数が呼ばれるとmockを使うためにpythonを呼び出す(テストスクリプト)
  2. python: mockでsmtplibの挙動を制御して外部モジュールを呼び出す(テストスクリプト)
  3. Vim script: 引数を受け取ってpythonに渡す(外部モジュール)
  4. python: smtplibを使ってメールを送信し、例外が発生したらVim scriptに返す(外部モジュール)
  5. Vim script: pythonで例外が発生していたらthrowする(外部モジュール)
  6. python: 外部モジュールで例外が発生していたら文字列にして返す(テストスクリプト)
  7. Vim script: 戻り値が期待通りか判定する(テストスクリプト)

と、Vim scriptとpythonを行ったり来たりでとても気持ち悪いものになってしまいました。


さて、目的のメール送信プラグインは作れたのでそのうちunite-notmuchにvital-smtpを組み込むなどしてメールを送信できるようにしたいと思います。
が、MIME関連の機能が足りないのでその前にvital-mimeが必要になるのかも...!?

それからテストをTravis CIで動かしたくてTravis CIにアカウントを作ってみたのですがローカルで全部通ったテストが大コケしたまま、 この記事を書いていたTokyo Vim#23タイムアウト(スマブラタイム)してしまったので時間があるときに調べてみることにします。

 
明日は去年に引き続き@Linda_ppさんです。  
 
 
スマブラでボコボコにされている様子。

VimConf 2014に行ってきて

改めて思ったのは、

若手の勢いがすごい

ということ。


今回の発表者は多分ほとんどが自分と同年代かそれ以下だったはず。
参加者も懇親会でちょこちょこと話した感じだと若い/ビギナーな人が多かったし、
(凡人の自分と比べても仕方がないんだけど)みんな才能に溢れているように感じた。


他の勉強会にはほとんど行ったことがないからよくわからないけど
10年以上使われているとはいえ、プログラミング言語ではなく
ソフトウェアでこんなに素晴らしい若手が集まるのは本当に凄いと思う。


一利用者として今後のVimがとても楽しみだし期待しています。
って言ってるだけじゃなく、負けずに少しでも何かに貢献していきたいとは思うんけど
さてどうなることやら...



あ、各セッションの感想については小並感なので割愛で。

autorepeat.vim作った

Vimmerはf拡張プラグインを作る*1

自分も犬Vimmer

けどf系って実はあまり使っていない...

ひとまずfにこだわらず横移動プラグインを考えてみよう

1キーで自動的にカーソル移動が始まって好きなタイミングで止める、とかどうだろう?

autorepeat.vim完成

結局1キーではできなかったのでトリガーを入力した後に
繰り返したい操作を続けて入力するという作りにしました。

具体的な使い方としてはvimrcに

nmap <Space>. <Plug>(autorepeat)

のような設定をし、

<Space>.

の後に繰り返したいノーマルモードコマンドを入力します。

" 例
<Space>.l

なお、今のところノーマルモードにしか対応していません。

繰り返しが始まるまでの時間は

g:autorepeat_timeout

に秒単位の数値、

繰り返し操作の間隔は

g:autorepeat_interval

に:sleepコマンドの引数と同様の文字列で指定することが可能です。

ちょっと使ってみた感じ、慣れないと使いこなすのは難しそう...
まだ微妙なプラグインを作ってしまったか。

*1:日本の代表的な犬Vimmerである@Linda_ppさん、@deris0126さんが作っていたので勝手にそう思っただけです

Vimでメールを読む

前回のTokyoVim#19unite-notmuchというプラグインを作りました。
このプラグインnotmuchというコンソール上で動作するメールリーダーを使い、
Uniteのインターフェースから

  • メールの表示
  • メールの検索
  • メールの未読/既読の切替

をすることができます。


なお、

  • メールの受信
  • メールの送信

はそもそもnotmuch本体が出来ないのでこのプラグインでも出来ません。

また、notmuchがWindowsでは使えないようなのでこのプラグインも使えません。

必要なソフト

メール環境の設定(offlineimap編)

  1. notmuchのインストール
# Mac OS X
$ brew install notmuch

# Linux(gentoo)
$ sudo emerge notmuch
  1. notmuchの設定
$ vim ~/.notmuch-config
[database]
# 絶対パスで指定する
path=/Users/ユーザ名/Maildir
#path=/home/ユーザ名/Maildir

[user]
name=アカウント名
primary_email=メールアドレス

[new]
tags=unread;inbox;
ignore=

[search]
exclude_tags=deleted;spam;

[maildir]
synchronize_flags=true
  1. offlineimapのインストール
# Mac OS X
$ brew install offlineimap

# Linux(gentoo)
$ sudo emerge offlineimap
  1. offlineimapの設定
$ vim ~/.offlineimaprc
[general]
metadata = ~/.offlineimap
accounts = アカウント設定名

[Account アカウント設定名]
localrepository = ローカル設定名
remoterepository = リモート設定名
status_backend = sqlite
postsynchook = notmuch new

[Repository ローカル設定名]
type = Maildir
# notmuch-configのdatabaseで指定したパス
localfolders = ~/Maildir/

[Repository リモート設定名]
type = IMAP
remotehost = メールサーバ
remoteuser = アカウント名
remotepass = パスワード
maxconnections = 1

folderfilter = lambda foldername: foldername in ['INBOX']

使い方(offlineimap編)

事前に

$ offlineimap

でメールを受信しておく必要があります。
いちいちコマンドを実行するのが面倒ならcronにでも仕込んでおけば良いらしいです。

メールを受信したらVimから以下のコマンドを実行します。

:Unite notmuch

フォルダ一覧画面では以下のアクションが実行可能です。

  • フォルダを開く(open)
  • フォルダ内のメールを既読にする(read)
  • フォルダ内のメールを未読にする(unread) => TokyoVim#20で追加
  • フォルダ内のメールを検索する(search) => TokyoVim#20で追加


フォルダを開いた後のメール一覧画面では以下のアクションが実行可能です。

  • メールを開く(open)
  • 選択したメールを既読にする(read)
  • 選択したメールを未読にする(unread) => TokyoVim#20で追加
  • メールをプレビューウィンドウで開く(preview) => TokyoVim#20で追加

興味がある人は使ってみてください。

TokyoVim#19に行ってきます

今日はTokyoVim#19です。
ゴールデンウィークで鈍ったVim力を鍛え直しましょう。

今年のゴールデンウィークは去年よりたくさん休んでしまい、
なんとその間にメールが4000通近くもたまってしまいました。

普段メーラーWindows上のThunderbirdを使っていますが、
処理するのがさすがにしんどかったのでなんとかしたいです。

そこで思いついたのがVim上でメールを処理するという方法。
リモートからでもsshで繋いでコンソールから使うことができ、
就業時間の99%をVim上で過ごす人にはかなり便利そうです。

ただVim上で動くメーラーというのはGmail用ばかりで普通のメーラー
なかなか良さそうなのがみつかりませんでした。

notmuch.vimというプラグインはあるものの、

  • Vimの設定を勝手に変えるっぽい
  • フォルダに大量のメールがあると固まる

など、ちょっとイマイチだったので今回のTokyoVimでは
このnotmuchをUniteあたりから使えるようにしてみたいと思います。