5.1さらうどん

@giginetの技術ブログ。ゲーム開発、iOS開発、その他いろいろ

Djangoでgitのリビジョンを表示するプラグインを作った

django-debug-toobar-vcs-info

Djangoにはdjango-debug-toolbarというプラグインがあります。

github.com

このプラグインを導入すると、プロファイリングを行ったり、利用されているライブラリのバージョンを表示したりといった、デバッグに必要な情報を簡単にサービス上に表示することができます。

f:id:gigi-net:20151227182311p:plain

現在、Djangoで運用しているサービスがあるのですが、本番で現在のGitリビジョンを確認したいという需要があったので、このdjango-debug-toolbarの拡張として、以下のような物を作りました。

github.com

django-debug-toolbar-vcs-infodjango-debug-toolbarにGitなどのバージョン管理システムの現在の状態を表示するパネルを追加するプラグインです。

このプラグインを導入すると、以下のように現在のHEADのハッシュやコミットログを確認することができます。これを本番環境に導入しておくと結構便利です。

f:id:gigi-net:20151227182421p:plain

非常に需要の少ないモノですが、簡単に導入できますし、入れておいて損はないので、Djangoでサービスを運用している方は是非使ってみてください。

vcs-infoという名前ですが、現状、gitにしか対応していないので、Mercurial対応などのPRお待ちしています。

作ってみて

そもそも、作ってみた動機として「PyPIにしっかりテストしたパッケージをホストしたい」という気概がありました。

PyPIにパッケージを登録するのは、3~4年前に一度挑戦したことがあったのですが、全くテストがされていなくて、使いやすい物になっていなかったので、今回はガッチリとテストをしてみました。

f:id:gigi-net:20151227183355p:plain

toxを利用し、Django1.7から1.9に対応させたり、Python2, 3に両対応させたり、カバレッジを計測したり、しっかりモックテストを書いたりと言った知見が溜まりましたし、そういう意味で小さなプラグインを作ってみるのは良いと思います。

今回のような複数のPython, Djangoのバージョンに対応させたテスト手法について、Python Advent Calendar 2015の記事として投稿していますので、ご興味のある方はこちらも併せてご覧ください。

複数バージョンのPython向けにCI環境を構築してテストする - Qiita

cocos2d-x向けの究極のソーシャル連携プラグイン作った

この記事は

cocos2d-x Advent Calendar1日目の記事です。

cocos2d-x Advent Calendar 2015 - Qiita

誰も立ててないので立ててみましたが、今年は参加者が少なく、炎上気味なのでご興味のある方はぜひ参加してみてください。

QiitaのAdvent Calendarなので、Qiitaで書いた方が見やすいかと思ったのですが、自分の作った物を発信する場としてはQiitaは不適だと思い、ブログに書くことにしました。

ソーシャル連携用のプラグイン作った

今回はCCSocialShareというcocos2d-xから簡単にTwitter/Facebookに投稿できるプラグインを作ってみたのでご紹介します。

github.com

cocos2d-xでTwitterFacebookスクリーンショットなどを投稿したい!という需要は高いはずだけど、どうにも共通化された上手い仕組みが見つからない。

cocos2d-xが公式で提供されているplugin-xというプラグインで、ソーシャル連携機能が提供されているけれど、組み込み方が煩雑だったり、OS標準の機能を使っていないため、使い勝手が悪い感じでした。

github.com

plugin-xでは、認証に独自の機構を使っていて、いちいちoAuth認証をしないといけなかったりで非常に面倒。iOSの場合は標準の仕組みを使いたい!

というわけで、以前リリースした 『Wave Weaver』 などに使っていたコードを切り出して汎化してみた。

「究極」っていうのは若干誇張が入っているけど、言った物勝ちだと思ってる。

使い方

#include "CCSocialManager.h"

void onShareButtonTapped() {
    if (CCSocialShare::SocialManager::isAvailable(CCSocialShare::Service::TWITTER)) {
        CCSocialShare::SocialManager::postMessage(CCSocialShare::Service::TWITTER,
                                                  "I beat this game!",
                                                  path.c_str(),
                                                  [](CCSocialShare::PostResult result) {
            if (result == CCSocialShare::PostResult::SUCCEED) {
                // When to post is succeed
                log("Done");
            } else if (result == CCSocialShare::PostResult::CANCELED) {
                // When to post is canceled
                log("Canceled");
            }
        });
    }
}

