MilkodeとChromeでサクサクっとソースコード検索


ソースコード検索をブラウザの検索エンジンに組み込んで、
いつでもサクッとコードを検索しちゃおうという試みです。


Milkodeとはなんぞ

これ↓
http://d.hatena.ne.jp/tuto0621/20110730/1312040692


仕事上でソースコードを横断して検索することが多くなってきたので独自にgrepを拡張してアレコレやっていたのですが、
ヒットしたキーワードの周辺行を出力して欲しかったり(もしかしてできる?)、
量が多すぎて読みづらくなってしまったりと困ることがいくつかあったので
Webブラウザで動作するソースコード検索システムであるMilkodeを導入してみました。

Milkode自体は去年の夏ぐらいに流行っていたみたいですね。遅ればせながら導入してみました。

インストール

OSはUbuntu11.04
RubyGemsで一発で入ります。

$ gem install milkode

すみません嘘をつきました、私の環境では一発で入りませんでした。

$ sudo apt-get install libxml2-dev libxslt-dev

必要なライブラリをインストールしたあとでもう一度 gem install milkode すると無事インストールされました。

サーバ立ち上げ

まずは初期設定をし、検索対象のソースコードが入ったディレクトリをaddしていきます。

$ milk init --default
$ milk add ~/workspace

設定がおわったら後はサーバを起動するだけ。

$ milk web

デフォルトではhttp://127.0.0.1:9292/ が立ち上がるようです。
ホストや待受ポートを変えたい場合は以下のように指定します。

$ milk web -o example.com -p 1234

以上で準備が整いました。
たったこれだけ!簡単!

検索してみる

Googleのごとく検索バーに対象のキーワードを入れるとソースコードが検索されます。
私の環境にはソースファイルが5000ほどあるのですが、
作者さんが公称しているようにほんとに1秒,いや0.1秒で検索できます。速い!

他にも検索時にファイルや拡張子などの細かい指定もできるようです。
正規表現が使えたら完璧なのですが…。

hoge f:main.class    main.classから検索する
hoge s:java      拡張子がjavaのファイルを対象にする

Chromeと連携させてみる

せっかくWebブラウザで動くんだから、Chrome検索エンジンとして登録してしまいましょう。
Chromeの検索ボックス(Omniboxというらしいです。)を右クリックし、「検索エンジンの編集」を選択。

検索エンジン名:任意
検索キーワード:任意(grepにしました)
検索URL:http://127.0.0.1:9292/home?query=%s


あとは検索ボックスに「grep キーワード」と入力するだけでいつでも好きな時にソースコードを検索することができます。素敵!

*[本][レバレッジメモ]感情 A Very Short Introduction EMOTION

感情 (〈1冊でわかる〉シリーズ)

感情 (〈1冊でわかる〉シリーズ)

ユーザインタフェースの勉強の一環で
人が抱く感情について知りたかったので読んでみた.

要約

頭(理性)と心(感情).
人間の思考は2つに切り分けることができる.
理性と感情をうまく使い分けることが大切で,
例えば即時性を求められている仕事では感情を使うと,
ファジーなアイデアをたくさん出すことができる.


感情と理性はお互いが妨害しあう関係だと思われがちだが,実はそうではない.
「合理的」な判断を下すためには感情も必要なファクターである.

レバレッジメモ

他者から完全に受容されているときに覚える感情は喜びの一種.

歩行や道具を使うことは一人でできるが,
言語の習得には他者が絶対に必要.

ふむふむ,たしかにそうだ.
ひとりでできるもの,ひとりじゃできないもの.
学習にも色々種類があるが,
この2つが根本的な分類かもしれない.

「高次認知的情動」
いわゆる喜怒哀楽は基本情報で,
罪悪感,照れ,きまり悪さ,誇り,嫉妬などが高次認知的情動にあたる.
これらは全て”社会的”である.

現代人は基本情動よりも高次認知的情動のほうがよく見られるらしい.
かつて狩猟をしていた原始人は基本情動である「怒」の色が強かったらしいが.
社会が現代に近づくにつれて情動も複雑なものになっていったわけだ.

「生得的」(多義語)
[この本での意味]それを習得するために満たすべき特別な条件がないこと.

情動は知性的な活動の妨げである.
or not

これはどうなんだろう.
確かに考えがまとまらない時なんかはイライラするけど,
決して悪いことばかりじゃない気がする.
イライラすることによってリフレッシュするという機会が生まれ,
リフレッシュしたら考えがまとまって前進するということが過去に幾度もあったので.

2人がグループワークを行うとする.
両者はいつでもサボることができるのだが,
「罪悪感」のおかげでサボることを抑制することができる.
これを「コミットメント問題」という.

情動によって人の行動を制限する.
これはいろいろな用途で使えそう.

まとめ

ページ数を短くするあまりに,
話すべき内容まで省略してしまっている印象.
感情について知りたかったんだけど,入り口止まり.
興味を持った人は次の本を読んでください,というスタンスなのかな.

SRM510 DIV2 250

