sifue's blog

プログラマな二児の父の日常 ポートフォリオは www.soichiro.org

Erlangの開発環境をWindows上のCentOS6.4に整える

仕事ではMacを使っているけれども、プライベートで使うPCは大抵ゲームのためにWindowsPCだったりするので、vagrant上のCentOS6.4開発環境を作るための手順をまとめておく。

 

VirturalBoxをインストール

https://www.virtualbox.org/

 

vagrantをインストール

http://www.vagrantup.com/

 

boxファイルは、

http://www.vagrantbox.es/

 

から好きなものを利用する。本番環境でもCentOS6.4を使うつもりなら

CentOS 6.4 x86_64 Minimal (VirtualBox Guest Additions 4.2.16, Chef 11.6.0, Puppet 3.2.3)

このあたりの構成が良さそう。

ターミナルエミュレーターは、

Tera Term

http://sourceforge.jp/projects/ttssh2/

がオススメ。vagrant up後sshでつなぐ。

 

configureするためにgccとは必要になりそうになものはsudu yum install gccで予めインストールしておく。

https://gist.github.com/voluntas/8911384

を参考にインストール。

Erlangのインストール

 

これでerlコマンドやerlcコマンドが使えるようになる。

 

あと、vimも整備する。

vimは7.3以上をインストールしたいので

http://qiita.com/muniere/items/0569d05d470c5d3dc51b

をインストール

 

バージョン管理としてNeoBundleをインストール

https://github.com/Shougo/neobundle.vim

 

そして以下の設定をvimrcに追加。

erlang開発用に足すvimrc(NeoBundle前提)

を追加して

:NeoBundleInstall

する。

その後、

~/.vim/bundle/vim-erlang-runtime

のtest_syntax.erlがちゃんとシンタックスハイライトで表示されるか確認する。

 

ちなみに以下のコードはこんなかんじに表示される。

geometory.erl

 

f:id:sifue:20140428212244p:plain

 

無論、makeの設定もしたので、:makeでシンタックスチェックもしてくれるようになる。とりあえずこれだけあれば最低限の開発はなんとか、大丈夫そう。

 

ただ、Linux上のvimの開発にこだわらないのであれば、IntelliJ IDEA UtlimateのErlangプラグイン使ったほうが楽そうではある。

 

個人用にIntelliJ IDEA Utlimate13のライセンスを買うかは悩ましいところ。

 

まだErlang入門仕立てなので、またビルドツールrebarとの連携が入ってきたら追記していきたい。

Scalaでの切り出したい処理が処理の中間にあるメソッド同士の重複行排除のやり方

最近Scalaを書く人が増えてきたこともあっていろいろ教える機会も増えてきたのですが、その中でよくScala初心者がつまづきやすいポイントである、切り出したい処理が、処理の中間にあるメソッド同士の重複行排除のリファクタリングの例を書こうと思います。

 

重複のあるサンプルコードとしてはこのような感じになります。

例として、ランダムに文字列のテンプレートを選択してその中にメッセージを埋め込んだあと、そのバイト数と内容を出力するメソッドと、その文字数と内容を出力するメソッドを用意してみます。

切り出したい処理が処理の中間にあるメソッド

RandomTemplateProviderはテンプレートをランダムに渡すオブジェクトです。2つのメソッドは見ての通り仕様をそのまま実行していますが、printByteLengthAndContentメソッドとprintCharLengthAndContentメソッドには4行の重複行が含まれています。

 

こういう切り出したい処理が処理の真ん中に挟まっている場合の重複行排除は、関数を第一級オブジェクトでかけるScalaではこのようになります。

切り出したい処理が処理の中間にあるメソッド同士の重複行排除の例

 

関数をオブジェクトとして扱うことに慣れない方は、一瞬ん?とおもうかもしれませんが、このコードでは、printTargetLengthAndContentというメソッドを最下部で新たに定義し、そこでは、targetLengthProviderという関数を受け取って実行するという処理をしています。

 

この渡すtargetLengthProvider関数の中に切り出したい関数を元々のメソッドに設定すればよく、Scalaで簡単に匿名関数を作ることができる{}という記法を用いて上記のように表現してやることができます。これで見た目もわかりやすく存在していた重複行を排除することができました。

 

これでCPDなどのチェッカーなどに引っかかった時も柔軟に対応することができます。実際の業務のコードではこの重複行の長さが10行を超えるものである場合がほとんどですが、ぜひ応用にチャレンジしてみてください。

 

ちなみに、Java8になったことで、このような関数オブジェクトを使った重複行排除のリファクタリングが、Javaでもずいぶん書きやすくなっています。その例はまたの機会に。