こんな感じでSocialManager::postMessageを呼べばiOS/Androidから簡単に使える。渡す引数によってTwitter/Facebookに対応している。

iOSの場合、このように標準の共有機能が立ち上がるため、既に設定されていれば即座につぶやける。

Androidインテントを使って、Twitter/Facebookアプリを起動できるため、こちらも認証不要。

f:id:gigi-net:20151201233207p:plain

コールバックにも対応しているため、ラムダ式を渡すと、投稿したり、キャンセルした後になんらかの処理をさせることもできる。(iOSのみ)

ファイルパスを渡せば画像添付も行える。例えば単純にスクリーンショットを共有するだけなら以下の通り。

#include "CCSocialManager.h"

void onShareButtonTapped() {
    if (CCSocialShare::SocialManager::isAvailable(CCSocialShare::Service::TWITTER)) {
        Size size = Director::getInstance()->getWinSize();
        RenderTexture* texture = RenderTexture::create((int)size.width, (int)size.height);
        texture->setPosition(Point(size.width / 2, size.height / 2));
        texture->begin();
        Director::getInstance()->getRunningScene()->visit();
        texture->end();

        texture->saveToFile("screenshot.png",
                            Image::Format::PNG,
                            true,
                            [&](RenderTexture* rt, const std::string& path) {
            CCSocialShare::SocialManager::postMessage(CCSocialShare::Service::TWITTER,
                                                      "I beat this game!",
                                                      path.c_str(), 
                                                      [](CCSocialShare::PostResult result) {
                if (result == CCSocialShare::PostResult::SUCCEED) {
                    // When to post is succeed
                    log("Done");
                } else if (result == CCSocialShare::PostResult::CANCELED) {
                    // When to post is canceled
                    log("Canceled");
                }
            });
        });
    }
}

敢えて画像を縮小する機能などは実装していない。実際にこのようにしてスクリーンショットを添付してしまうと大きすぎるので、必要に応じて縮小すると良いと思う。

組み込み方法

https://github.com/giginet/CCSocialShare/blob/master/README.md#how-to-integrate

iOS/Androidへの組み込み方法は上記のREADMEに書いてあるので、この通りに組み込めば良いと思う。

iOS

iOSSocialManager.{h,mm}Social.frameworkをプロジェクトに読ませれば簡単に使える。便利。

Android

AndroidAndroid Studio + Gradleを用いてビルドするように設計している。

静的ライブラリをビルドするためのAndroid.mkと、Androidアプリ側に組み込むためのbuild.gradle両方の更新が必要で、ビルドもそれぞれ行わないといけないため、iOSに比べて煩雑になっている。

旧来のAntを使ったビルドのドキュメントは書いていないけど、上手い感じにやればビルドできると思う。

今後

Androidでのコールバック対応

現在、Android版ではコールバックを呼ぶ機構に対応していない。実装の目処は付いたが、以下のような理由で障害が多くて実装されていない。

JNIからC++の関数ポインタを叩くのが大変

良い方法が見つからなかった。JNI力が低い。

インテント終了のコールバック時の設計

インテントが終了したことの検知はActivityでやるのが一般的なようで、組み込む際にCocos2dxActivityを書き換える必要が出てきて、組み込みの手間が増えてしまう。

Android版の実装には旧来のインテントの仕組みを用いているんだけど、例えばSupport LibraryのShareCompatなどを利用すればさらにスマートに実装できるかもしれない。

Android+JNI力が高い方からのPull Requestお待ちしています 🙏

CIしたい

Android/iOSクロスプラットフォームで確認するのが大変面倒だったのでCI環境を整備したい感じ。

cocos2d-xをsubmoduleとして読んできてデモアプリをビルドする感じが良いかなあと考えています。

どうぞご利用ください

以下から導入できます!!!

インターフェイスなどは予告なく変更される可能性があります。