任意の2数値間に4もしくは7が含まれる,またはそれ以外の数字が1つだけ含まれている数値の数を返す

public class TheAlmostLuckyNumbersDivTwo {
	public int find(int a, int b) {
		int result = 0;
		for(int i=a;i<=b;i++){
			String s = Integer.toString(i);
			int luckycount = 0;
			for(int j=0;j<s.length();j++){
				if(s.charAt(j) != '4' && s.charAt(j) != '7') luckycount++;
			}
			if(luckycount <= 1) result++;
		}
		return result;
	}
}

SRM507 DIV2 250

任意の数字Xに整数iを加算or減算して回文にする時の最小のiを返す
ex) 1234 => return 13 (-13すると1221で回文)

public class PalindromizationDiv2 {
	public int getMinimumCost(int X) {
		int result = Integer.MAX_VALUE;
		for(int i = 0;i < 100000;i++){
			int a = X + i;
			int b = X - i;
			StringBuilder sa = new StringBuilder(Integer.toString(a));
			StringBuilder sb = new StringBuilder(Integer.toString(b));
			if(sa.reverse().toString().equals(Integer.toString(a))){
				result = Math.min(result,i);
			}
			if(b >= 0 && sb.reverse().toString().equals(Integer.toString(b))){
				result = Math.min(result, i);
			}
		}
		return result;
	}

}

SRM498 DIV2 250

import java.util.Arrays;

public class AdditionGame {
  public int getMaximumPoints(int a, int b,int c,int n){
     if(n > a+b+c){
      return a+b+c;
     }
    int sum = 0;
    int[] arr = new int[]{a,b,c};
    
    for(int i=0;i<n;i++){
      Arrays.sort(arr);
      sum += arr[arr.length-1]--;  
    }
    return sum;
  }
}

iPeer をインストールしてみた

iPeerというピアレビュー用のWebアプリケーションをインストールする機会があったんだけど,少し手こずったので作業メモを残しておく.

iPeer本体をダウンロード

バージョンは最新版(v2.2.1)を選ぶ.
http://ipeer.ctlt.ubc.ca/trac

さてインストール・・・あれ?

さてインストール,と思ったが困ったことにiPeerに関するドキュメントが圧倒的に少ない.
仕方が無いので(あきらかに手抜きな)公式のインストール手順( http://ipeer.ctlt.ubc.ca/trac/wiki/install )を参考に作業を進めることにする.

ちなみに環境はこんな感じです.
MacOSX Server10.6.5
PHP5.3.3
MySQL5.x

公式のインストール手順を参考にしてみる

えーと,MacOSXだからLinux installationの方を参考にすればいいのか?

というわけで以下を実行.

% chmod -R 777 app/tmp
  • 手順2 Apacheの設定を変更

iPeerをインストールしたディレクトリにAllowOverride Allオプションを付け加えるだけで良さそう.
例としてはこんな感じかな.

LoadModule rewrite_module modules/mod_rewrite.so
DirectoryIndex index.html index.html.var index.php
DocumentRoot "/var/www/html"


        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all

ipeerという名前でデータベースを新規作成.
一緒にipeerという名前でユーザを作成しておく.

ここまではいいんだが・・・

  • 手順4 ブラウザで http://自分のホスト名/インストールしたディレクトリ名/install を開く

ここで困ったのが,「install」というディレクトリがダウンロードしたファイルの中に存在しないということ.
少し調べてみるとどうやらinstallというディレクトリはバージョン2.xには存在しないようだ.だったらドキュメントに載せんなカス

というわけでv1.6のファイル群を落としてきてv2.2と同じディレクトリに入れてあげることで手順4を通過できた.

あとは手順通りに

その後の手順は公式の手順通りに行うことでなんとかiPeerをインストールすることができた.
その際にいくつかサンプルとしてプロジェクトが生成されるようなんだけど,
邪魔なので削除しても構わないと思う.

しかしまぁ・・・

ドキュメントの対応といい,公式にやる気があるのかどうか疑問.
そしてなにより使い方が分からん…

TENGA

    uri  = URI.parse('https://userstream.twitter.com/2/user.json')          
    http = Net::HTTP.new(uri.host, uri.port)                                
    http.use_ssl = true                                                     
    http.ca_file = './twitterstream.cert'                                   
    http.verify_mode = OpenSSL::SSL::VERIFY_PEER                            
    http.verify_depth = 5                                                   
                                                                            
    http.start do |ses|                                                     
      req  = Net::HTTP::Get.new(uri.request_uri)                            
      req.oauth!(ses,@consumer,@token)                                      
      buf = ""                                                              
                                                                            
      ses.request(req) do |res|                                             
        res.read_body do |body|                                             
          buf << body                                                       
          next if buf.index("\r\n").nil?                                    
          buf.chomp!.chomp!                                                 
          status = JSON.parse(buf) rescue next                              
          buf = ""                                                          
          if status["text"].index("テン")                                   
            client.update("ガッ", :reply_id => status["id"])                
          end                                                               
                                                                            
        end                                                                 
      end                                                                   
    end