Developers Summit 2014 で「Play2/Scalaでドメイン駆動設計を利用した大規模Webアプリケーションのスクラム開発の勘所」という内容で発表してきました

あまりにタイトルが長すぎるだろうと各所から突っ込まれ、あまりにも詰め込んだ内容で発表してしまったとちょっと反省しています。

お話としては、現在ニコニコ生放送の内部をPHPからScalaへ書きなおしているよ、というお話でした。

発表内容はこちら

これらの内容は、これからScalaを使ってWebサイトを構築、運営してみようとしているリーダーさん向けに書いたものとなっています。Play2/Scalaドメイン駆動設計、またスクラム開発の導入への足がかりにの情報となっていれば幸いです。

こんな雪の中わざわざ聞きに来てくださった皆様、そしてこの書き直しを着想するにあたってお世話になった特にじゅんいちかとうさん(id:j5ik2o)さんには多大な感謝を申し上げます。

 

追伸

もともと blog.soichiro.org にブログを移転していたのですが、もし大量にアクセスが有った時にさくらVPSだとさばけないと思いこちらに記載することとしました。

 

Twitterの検索結果をIRCにnoticeで転送し、閾値を超えるとmessageするボット

Scala2.9→2.10に移行するにあたって、公開することで誰かが使えるかもしれないScalaのツールがあったので、GitHubに公開しました。Twitter APIも1.0の廃止が近いので1.1への対応をしてあります。


https://github.com/sifue/twisearch_ircbot


使う用途は主にIRC上でのtwitter監視ですねw 内部的にStreaming APIではなくRESTのSearch APIを使っているので、ANDやOR、その他の検索指定演算子を利用することができます。http://blog.fkoji.com/2009/10191119.html の解説が丁寧です。


なおScala2.10といいつつ、akkaへの移行が大変だったりとか、長期間の検証をしなくていはいけないとかがあり、こいつはactorをそのまま使っています。build.sbtに

libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-actors" % _)

を書くことでactorをそのまま使い続けられます。id:xuweiさん、情報ありがとうございました。
なお内部的には、twitter4jとsircを梱包しており、assemblyコマンドでビルドすることでjava -jarコマンドで実行できるjarになります。

$ git clone git@github.com:sifue/twisearch_ircbot.git

を利用して、思い思いにコードを変更してご利用ください。


ビルド方法は、以下のとおり

ビルド方法

javaとsbtをインストールの上、

$ sbt
> assembly

これでtargetディレクトリの中に、twisearch_ircbot-assembly-2.0.jarがビルドされます。

使い方

twisearch_ircbot-assembly-2.0.jarと同じディレクトリに、 twisearch_ircbot_template.propertiesを正しく編集して、 twisearch_ircbot.propertiesというファイル名で保存ください。

irc.address = hostname
irc.channel = #channelname
irc.nickname = twisearch_ircbot
irc.charset = UTF-8
limitCount = 3
intervalSec = 60
keyword = #MT2
messageFormat = interval:%1$s keyword:%2$s count:%3$s
noticeFormat = @%1$s %2$s %3$s
consumerKey = consumerKey
consumerSecret = consumerSecret
accessToken = acessToken
accessTokenSecret = accessTokenSecret

twisearch_ircbot.propertiesの内容のうち、consumerKey、consumerSecret、accessToken、accessTokenSecretはTwitter Developpers https://dev.twitter.com/ より、ログインの後、アプリケーションを作成してaccessTokenを発行してご利用ください。

なお日本語などを入れたい場合には、javaのnative2asciiコマンドを利用してascii化する必要があります。 http://symfo.web.fc2.com/js-sample/jq/sample2.html 以上のようなサイトでも変換できます。


設定の後、

$java -jar twisearch_ircbot-assembly-2.0.jar

で実行することができます。 またIRCのボットが入っているチャンネルにて

ping nickname

とするとWorking now.とnoticeを返します。

コードの中身

メインルーチンは、
TwitterSeacher.scala

  def act() = loop {
    val query = new Query
    query.setQuery(keyword)
    query.setSinceId(maxId)
    query.setResultType(Query.RECENT);
    val tweets = twitter.search(query).getTweets().reverse
    if(maxId != 0L) tweets.filter(t => t.getId() > maxId).foreach(sendNoticeToIRC)
    val count = tweets.filter(t => t.getId() > maxId).size
    if(count > limitCount && maxId != 0L) sendMessageToIRC(count)
    tweets.foreach(t => {if(t.getId() > maxId) maxId = t.getId()})
    TimeUnit.SECONDS.sleep(intervalSec)
  }

これだけで表現できています。あとは設定の読込と例外ハンドルだけ。やっぱりScalaは短く書けて良いです。

