Hatena::ブログ(Diary)

Memo

2016-07-15

[] Vim-Pokemon 〜あなたが Vim で開いているファイルに潜んでいるポケモン〜

see Pokemon-Emacs 〜あなたが Emacs で開いているファイルに潜んでいるポケモン〜 - Thanks Driven Life

TL;DR

最近は Pokemon Go が流行っているようで、正式サービス開始を待ち望まれているようです。

『Pokemon GO』は、位置情報を活用することにより、現実世界そのものを舞台として、ポケモンを捕まえたり、交換したり、バトルしたりするといった体験をすることのできるゲームです。 このゲームはモニターの中だけで完結せず、プレイヤーは実際に家の外に出てポケモンを探したり、他のプレイヤーと出会ったりしながら楽しむことができます。

面白そうですね。海外でも既にユーザが爆発的に増えており、スマホ片手に街をうろうろする様子などを画像や動画でも目にします。

さて、日本は夏まっさかりであり、暑い日が続いています。そんな中

「私もポケモン探しにいきたいけどまだサービス開始してないし、 そもそも外に出たくない… 」

という Vimmer も多いと思います。

でもよく考えてみてください。ポケモンは何も外だけに居るわけじゃないんです。 昔はゲームボーイにいました。じゃあ Vim にも居るかもしれないですよね。

Vim-Pokemon とは

https://github.com/heavenshell/vim-pokemon

Vim のライブラリーの一つです。効果としては「今開いているファイル名の絶対パス(もしくはバッファー名)で一意に決まるポケモン名を表示する」だけです。

とりあえずいろいろがんばって .vimrc に設定してもらったあと

$ vim /path/to/俺のリポジトリ/github/vim/vim-pokemon/README.md

を実行すると、(おそらく)ファイル名の横あたりに、下図っぽい感じでポケモン名が表示されます。

この場合は ジュゴン が選ばれました。

つまり /path/to/俺のリポジトリ/github/vim/vim-pokemon/README.md にはジュゴンが潜んでいる。豆知識です。

ちなみに 無名バッファー にはフシギダネが居ます。多分。

実装についてちょっとだけ

特に難しいことはしてませんが

  • ファイル名、もしくはバッファ名を seed として乱数をゲット
    • なのでどの環境でもファイル名が同じ = 同じポケモンが出てくる。はず。
  • (もちろんポケモン一覧 s:monsters が変化したら変わりますが…)
    • ポケモン一覧から↑の乱数を index としてポケモンをゲット

これだけです。

少し前に Pokemon-Go におけるポケモン出現率*1 みたいな画像を見たので、出現率に併せて「出やすいポケモン」「出にくいポケモン」みたいな実装をしてたんですが、 あの画像自体デマだったみたいなコメントもあったので、まあいいかってことでとりあえず愚直にリストから取るようにしました。

あとはポケモン一覧はとりあえず初代の 151 匹*2をチョイスしました。他のシリーズ追加すれば勝手に出てくるとおもいます

まとめ

「/path/to/foo にピカチュウが潜んでいたぞ!!」 「ミュウが見つからねえ!!」

みたいな楽しみ方で、エディタ生活に華を添えてください。ポケモン大好き!!


蛇足

あとネタとしてパクらせてもらった、偉大な Emacs ハッカーの @gongoz さん大好き!

2016-06-25

[] Testinfra を使って見る

Ruby の Infrataster ではなく Testinfra


Testinfra aims to be a Serverspec equivalent in python and is written as a plugin to the powerful Pytest test engine

https://github.com/philpep/testinfra

ってある通り Python 版 Serverspec。

テストランナーに PyTest を使っている。


# -*- coding: utf-8 -*-
import re

class TestNginx(object):
    def test_nginx_should_installed(self, Package):
        """ nginx should be installed. """
        nginx = Package('nginx')
        assert nginx.is_installed        
        assert nginx.version.startswith('1.6.1')
          
    def test_nginx_should_running(self, Command):
        nginx = Command('/etc/init.d/nginx status')
        assert re.match(r'^nginx*', nginx.stdout)

    def test_nginx_conf_should_exists(self, File):
        f = File('/etc/nginx/nginx.conf')
        assert f.exists                  

    def test_nginx_confd_should_exists(self, File):
        f = File('/etc/nginx/conf.d')    
        assert f.is_directory

ドキュメントのサンプルは PyTest の関数で書かれていたけど、クラスでも書ける。

$ testinfra -vs test_nginx.py --connection=ssh --ssh-config=~/.ssh/config --hosts="host_name_is_here"

こんな感じに書くと、対象のサーバーに PyTest がテストを実行してくれる。


