Hatena::ブログ(Diary)

C++でゲームプログラミング

2014-08-30

[]Vim で RSS の取得

ってできないのかなーと思ったら webapi.vim にすでにあった。


[ソース]

let result = webapi#feed#parseURL("http://d.hatena.ne.jp/osyo-manga/rss")
for item in result
    echo item.title
endfor

[出力]

[vim]unite-github を非同期に対応させた
[vim]watchdogs.vim に hdevtools を追加した
[vim]unite-vimpatches を非同期で読み込むようにしてみた
[vim]unite-vimpatches の内容を Vim で読みこむようにしてみた
[vim]Vim で bash の reverse-i-search のようなことを行う

webapi.vim 便利。

unite.vim であれする予定。

2014-08-29

[]unite-github を非同期に対応させた

unite-github を非同期に対応させてみました。

表示するまで Vim をブロックしなくなります。


https://cloud.githubusercontent.com/assets/214488/4089531/a7e33daa-2f6d-11e4-8f54-d79b507a48e8.gif


不具合等があれば Issues までお願いします。

2014-08-28

[]watchdogs.vim に hdevtools を追加した

そんな要望があったので追加してみました。

haskell で使用したい場合は次のように設定すると hdevtools が使用されます。


let g:quickrun_config = {
\   "haskell/watchdogs_checker" : {
\       "type" : "watchdogs_checker/hdevtools",
\   },
\}

2014-08-27

[]unite-vimpatches を非同期で読み込むようにしてみた

してみました。

以前は unite-vimpatches を起動すると Web と通信を行うため Vim がブロックされましたが、その部分を非同期で処理するようにしてみました。


https://cloud.githubusercontent.com/assets/214488/4059766/d2123832-2de8-11e4-80e7-1a205a2a4231.gif


問題があれば Issues 等で教えてもらえると助かります。

2014-08-26

[]unite-vimpatches の内容を Vim で読みこむようにしてみた

以前作った unite-vimpatches ですが、ブラウザで開くのではなくて Vim で読みこむようなアクションを追加してみました。

次のように設定すれば Vim で内容を開くようになります。


call unite#custom#default_action("source/vimpatches/*", "openbuf")

http://gyazo.com/b3115d3b27ec026795643fe057bef64b.png


バッファの生成周りあんまり理解してないのがつらい。

2014-08-25

[]Vimbash の reverse-i-search のようなことを行う

そんな話が Lingr の Vim 部屋で出ていたので。



" <C-r> で unite-history/command を起動
" 選択するとコマンドラインに選択したコマンドが挿入される
" unite.vim と vim-unite-history が必要
cnoremap <C-r> :Unite history/command -start-insert -default-action=edit<CR>

http://i.gyazo.com/4479150a33ebee0c084e509fc51572ee.png


上の設定を行ってからコマンドラインで <C-r> を押すと unite-history/command が起動してインクリメンタルにコマンド履歴を検索する事ができます。

地味に便利そう?

コマンドラインで <C-r> 上書きするとかないわー

2014-08-24

[]Vim script でリストの範囲にリストを代入する

某 Lingr で話が出ていたので覚書。


let list = range(10)
let list[3:6] = [-1, -2, -3, -4]
echo list
" => [0, 1, 2, -1, -2, -3, -4, 7, 8, 9]
" :help E711
                            *E711* *E719*
:let {var-name}[{idx1}:{idx2}] = {expr1}        *E708* *E709* *E710*
            リスト|List|の一部を式{expr}の値で置き換える。{expr}の
            値は正しい個数の要素を持つリストでなければならない。
            {idx1}を省略すると0となる。
            {idx2}を省略するとリストの末尾となる。
            指定された範囲の一部がリストの末尾を越える場合、要素が
            追加される。

知らなかった。

2014-08-23

[]Vim から現在開いているファイルをコミットする

ちょっと編集したファイルを毎回端末開いてコミットするのが手間だったので適当にラッパーコマンドを定義してみた。


" Commit {コミットメッセージ}
command! -nargs=* Commit echo system("git commit " . expand("%:p") ." -m " . shellescape(<q-args>))

Commit {コミットメッセージ} で現在のファイルをコミットします。

さっとコミットしたい場合い便利。

2014-08-22

[]Vimシンタックスハイライトで他のシンタックスよりも優先してハイライトする

毎回設定する度に忘れるので覚書。

書いたあとに書いたことすら忘れそうだけど


さて、例えば、次のようなシンタックスハイライトを設定するとします。


" aaa を highlight Error でハイライト
syntax match Error /aaa/

