Visual Studio Community 2013始めました。

Visual Studio Community 2013が出ましたね。Expressでは使えなかった拡張が使えるようになりました。これのためにProの購入を考えては踏み止まって、ということを繰り返していたところなのでやっと来たかという感じ。

真っ先に入れたのがVsVim。お仕事ではPHPStorm + ideavimなので、この環境に慣れ切った指で素のVSでC#を書くのはちょっと腰が重かったのです。

Ctrl+n、Ctrl+pを上下に割り当てて、インテリセンスの選択もカーソルを使わないようにしているのですが、Ctrlを押しているとインテリセンスが半透明になってしまうのが邪魔になっていて回避策を模索中。この機能が付いた当時はとても嬉しかったんですけどね。

あとはPython Tools for Visual Studio。まだしっかりとは試せていないのですが、ClipboardExtenderの拡張スクリプト(IronPython)を書くのが捗りそうです。

MSさん超GJです。

PHPStormでSQLを含む大きなPHPファイルを開くと重い

PHPStormはPHPコードの文字列に含まれるSQLを認識して補完、色分け表示をしてくれます。コーディングが極めて捗る機能ではあるのですが、うん万行も延々とSQLが連なるPHPファイルを開くと流石の軽快なPHPStormも数秒の間フリーズしてしまいます。
そんなときは機能を無効にしてしまうと軽くなります。

  1. File→Settings…で設定画面を開く
  2. 左側の一覧のProject Settings→Language Injectionsを開く
  3. php:”SQL select/delete/insert/update/create”のチェックを外す
  4. php:”<<< SQL”のチェックを外す
  5. OKで設定画面を閉じる

PHPStormの補完とかが何となく調子悪くて困ってた

補完候補が出るのに妙に時間がかかったり、表示される候補も不完全だったり、正しいコードなのに波線で怒ってきたり。
そんなとき C:\Users\USERNAME\.WebIde*\system\index を丸ごと削除すると快調になったのでメモ。
いろんな箇所を疑いつつ数日イライラしながら仕事してたけど、こんな単純なことで解決して拍子抜け。

@Vexus2 さんより以下の情報を頂きました。ありがとうございます。

ちゃんと正攻法が用意されていたんですね。

PHPでの文字列の扱いには注意しよう、と自分への戒め

if ('0' == '00') {
    //trueになる
}

if ('0' === '00') {
} else {
    //falseになる
}
//文字列の比較には===、!==の3文字シリーズを使わないと事故るよ!文字列と文字列の比較でも数値に変換可能な場合は数値として比較されちゃうよ!

if ('0') {
    //falseになる
}
if ('00') {
    //trueになる
}
//ifに文字列を突っ込んでも何の判定にも使えないよ!

PHPをdisるのはプログラマの嗜みではあるけれど、disってもPHPは無くならないんだから戦い方を身に付けないとね。

幸いマニュアルは大変に親切な作りなので最大限に活用しましょう!

http://php.net/manual/ja/index.php

IronPythonでインターフェースのイベントを実装する

Pythonにはイベントを定義する構文がないから困った。

そんなときはadd_イベント名(self, handler)、remove_イベント名(self, handler) を実装する。

例えば、INotifyPropertyChangedインターフェースのPropertyChangedイベントだとこう。

class NotifyObject(INotifyPropertyChanged):
	def add_PropertyChanged(self, handler):
		if not hasattr(self, "_propertyChangedHandlers"):
			self._propertyChangedHandlers = [handler]
		else:
			self._propertyChangedHandlers.append(handler)

	def remove_PropertyChanged(self, handler):
		if not hasattr(self, "_propertyChangedHandlers"):
			self._propertyChangedHandlers = []
		else:
			try:
				self._propertyChangedHandlers.remove(handler)
			except ValueError:
				pass

	def RaisePropertyChanged(self, propertyName):
		if not hasattr(self, "_propertyChangedHandlers"):
			self._propertyChangedHandlers = []
		else:
			for handler in self._propertyChangedHandlers:
				handler(self, PropertyChangedEventArgs(propertyName))

 

こんな感じでイベントハンドラの管理も自分でやる。

TwitterizerでUserStreamを利用する

TwitterのAPIライブラリ、Twitterizer Ver 2.3.1を使ってUserStreamを利用しようと以下のコードを書いたんです。

using System;
using System.Net;
using System.Reflection;