Scala2.9から2.10への移行作業の健忘録

ただの作業ログです。

build.sbtのscalaVersionを2.10.0に変更

scalaVersion := "2.10.0"

以上のようにする。

Seq#firstをSeq#headに置換

盲目的に置き換え。

Squerylを2.10対応の最新バージョンに。でもリポジトリのURLがおかしいので直接追加

libraryDependencies  ++=  Seq(
  "org.squeryl" %% "squeryl" % "0.9.5-6" from "http://repo1.maven.org/maven2/org/squeryl/squeryl_2.10/0.9.5-6/squeryl_2.10-0.9.5-6.jar",
  "mysql" % "mysql-connector-java" % "5.1.21"
)

actor使えなくなるのでakkaへの乗り換え。実装量大。

object actors is not a member of package scala
[error] import scala.actors.Actor

悲しい...。build.sbtに

resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"
 
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.1.1"

を追加して、あとはakkaのAPIを見ながら実装していきます。
というかActorの作り方も、実装の仕方や例外のハンドリングなんかも基本全然違うのでakkaに合わせて書きなおさないと、変な感じになってしまう。というか書きなおしたほうが早い。

まとめ

結構コード量があったこと、元々Actorを使いたくてScalaを選んでいたところもあるので、2.9からの移行はそれなりに大変でした。というか全部終わらず、無理にバージョンアップさせる必要はないと感じました...。辛すぎる。せめてコードコンバーターとかあれば。


まだ生まれて10年経ってない言語の辛さだなぁ。まだ2.11と3.0でも大きく変わりそうだし。しゃーなし。

ssh上でマウススクロールも使える大規模PHP開発向けvim+tmux環境の構築

全体で数百万行、1ファイル1万行超のPHPファイルも一秒以内で開き、開発していくことのできる大規模開発向けのvim+tmux環境を紹介しようと思います。この設定この環境で半年ぐらい安定して利用できています。(無論そんな1万行あるファイルや数千行で複雑性循環度500超のメソッド作るなよという話もあるんですが、すでに存在する魔獣とは向き合わなければならないのです...)
なので数百万行レベルの大規模開発となると重すぎて使えない設定やプラグインもあります。そのようなものはきちんと外してあります(PHPの関数折りたたみ機能、デフォルトのPHPシンタクスハイライト、neocomplcache.vim、ツリーの構成に時間のかかるproject.vimなど)。
基本的にはターミナルエミュレーターとして、macならばiTerm2、windowsならばTeraTermまたはPuttyを利用することを想定しています。
ただ自分自身は、普段はチームでのペアプロ環境維持のためにSublimeText2を利用しており、ssh上で作業する時にのみvimを利用しています。基本的にはマルチカーソルなど独特なものを除きSublimeText2でできることは大抵vimでもできるようにしてあります。


スクリーンショットはこのような感じです。

以上の例では、上のペインではvimを膻分割で利用して、下にも2つペインを用意して、一つはSymfony2のphpunitテストの実行、もうひとつはtopの監視をしています。


実際に現在自分が利用しているtmux及びvimの設定の全体は、
https://github.com/sifue/dotfiles/blob/master/.tmux.conf
https://github.com/sifue/dotfiles/blob/master/.vimrc
以上のようになっています。


なお、仮想端末になぜscreenでなくtmuxを使うかというと、既存セッションへのアタッチが高速(1秒以内)であること、マウス操作が優秀なこと、単一セッションを複数のマシンからデフォルトで使えることなどがあります。(screenでも設定で複数マシンからというのはできるそうですが...)


最終的にはssh上からの利用で以下のようなことができます。

  • 仮想端末機能の利用(tmuxの持っている機能)
    • セッション維持
    • 複数セッションのタブやペインでの使い分け
    • 単一セッションの複数マシンからの利用
  • マウス操作
    • マウスを使った分割されたtmuxペイン選択
    • マウスを使った分割されたtmuxペインのサイズ変更
    • マウスのホイールを使ったvim上のスクロール
    • ドラッグを利用したvim上の文書選択
    • ダブルクリックを使ったvim上の単語選択
    • vimのタブのマウス選択
  • vimプラグイン管理 (NeoBundle)
  • ファイル、履歴、バッファ、レジスタ等のワイルドカードを利用したリソース選択 (Unite)
  • 軽くてPHP5.4に対応したのシンタクスハイライト (shawncplus/php.vim)
  • 自動補完入力 (デフォルト機能/ctags)
  • シンタクスチェック(make)
  • 関数の定義元にジャンプ(ctags)
  • コードスニペット(snipMates)
  • svn, gitの履歴確認 (vcscommand.vim)
  • クラス内メソッドのアウトライン表示 (unite-outline)
  • ファイル名のファジー検索 (ctrlp.vim)


