2016/11/28

vim-themis, vital-power-assert を使って vim plugin の単体テストを書いてみた

vim-themis, vital-power-assert を使って単体テストのコードを書いたので、ここに作業を記録する。

手順概要

  1. 必要なパッケージを導入
  2. .themisrc を作成する
  3. テストコードを書く
  4. テストを実行する

以下、各手順を説明していく。

1. vim-themis 導入

vim 標準のパッケージマネージャを使っているので、下記構成で git submodule add した。

.vim
└── pack
     └── test
         └── opt
             ├── vim-themis
             ├── vital.vim
             ├── vital-power-assert
             ├── vital-safe-string
             └── vital-vimlcompiler

注意点 :

  • vital-power-assert は、 vital.vim, vital-vimlcompiler, vital-safe-string に依存しているので忘れず導入する
  • テスト時しか使用しないので、 opt に入れる

2. .themisrc を作成する

vital-power-assert の README, '.themisrc' を参照しつつ .themisrc を作成。

packadd! vital.vim
packadd! vital-vimlcompiler
packadd! vital-safe-string
packadd! vital-power-assert
"
let g:__vital_power_assert_config = {
\   '__debug__': 1,
\   '__pseudo_throw__': 0
\ }

注意点 :

  • 必要なパッケージを packadd! で追加
  • themis へのランタイムパス追加は必要なかった。(packadd! で追加されるのかな?)

3. テストコードを書く

テストコードは、プラグインディレクトリ直下に test ディレクトリを作ってその中に書いていく。

vital-power-assert の README, 'test/Example.vimspec' をマネして Vimspeck-style で記述した。

Describe Test for buffer_selector
  Before all
    let V = vital#of('vital')
    let PowerAssert = V.import('Vim.PowerAssert')
    let s:assert = PowerAssert.assert
  End

  It test_GetBufNo
    let buffers_buffer =  '  1  h   "[無名]"                       行 0'
        \ . "\n" . '  9  h   "[無名]"                       行 0'
        \ . "\n" . ' 10  h   "[無名]"                       行 0'
        \ . "\n" . '119 %a   "[無名]"                       行 1'

    put!=buffers_buffer

    call cursor(1, 1)
    let bufno = buffer_selector#GetBufNo()
    execute s:assert('bufno is# "1"')

    call cursor(2, 1)
    let bufno = buffer_selector#GetBufNo()
    execute s:assert('bufno is# "9"')

    call cursor(3, 1)
    let bufno = buffer_selector#GetBufNo()
    execute s:assert('bufno is# "10"')

    call cursor(4, 1)
    let bufno = buffer_selector#GetBufNo()
    execute s:assert('bufno is# "119"')
  End
End

4. テストを実行する

ターミナルでプラグインのルートディレクトリに移動して、themis を実行すると、 vimspec ファイルを探して実行してくれる。

 ~/.vim/pack/test/opt/vim-themis/bin/themis --reporter spec
Test for buffer_selector
  [✓] test_GetBufNo

tests 1
passes 1

fail の場合は下記のようになる。

~/.vim/pack/test/opt/vim-themis/bin/themis --reporter spec
Test for buffer_selector
  [✖] test_GetBufNo
      function 89() abort dict  Line:22  ()

      vital: PowerAssert:
      bufno is# "120"
      |     |
      '119' 0

tests 1
passes 0
fails 1

実際にやってみたプロジェクトはこちら

buffer_selector.vim - Added test code.

「どうすればテストしやすいか」と、「どうやってテストするか」はまだまだ勉強が必要だ...。

以上。

2016/11/21

シンプルバッファーセレクタープラグイン buffer_selector.vim を作成した

シンプルバッファーセレクタープラグイン buffer_selector.vim を作成した。

mikoto2000/buffer_selector.vim: シンプルで簡単に使えるバッファーセレクター

目的と経緯

目的のバッファーへの切り替えをもっと簡単に行いたい。

今までは、:buffers してバッファー番号を確認した後 :buffer number でバッファを切り替えていた。 これが意外とつらい。

  1. :Unite buffer みたいに選びたいけど、Unite ヘビーなので入れたくない
  2. bufferlist.vim を試したけど、縦分割が気に入らない
  3. 勉強がてら作ってみようか

という感じ。