namespace ConsoleApplication1
{
	class Program
	{
		static void Main(string[] args)
		{
			string consumerKey = "hoge";
			string consumerSecret = "hogehoge";
			Twitterizer.OAuthTokenResponse reqToken = Twitterizer.OAuthUtility.GetRequestToken(consumerKey, consumerSecret, "oob");
			Uri uri = Twitterizer.OAuthUtility.BuildAuthorizationUri(reqToken.Token);
			System.Diagnostics.Process.Start(uri.ToString());
			Console.WriteLine("Pinコードを入力しる");
			string pinCode = Console.ReadLine();
			Twitterizer.OAuthTokenResponse accToken = Twitterizer.OAuthUtility.GetAccessToken(consumerKey, consumerSecret, reqToken.Token, pinCode);
			Twitterizer.OAuthTokens token = new Twitterizer.OAuthTokens
			{
				ConsumerKey = consumerKey,
				ConsumerSecret = consumerSecret,
				AccessToken = accToken.Token,
				AccessTokenSecret = accToken.TokenSecret
			};
			using (var twitterStream = new Twitterizer.Streaming.TwitterStream(token))
			{
				twitterStream.OnStatusReceived += (Twitterizer.TwitterStatus status) =>
				{
					Console.WriteLine(string.Format("{0}/({1})\r\n\t{2}",
						status.User.Name,
						status.User.ScreenName,
						status.Text));
				};
				twitterStream.StartUserStream();
				while (true) { }
			}
		}
	}
}

何度試しても404が返ってくる。実はこれ、ベータ版のアドレスにアクセスしてるんですよ。これがソースコード

no title

がっつりとハードコーディングされちゃっててどうにもなりません。自家ビルドして使う?嫌ですよ、そんなの。面倒じゃないですか。幸い、このStartUserStreamメソッドは短いです。じゃあStartUserStreamメソッドを呼び出してる部分のコードをURLだけ置き換えた同じ内容のコードに書き換えればいいじゃない!

以下の3行までは問題ないです。

WebRequestBuilder builder = new WebRequestBuilder(new Uri("http://betastream.twitter.com/2b/user.json"), HTTPVerb.GET, this.Tokens);
HttpWebRequest request = builder.PrepareRequest();
request.KeepAlive = true;

URLを置き換えるだけです。WebRequestBuilderクラスはpublicなので問題なく利用出来ます。引数に渡しているthis.Tokensはコンストラクタに渡したインスタンスそのものなので、こちらのスコープで保持しているものに置き換えればいいです。

問題は最後の行ですね

request.BeginGetResponse(StreamCallback, request);

引数に渡しているStreamCallbackっての、これprivateなメソッドなんですよ。これはリフレクションで取ってくることにしました。

MethodInfo method = twitterStream.GetType().GetMethod("StreamCallback",
    BindingFlags.Instance |
    BindingFlags.NonPublic);
AsyncCallback callback = (_) =>
{
    method.Invoke(twitterStream, new[] { _ });
};

リフレクションで取ってきたメソッドをInvokeするコードをAsyncCallbackデリゲートで包んであげればOKじゃんって寸法です。

で、最終的なコードがこんな感じ

using System;
using System.Net;
using System.Reflection;

namespace ConsoleApplication1
{
	class Program
	{
		static void Main(string[] args)
		{
			string consumerKey = "hoge";
			string consumerSecret = "hogehoge";
			Twitterizer.OAuthTokenResponse reqToken = Twitterizer.OAuthUtility.GetRequestToken(consumerKey, consumerSecret, "oob");
			Uri uri = Twitterizer.OAuthUtility.BuildAuthorizationUri(reqToken.Token);
			System.Diagnostics.Process.Start(uri.ToString());
			Console.WriteLine("Pinコードを入力しる");
			string pinCode = Console.ReadLine();
			Twitterizer.OAuthTokenResponse accToken =Twitterizer.OAuthUtility.GetAccessToken(consumerKey, consumerSecret, reqToken.Token, pinCode);
			Twitterizer.OAuthTokens token = new Twitterizer.OAuthTokens
			{
				ConsumerKey = consumerKey,
				ConsumerSecret = consumerSecret,
				AccessToken = accToken.Token,
				AccessTokenSecret = accToken.TokenSecret
			};
			using (var twitterStream = new Twitterizer.Streaming.TwitterStream(token))
			{
				twitterStream.OnStatusReceived += (Twitterizer.TwitterStatus status) =>
				{
					Console.WriteLine(string.Format("{0}/({1})\r\n\t{2}",
					status.User.Name,
					status.User.ScreenName,
					status.Text));
				};
				//twitterStream.StartUserStream();
				//StartUserStreamメソッドがベータ版のURLに繋いでエラーになるから
				//下記ソースの動作をURLだけ変えて実行
				//http://pm.twitterizer.net/projects/twitterizer/repository/entry/tags/twitterizer-2.3.1/Twitterizer2.Streaming/TwitterStream.cs#L138
				var builder = new Twitterizer.WebRequestBuilder(new Uri("https://userstream.twitter.com/2/user.json"), Twitterizer.HTTPVerb.GET, twitterStream.Tokens);
				HttpWebRequest request = builder.PrepareRequest();
				request.KeepAlive = true;
				MethodInfo method = twitterStream.GetType().GetMethod("StreamCallback",
					BindingFlags.Instance |
					BindingFlags.NonPublic);
				AsyncCallback callback = (_) =>
				{
					method.Invoke(twitterStream, new[] { _ });
				};
				request.BeginGetResponse(callback, request);
				while (true) { }
			}
		}
	}
}

 