github.com

cocos2d-xでゲームを作りたい方は

拙著ではございますが、ぜひこちらの本で入門しましょう。

併せてAdvent Calendarにも参加いただけると幸いです。

そろそろ発売から1年が経つんですね。

ついでにゲームもよろしく

最近新作が出せていないのですが、以前出したゲームを貼っておきます。ご興味のある方はぜひ。

https://itunes.apple.com/jp/app/wave-weaver/id841280819?mt=8&uo=4&at=10l8JW&ct=hatenablog

neovimが実用段階になったようなのでvimを置き換えてみた話

去る11月21日にmixiで開催されたVimConf 2015に参加してきました。

vimconf.vim-jp.org

僕はvimを使い始めてもう7年目になるけれど、最近はあまりvimを使っていません。

最近は主にモバイルアプリ開発をしているので、XcodeAndroid StudioなどのIDEを使う機会が多いし、JetBrainsのIDEが最高すぎるので、趣味でPythonを書く時はPyCharm、仕事でもRubyMine(+IdeaVim)を使ってコードを書いてます。

一昔前は、まともなIDEがなくて、どんなものを書くにも大体vimでなんとかしなくてはならなかったけど、今は札束を積めばいくらでも優秀なIDEが金で買えるので、メインのコーディングを全てvimで行うモチベーションがあまりありません。

とはいえ、IDEが無い言語を書いたり、Markdownやちょっとした設定ファイルの変更、コミットログなどはvimで書いているので、相変わらず毎日vimは使っています。

vim Scriptなども書いたことがないので、vimの闇の集団が集まるカンファレンスに出て、話に付いていけるのかなー、と不安だったのですが、行ってみると、エンドユーザー向けの話が多くて非常に楽しめ、良いカンファレンスでした。

久しぶりにvimに触れてモチベーションが上がったので、この機会に前から気になっていたneovimを導入してみました。

neovimとは

f:id:gigi-net:20151124202836p:plain

neovim/neovim

neovimはvimをモダンな環境で再実装したプロジェクト。

従来のvimは開発方針などがオリジナルの開発者に委ねられていて、パッチが送りづらかったり、コードベースが古く、改修が難しいという問題があってリプレースを進めているらしい。

最近はすでにvimのほとんど全ての機能について互換性を維持している様子。

今回はOS X El Capitanにneovimを導入した過程を書いてみました。

neovimは開発が非常に活発で、この記事の内容は近い将来に役に立たなくなる可能性がありますことご了承ください。

neovimをインストール

Macでは、Homebrew用のFormulaが公開されているので、Homebrewを使えば簡単に導入することができます。簡単便利。

$ brew install neovim/neovim/neovim
$ nvim

大抵これだけで導入することができますが、ある環境では以下のようなエラーが出てハマった。

'/tmp/neovim20151122-89538-xdq4vm/neovim-0.1.0/deps-build/usr/bin/luajit' -e "package.path=[[`echo "$PWD" | sed -e 's/\([][]\)\1/]]..'\''\1\1'\''..[[/g'`/src/?.lua;]]..package.path" src/bin/luarocks make rockspec --tree="/tmp/neovim20151122-89538-xdq4vm/neovim-0.1.0/deps-build/usr"
make[3]: *** [bootstrap] Abort trap: 6
make[2]: *** [build/src/luarocks-stamp/luarocks-install] Error 2
make[1]: *** [CMakeFiles/luarocks.dir/all] Error 2
make: *** [all] Error 2
couldn't understand kern.osversion `15.0.0'
<Paste>

このエラーが出て困ったのだけど、どうやら--env=stdを指定したらビルドが通った。

$ brew install --env=std neovim/neovim/neovim

vimの設定を移す

今までは.vimrc.vimに設定ファイルを置いていたけど、neovimではXDG Base Directory Specificationというディレクトリ構造の標準規格に則った仕様変更がされており、$XDG_CONFIG_HOME/nvim以下に設定ファイルを置く仕様に変更になった。

vimと設定ファイルを共存したい人は、symlinkを貼ればvimとneovimの設定を共存することができる。