上の設定を行うと

http://i.gyazo.com/c161ea46e8f8a72b75f40db4b925bb82.png

こんな感じにハイライトされるんですが、この時にコメントや文字列リテラルハイライトよりも優先してハイライトして欲しい場合があります。


[解決]

こういう場合は containedin=ALL を使用することで解決する事ができます。


syntax match Error containedin=ALL /aaa/

http://i.gyazo.com/81170c3642b19072b9a3e74b38b8e81c.png


これで他のシンタックスハイライトよりも優先してハイライトを行うことができます。

Vimシンタックス周りは結構細かく制御する事ができるんですが、その分意図した設定をするのがむずい…。

2014-08-21

[]unite.vim のプロンプトの位置による違い

たまにハマる人がいるようなので簡単にまとめてみた。

  • 候補順が逆
  • マークした後に上にカーソルが移動する
  • -auto-resize になる(候補の数によって自動的にウィンドウの高さが変わる)

また、下に split された場合は自動的にプロンプトが下に来ます。

プロンプトの位置は :Unite コマンドの -direction オプションで制御することができます。


" プロンプトを上に
Unite -prompt-direction=top
" プロンプトを下に
Unite -prompt-direction=below

2014-08-20

[]neosnippet.vim のマーカーを常に表示させる

この間の Vimプラグイン読書会で話に出ていたので覚書。

さて、neosnippet.vim のマーカー(カーソルのジャンプ先)は syntax の conceal によって制御されています。

conceal を使用することでユーザ側が表示・非表示の制御を 'conceallevel' にて行うことができます。


" マーカー(conceal)を非表示にする
set conceallevel=3

[問題]

conceal が neosnippet.vim だけで使用されているのであれば問題ないのですが、他のプラグインでも使用されている場合に問題が出てきます。

例えば indetLine でも使用されており、このプラグインの性質上 conceal を非表示にして使用する必要があります。

そうすると neosnippet.vim のマーカーも非表示になってしまい、しばしば不便になります。


[解決]

常に表示させたいのであれば conceal を設定している syntax ごと無効にするのがよさそうです。


" 削除する適当なタイミングが思いつかなかったので…
autocmd InsertLeave * syntax clear neosnippetConcealExpandSnippets

これで conceal が設定されている neosnippet.vim の syntax が削除され常に表示されるようになります。

2014-08-19

[]unite-quickfix をいろいろと改良した

某所から突かれていろいろと直してました。

主に見た目的な部分を。

修正箇所は以下の通り。

  • 表示形式をなるべく標準の quickfix に近づけた
  • ハイライトの改良
  • w:quickfix_title を出力
  • yank アクションの対応(yy で候補のエラー内容をヤンク)

http://gyazo.com/f1cd6dbce4a8e1404dd6ab8b2f352c27.png


問題があれば Issues までお願いします。

2014-08-18

[]neosnippet.vim でヤンクした HTML を Slim で展開する

これの Slim 版。


[vimrc]

