blog.tkeo.info

UTF-16なファイルのgit diffを見たい

gitがUTF-16のファイルをバイナリだと認識してしまって、diffが表示されずに困ったので以下の設定をした。

1
$ git config diff.toutf8.textconv 'nkf -w8'

.gitattributesファイルに以下の一行を書く。

1
*.cs diff=toutf8

これでcsファイルをUTF-8に変換してからdiffを取るようになった。

ググるとiconvを使うのが見つかるけど、UnityアセットのソースコードがUTF-8のものとUTF-16のものが混在しているので、入力をよしなに判別してくれるnkfを使うようにした。

社内LT大会で家電ChatOpsについて話した

IRKitを使って、ChatOpsやってみたよっていう話を先週の社内LT大会で話しました。 ChatOpsしたい、rubotyとhubot使いたいっていうのが目的なので、わざとまわりくどいことをやってます。

EmacsでUnity開発をする

これはドリコム Advent Calendar 2014の10日目の記事です。

9日目は@hiracyさんによるサーバが増えた時にインフラ担当者がやってきたことです。

自己紹介

  • @tkeo
  • 2007年新卒でドリコムに入社、8年目
  • メインの仕事はスマホゲームのサーバサイド(Rails)で、今年からクライアント(Unity)のほうも触り始めた
  • Rails歴 6年、Unity歴 8ヶ月
  • いまの作業比率は サーバ:クライアント = 2:1 ぐらい

今回の話

Unityを始めた当初はMonoDevelopを使っていたのですが、どうにも手になじまず腹が立ったので、普段サーバ側の開発で使っているemacsを使うことにしました。

以下はいろいろハマりながらも、インターネット上の先人の力を借りてまとめた自分の設定です。

環境

  • Mac OS X Mavericks
  • emacs 24.4.1
  • パッケージ管理はcask

csharp-mode

これがなくては始まらないC#用のメジャーモード。