基本的レンタルサーバーなどでも利用できるようにホームディレクトリ以下にローカルインストールする前提で~/local以下にインストールします。サーバー自体にインストールされる方は、~/localを/usr/localと読み替えて下さい。
そのため、利用しているシェルで~/local/binと~/local/libにパスを通してください。
特に自分の使っているシェルがわからないよという方は、デフォルトシェルのbashでパスを通すように、

$ echo "export PATH=/usr/local/bin/:/usr/local/lib/:\$PATH" >> $HOME/.bashrc
$ source  $HOME/.bashrc

以上を実行して始めて頂ければと思います。


説明の順番は

  1. インストールと使い方
  2. 大規模開発の際に使えるvimテクニック

となっています。

インストールと使い方

tmuxのインストール

まずはtmuxをインストールします。
http://web.sfc.keio.ac.jp/~t10078si/wpx/?p=615
を参考に。libeventの適切なバージョンが無いこともあるので一緒にインストールしていまいます。

$ cd
$ mkdir -p ~/local/source
$ cd ~/local/source
$ wget http://downloads.sourceforge.net/project/tmux/tmux/tmux-1.7/tmux-1.7.tar.gz
$ wget https://github.com/downloads/libevent/libevent/libevent-2.0.17-stable.tar.gz
$ tar zxvf tmux-1.7.tar.gz
$ tar zxvf libevent-2.0.17-stable.tar.gz
$ cd libevent-2.0.17-stable
$ ./configure --prefix=$HOME/local
$ make
$ cd ../tmux-1.7
$ /configure --prefix=$HOME/local CPPFLAGS="-I$HOME/local/include -I$HOME/local/include/ncurses" LDFLAGS="-static -L$HOME/local/include -L$HOME/local/ncurses -L$HOME/local/lib"
$ make
$ make install
$ cd ~
$ wget "https://raw.github.com/sifue/dotfiles/b14f380ad667bc02a1fcad402d2cbf4a3eb0e36a/.tmux.conf"
$ tmux

これでOK。設定はgithubにおいてあるものを取得して早速起動しています。セッションを抜けるのには、ctrl+t d、また引き続き続けるにはtmux aコマンドでOKです。
詳しい設定の内容、各種ショートカットの説明は以下の通り。
~/.tmux.conf

# Prefix
set-option -g prefix C-t
unbind-key C-b
bind-key C-t send-prefix

## disable ESC delay
set -s escape-time 0

# View
set -g status-interval 1
set -g status-left-length 16
set -g status-right-length 50

set -g status-bg black
set -g status-fg white
set -g status-left '#[fg=cyan,bold][#14H:#S]#[default]]'
set -g status-right '|#[fg=magenta,bold]#(load.sh)#[default]| #[fg=blue,bold][%a %m/%d %H:%M:%S]#[default]'
set -g message-attr bold
set -g message-fg white
set -g message-bg red

set  -g pane-active-border-fg cyan
set  -g pane-active-border-bg black
setw -g window-status-current-fg blue

set-window-option -g mode-bg white
set-window-option -g mode-fg black
set-window-option -g window-status-fg white
set-window-option -g window-status-bg black
set-window-option -g window-status-current-bg black
set-window-option -g window-status-current-fg green

# Option
set-window-option -g utf8 on
set-window-option -g mode-keys vi
set-window-option -g automatic-rename off
set-window-option -g mode-mouse on
set-window-option -g mouse-resize-pane on
set-window-option -g mouse-select-pane on
set-option -g base-index 1

# KeyBindings
unbind ^C

bind r source-file ~/.tmux.conf; display-message "Reload Config!!"

bind c new-window
bind p previous-window
bind n next-window
bind t last-window

bind k kill-pane
bind K kill-window
bind y copy-mode
bind P paste-buffer


ショートカットですがキーインはCtrl-tになっています。
Ctrl-tを入力したい際には、Ctrl-t Ctrl-tです。

機能 ショートカット
横分割 Ctrl-t "
縦分割 Ctrl-t %
ペインを除去 Ctrl-t k
ペインを移動 Ctrl-t o
ペインを交換 Ctrl-t Ctrl-o
セッションを抜ける Ctrl-t d
セッション再開 コマンドでtmux a
ウインドウを作成 Ctrl-t c
ウインドウを除去 Ctrl-t K
ウインドウ名を編集 Ctrl-t ,
次のウインドウへ Ctrl-t n
前のウインドウへ Ctrl-t p
好きな番目のウインドウへ Ctrl-t 数字
直前のウインドウへ Ctrl-t t
マウスで選択したバッファを貼り付ける Ctrl-t P
設定を読み込む Ctrl-t r
ショートカット一覧を見る Ctrl-t ?