" Html2Slim({slim})
" => {html}
function! Html2Slim(html)
    if !executable("html2slim")
        return ""
    endif
    let input  = tempname()
    call writefile(split(a:html, "\n"), input)
    let output = tempname()
    call system(printf("html2slim %s %s", input, output)
    return join(readfile(output), "\n")
endfunction

[slim.snip]

snippet html2slim
options word
    `Html2Slim(getreg(v:register))`

2014-08-17

[]Vim script で html2slim のラッパー

さて、html ファイルから slim ファイルへ変換したい場合、gem の html2slim が利用できます。


$ gem install html2slim
$ html2slim input.html output.slim

こんな感じで変換元の html ファイルと変換後の slim ファイルを指定します。


[Vim script でテキストを直接変換させる]

Vim script で扱う場合、ファイルを指定する方式だとちょっと使いづらいので、簡単なラッパーを書いてみた。


" Html2Slim({slim})
" => {html}
function! Html2Slim(html)
    if !executable("html2slim")
        return ""
    endif
    let input  = tempname()
    call writefile(split(a:html, "\n"), input)
    let output = tempname()
    call system(printf("html2slim %s %s", input, output)
    return join(readfile(output), "\n")
endfunction

これで生テキストを扱いやすくなった。

2014-08-16

[]Vimプラグイン読書会で neosnippet.vimスニペット読んでます


絶賛リアルタイムで進行中。

気になる方は Lingr の Vim 部屋まで。

2014-08-15

[]watchdogs.vim に flake8 を追加した

watchdogs.vim に flake8 の設定を追加しました。

デフォルトでは pyflakes の方を優先して使用するようになっているので、pyflakes と flake8 の両方を入れている方は次のように設定してしている必要があります。


" filetype=python 時に使用するチェッカーを flake8 にする
let g:quickrun_config = {
\   "python/watchdogs_checker" : {
\       "type" : "watchdogs_checker/flake8",
\   }
\}

2014-08-14

[]任意の unite-source が使えるかどうかを判定する

みたいなのが某 issues に飛んできたので簡単に調べてみた。

とりあえず、以下のようには判定できるぽい感じ。


let name = "file"
echo index(keys(unite#variables#all_sources()), name) != -1

ソースコードから直接拾ってきただけなので他にそれっぽい関数があるかも知れない。

2014-08-13

[]Vim で行継続の \ を削除して行結合を行う

以前、任意の区切り文字を入力して行結合を行う jplus.vim というプラグインを作ったのですが、それに行継続の \ を削除して行結合を行う機能を実装してみました。


https://cloud.githubusercontent.com/assets/214488/3864436/f747a67c-1f5c-11e4-8918-45bfa0a2aced.gif


[プラグイン]

NeoBundle "osyo-manga/vim-jplus"

[使い方]

" J の挙動を jplus.vim で行う
" 行結合時に \ を削除する
nmap J <Plug>(jplus)
vmap J <Plug>(jplus)

" getchar() を使用して挿入文字を入力します
nmap <Leader>J <Plug>(jplus-getchar)
vmap <Leader>J <Plug>(jplus-getchar)

" <Plug>(jplus-getchar) 時に左右に空白文字を入れたい場合の設定
" %d は入力した結合文字に置き換えられる
let g:jplus#config = {
\   "_" : {
\       "delimiter_format" : ' %d '
\   }
\}

" input() を使用したい場合はこちらを使用して下さい
" nmap <Leader>J <Plug>(jplus-input)
" vmap <Leader>J <Plug>(jplus-input)

[対応している filetype]


その他、挙動などを細かく設定できるようにしました。

詳しくは :help jplus-config を参照してください。

なにか問題等があれば Issues までお願いします。

2014-08-12

[]Vim script で明示的に補完ウィンドウを呼び出す

昨日、Lingr の Vim 部屋で出てきてたのですが Vim script の組み込み関数に complete() というのがあります。


:help complete()
complete({startcol}, {matches})            *complete()* *E785*
        挿入モード補完の候補を設定する。
        挿入モードでのみ使用できる。CTRL-R = |i_CTRL-R|と組み合わせて
        マッピングを作る必要がある。CTRL-Oの後や、<expr>マッピングの中
        では正しく動作しない。
        {startcol}は補完すべき単語の開始位置を示す、行内のバイトオフセッ
        トである。その位置からカーソルまでのテキストが補完すべき単語と
        なる。
        {matches}はリスト|List|でなければならない。リストの各要素が1つ
        の候補となる。この要素として許される値については
        |complete-items|を参照。
        Note この関数を呼んだ後は補完を停止させるようなテキストの挿入
        をしないように注意しなければならない。
        この関数で設定した候補は普通の挿入モード補完と同じ様にCTRL-Nと
        CTRL-Pで選択できる。設定されていればポップアップメニューが表示
        される。|ins-completion-menu|を参照。
        例: >
    inoremap <F5> <C-R>=ListMonths()<CR>
    func! ListMonths()
      call complete(col('.'), ['January', 'February', 'March',
        \ 'April', 'May', 'June', 'July', 'August', 'September',
        \ 'October', 'November', 'December'])
      return ''
    endfunc
<        この例はそれほど役には立たないが、使い方を示している。Note 0が
        挿入されてしまわないように空文字列を返していることに注意。


これを利用すれば明示的に任意の候補の補完ウィンドウを呼び出す事ができます。

使い方は上のヘルプに載っている通り補完位置と補完候補のリストを渡して呼び出します。

コード補完とか 'omnifunc' に設定しないでこれで呼び出してしまった方が楽なのではないだろうか。

2014-08-11

[]C++14 で名前付き引数

標準ライブラリでできる範囲で書いてみました。


[ソース]

#include <tuple>


template<typename T, typename Uniq>
struct holder{
    T value;
    operator T(){
        return value;
    }

    holder&
    operator =(T t){
        value = t;
        return *this;
    }
};


template<typename T, typename Uniq, typename ...Args>
T
get(holder<T, Uniq>, Args... args){
    return std::get<holder<T, Uniq>>(std::make_tuple(args...));
}


#include <iostream>
#include <string>

holder<int, struct age_> age;
holder<int, struct index_> id;
holder<std::string, struct name_> name;


template<typename ...Args>
void
func(Args... args){
    std::cout << "id = "    << ::get(id, args...)    << std::endl;
    std::cout << "age = "   << ::get(age, args...)   << std::endl;
    std::cout << "name = "  << ::get(name, args...)  << std::endl;
}


int
main(){
    func(age = 13, name = "homu", id = 0);
    func(id = 1, name = "mami", age = 14);
    return 0;
}

[出力]

id = 0
age = 13
name = homu
id = 1
age = 14
name = mami

思ったよりもスッキリと書くことができた。

C++14 依存といっても必要なのは std::get() の部分だけなのでそこを何とかすれば C++11 でも動作するはず。

デフォルト引数なんかに対応したい場合はもうちょっと工夫が必要かなー。

2014-08-10

[]std::unique のデフォルトのデリータ

std::unique のデフォルトのデリータは何なのか調べてみたら次のように定義されているみたい。



template<
    class T,
    class Deleter = std::default_delete<T>
> class unique_ptr;

template <
    class T,
    class Deleter
> class unique_ptr<T[],Deleter>;

と、いうことでデフォルトでは std::default_delete が使用されているみたいです。

std::default_delete<T> は delete を行うための関数オブジェクトで次のように利用できます。


[ソース]

#include <iostream>
#include <memory>

struct X{
    X(){
        std::cout << "new X" << std::endl;
    }
    ~X(){
        std::cout << "delete X" << std::endl;
    }
};

int
main(){
    std::cout << "start" << std::endl;
    auto xp = new X{};
    std::default_delete<X> deleter;
    deleter(xp);
    std::cout << "end" << std::endl;
    return 0;
}

[出力]

start
new X
delete X
end

std::default_delete<T> なんて標準ライブラリにあったのか。

2014-08-09

[]std::unique_ptr のデリータをあとから設定する

と、いうのが Lingr の C++ 部屋に貼られていたので覚書。


[ソース]

#include <memory>
#include <functional>
#include <iostream>

int
main(){
    auto p = std::unique_ptr<int, std::function<void(int*)>>{ new int{42}, std::default_delete<int>{} };

    // deleter を設定
    p.get_deleter() = [](int* p){
        std::cout << "call deleter" << std::endl;
        delete p;
    };

    std::cout << *p << std::endl;

    return 0;
}

[出力]

42
call deleter

get_deleter() は参照オブジェクトを返すのでこんな感じで代入する事ができます。

便利……なのかな?

[]std::unique_ptr のデリータをあとから設定する

と、いうのが Lingr の C++ 部屋に貼られていたので覚書。


[ソース]

#include <memory>
#include <functional>
#include <iostream>

int
main(){
    auto p = std::unique_ptr<int, std::function<void(int*)>>{ new int{42}, std::default_delete<int>{} };

    // deleter を設定
    p.get_deleter() = [](int* p){
        std::cout << "call deleter" << std::endl;
        delete p;
    };

    std::cout << *p << std::endl;

    return 0;
}

[出力]

42
call deleter

get_deleter() は参照オブジェクトを返すのでこんな感じで代入する事ができます。

便利……なのかな?

2014-08-08

Boost 1.56.0 がリリース

Boost 1.56.0 がリリースされました。


結構久しぶりのリリース。

AlignType_Index の 2 つが新しいライブラリとして追加されました。


  • Align:
    • Memory alignment functions, allocators, and adaptors, from Glen Fernandes.
  • Type_Index:
    • Runtime/Compile time copyable type info, from Antony Polukhin.

その他、リリースノートはここら辺を参照してください。

最近 C++ に飢えているのでモチベーション上げたいなぁ…。

2014-08-07

jedi.vim の自動補完で第一候補を選択肢ないようにする

某所で話題になって調べてみたんですが、以下の記事が参考になりました。


これで動作するようになります。

ただ、jedi.vim 側の設定の仕組みがなんかおかしいような気がするのでもうちょい調べてみる必要がありそう。

2014-08-06

[]Vim の complete-functions でハマった

久しぶりに Vim の complete-functions を書いていたんですが、知らなかった仕様にはまったので覚書。

さて、Vim でオレオレコード補完処理を行いたい場合は 'completefunc' や 'omnifunc' などのオプションにコード補完関数を設定して実現します。


function! Complete(findstart, base)
    if a:findstart
        return 補完を開始する列の位置
    endif
    return 補完の候補
endfunction

set omnifunc=Complete

雑に書くと上のような感じです。

実際に <C-x><C-o> でオムニ補完を呼び出すと Complete() が2回呼び出されます。

1回目は『補完を開始する列の位置』を返し、2回目の呼び出しで『補完の候補』を返します。

詳しくは :help complete-functions を参照してください。


[ハマりポイント]

結論からいうと1回目と2回目の呼び出しでは getline(".") の値が異なります。

具体的に言うと 1回目に返した列位置からカーソルの列位置間のテキストが 2回目に呼び出された時には削られます。

どういうことかというと、動作を確認するために次のような補完関数を設定しておきます。


function! Complete(findstart, base)
    echom printf("%d 回目" , a:findstart ? 1 : 2)
    echom "line : " . getline(".")
    if a:findstart
        return 1
    endif
    return []
endfunction
set omnifunc=Complete

この時に


homu " ここで <C-x><C-o>

すると


1 回目
line : homu
2 回目
line : h

というような結果が出力されます。

こんな感じで1回目と2回目の呼び出しでは getline(".") の値が異なっている事がわかると思います。

また、この影響のためか、補完を呼び出す前と呼び出したあとでは b:changedtick の値が変わっています。

ちなみに <C-x><C-o> で補完を呼び出してユーザに操作が戻った時にはバッファの内容は元に戻っています。

以前、marching.vim でオムニ補完を書いていたときはこんな仕様にはまらなかったんだけど気づかなかっただけなのかなぁ…。

2014-08-05

[]Bugs Fixed in Visual Studio 2013 Update 3

http://blogs.msdn.com/b/vcblog/archive/2014/08/04/bugs-fixed-in-visual-studio-2013-update-3.aspx


最近の Visual Studio 事情はよく知らないのだけれどだいぶ修正されているみたい。

Visual Studio も気になる環境ではあるのだけどいかんせん自由に動作できる環境がないからなぁ…。

だれか Windows マシンくだしあ

2014-08-04

[]C++ で簡単にアクセッサを書けるようにしたかったけど Non-static data members で auto が使えなくて死んだ


class X{
    int value_ = 42;
public:
    auto value = accessor(this, &X::value_);
};

みたいな感じで書きたかった。


[ソース]

template<typename Class, typename T>
struct accessor_impl{
    Class* class_;
    T Class::* member;

    T operator ()() const{
        return class_ ->* member;
    }

    void operator ()(T const& t) const{
        class_ ->* member = t;
    }
};


template<typename Class, typename T>
accessor_impl<Class, T>
accessor(Class* class_, T Class::* member){
    return { class_, member };
}


class X{
    int value_ = 42;
public:
//  auto value = accessor(this, &X::value_);
    accessor_impl<X, int> value{ this, &X::value_ };
};


#include <iostream>

int
main(){
    X x;
    std::cout << x.value() << std::endl;

    x.value(72);
    std::cout << x.value() << std::endl;

    return 0;
}

[出力]

42
72

つらい。

2014-08-03

[]brightest.vimハイライトしない単語のパターンを設定できるようにした

brightest.vimハイライトしない単語のパターンを設定できるようにしました。


[プラグイン]

[使い方]

" アンダーバーから始まる単語はハイライトしない
let g:brightest#ignore_word_pattern = '^_\k\+'

2014-08-02

[]移動する度にカーソル上の単語をハイライトする brightest.vim に特定のシンタックス上でハイライトしない機能を実装した

先日公開した brightest.vim ですが、公開後に色々と意見もらって特定のシンタックス上だとハイライトしない機能を実装してみました。

if とか for とかそういうシンタックスハイライトしたくない場合に有効です。


[プラグイン]

[使い方]

" シンタックスが Statement の場合はハイライトしない
" e.g. Vim script だと let とか if とか function とか
let g:brightest#ignore_syntax_list = [ "Statement" ]

[注意]

これはカーソル上のシンタックスで判定しています。

しかし、g:brightest#pattern の設定を行っていない場合は <cword> を使用するため、カーソル上以外の単語もハイライトする事があります。

そういう場合は正しく動作しない可能性があるので注意してください。

これを回避する場合は以下のようにして、カーソル上の単語のみハイライトするように設定する必要があります。

let g:brightest#pattern = '\k\+'

2014-08-01

[]vimhelp に関数へのタグリンクを追加した

vimhelp で ":help string-functions" してて関数にタグリンクがないのが不便だったので追加してみました。


:help string-functions

http://gyazo.com/c45392dd76408773fac8e970941e79e1.png


そろそろパフォーマンスが気になり始めてきたので何とかしたいなぁ。