なお現状バックエンドに MacOSX は対応しておらず動かない。

また

def test_nginx_running_and_enabled(Service):
    nginx = Service("nginx")
    assert nginx.is_enabled

が、service コマンドが見つからないと怒られた。

2016-05-29

[] Flask 0.11 の後方互換がなくなる機能

Flask 0.11 がリリースされた。

Flask 0.11 Released | The Pallets Projects

# ちなみにどうでもいいけど、Flask のコードネームは酒の名前


後方互換がいくつかなくなってるので、まとめてみる。

# 漏れがあったら追記する予定


とりあえず自分のプロジェクト生成ツールで作成した Flask project を起動して試してみただけ。

flask.ext.* が非推奨に

/tmp/virtualenvs/flask_011/lib/python3.5/site-packages/flask/exthook.py:71: ExtDeprecationWarning: Importing flask.ext.cache is deprecated, use flask_cache instead.
  .format(x=modname), ExtDeprecationWarning

こんな感じで、Flask の拡張ライブラリ系で flask.ext.* を使っていると、警告が表示される。

自分のプロジェクトは flask.ext.* を flask_* に変更すればいい。

GitHub - pallets/flask-ext-migrate: A script for migrating extension import syntax.

あるいはマイグレーションツールがあるので、それを利用すると解決する。


ただし、ライブラリ内で使われている(例えば、Flask-Cache)場合は、ライブラリの対応を待つ必要がある。

Flask-Cache は Pull Request が出てたので、取り込まれるのを待つ。

# 自分のプロジェクトの場合、未だに flask.ext.* を使ってたのが、Flask-Cache だけだった


個人的には名前空間的に ext というのに属しているのはわかりやすくて良いし、flask_ とプレフィックスがつくのはイマイチ好きじゃない…。

# ext hook を呼んでいてるのでそのオーバヘッドはもちろんあるだろうけど…。

request.json が非推奨に

API サーバーとして Flask を利用していて、クライアントから JSONパラメーターとして要求している場合に、よく使われると思うけど、request.json じゃなくて request.get_json() にする必要がある。


メソッドを呼ぶ方がわかりやすいので、良いと思う。

Jinja2 のテンプレートのオートリロード

今まで、アプリケーションを起動したまま、Jinja2 のテンプレートを変更したら、次のリクエストからは、変更されたテンプレートが反映されたが、今回からは TEMPLATES_AUTO_RELOAD を Flask の設定に含めないといけない。

TEMPLATES_AUTO_RELOAD の設定がない場合は、デバッグモードの値を Jinja2 に auto_reload に突っ込んでいる。


本番環境では debug=False にしているので、ちょっと HTMLテンプレートを起動したまま変更…というのをやりたい場合は、TEMPLATES_AUTO_RELOAD にする必要がある。


大きい変更

flask コマンドが追加された。

Command Line Interface — Flask Documentation (0.11)

今まで、Flask-Script を使って、Flask にコマンドを追加していた。

それを使わなくても Flask だけでできるようになる(つまり Flask-Script を差し替える必要がある)。

時期を見て置き換えよう…。


他諸々追加になったりしてるものがあるので、何かあったら追記する。

# きになるのが、SESSION_REFRESH_EACH_REQUEST くらいか。

2016-05-14

[] Electron1.0 の起動時のエラー

遊びで作ってる Electron なアプリケーションの electron-prebuilt を 1.0.2 にあげて起動したら、エラーになった。

Cannot find module ‘app’

Cannot find module 'app' - electron - Atom Discussion


ということで、

import electron from 'electron';
import path from 'path';

const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const crashReporter = electron.crashReporter;

というふうに変えたら、いけた。

あと、crashReporter で submitURL を設定してないとエラーになって起動しないので、適当な URL を設定した。

2016-04-30

[] Vim の起動速度2

前回 Vim の packadd を使って、起動速度改善をした。

その後 MacVim Kaoriya に Timer 機能が追加されたバージョンが出たので、Timer に置き換えた。

.vimrc は以下みたいな感じで定義。

let s:plugins = [
  \ 'vim-l9',
  \ 'vim-fuzzyfinder',
  \ 'vim-fuzzyfinder-plugins',
  \ 'yankround.vim',
  \ ]
let s:idx = 0

function! PackAddHandler(timer)
  execute 'packadd ' . s:plugins[s:idx]
  let s:idx += 1
  "doautocmd BufReadPost
  autocmd! lazy_load_bundle
endfunction

augroup lazy_load_python
  autocmd! VimEnter *.py call timer_start(1, 'LazyLoadPython', {'repeat': 0})