こんな感じの設定になっています。詳しくはCtrl-t ?で起動するショートカット一覧を見ててみてください。もちろんタイトルや色なども自由に設定することができます。

gitとctagsとvimのインストール

http://d.hatena.ne.jp/sifue/20120406/1333738754
を参考にしています。gitは各種vimプラグインをクローンしてくる際に必要だったりするので、入れておきます。また、ctagsの日本語版も利用するのでインストールしておきます。

$ mkdir -p ~/local/source
$ cd ~/local/source
$ wget http://git-core.googlecode.com/files/git-1.8.1.3.tar.gz
$ tar zxvf git-1.8.1.3.tar.gz
$ cd git-1.8.1.3
$ make prefix=$HOME/local
$ make prefix=$HOME/local install
$ cd ..
$ wget http://hp.vector.co.jp/authors/VA025040/ctags/downloads/ctags-5.8j2.tar.gz
$ tar zxvf ctags-5.8j2.tar.gz
$ cd ctags-5.8j2
$ ./configure --prefix=$HOME/local
$ make
$ make install
$ cd ..
$ wget ftp://ftp.vim.org/pub/vim/unix/vim-7.3.tar.bz2
$ tar -jxf vim-7.3.tar.bz2
$ cd vim73
$ ./configure --enable-multibyte --enable-xim --enable-fontset --with-features=big --prefix=$HOME/local
$ make
$ make install
$ wget "https://raw.github.com/sifue/dotfiles/2e722bb2e186ace5ca8f1587cae86d45a99df83b/essential/.vimrc"
$ mkdir -p ~/.vim/bundle
$ export GIT_SSL_NO_VERIFY=true
$ git clone https://github.com/Shougo/neobundle.vim ~/.vim/bundle/neobundle.vim

最後にある程度の設定がしてある、.vimrcを取得し、neobundleをgitでインストールして完了です。

まず、vimを起動して、:NeoBundleInstallと入力して、必要なプラグインをインストールしましょう。

$ vim
:NeoBundleInstall

無事インストールが終われば、それぞれのプラグインの全機能を使うことができます。
基本的には各プラグインの使い方は、各webサイトの最新や、~/.vim/bundlesの中の各プラグインフォルダ内にあるドキュメントを参照お願いします。ちょっと説明をすると

neobundle

基本的には、.vimrcにインストールしたいgithubおよびvim online上のプラグインプロジェクト名を記述して:NeoBundleInstallを実行する使い方しかしません。プラグインを最新のものにバージョンアップする際は、:NeoBundleInstall!、アンインストールする際は、設定を消した後に:NeoBundleCleanを実行するだけです。
プラグイン管理されてると、簡単にいろんなプラグインの相性を試せるので本当に楽です。

unite

下の.vimrcで設定しているショートカット(ファイルなら;uf、履歴なら;umなど)で、各種リソースを開くことができます。
起動後、文字を入力するとマッチするものに絞りこまれますが、Escしてカーソルを動かし、tabを押して実行したいコマンド選ぶモードにいくこともできます。キャンセルはqとなっています。ちなみに絞込み時には*を利用したワイルドカードも利用できます。大規模プロジェクトでは複数階層を検索する**/を入力すると大抵落ちるのでそれだけは注意です。
詳しくは、
https://github.com/Shougo/unite.vim/blob/master/doc/unite.txt
を参考に。

snipMate

PHPの各種スニペットをtabキーで展開することができます。
たとえばforと入力してtabキーを押すと

for ($i = 0; $i < count; $i++) {
     // code...
}

のように展開されます。
~/.vim/bundles/snipMate/snippets
以上のフォルダ内に利用できるスニペットの一覧が入っています。
自作のスニペットも登録することが可能です。
詳しくは、
http://www.vim.org/scripts/script.php?script_id=2540

ctrlp

Ctrl+pでカレントフォルダ以下のファイルをファジー検索をすることができます。
まさにSublimeText2のCtrl+pと同じ役割となっています。Uniteよりもファジーに検索してくれ巨大なプロジェクトにおいても高速です。

unite-outline

下記に説明してあるctagsコマンドでtagsファイルを作成の後、設定したショートカット(Ctrl+o)でメソッド一覧などを表示してくれます。

vcscommand

:VCSで始まる様々なバージョン管理システムの機能を利用することができます。
詳しくは、
http://www.vim.org/scripts/script.php?script_id=90
特に:VCSLogと:VCSBlame、:VCSDiffはよく使うのではないかと思います。