$ export XDG_CONFIG_HOME=~/.config
$ ln -s ~/.vim ~/.config/nvim/
$ ln -s ~/.vimrc ~/config/nvim/init.vim

詳しくは公式のドキュメントを読めば良さそう。

Vim documentation: nvim_from_vim

neovimの互換性はほぼ完璧で、設定はもちろん、現時点で大部分のプラグインが正常に動作する。

vimのパッケージマネージャーである、NeoBundleも問題なく動作するため、今までNeoBundleInstallしていたプラグインも問題なく使用可能。

一方で、現段階ではLuaサポートが未実装なため、Luaを使ったプラグインは動作しないようだ。

僕のvimrcを移しても、ほぼ書き換えることなく動作しました。

Transition to nvim :rocket: · giginet/castle@2b2ce1c · GitHub

最後に、必要に応じてエイリアスを貼っておく。

$ alias vim=nvim

deoplete.nvimを導入する

動作しない一部のプラグインvimでインクリメンタルな補完を実現するneocompleteがあるのだけど、同じ作者である暗黒美夢王様がneovimで動作するneocompleteであるdeopleteをリリースしてくださっているのでこれもNeoBundleを用いてインストールする。

Shougo/deoplete.nvim

deoplete.nvimはPython3サポートが必須なので、Python3へのパスを通してあげる必要がある。

僕はpyenvを使ってPython3を使っているので、以下のような設定を追加した。

"Python3 support
let g:python3_host_prog = expand('$HOME') . '/.pyenv/shims/python'

その後、Python3にneovimというパッケージを導入する。

$ pip install neovim

Python3が問題なく動いているかどうかは、以下のコマンドで確認できる。 これで1が返ってきたらPython3サポートが有効になっている。

:echo has('python3')

最後に、vimの場合はneocompleteを、neovimの場合はdeopleteを利用するように設定する。以下ではNeoBundleの遅延ローディングを使って設定している。

  if has('nvim')
    NeoBundleLazy 'Shougo/deoplete.nvim', {
          \ "autoload": {"insert": 1}}
  else
    NeoBundleLazy 'Shougo/neocomplete.vim', {
          \ "autoload": {"insert": 1}}
  endif

if has('nvim')
  let s:hooks = neobundle#get_hooks("deoplete.nvim")
  function! s:hooks.on_source(bundle)
    let g:deoplete#enable_at_startup = 1
  endfunction
else
  let s:hooks = neobundle#get_hooks("neocomplete.vim")
  function! s:hooks.on_source(bundle)
    let g:neocomplete#enable_smart_case = 1
    let g:neocomplete#enable_at_startup = 1
  endfunction
endif

最後に、READMEにあるとおり、初回起動時は以下のコマンドを実行する。

:UpdateRemotePlugins

無事に動作しました。

f:id:gigi-net:20151124203430p:plain

現状、僕の環境ではtmux上で起動するとハイライトの表示がバグってしまうようだ。 全ての設定を無効にしても再現したため、おそらくneovimかdeopleteのバグな気がする。

f:id:gigi-net:20151124203444p:plain

僕は闇の力を使役することができないのでこの問題を修正できそうになかった。何か知見がある方は是非教えてください。

追記

.tmux.confdefault-terminalxterm-256colorに設定したところ、上手く表示されるようになりました。 id:lambdalisueさんありがとう!

# Force to use 256 colors in tmux
set -g default-terminal   'xterm-256color'
set -g terminal-overrides 'xterm:colors=256'

Set default-terminal into tmux.conf · giginet/castle@5657b0b · GitHub

使ってみての感想

驚くほど問題なく動作していい感じ。使用感が今までと全く変わらなくて良い。

動作速度も向上しているという話だったのですが、気持ち早くなったかな?程度で見違えるほど早くはなっていない気がする。

問題なく動作するとはいえ、今のところ積極的に乗り換えるメリットもあまり感じないような印象です。

ヘビーに使う人だと、また使用感に違いがあるかもしれないので、ご興味のある方はお試しください。

vimを使って書くコードがない方は

この本を購入してvimを使って思考のスピードでコーディングしましょう。