augroup END

augroup lazy_load_filetype
  autocmd! VimEnter *.go,*.js,*.php call timer_start(1, 'LazyLoadFileType', {'repeat': 0})
augroup END

augroup lazy_load_bundle
  autocmd VimEnter * call timer_start(1, 'PackAddHandler', {'repeat': len(s:plugins)})
augroup END

.vim/config/plugins.vim

function! LazyLoadPython(timer) abort
  let _ft = &filetype
  packadd jedi-vim
  packadd pyflakes-vim
  packadd vim-autopep8
  packadd vim-virtualenv

  " Reload autocmd
  exec 'doautoall BufRead'

  " For Quickrun.vim
  exec 'set ft=' . _ft

  autocmd! lazy_load_python
endfunction 

function! LazyLoadFileType(timer) abort
  let _ft = &filetype
  echomsg string(_ft)
  if _ft =~ 'go'
    packadd vim-ft-go
    packadd vim-go-extra
    packadd vim-godef
  elseif _ft =~ 'javascript'
    packadd! vim-javascript
    packadd! vim-jsx
    packadd vim-jsdoc
  elseif _ft =~ 'php'
    packadd vmustache
    packadd pdv
  endif
  exec 'doautoall BufRead'
  " For Quickrun.vim
  exec 'set ft=' . _ft
  autocmd! lazy_load_filetype
endfunction

~/.vim/pack/ftbundle にファイルタイプごとのプラグインを入れている。

ftbundle は Timer を使って、Vim 起動後にバックグラウンドプラグインを読み込む。


他のプラグインは ~/.vim/pack/bundle/start というところに入れて、起動時に読み込むようにしている。


これで起動速度がどうなったかというと、vim-plug と比べてみた。

vim-plug の速度。

357.614  030.946: opening buffers
359.083  001.469: BufEnter autocommands
359.089  000.006: editing files in windows
359.430  000.341: VimEnter autocommands
359.436  000.006: before starting main loop
360.991  001.555: first screen update
360.993  000.002: --- VIM STARTED ---

packadd の速度。

132.434  030.058: opening buffers
132.907  000.473: BufEnter autocommands
132.913  000.006: editing files in windows
134.438  000.653  000.653: sourcing /Users/s_ohyanagi/.vim/pack/bundle/start/unite.vim/autoload/unite/custom.vim
139.671  004.501  004.501: sourcing /Users/heavenshell/.vim/pack/bundle/start/vim-watchdogs/autoload/watchdogs.vim
143.496  010.225  005.071: sourcing /Users/heavenshell/.vim/config/plugins.vim
143.862  000.724: VimEnter autocommands
143.868  000.006: before starting main loop
145.161  001.293: first screen update

起動速度が大体倍ほど速くなった。

2016-03-21

[] Jedi.vimVim の起動速度

あるいは、いかにして Vim の起動速度を取り戻したか。


いつのころか Vim の起動速度が遅くなった。

正確に言うと、Python のファイルを起動する際に遅い。


とりあえず起動時に何が遅いかプロファイルを取ってみた。

954.157  614.589  614.589: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./autoload/jedi.vim
954.426  617.175  002.586: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./ftplugin/python/jedi.vim
2947.941  1926.078  1926.078: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./autoload/jedi.vim
2948.210  1946.837  020.759: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./ftplugin/python/jedi.vim
757.152  499.467  499.467: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./autoload/jedi.vim
757.358  500.011  000.544: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./ftplugin/python/jedi.vim

速度が安定しないけど、酷い時で約 1.95sec 速い時で 500msec かかってる。

一度 Vim を起動して、すぐに再起動すると、もっと速い。

# OSキャッシュにのせないため、マシンを再起動しながらやったから時間かかった…


いつからこんな遅くなったのかというのを調べてみた。

jedi-vim 0.7 jedi 0.7

108.692  000.672  000.672: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./ftplugin/python/jedi.vim
172.864  000.078  000.078: sourcing /Users/s_ohyanagi/.vim/ftbundle/python/jedi-vim/./after/./ftplugin/python/jedi.vim

速い。ただし補完の候補が出てくるのが遅い(最新は0.7 に比べると速い)。


jedi-vim 0.8 jedi 0.8

1255.951  984.472  984.472: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./autoload/jedi.vim
1256.185  1009.923  026.451: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./ftplugin/python/jedi.vim

どうやら 0.8 から遅くなった。


ソースコードを見ていると、0.7 に比べて jedi 自体がファイル数が増えている。

最新の jedi 0.9 になるともっと増えている。