1
2
; cask
(depends-on "csharp-mode")
1
2
3
4
5
6
7
8
9
; init.el
(require 'csharp-mode)
(add-hook 'csharp-mode-hook
          '(lambda ()
             (setq indent-tabs-mode nil)
             (setq c-basic-offset 4)
             (c-set-offset 'substatement-open 0)
             (flycheck-mode 1)
             (omnisharp-mode)))

自動補完

OmniSharpServer

C#のコードをパースしたりいろいろやってくれる(らしい)サーバです。 他のエディタでも使えるらしいです。

monoが必要なのでインストールして、

1
$ brew install mono

あとはREADME通りにビルド。

1
2
3
4
$ git clone https://github.com/nosami/OmniSharpServer.git
$ cd OmniSharpServer
$ git submodule update --init --recursive
$ xbuild

するとOmniSharp/bin/DebugOmniSharp.exeができているはず。 試しに起動してみる。

1
$ mono OmniSharp/bin/Debug/OmniSharp.exe -s /path/to/unity-project.sln

するとずらずらっとLoadingほげほげと出てきて、Solution has finished loadingで起動完了。無事起動が確認できたらCtrl+Cで止めておく(このあとemacsから起動するので)

omnisharp-emacs

OmniSharpServerをemacsから使うためのものです。

1
2
; cask
(depends-on "omnisharp")
1
2
3
; init.el
(require 'omnisharp)
(setq omnisharp-server-executable-path (expand-file-name "/path/to/OmniSharp/bin/Debug/OmniSharp.exe"))

csファイルを開いた時にslnファイルを選べと言われるので、選んであげるとバックグラウンドで起動してくれます。

M-x omnisharp-auto-completeで候補表示、M-x omnisharp-go-to-definitionで定義にジャンプできます。 適当なキーバインドを設定しておくと便利。

文法チェック

flycheck

omnisharp-emacsにcheckerが含まれていて、OmniSharpサーバと連携してチェックをしてくれます。

1
2
; cask
(depends-on "flycheck")
1
2
3
4
; init.el
(require 'flycheck)
(setq flycheck-check-syntax-automatically '(mode-enabled save idle-change))
(setq flycheck-idle-change-delay 2)

emacsclientアプリ化

Unity上でcsファイルをダブルクリックして開きたくなったときのための設定(あまりしないけど)

Unityの設定で外部エディタに指定できるのはMacのアプリ(*.app)だけなので、emacsclientを起動するアプリを作ります。 vim用にやっている人がいたのでその設定を参考にしました。

アプリを作るのにはAutomatorを使います。手順は以下のとおり。

  1. アプリケーションを選択。
  2. アクション>ユーティリティの中にある「AppleScriptを実行」を右にドラッグ&ドロップ。
  3. 下記コードを貼り付けて、appを適当な場所に保存。
1
2
3
on run {input, parameters}
    do shell script "/usr/local/bin/emacsclient -n " & quoted form of POSIX path of input
end run

automator

作ったappをUnity上で指定してあげると、外部エディタとしてemacsが使えるようになります。 あとはserverとして起動するのを忘れずに。

1
2
3
4
; init.el
(require 'server)
(unless (server-running-p)
  (server-start))

リファレンス検索

rubyの開発でも使っているDashを使えるようにします。

dash-at-point

1
(depends-on "dash-at-point")
1
2
3
4
; init.el
(global-set-key (kbd "C-c d") 'dash-at-point)
(global-set-key (kbd "C-c e") 'dash-at-point-with-docset)
(add-to-list 'dash-at-point-mode-alist '(csharp-mode . "cs"))

カーソル位置の単語で検索します。 上記設定ではcsharp-modeのときはキーワード “cs” が設定されたdocsetの中から検索します。

dash

Dash側で画像のようにキーワードを設定しておくと、.NET FrameworkとUnity 3Dのドキュメントを同時に検索できます。

自前docsetを作る

doxygenを使えばDash用のdocsetを作れます。 コードを含むアセットを購入した時に(たまに)やってます。

1
$ brew install doxygen
1
2
3
4
5
6
7
8
9
10
11
12
13
$ cat doxygen.config
GENERATE_DOCSET        = YES
SEARCHENGINE           = NO
DISABLE_INDEX          = YES
GENERATE_TREEVIEW      = NO
GENERATE_LATEX         = NO
GENERATE_HTMLHELP      = YES
RECURSIVE              = YES

PROJECT_NAME           = hogehoge
OUTPUT_DIRECTORY       = output
INPUT                  = path/to/Scripts
DOCSET_BUNDLE_ID       = hogehoge

こんな感じの設定ファイルを作って、まずはHTMLドキュメントを生成。

1
$ doxygen doxygen.config

htmlディレクトリに移動してmakeをたたくとdocsetが作られます。

1
2
3
$ cd output/html
$ make
$ open hogehoge.docset

その他

日本語を含むときはBOM付きで保存しないと化けます。C-x RET futf-8-with-signatureに変更。

まとめ

以上、MonoDevelopを使わずにemacsでUnity開発するための設定を紹介しました。

明日はみっきーさんです。

参考リンク

ブログ引っ越し

hatenablogから引っ越してきた。 octopressお手軽でいい感じ。

zshだとrake new_postのときにglob展開しようとして怒られるので、noglobをつける。

1
2
3
4
5
$ rake new_post['hoge']
zsh: no matches found: new_post[hoge]
$ noglob rake new_post['hoge']
mkdir -p source/_posts
Creating new post: source/_posts/2014-12-09-hoge.markdown

面倒なのでaliasを書いてしまった。

1
alias rake='noglob rake'

日記

railsアプリ開発中にmigrationでエラーが起こって、一部だけ変更が適用された戻すのがめんどくさい中途半端な状態になることがよくあって今日もうぎゃーってなったので、トランザクションで囲んでくれるような仕組みないのかなと思って調べてみると

http://guides.rubyonrails.org/migrations.html

On databases that support transactions with statements that change the schema (such as PostgreSQL or SQLite3), migrations are wrapped in a transaction. If the database does not support this (for example MySQL) then when a migration fails the parts of it that succeeded will not be rolled back. You will have to rollback the changes that were made by hand.

なんだってー

postgresはデフォルトで対応しているが、mysqlはサポートされてなくて非対応。知らなかった…。

一応mysqlのドキュメントにもあたってみる。

http://dev.mysql.com/doc/refman/5.6/en/cannot-roll-back.html

Some statements cannot be rolled back. In general, these include data definition language (DDL) statements, such as those that create or drop databases, those that create, drop, or alter tables or stored routines.

DDLはロールバックできない、と。

開発環境だけDBサーバ変えるとかしたくないし、どうしたらいいかなあ。

という日記。

追記

change_tablebulk: trueオプションを付けてあげればいいらしい。 ひとつのALTERでまとめてカラム追加・削除されるので中途半端な状態は作られない。

Rails4 で MiniTest + Spork + Guard

正式版が出る頃には変わっている可能性が高いが、現時点でのメモを残しておく。

minitest-rails

https://github.com/blowmage/minitest-rails

Gemfile に追加。

gem "minitest-rails"

必要なファイルを生成。

$ rails generate mini_test:install

test/minitest_helper.rb が生成される。

ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)

require "minitest/autorun"
require "minitest/rails"

# Add `gem "minitest/rails/capybara"` to the test group of your Gemfile
# and uncomment the following if you want Capybara feature tests
# require "minitest/rails/capybara"

# Uncomment if you want awesome colorful output
# require "minitest/pride"

class ActiveSupport::TestCase
  # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
  fixtures :all

  # Add more helper methods to be used by all tests here...
end

各testファイルでこれを読み込むために下の一行が必要。

require 'minitest_helper'

動作確認。

$ ruby -Itest test/foo/bar_test.rb

spork-minitest

https://github.com/semaperepelitsa/spork-minitest

Gemfile に追加。

gem "spork", "~> 1.0rc"
gem "spork-minitest", "~> 1.0.0.beta1"

下記コマンドを実行し、minitest_helper に spork 向けの設定を追加する。

$ spork minitest --bootstrap

test/minitest_helper.rb に追記されるので適宜編集する。

$LOAD_PATH << "test"
require 'rubygems'
require 'spork'
#uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug'

Spork.prefork do
  # Loading more in this block will cause your tests to run faster. However,
  # if you change any configuration or code from libraries loaded here, you'll
  # need to restart spork for it take effect.

  ENV["RAILS_ENV"] = "test"
  require File.expand_path('../../config/environment', __FILE__)

  require "minitest/autorun"
  require "minitest/rails"
  require 'simplecov'
  require 'simplecov-rcov'

  SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
  SimpleCov.start 'rails'

  # Add `gem "minitest/rails/capybara"` to the test group of your Gemfile
  # and uncomment the following if you want Capybara feature tests
  # require "minitest/rails/capybara"

  # Uncomment if you want awesome colorful output
  # require "minitest/pride"

  class ActiveSupport::TestCase
    # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
    fixtures :all

    # Add more helper methods to be used by all tests here...
  end
end

Spork.each_run do
  # This code will be run each time you run your specs.

end

# --- Instructions ---
# Sort the contents of this file into a Spork.prefork and a Spork.each_run
# block.
#
# The Spork.prefork block is run only once when the spork server is started.
# You typically want to place most of your (slow) initializer code in here, in
# particular, require'ing any 3rd-party gems that you don't normally modify
# during development.
#
# The Spork.each_run block is run each time you run your specs.  In case you
# need to load files that tend to change during development, require them here.
# With Rails, your application modules are loaded automatically, so sometimes
# this block can remain empty.
#
# Note: You can modify files loaded *from* the Spork.each_run block without
# restarting the spork server.  However, this file itself will not be reloaded,
# so if you change any of the code inside the each_run block, you still need to
# restart the server.  In general, if you have non-trivial code in this file,
# it's advisable to move it into a separate file so you can easily edit it
# without restarting spork.  (For example, with RSpec, you could move
# non-trivial code into a file spec/support/my_helper.rb, making sure that the
# spec/support/* files are require'd from inside the each_run block.)
#
# Any code that is left outside the two blocks will be run during preforking
# *and* during each_run -- that's probably not what you want.
#
# These instructions should self-destruct in 10 seconds.  If they don't, feel
# free to delete them.

sporkの動作確認をする。

$ spork

sporkを立ち上げた状態のまま、別窓を開いて testdrb でテスト実行してみる。

$ testdrb test/**/*.rb

guard-minitest

https://github.com/guard/guard-minitest

本家のものを使いたいところではあるが、sporkと組み合わせた時に動かないので一旦他の人が作ったブランチを使わせてもらう。 (ref. https://github.com/guard/guard-minitest/pull/41)

sporkを使わないのであれば本家のものでもおそらく問題ない。

Gemfile に追加。

gem "guard-minitest", github: "itrcdevs/guard-minitest", branch: "fix_for_spork-minitest"

設定ファイルを生成する。すでにファイルが存在する場合は内容が追記される。

$ guard init minitest

生成された Guardfile を編集する。

# More info at https://github.com/guard/guard#readme

guard 'minitest' do
  # with Minitest
  watch(%r|^test/(.*)_test\.rb|)
  watch(%r|^lib/(.*)([^/]+)\.rb|)     { |m| "test/#{m[1]}test_#{m[2]}.rb" }
  watch(%r|^test/test_helper\.rb|)    { "test" }

  # Rails
  watch(%r|^app/controllers/(.*)\.rb|) { |m| "test/controllers/#{m[1]}_test.rb" }
  watch(%r|^app/helpers/(.*)\.rb|)     { |m| "test/helpers/#{m[1]}_test.rb" }
  watch(%r|^app/models/(.*)\.rb|)      { |m| "test/models/#{m[1]}_test.rb" }
end

guard の動作確認。

$ guard

適当にファイルをtouchしてみるとテストが走るはず。 何も起こらない場合はちゃんと監視対象に入っているか記述を見なおしてみる。

guard-spork

Gemfile に追加。

gem "guard-spork"

Guardfile に設定を追加する。

$ guard init spork

Guardfile に追加された spork の箇所の編集と、minitest で drb を使うように変更する。

guard 'spork', minitest: true, minitest_env: { 'RAILS_ENV' => 'test' }, bundler: true do
  watch('config/application.rb')
  watch('config/environment.rb')
  watch('config/environments/test.rb')
  watch(%r{^config/initializers/.+\.rb$})
  watch('Gemfile')
  watch('Gemfile.lock')
  watch('test/minitest_helper.rb') { 'test' }
end

guard 'minitest', drb: true do
  # (省略)
end

実行。

$ guard

これだけで spork が自動的に起動する。 先と同じようにファイルを編集したときに動けばOK

その他

  • factory_firl_rails を入れると mintiest 用のgeneratorがちゃんと動かない (追記:githubのmasterは修正されてた)
  • まだプロジェクトの規模が小さいのでsporkの恩恵を感じられない…
  • spork-rails が必要かと思ってrails4ブランチも含めて試してみたが要らなかった(入れると逆にダメになる)

Ruby2.0+Rails4で新規プロジェクトを作成したメモ

前準備

$ brew install openssl
$ brew link openssl
$ brew install readline
$ brew link readline

プロジェクトのディレクトリ作る。

$ mkdir hoge && cd hoge

ruby

ruby 2.0.0-devを入れる。

$ CONFIGURE_OPTS="--with-openssl-dir=`brew --prefix openssl` --with-readline-dir=`brew --prefix readline`" rbenv install 2.0.0-dev
$ rbenv local 2.0.0-dev

bundlerのバージョンが1.2だと怒られるので1.3を入れる。

$ gem install bundler -v 1.3.0.pre.4

rails

一旦Gemfileにrailsだけ書いてbundle installする。 まだrails 4.0のgemがないのでgithubから取ってくるように指定。

$ cat Gemfile
source :rubygems
gem 'rails', github: 'rails/rails'

bundle installを実行し、まずrails本体だけ入れる。

$ bundle install

rails newしていろいろファイルを生成。Gemfileを上書きするか聞かれるので Y で上書き。

$ bundle exec rails new . -d mysql -T --skip-bundle --edge

再度bundle install

$ bundle install

これで完了。あとはいつもどおりDBを作って…

$ bundle exec rake db:create

起動する。

 $ bundle exec rails s
=> Booting WEBrick
=> Rails 4.0.0.beta application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
        SECURITY WARNING: No secret option provided to Rack::Session::Cookie.
        This poses a security threat. It is strongly recommended that you
        provide a secret to prevent exploits that may be possible from crafted
        cookies. This will not be supported in future versions of Rack, and
        future versions will even invalidate your existing user cookies.

        Called from: xxx/ruby/2.0.0/bundler/gems/rails-e63e280bed3a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb:24:in `initialize'.
[2013-01-07 19:35:35] INFO  WEBrick 1.3.1
[2013-01-07 19:35:35] INFO  ruby 2.0.0 (2013-01-07) [x86_64-darwin11.4.2]
[2013-01-07 19:35:35] INFO  WEBrick::HTTPServer#start: pid=76843 port=3000

なにやらWARNING出てるけど、とりあえずwelcome画面が出た。

参考

ログイン直後にtmuxを起動する

SHLVLっていう環境変数があることを知ったので、.zshrcに以下を追記してログイン直後にtmuxを起動するようにしてみた。

1
2
3
if [ $SHLVL = 1 ]; then
  tmux attach || tmux new
fi

macでsshfsを使う

なんかぐぐるとMacFUSEを入れる方法ばっかり出てくるけど、brewで入れるのであれば不要。

1
2
3
4
5
6
7
$ brew install sshfs
(略)
==> Caveats
Make sure to follow the directions given by `brew info fuse4x-kext`
before trying to use a FUSE-based filesystem.
==> Summary
/usr/local/Cellar/sshfs/2.3.0: 7 files, 120K, built in 12 seconds

installすると上のように言われるので指示に従う。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ brew info fuse4x-kext
fuse4x-kext 0.8.14
http://fuse4x.org/
/usr/local/Cellar/fuse4x-kext/0.8.14 (7 files, 312K)

In order for FUSE-based filesystems to work, the fuse4x kernel extension
must be installed by the root user:

  sudo cp -rfX /usr/local/Cellar/fuse4x-kext/0.8.14/Library/Extensions/fuse4x.kext /System/Library/Extensions
  sudo chmod +s /System/Library/Extensions/fuse4x.kext/Support/load_fuse4x

If upgrading from a previous version of Fuse4x, the old kernel extension
will need to be unloaded before performing the steps listed above. First,
check that no FUSE-based filesystems are running:

  mount | grep fuse4x

Unmount all FUSE filesystems and then unload the kernel extension:

  sudo kextunload -b org.fuse4x.kext.fuse4x


http://github.com/mxcl/homebrew/commits/master/Library/Formula/fuse4x-kext.rb

上のsudoコマンド2つを叩くだけで使えるようになる(下の方はアップグレードのときに実行するらしい)