これ書きながら思ったのが、バッファーセレクターじゃなくて、 ファイルセレクターあたりも視野に入れてプラグイン探したほうが良かった気がする。

手順概要

大体こんな流れで実装していった。

  1. とりあえず書く
  2. 関数化して、それっぽい場所に移動
  3. help ドキュメントを書く
  4. plugin として切り出す

以下、各手順について説明していく。

1. とりあえず書く

適当なファイルにスクリプトを書いて、都度都度 source % で実行していった。

最初は、こんな感じのスクリプトを書いてバッファ一覧がとれるか確認した。

""" 変数 buffer_list に ``ls`` の結果を格納
let buffer_list=""
redir => buffer_list
silent ls
redir END

""" 新しいバッファを作成
new __BUFFERLIST__

""" __BUFFERLIST__ に ``ls`` の結果を表示
put!=buffer_list

その後、インクリメンタルに source % しながら実装していき、最終的にできたのがこれ。

""" 変数 buffer_list に ``:ls`` の結果を格納
let buffer_list=""
redir => buffer_list
silent ls
redir END

""" 新しいバッファを作成
if bufexists(bufnr('__BUFFERLIST__'))
    bwipeout! __BUFFERLIST__
endif
silent bo new __BUFFERLIST__

""" __BUFFERLIST__ に ``:ls`` の結果を表示
silent put!=buffer_list

""" 先頭と末尾が空行になるのでそれを削除
normal G"_dd
normal gg"_dd

""" ウィンドウサイズ調整
let current_win_height=winheight('%')
let line_num=line('$')
if current_win_height - line_num > 0
    execute "normal z" . line_num . "\<Return>"
endif

""" バッファリスト用バッファの設定
setlocal noshowcmd
setlocal noswapfile
setlocal buftype=nofile
setlocal bufhidden=delete
setlocal nobuflisted
setlocal nomodifiable
setlocal nowrap
setlocal nonumber

""" 選択したバッファに移動
map <buffer> <Return> ^viwy:bwipeout!<Return>:buffer <C-r>"<Return>
map <buffer> q :bwipeout!<Return>

2. 関数化して、それっぽい場所に移動

「1.」の段階で、 source % すれば所望の動きになることが確認できているので、 あとは

  1. 関数化して autoload に突っ込む
  2. .vimrc で関数を呼び出すマッピングを定義する

をすれば OK。

具体的に、どこにどう配置したかは、 コミット見るのが早そうなのでリンク張る。

Added simple buffer select process

3. help ドキュメントを書く

はじめてプラグインを作ってみた。それとhelpの書き方など - 反省はしても後悔はしない を参考に、 jax ファイルを作成。

これもコミットへのリンクのほうがわかりやすいか。

Added document of 'buffer_selector'.

4. plugin として切り出す

新しいリポジトリを作って作成したファイルを追加。

mikoto2000/buffer_selector.vim: シンプルで簡単に使えるバッファーセレクター

その後、もともと作っていたソースを削除し、代わりに、新しく作ったリポジトリをパッケージに登録。

Carve out 'buffer_selector.vim' to external plugin.

プラグイン作成作業は以上。

所感

だらだら作っていったけど、 プラグイン管理の仕組みを使ってすぐインストールできる vim プラグインが作れたからとりあえず満足した。

以上。

2016/11/15

Sphinx によるドキュメント執筆管理環境の検討

ここ数週間、隙間時間で悶々と考えていたことを吐き出す。

管理方法

一行で : 『Sphinx + VCS + Redmine + redmine_code_review』

  • Sphinx でドキュメントを作成する
  • ソースは VCS で管理
  • ビルドしたドキュメントはドキュメントサーバーにデプロイ & 共有ディレクトリに格納
  • ドキュメントのレビューは、 redmine_code_review プラグインを使い実施、管理する

※ VCS: できれば git + LFS, 次点で SVN

メリット

  • Excel 共有と比べて
    • 誰がいつ変更したかが失われない
    • コミットコメントのルールを決めることで、「何故」も記録できる
    • redmine_code_review の仕組みを使うことで、レビュー記録も Redmine に集約できる
  • Redmine の wiki と比べて
    • ビルドしてしまえばサーバーなしで参照できる

弱点

  • Excel のようにシームレスな作図ができない
  • reStructuredText がマイナー

reStructuredText 執筆のコツ