プロファイル取るために全てのコードにデバッグコードを仕込んだわけではないが、おそらく Python のファイルの import に時間が掛かっている模様。


インポートが遅いのは Python 自体を速くする、マシンの性能を速くする、ファイル数を減らすなどをしないと無理なので、ちょっと簡単に手を出せない。


次に試したのが、Vim-Plug による lazy load。

Vim-Plug とかそこら辺のプラグインマネージャ系は lazy load があるそうなので試してみた。

結果は対して変らない。

Lazy load ってのが filetype が python の時に読み込むというのが lazy load やら on demand load という事ならそらそうだ。

もともと unbundle.vim を使って filetype ごとのロードしかしていない。

# 余談だけど、vimrc とかに読み込むプラグイン候補をいちいち書くの、めんどくさかった


どうしたもんかと思っていたら、Vim 自体のパッケージ機能は使えないかと思ったら、タイムリーに

vim pluginのbackground loading - daisuzu's notes を読んだ。


MacVim Kaoriya(7.4 1-1537) にはまだタイマー機能は入っていなかったが、 Vimのパッケージ機能を試してみました - Blank File にある遅延読み込みをすれば出来るんじゃないかと思い、試してみた。

" ~/.vim/config/plugins.vim に定義
function! LazyLoadPython() abort
  packadd jedi-vim
  packadd pyflakes-vim
  packadd vim-autopep8
  packadd vim-virtualenv
  set filetype=python
  autocmd! lazy_load_python
endfunction

" .vimrc に定義
autocmd VimEnter * source ~/.vim/config/plugins.vim
augroup lazy_load_python
  autocmd! InsertEnter *.py :call LazyLoadPython()
  autocmd Filetype python    setlocal omnifunc=jedi#completions
augroup END

タイマー機能でバックグラウンドで読み込みたいが、まだできないので、とりあえず初回のインサートモードに入った際に実行するようにした。

これで Vim の起動速度が以下の感じになった。

jedi-vim 0.7 191.565
jedi-vim 0.8 482.318
jedi-vim 0.91015.580
pack178.358

ただこれでもインサートモードの最初は遅いので、早くタイマー機能使ってバックグラウンドで読み込みさせたい。

Pack について

Pack については、Vimのパッケージ機能を試してみました - Blank File にあるとおり、ハマりどころがある。

完全に stable になっているわけではないし、変更が色々入る可能性が高い。

ただ packadd したらプラグインが有効になるという設計は素晴らしいと思った。

タイマー機能が安定して使えるようになれば、完全にバックグラウンドで遅延読み込みができる。


vimrc などに読み込むパッケージを定義しなくて良いのも素晴らしい。

自分は気になるプラグインgit clone して Vim を起動するだけにしたいので、自分の使い方にもあっている。

2016-03-18

[] Browserify と fs モジュール

Electron で Watchify(Browserify)使ってると、fs モジュールが使えないという現象にあたった。


今遊んでいる環境が、Gulp で babel と wathify で Electron なアプリケーションを差分コンパイルしながらのため、brfs を使えばいけるとか、ググったら色々でてくるが、gulp で brfs を transform に入れてもだめだった。

const fs = window.require('fs');

とかだと行けた。


が、window とかつけなくても Electron で Babel を使った Markdownアプリケーションとかあるので、絶対いけるはずと、ググったら、node-webkitでもbrowserify使いたいしnodeのrequireも使いたい - Qiita がヒットした。

gulp.task('compile:js', $.watchify((watchify) => {
  var b = watchify({
    watch: watching,
    verbose: true,
    debug: true,
    ignoreMissing: true,     // これ
    detectGlobals: false,     // これ
    bare: true,
    transform: ['babelify', 'envify'],
    builtins: [],                   // これ
  });

  ['boot.js'].forEach((f) => {
    gulp.src(SRC_DIR + f)
      .pipe($.plumber())
      .pipe(b)
      .pipe(buffer())
      .pipe($.sourcemaps.init({ loadMaps: true }))
      .pipe($.if(DEBUG, $.uglify({ compress: true })))
      .pipe($.if(DEBUG, $.sourcemaps.write()))
      .pipe(gulp.dest(DIST_DIR));
  });
}));

上記のように watchify の定義の順番を変えてやればいけた。


なお環境は

    "babel-core": "^6.5.2",
    "babel-plugin-react-transform": "^2.0.0",
    "babel-preset-es2015": "^6.5.0",
    "babel-preset-react": "^6.5.0",
    "babelify": "^7.2.0",
    "electron-prebuilt": "^0.36.9",
    "watchify": "^3.7.0"

な環境。