Middleman(Slim) + Ractive.jsでWeb AppのUIを作る
JSONでバックエンドサーバとデータをやり取りするというごく普通のWeb Appを作るにあたり、 UIをどうするか悩みつつ Middleman と Ractive.js を使ってみることにした。
Middlemanを選んだのは
- 開発中のlivereload
- css, jsのconcat/minify
- ページの構造化
- 各種ライブラリの管理
がお手軽そうだったのと直接htmlを書かなくて済むから。
Ractive.jsはデータバインディングでMiddlemanと組み合わせても違和感無く使えそうな感じだったから。
そして一番の理由は
「htmlがよくわからない」
ってメンバーでもtracやredmineのwikiとかチケットはバリバリ使っていたので、
Slimで書かれているところは内容を理解してもらえそうだったから。
あわよくばUIや(フロント側が要求する)APIの修正なんかもやってくれるようになるかもと思い、ひと通りデモを見せたところ
「全然わかりませんでした」
と言われれるという残念な結果に...
そんなこんなで実際に作ったものはこのまま消えていってしまいそうなので 忘れないようにサンプルを残しておくことにする。
Goでhttp.ClientのテストをするときにProxyを書き換えてテストサーバにリクエストを投げる
Goで外部リクエストが関わる処理をテストする - Qiita
のfetch(url string)
と違って引数でURLを取れないような関数をテストする場合、
http.DefaultTransport.(*http.Transport).Proxyを書き換えるとテストサーバにリクエストを飛ばせる。
main.go
package main import ( "fmt" "io/ioutil" "log" "net/http" ) func fetch() []byte { res, err := http.Get("http://localhost:8000/test") if err != nil { log.Fatal(err) } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatal(err) } return body } func main() { fmt.Printf("%s", fetch()) }
main_test.go
package main import ( "fmt" "net/http" "net/http/httptest" "net/url" "testing" ) func TestFetch(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "test") })) defer ts.Close() defaultProxy := http.DefaultTransport.(*http.Transport).Proxy http.DefaultTransport.(*http.Transport).Proxy = func(req *http.Request) (*url.URL, error) { // テストサーバのURLをProxyに設定 return url.Parse(ts.URL) } // テストが終わったらProxyを元に戻す defer func() { http.DefaultTransport.(*http.Transport).Proxy = defaultProxy }() value := string(fetch()) expected := "test" if value != expected { t.Errorf("Expected %v, but %v:", expected, value) } }
参考
前にどこかで似たような記事を見たような気がしたんけど今探したら見つからず...
かわりに
なんてのがあることを知った。
neocompleteのomniソースからneosnippetのスニペットを生成する
TokyoVim#24に行ってきた
今日の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-smtpがVimの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を使うことにしました。
ただテストが
- Vim script: テスト関数が呼ばれるとmockを使うためにpythonを呼び出す(テストスクリプト)
- python: mockでsmtplibの挙動を制御して外部モジュールを呼び出す(テストスクリプト)
- Vim script: 引数を受け取ってpythonに渡す(外部モジュール)
- python: smtplibを使ってメールを送信し、例外が発生したらVim scriptに返す(外部モジュール)
- Vim script: pythonで例外が発生していたらthrowする(外部モジュール)
- python: 外部モジュールで例外が発生していたら文字列にして返す(テストスクリプト)
- Vim script: 戻り値が期待通りか判定する(テストスクリプト)
と、Vim scriptとpythonを行ったり来たりでとても気持ち悪いものになってしまいました。
さて、目的のメール送信プラグインは作れたのでそのうちunite-notmuchにvital-smtpを組み込むなどしてメールを送信できるようにしたいと思います。
が、MIME関連の機能が足りないのでその前にvital-mimeが必要になるのかも...!?
それからテストをTravis CIで動かしたくてTravis CIにアカウントを作ってみたのですがローカルで全部通ったテストが大コケしたまま、 この記事を書いていたTokyo Vim#23がタイムアウト(スマブラタイム)してしまったので時間があるときに調べてみることにします。
明日は去年に引き続き@Linda_ppさんです。
スマブラでボコボコにされている様子。
そのあと本日発売のWii U版スマをブラした!
一回だけ奇跡の一位! pic.twitter.com/cKKYhaSOgM
— yoshiko (@yoshiko_pg) 2014, 12月 6
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コマンドの引数と同様の文字列で指定することが可能です。
ちょっと使ってみた感じ、慣れないと使いこなすのは難しそう...
まだ微妙なプラグインを作ってしまったか。