reStructuredText は、 tex, html などから続く『文章の意味と見た目が分離されているドキュメント』の一族。 執筆時には、文章構造に意識を集中すること。

これができると、あとは reStructuredText のルールに従って .rst に書き下していくだけで、誰でも同じ見た目の文章が作成できる。

Word, Excel と違い、編集するファイルの中に『見た目の情報』が存在しないため、 『うっかりフォントが変わった』や『ここだけインデントがずれた』 みたいなことがない。

ディレクトリ構成

docroot
   +- ワーキンググループ/
   |  +- ワーキンググループ_XXX/
   |  |  +- work/
   |  |  +- image/
   |  |  +- attachment/
   |  |  +- xxx.rst
   |  |  +- ワーキンググループの規模によってはサブディレクトリ作成も辞さない/
   |  |     +- work/
   |  |     +- image/
   |  |     +- attachment/
   |  |     +- yyy.rst
   |  |
   |  +- ワーキンググループ_ZZZ/
   |     +- ...(略)
   |
   +- 開発資料
   |  +- ...(略)
   |
   +- 運用資料
      +- ...(略)
  • image : 本文に表示する画像(png)を格納
  • work : image 加工用の元ネタを格納(xlsx, xcf 等)
  • attachment : 添付ファイルを格納

うーん、もやもやする。

2016/11/09

オープンソースカンファレンス 2016 Tokyo/Fall にいってきました

オープンソースカンファレンス 2016 Tokyo/Fall への参加記録として、殴り書きメモを張り付けていきます。

.NETで動くチケット管理ツール「プリザンター」

デフォルトで Redmine よりリッチなチケットトラッキングシステム。

  • OS は Windows 前提
  • デフォルトで WBS, ガントチャート, バーンダウンチャート, カンバンが使用可能
  • 既存の、 Excel, メール, 共有フォルダをプリザンターで置き換えられる
  • カスタムフィールドでグルーピングして集計みたいなことがリッチ UI でできる
  • VCS との連携がないのが残念

VCS 連携機能がないのが残念だけど、 全体的に Redmine よりリッチで使いやすそうな印象だった。 今の現場、管理用サーバーが Windows Server なので、これ使ってみたいが、 VCS 連携あたりでメンバに文句言われそう...。

今の現場ならいいけど、 「他の現場でノウハウが使えるか」とか考えてしまうと、 やっぱり導入ためらってしまう感じというのが正直なところか。

とりあえず触ってみないとか。

30分で分かるOSの作り方──自作OSもくもく会・出張版

  • OS とは
    • 他の OS の力を借りずに起動するソフトウェアのこと。
    • それぞれの作者が「OS」だと言い張って、周りが「まぁそうかな」と納得すればそれが OS。
  • 方向性
    • システムプログラミングを楽しむ
    • OS 理論を学ぶ
    • 実用的な OS を作る
    • 既存 OS を改良する
      • この発表でいう「OS 自作」ではない
  • OS 自作方法
    • 入門書を手に入れる
    • とりあえずその通りやる
      • 1 日 2 時間 x 30 日 くらい。
    • 改造する
  • 参考書
    • 30日でできる! OS自作入門
    • 12 ステップで作る組み込み OS 自作入門
  • 2016, osdev-jp 結成
  • 第 4 回 自作 OS もくもく会 11/26(土) 14:00 から

最近低レイヤの仕事してるのもあって、この辺への興味が増してしてきた。 実際作るかは置いておいて、OS 理論的なものの勉強はちょっとやっていかねば...。

ロケットや自動車にも搭載!高品質な組込み向けオープンソースを開発するTOPPERSプロジェクトのご紹介

遅刻。

  • Sessalelt
    • SESSAME(状態遷移図の設計セミナー)の成果物を実際に実装したもの
    • TOPPERS/EV3RT
    • 言語 : C or mruby
    • 状態の入れ子, 入れ子のない状態が存在するモデル
  • 状態マシン図設計セミナー
    • 11/28,29
    • Sessalet のモデルを持ち寄ってレビュー大会を開く
    • メーカーで設計していた人が講師
      • 今は社内でレビューを行っている
    • http://www.sessame.jp/seminar/Seminar2016_11/index.htm