これでめでたくUserStreamが使えるようになりました。ちなみにtrunkの最新のソースコードでもURLはベータ版のものがベタ書きのままでした。中の人忙しいのかな…。

IronPythonでメソッドをオーバーライドして基底クラスに投げる。

IronPythonに限ったことじゃないけど、IronPythonでWinforms触ってたら避けられない問題なので。組込み関数のsuperを使う。

import clr
clr.AddReference("system.windows.forms")
from System.Windows.Forms import *
class HogeForm(Form):
	WM_LBUTTONDBLCLK = 0x0203
	count = 0

	def WndProc(self, m):
		if m.Msg == self.WM_LBUTTONDBLCLK:
			self.Text = self.count.ToString()
			self.count += 1
		super(HogeForm, self).WndProc(m)

if __name__ == "__main__":
	Application.Run(HogeForm())

 

Form.WndProc(self, m)

でも動くけど推奨されていないみたい。

Windowsのコマンドライン版Subversion(SVN)の外部DIFFツールにWinMergeを設定したが上手くいかなかった

WinMergeをSubversionのdiffとして使用する – てんぷらメモの方法でSubversionの外部DIFFツールにWinMergeを設定したけど上手くいかなかった。WinMergeに渡される比較用の一時ファイル(tmpfile.tmp)が存在しない為にWinMergeのファイル選択のダイアログが表示されてしまう。

色々と検索ワードを変えて調べてみたが解決せず。ふと”subversion diff tempfile.tmp”で検索したらドンピシャリ。Subversion r12がヒット。2ちゃんねるの過去ログでしょうか。

138デフォルトの名無しさんsage2009/12/02(水) 01:52:09

ttp://terai.xrea.jp/Subversion/WinMerge.html

このページを参考にWinMergeをSubversionのdiffとして使用する設定を行ったのですが

svn diff test.txt

はうまくいきますが

svn diff -r 100 test.txt

はWinMergeのファイル指定のダイアログが表示されうまくいきません。

どうもリビジョン100のファイルが取得できないようです。

どなたか原因がわかる方いらっしゃいませんか?

140デフォルトの名無しさんsage2009/12/02(水) 02:25:53

svn diff -r 100 test.txt .

じゃないの?

143デフォルトの名無しさんsage2009/12/02(水) 23:04:26

>>140

ダメでした。

“svn diff -r 100:101 test.txt”もダメです。

コマンドラインでは成功します。

ただ最新版がr102の場合、

“svn diff -r 102 test.txt”なら成功します。

ルーターのLEDが点滅しているので取りにはいっているようです。

考えられる原因は「OSがVista、ノートンを使っている」くらいでしょうか。

144デフォルトの名無しさんsage2009/12/03(木) 10:10:05

それぞれのバージョンは?

145デフォルトの名無しさんsage2009/12/03(木) 23:00:08

>>144

バッチファイルの

START “WinMerge” /B

を削除するとうまくいきました。

どうもこれがあると比較用のtempfile.tmpが消えてしまうようです。

ちなみにsvnクライアントのバージョンは1.6.6です。

サーバーはわかりません。

138さんは神ですね。

手順をまとめると…

以下のようなバッチファイルを作成して、そのパスを%APPDATA%\Subversion\configファイルのhelpersセクション→diff-cmdキーに設定する。

@ECHO OFF

[WinMergeU.exeのパス] /e /s /ub /dl %3 /dr %5 %6 %7

というわけでした。