マウスやスクロールの使い方について

説明は不要かと思いますが、tmuxのペインの区切り、ペインの選択、vimのタブ、vimの文章、ダブルクリックでvimの単語が編集でき、マウスのスクロールも効くのではないかと思います。トラックパッドや慣性スクロールをつかっていると、でかいファイルでもスルーっとなめらかにスクロールできます。

.vimrcについて

なお~/.vimrcの内容は以下のようになっています。それぞれの設定の説明に、どのような意味なのか、どのようなショートカットで読み出せるかコメントで書いてありますので確認ください。
ほとんどのPHP開発で、必要な設定になっているのではないかと思います。なお、でかいファイルを開くのに障害になる設定や、JavaScriptやHTML用のプラグインや設定は省いてあります。

"VimをなるべくVi互換にする
set nocompatible

""""""""""" NeoBundle設定  """""""""""{{{
" https://github.com/Shougo/neobundle.vim
" インストール
" $ mkdir -p ~/.vim/bundle
" $ export GIT_SSL_NO_VERIFY=true
" $ git clone https://github.com/Shougo/neobundle.vim ~/.vim/bundle/neobundle.vim
" :NeoBundleInstall でプラグインインストール :NeoBundleInstall! で更新
filetype plugin indent off     " required!
if has('vim_starting')
  set runtimepath+=~/.vim/bundle/neobundle.vim/
  call neobundle#rc(expand('~/.vim/bundle/'))
endif

" gitを使ったプラグインマネージャ 基本Vundleと一緒
NeoBundle 'Shougo/neobundle.vim'

"""""""" github
" Uniteコマンドによるフィルタ付き読み出し等
NeoBundle 'Shougo/unite.vim'
" Uniteコマンドでアウトラインを表示
NeoBundle 'h1mesuke/unite-outline'
" PHP5.4にも対応している新しいPHPのシンタックスハイライト
NeoBundle 'shawncplus/php.vim'
" ctrl+pで起動するファジー検索に対応したファイラー
NeoBundle 'kien/ctrlp.vim'

" SVNやgitなど http://blog.blueblack.net/item_144 :VCS* で実行
NeoBundle 'vcscommand.vim'
" tabでスニペット補完
NeoBundle 'snipMate'

filetype on
filetype indent on
filetype plugin on
"}}}
""""""""""" プラグインごとの設定 """""""""""{{{
" Unite起動時にインサートモードで開始
let g:unite_enable_start_insert = 1

" Uniteの各種ショートカット設定
" バッファ一覧
nnoremap <silent> ;ub :<C-u>Unite buffer<CR>
" ファイル一覧
nnoremap <silent> ;uf :<C-u>UniteWithBufferDir -buffer-name=files file<CR>
" レジスタ一覧
nnoremap <silent> ;ur :<C-u>Unite -buffer-name=register register<CR>
" 最近使用したファイル一覧
nnoremap <silent> ;um :<C-u>Unite file_mru<CR>
" 全部乗せ
nnoremap <silent> ;ua :<C-u>UniteWithBufferDir -buffer-name=files buffer file_mru bookmark file<CR>

" Ctrl +  o でタグアウトラインを表示
nnoremap <C-o> :<C-u>Unite outline<CR>

"}}}
""""""""""" Vimの基本的な設定  """""""""""{{{
"バックスペースキーの動作を決定する
"2:indent,eol,startと同じ
set backspace=2

"行数表示
set number

"新しい行を開始したときに、新しい行のインデントを現在行と同じ量にする
set autoindent

"検索で小文字なら大文字を無視、大文字なら無視しない設定
set smartcase

"(no)検索をファイルの末尾まで検索したら、ファイルの先頭へループする
set nowrapscan

"インクリメンタルサーチを行う
set incsearch

"highlight matches with last search pattern
set hlsearch

"閉じ括弧が入力されたとき、対応する括弧を表示する
set showmatch

"カーソルが何行目の何列目に置かれているかを表示する
set ruler

"新しい行を作ったときに高度な自動インデントを行う
set smartindent

"保存しないで他のファイルを表示することが出来るようにする
set hidden

"カレントバッファ内のファイルの文字エンコーディングを設定する
set fileencoding=utf-8

"Insertモードで<Tab> を挿入するのに、適切な数の空白を使う
set expandtab
set ts=4

"ファイル内の <Tab> が対応する空白の数
set tabstop=4

"自動インデントの各段階に使われる空白の数
set shiftwidth=4

"行頭の余白内で Tab を打ち込むと、'shiftwidth' の数だけインデントする
"set smarttab

"強調表示(色付け)のON/OFF設定
syntax on

"ステータスラインを表示するウィンドウを設定する
"2:常にステータスラインを表示する
set laststatus=2

"ステータス行の表示内容を設定する
set statusline=%<%f\ %m%r%h%w%{'['.(&fenc!=''?&fenc:&enc).']['.&ff.']'}G8%=%l,%c%V%8P

"vimのバックアップファイルとスワップファイル
set nobackup
set noswapfile

"バッファをクリップボードにコピー(for OSX)
set clipboard=unnamed,autoselect

"自動改行オフ
set tw=0

" マウスモード有効
set mouse=a

" xtermとscreen対応
set ttymouse=xterm2

"MacVimやGVimを利用する際にIMEがモードの切替でオフとなる設定
set imdisable

"UTF-8文字化け対応
set termencoding=utf-8
set encoding=utf-8
set fileencoding=utf-8
set fileencodings=utf-8,cp932


"}}}
""""""""""" 効率化UPのための設定 """""""""""{{{
" <Leader>を\にリマッップ
nnoremap \ <Leader>
vnoremap \ <Leader>

"全角スペースを で表示
highlight JpSpace cterm=underline ctermfg=Blue guifg=Blue
au BufRead,BufNew * match JpSpace / /

"タブを見えるように設定
set list
set listchars=tab:>-,trail:-

" サーチハイライトををESC二回で消す
nnoremap <Esc><Esc> :nohlsearch<CR><Esc>

" 挿入モードとノーマルモードでステータスラインの色を変更する
au InsertEnter * hi StatusLine guifg=DarkBlue guibg=DarkYellow gui=none ctermfg=Blue ctermbg=Yellow cterm=none
au InsertLeave * hi StatusLine guifg=Black guibg=White gui=none ctermfg=Black ctermbg=White cterm=none

"バイナリ編集(xxd)モード(vim -b での起動、もしくは *.bin で発動します)
augroup BinaryXXD
	autocmd!
	autocmd BufReadPre  *.bin let &binary =1
	autocmd BufReadPost * if &binary | silent %!xxd -g 1
	autocmd BufReadPost * set ft=xxd | endif
	autocmd BufWritePre * if &binary | %!xxd -r
	autocmd BufWritePre * endif
	autocmd BufWritePost * if &binary | silent %!xxd -g 1
	autocmd BufWritePost * set nomod | endif
augroup END

" ヴィジュアルモードで選択したテキストをnで検索する(レジスタv使用)
vnoremap <silent> n "vy/\V<C-r>=substitute(escape(@v,'\/'),"\n",'\\n','g')<CR><CR>

" gfでカーソル下のファイル名を新しいタブで開く
nnoremap gf :tabe <cfile><CR>
vnoremap gf :tabe <cfile><CR>

" 検索語が画面中央にくるように
nmap n nzz
nmap N Nzz

" ヤンク、切り取り時にレジスタ"の値をzにもコピーしておく(連続貼付可に使う)
vnoremap <silent> y y:let @z=@"<CR>
vnoremap <silent> d d:let @z=@"<CR>

" ビジュアルモードで選択したテキストを消してレジスタzの内容を貼付ける(連続貼付可)
vnoremap <silent> p x"zP

" vimrcの新しいタブでの編集と読み込みのショートカット設定
nnoremap ;s :source $MYVIMRC<CR>
nnoremap ;v :tabe $MYVIMRC<CR>
nnoremap ;g :tabe $MYGVIMRC<CR>
nnoremap ;l :tabe ~/.vimrc.local<CR>

" :makeや:grepをした際に自動的にquickfixが開くようにする
autocmd QuickfixCmdPost make,grep,grepadd,vimgrep,vimgrepadd if len(getqflist()) != 0 | cw | endif

" テキストファイル専用の設定
augroup ettext
	autocmd!
	autocmd BufRead,BufNewFile *.txt setlocal expandtab nolist nonumber tw=0
augroup END

" ファイルを開いたときに前回の編集箇所に移動
autocmd BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal g`\"" | endif


"}}}
""""""""""" 言語ごとの設定 """""""""""{{{
"ctagsのファイルをカレントディレクトリから検索して上位にあるもの読み込む
if has('path_extra')
	set tags+=tags;
endif

""""" VIM用設定 """"""""
" vimファイルに関して{と}による折りたたみ設定をする
au FileType vim setlocal foldmethod=marker

""""" PHP用設定 """"""""
" :makeでPHP構文チェック
au FileType php setlocal makeprg=php\ -l\ %
au FileType php setlocal errorformat=%m\ in\ %f\ on\ line\ %l

" PHPの関数やクラスの折りたたみ(非常に重い)
let php_folding = 0

" 文字列の中のSQLをハイライト
let php_sql_query = 1

" Baselibメソッドのハイライト
let php_baselib = 1

" HTMLもハイライト
let php_htmlInStrings = 1

" <? を無効にする→ハイライト除外にする
let php_noShortTags = 1

" ] や ) の対応エラーをハイライト
let php_parent_error_close = 1
let php_parent_error_open = 1


"}}}

以上で環境構築自体は完了となります。変えたい部分は随時設定などしてみてください。
実際に設定を一つ一つ確認しながら、使ってみて頂ければと思います。個人の好みなどがあると思いますので、カラースキームなどの設定は予め外してあります。


なおctagsだけは、必要になった後にタグを付けたいPHPのプロジェクトのフォルダのルートにて、

$ rm tags
$ ctags -R --langmap=PHP:.php.inc --php-types=c+f+d+v+i;

を実行ください。これで、古いtagsファイルが消し、新たにtagsファイルが作られます。
そのフォルダ以下のファイルをvimで開く際に自動的にtagsファイルが読み込まれ、Ctrl+]で関数の定義元にジャンプCtrl+t Ctrl+t(tmuxのキーバインドとかぶっているため)で戻ってくることができます。また、Ctrl+pやCtrl+nで表示する補完候補にもこのctagsの情報が使われるようになります。
後はvimのタグジャンプのヘルプなどを読んで使ってみてください。

大規模開発の際に使えるvimテクニック

最後に大規模開発でよく使うテクニックを紹介します。
一応、vimはvimtutorで説明される使い方は基本的に使えることを前提とします。その上で開発するのに便利なvimのデフォルト機能を紹介します。

1. コピペモード :set paste

これをやっておけば貼りつけた際にインデントがくずれたりすることがありません。
戻すときは、:set nopaste
でもコピペ開発はいけませんよ!
テンプレートやスニペットを利用したい際のみに使いましょう。重複は大規模開発の保守における悪!

2. マクロ qaで覚えてqで記録終了@aで実行

aは記憶領域の名前なだけで、同じキーであれば別にどれでも大丈夫です。
同じような入力操作、たとえばgetterやsetterを書いたりするのはすぐにマクロにして効率化した方がよいですよね。

3. 前回の動作を繰り返す . 10回繰り返す10.

同じ操作の繰り返しは、.で実行。それを10000回実行するのもモニターを見ているだけで十分です。

4. ミニバッファでヤンクした文字列を呼び出す C-r"

ミニバッファにて、レジスタの情報を呼び出したい時、よく選択した単語をヤンクして検索した時などに便利です。

5. 数値のインクリメント、デクリメント C-a と C-x

これとマクロを組み合わせると、数値の羅列やテストデータの作成などが非常に楽になります。

1, 20, 40
2, 21, 41
3, 22, 42
4, 23, 43
5, 24, 44

こういうのはマクロとインクリメント・デクリメントでサクッと作ってしまいましょう。

6. テキストオブジェクトの選択 viw

マウスのダブルクリックと同じなのですが、iwなどで選択できるテキストオブジェクトを意識してマクロなどを組みはじめると、一気にいろんな操作ができるようになります。

7. 今のファイルと比較 :vertical diffsplit [ファイル名]

コマンドが長いので忘れがちですが、2つのファイルのdiffをssh上で調べなきゃいけない時に便利です。環境の設定差異を見たりするのに使います。

8. 複数行同時編集 C-vで矩形選択、IまたはAの後好きな文字列を入力して、Escで反映

これは複数行コメントアウトや、複数行同時編集のマクロ化などいろいろなシーンで役に立つテクニックです。

9. ls | vim - などで標準出力をvimに渡す

結果をvimで編集、調査したいときなどに便利です。
またシンタクスハイライトを目的に利用することもあります。
よく使うのが、diffでの利用

$ svn diff | vim -
$ git diff | vim -

になります。

10. gf でカーソル下のパスを開く

これはvim -で読みだした標準出力と非常に相性の良いテクニックです。

$ git diff | vim -

でdiffを開き、更にそこから、パスの上にカーソルを持って行き、gfで実際のファイルにジャンプして:VCSLogなどで、過去の履歴などを調べたりすることもできます。

11. :makeでシンタックスチェック

まさかシンタックスエラーのあるコードなんてコミットしませんよね。設定によっては保存するたびに:makeが走るようにすることもできます。ただ、:makeが重い場合もあるので、その時に合わせた運用で。


以上が、ssh上でマウススクロールも使える大規模PHP開発向けvim+tmux環境の構築と大規模開発の際に使えるvimテクニックの紹介でした。
お疲れ様でした。