mikutter会議2016東京

  • mikutter は Twitter クライアントではない
  • Pluggaloid
    • Yukari for Android
      • Pluggaloid on mruby on Androi!
  • mikutter 3.5
    • Model
      • ツイート, ユーザー, リストなど
      • ユーザーがカスタムモデルを作れるようになった
        • 適当なモデルを作ってタイムラインに流し込むと、よしなに表示してくれる

この辺からライブコーディングに夢中になってメモを忘れている...。

エンターテイメントなプレゼンだった。

進化の方向としては、モデルをさばくためのフレームワークだけ提供して、 モデルを作る(引っ張ってくる)部分とモデルを処理する部分は プラグインに任せる形になっていくっていう認識でいいのかな? この辺 Embulk とか Fluentd とかを思い出した。 この手のソフトウェア大好き。

ツイート以外のモデルを流しやすくなっているようなので、いろいろ触っていきたい。

AzureでOSSを気軽に試そう!~ LAMPからDevOpsまで ~

  • Microsoft には OS ハラスメントは無いみたい(Mac 使えるみたい)
  • けど、検索エンジンハラスメントはあるみたい(Bing 使えっていわれるみたい)

Azure で VM 作る実演。 Bitnami に、要求にマッチするイメージが存在すれば、数分で作成作業終わる感じ。 初期設定とかイメージの説明書読まないとだけど、その辺に慣れればすごい便利そうだった。

LT

みなさんネタと勢いのある素晴らしいプレゼン。見習いたい。(会社でやったら怒られるか...) Marp って初めて聞いたので試してみようと思った。

2016/11/08

VimConf 2016 に参加しました

VimConf 2016 への参加記録として、殴り書きメモを張り付けていきます。

Introduction to Vim 8.0

  • See :help version8
  • See :help channel-demo
  • See :help job_start()
  • See :help timer_start()
  • See :help Partial
    • Partial : 部分適用, コールバック等で便利らしい
  • See :help lambda
  • See :help closure
  • See :help window-id
    • Window に、不変の、一意な Window ID がつくようになったらしい。
  • See :help test-functions
  • See :help breakindent
    • マージに 10 年!
  • See :help renderoptions
  • Search Coveralls

知らない機能たくさん。特に、「Partial」「window-id」「breakindent」は今の自分に有用そうなので調べる。

VIM AS THE MAIN TEXT EDITOR

  • 「vimrc をオリジナルにする」、同感。
  • Vim に移行するためのモチベーションは何だろうか?
    • 仕事で使う必要があった
  • Vim を使うための準備運動
    • vim tutorial
    • VIMIUM
  • Vim を育てる
    • github で vimrc を検索
    • 内容を把握してコピペ
    • 気になったことを issue で書く
  • Q: Vim に移行して一番テンションの上がった機能は?
    • A: VimFiler, UI, 操作性が直感的で感動した

プロジェクトメンバに Vim 布教するにあたりこの辺のステップを参考にしていきたい。

Denite.nvim ~The next generation of unite~

NeoVim かー、 Python かー、速いのかー、うらやましいなー。って聞いてた。 (NeoVim 専用と誤解してた、NeoVim が Linux でしか動かないと思ってた。)

※ 懇親会にて Shougo さんに NeoVim は Windows ネイティブでも動くようになってるし、Bash on Ubuntu on Windows なら完璧に動くという話をしていただいたので試す。

Go、C、Pythonのためのdeoplete.nvimのソースの紹介と、Neovim専用にpure Goでvim-goをスクラッチした話

NeoVim かー、 Python かー、速いのかー、うらやましいなー。って聞いてた。

エディタの壁を超える Go の開発ツールの文化と作成方法

  • 特徴
    • 強力でシンプルな言語設計と文法
    • 平行プログラミング
    • 豊富なライブラリ
    • 豊富なツール
    • シングルバイナリ/クロスコンパイル
      • Windows 界隈だとシングルバイナリ便利
  • ツール群
    • govet
    • guru
    • gocode
    • errcheck
    • gorename
    • gomvpkg
  • Search gofmt -s

社内ツールで Go 使うときの宣伝文句としてスライド ぱくりたい 超参考になった。

vim-mode-plus for Atom editor

  • Search operation-stack
  • Search Vim で
  • Search occurrence
  • Search Vim で vip
  • Search Vim で「キャメルケース/スネークケース」変換

モーションとオペレータの考え方がわかりやすかった。 そのあたりを意識しながらコマンド使っていきたいと思った。

Vimの日本語ドキュメント

  • vim のドキュメント
    • vim-jp/vimdoc-ja
      • リファレンスとユーザーマニュアル
    • vim-jp/lang-ja
      • メニュー・メッセージ
    • Vim のユーザーマニュアルは、 usr_ で始まるやつ
  • Travis-CI 上で表記ゆれチェック
    • koron/nvcheck
  • vimdoc-ja の課題
    • 訳文の統一
      • 表記ゆれ
      • 文体の統一
    • 翻訳支援ツールの利用
      • 原文成形済み
        • なので、差分検出が難しい
          • なので、マークアップと成形ツールがほしい
      • これで、翻訳の品質向上を目指す

ドキュメント翻訳って、翻訳そのものも大変だけど、翻訳のための仕組み作りもまた大変なんだなぁ。 表記ゆれチェックはうちのプロジェクトに取り込めたら取り込んでいきたい。

Vim script parser written in Go

  • Linter
  • Fixer
  • Formatter
  • Completion

殴り書きで上記単語だけ書かれていた...。完全に内容についていけてなかった...。

僕の友達を紹介するよ

この辺試していきたい。

Best practices for building Vim plugins

  • ドキュメントを書きましょう
    • README を置くだけでは不十分
    • See :help design-documented
  • namespace を意識しましょう
    • 他プラグインと名前がバッティングしないように注意
    • プラグイン名を prefix にする
      • 勝手に省略するのはダメ
      • 実際どう呼ぶかはユーザーに任せる
    • プラグイン名を決める前にググる
    • 外部インターフェースの関数, 変数名も同じなので注意
  • autoload を使いましょう
    • plugin/xxx.vim には UI 定義のみ
    • 逆に言うと、 plugin/xxx.vim から autoload 内のコードを呼ぶのは残念な感じ
  • カスタマイズできるようにするのが Vim っぽい
    • 高カスタマイズ性
  • <Plut> キーマッピングを使いましょう
  • Plugin original buffer is useful
    • 実際のバッファに紐づかないバッファ?
    • BufReadCmd, BufWriteCmd
    • {plugin-name}://...
    • バッファを使うプラグインはスコープに注意
  • デフォルトで移動するキーのマッピングを上書きしちゃうと顰蹙を買うかも...
  • See <Leader>, <LocalReader>
  • Open API
  • マルチプラットフォーム対応しましょう
    • See :help design-multi-platform
  • テスト書くとよい
  • スクリプト内で省略形を使うのはダメ
    • 省略形はコマンドモードで楽に入力するためのもの

もりだくさん。 Vim script 書くときに意識していきたい。

所感

  • 書き殴ったことを消化・吸収しつつ、Vim 力を高めていきたい
  • NeoVim, Go を全くウォッチしていなかったのが悔やまれる
  • Windows で NeoVim 動かして deoplete.nvim を使ってみよう

2016/11/01

[Vim] Vim で、カーソル下の数値を変換したい

上から順に、

  • 2 進数変換
  • 10 進数変換
  • 16 進数変換
  • 数値の桁(ゼロオリジン)のマスク値に変換
  • 数値の桁(1オリジン)のマスク値に変換

という感じ。

マクロ

viwc^R=printf("0b%b", ^R")^M^[
viwc^R=printf("%d", ^R")^M^[
viwc^R=printf("0x%04X", ^R")^M^[
viwc^R=printf("0x%04X", printf("%.f", pow(2, ^R")))^M^[
viwc^R=printf("0x%04X", printf("%.f", pow(2, ^R"-1)))^M^[

コマンドバージョン

command! Num2b execute "normal viwc<C-R>=printf(\"0b%b\", <C-R>\")<Return><Esc>"
command! Num2d execute "normal viwc<C-R>=printf(\"%d\", <C-R>\")<Return><Esc>"
command! Num2x execute "normal viwc<C-R>=printf(\"0x%04X\", <C-R>\")<Return><Esc>"
command! Num2Mask0 execute "normal viwc<C-R>=printf(\"0x%04X\", printf(\"%.f\", pow(2, <C-R>\")))<Return><Esc>"
command! Num2Mask1 execute "normal viwc<C-R>=printf(\"0x%04X\", printf(\"%.f\", pow(2, <C-R>\"-1)))<Return><Esc>"