SDD(Sleep-Driven Development)

睡眠の重要性!!睡眠の重要性!!

MacでもRiderを使って快適にXamarinで開発しよう!!

これは

[学生さん・初心者さん大歓迎!]Xamarin Advent Calendar 2016 - Qiita

の7日目の記事です。

前日は

qiita.com

でした。
大学の講義でJavaやって2年目でServletその後Xamarinの流れとか完全に「自分かな?」と思いましたがこの話はまたいずれ。

今回はモバイルどころかIDEでほぼMac向けのお話ですがタイトルに(無理やり)Xamarinが入ったのでセーフ

祝!!Rider Public EAP Release!!

2016/11/22、RiderがPublic EAPになりました!!
長かった・・・

今回はそんなRiderの紹介です!

Riderとは

RiderはJetBrainsが絶賛開発中のクロスプラットフォームC# IDEです。詳しくは以下をお読み下さい。

Project Rider – 新しい C# IDE #jetbrainsrider | JetBrains ブログ

簡単に言うとJavaなどの開発環境でお馴染みのIntelliJ Platformで動作し、バックエンドではC#で書かれたReSharperが動作しています。

つまりは最強。

Riderの対応状況

最初にXamarinプロジェクトで使うに当たってのRiderの対応状況を見ていきたいと思います。現在のRiderの対応状況は以下のとおりです。

機能 対応状況 備考
プロジェクト読み込み UWPとかは無理(遠い未来対応するかも?)
ビルド 私はなぜかできるけどできない人もいる?
実行
デバッグ
コーディングスタイル 近いうちにきそう
XAML ハイライトが残念だけどReSharperと遜色ない補完
F# こんなに投票されてるのだから対応されないはずがない!
NuGet Xamarin Studioより高機能だけど若干怪しいところがある
ReSharperの機能
(補完やpostfixなど)
だいぶ対応したけど細かいところがまだ
IntelliJ Platformの機能
(Gitや各種プラグインなど)
普段使いには全く問題なく感じる

あくまで主観なので間違いがあったらコメントをぜひ。
コーディングスタイルは裏道がありそうですがそれは後述。

XamarinでRiderを使うにあたり、実行・デバッグはできません。なのでRider単体での開発は不可能です。
よってRiderでコーディング→Xamarin Studioでビルド・実行になります。

面倒くさいし切り替え忘れてXamarin Studioで編集してイライラする事もありますが、それでもRiderでコーディングすると圧倒的に書きやすいです。

始め方

そんな超有望なRiderをさっそくインストールしていきましょう!
インストール方法は2パターンあって www.jetbrains.com

からダウンロードしていつも通りインストールする方法とJetBrains Toolboxを使ってインストールする方法があります。Toolboxのダウンロードは以下からできます。

www.jetbrains.com

個人的には他のJetBrains製品を使っているならToolboxを利用したほうが楽だと思います。

初期設定

前回とほぼ変わりませんが初期設定について。

Riderを初めてインストールして起動するとおそらく以下の画面が表示されます。

f:id:crocus7724:20161127101303p:plain

前のバージョンから設定をインポートする?って聞かれますが初めてなのでデフォルトのままOK。
次はテーマを聞かれます。

f:id:crocus7724:20161127101441p:plain

個人的にダークテーマが好きなのでDarcula一択。
お次はエディターのカラーテーマです。左から独自、Visual Studio風(あくまで風)、IntelliJ風(というかそのまま)になります。お好きなものをどうぞ。

f:id:crocus7724:20161127104435p:plain

次にキーマップを選択できます。Visual Studio風とReSharperIntelliJ(macOS)から選択できます。

f:id:crocus7724:20161127104447p:plain

なおキーマップはあとで設定から下記も選べるようになります。

キーマップが選択し終わったらお次はDefault Pluginsです。私はいつも全部Enableのままにするのですが、もし「絶対使わねーよ!」という機能があれば無効にすれば起動が少し早くなるかも?

f:id:crocus7724:20161127104523p:plain

そして次におすすめっぽいPluginsがインストールできます。

f:id:crocus7724:20161127104513p:plain

IdeaVimは私は使ったことないのでなんとも言えません。
ReSharper UnityではデバッグまでできるっぽいのでそのXamarin版マダーと常々思っていますがくる気配はまだありません。
Heap Allocations Viewerは前にも書きましたが、あると便利だと思います。ただnewとかまで表示するのは正直邪魔なので表示・非表示の設定ができればなーと思います。
最後のPython Community Editionは・・・なんでしょう?Pythonスクリプトが書けるらしいのですが果たしてC# IDEであるRiderで使う機会あるの?

欲しいと思ったPluginをインストールしたら最後に

f:id:crocus7724:20161127104059p:plain

で初期設定は終了です。
それではStart using Riderを押しましょう!

f:id:crocus7724:20161127104217p:plain

これで今日からあなたもRiderを使い始めることができます。お疲れ様でした!!

機能

本当は機能をいろいろ紹介していきたいのですが確実に長文駄文になるので泣く泣く諦めます。。。が、せっかく調べたので2点紹介致します。

Postfix

よくコーディングをしていると途中まで式を書いて「これ変数にしたいな」とか「これをリターンしたいな」と思うことがあるのですが、そのときに役立つのが「Postfix」です。変数名やクラス名のあとで.を入力して対象の文字を入力してTabを押すか補完で出てきたものを選択すると展開します。

現在Riderで使えるPostfixは以下のとおりです。

入力 展開後 備考
Foo.var var foo = new Foo();
Foo.new new Foo()
foo.return return foo; 戻り値と型が一致してるとき
foo.yield yield return foo;
foo.throw throw foo;
Foo.typeof typeof(Foo) クラス
foo.null if(foo==null) { }
foo.notnull if(foo!=null) {}
foo.switch switch(foo) {}
foo.not !foo bool型
foo.if if(foo) {} bool型
foo.else if(!foo) {} bool型
foo.while while(foo) {} bool型
foo.lock lock(foo) {} 参照型
foo.using using(foo) {} IDispose型
task.await await task Task型
list.for for (var i = 0; i < list.Count; i++) {} コレクションや配列など
list.forr for (var i = list.Count - 1; i >= 0; i--) コレクションや配列など
list.foreach foreach (var item in list){ } コレクションや配列など
foo.parse int.Parse(foo) string型
foo.tryparse int.TryParse(foo, ) string型
foo.arg Method(foo) *
foo.cast ((object)foo) *
foo.par (foo) *
foo.prop Foo = foo; *
プロパティを生成してくれる
foo.field _foo = foo; *
フィールドを生成してくれる
foo.sel foo *
fooが選択状態になる
foo.to target = foo; *
まずToString()が出てくるのでescで消してからTab

結構あります。幾つかは私も初めて知りました。個人的にfoo.nameofがほしいのですがnameofはC#でも特別扱いっぽいので難しいのかも。

基本的に型が一致してないと補完に出てきませんが、いくつか(たとえばifとか)は補完に出てこなくてもTabを押せば展開されます。
また、*がついているやつは補完には出てきません。たまに展開に失敗するのでおそらく正式対応していないと思います。

自作Live Templates

ReSharperのLive Templateはマクロが使えてものすごく便利です。ただ、現時点では自分でLive TemplateをRiderで作成できません。(Live Templateの項目はありますが、言語にC#がなくXamarin StudioのTemplateに毛が生えた程度)

これについて先日行われた?中の人へのQ&Aにてサポートされることは確定なのですが、回答の中で

Current workaround: create a template in Visual Studio + ReSharper, save it to solution-wide .dotSettings file, and Rider will pick it up.

とあります。
なるほど、.dotSettingsファイルがあればLive Template自体は動くらしいです。
私はVisual Studioには詳しくはないのですが、とりあえずVisual Studio + ReSharperで下記のようなLive Templateを作成しました。

f:id:crocus7724:20161206021451p:plain

あとはReSharperのTemplateウィンドウにあるExportボタンをクリックするとUser.DotSettingsファイルが吐き出されます。

それをMacに持ってきたら適当なソリューションと同じ階層にUser.DotSettingsファイルを置いて{ソリューション名}.sln.DotSettingsにリネームすれば・・・

f:id:crocus7724:20161206121450g:plain

展開できました!!(若干バグってるけど)
これでBindable Propertyが爆速で書けます!

なお.DotSettingsファイルの置き場所がわからなくて右往左往してましたが、mdfindで.DotSettingsを検索したところクローン後放置して久しいXamarin.Formsリポジトリに.DotSettingsファイルがあり、それを参考にしました。ありがとうございます。

ちなみに.csprojも.slnも.storyboardも手で編集する昨今、「GUIで編集できないなら手動で編集すればいいじゃない」なノリで.DotSettingsファイルを開いてみたら

<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/@KeyIndexDefined">True</s:Boolean>
    <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Shortcut/@EntryValue">bindable</s:String>
    <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Description/@EntryValue">Generate Bindable Property</s:String>
    <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Text/@EntryValue">#region $name$ Bindable Property&#xD;
&#xD;
public static readonly BindableProperty $name$Property&#xD;
            = BindableProperty.Create(nameof($name$),typeof($type$),typeof($declearType$));&#xD;
&#xD;
public $type$ $name$&#xD;
{&#xD;
    get { return (($type$)GetValue($name$Property)); }&#xD;
    set { SetValue($name$Property, value); }&#xD;
}&#xD;
&#xD;
#endregion</s:String>
    <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Reformat/@EntryValue">True</s:Boolean>
    <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/ShortenQualifiedReferences/@EntryValue">True</s:Boolean>
    <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Applicability/=Live/@EntryIndexedValue">True</s:Boolean>
    <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean>
    <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String>
    <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String>
    <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Field/=type/@KeyIndexDefined">True</s:Boolean>
    <s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Field/=type/InitialRange/@EntryValue">1</s:Int64>
    <s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Field/=type/Order/@EntryValue">0</s:Int64>
    <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Field/=name/@KeyIndexDefined">True</s:Boolean>
    <s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Field/=name/InitialRange/@EntryValue">2</s:Int64>
    <s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Field/=name/Order/@EntryValue">1</s:Int64>
    <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Field/=declearType/@KeyIndexDefined">True</s:Boolean>
    <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Field/=declearType/Expression/@EntryValue">typeName()</s:String>
    <s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Field/=declearType/InitialRange/@EntryValue">-1</s:Int64>
    <s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=02646611FBC11F46BCFB19BD6AE7495C/Field/=declearType/Order/@EntryValue">2</s:Int64></wpf:ResourceDictionary>

諦めました。

また、この.DotSettingsファイルはコーディング規則的なのを決められるみたいですが、こちらで簡単にやってみたところ変更できませんでした。ただ、私自身.DotSettingsを理解してないのでもうちょっと調べてみます。

→Xamarin.Formsリポジトリから.DotSettingsファイルをパクってきたところ、private修飾子をつけたら「いらねえよ」と言われるようになりましたなんでや!

f:id:crocus7724:20161206131042p:plain

Xamarin.Formsで開発するときは本家に合わせる意味でXamarin.Forms.sln.DotSettingsファイルをコピペしてもいいのではないでしょうか?

なお、Riderのyoutrackによると、RiderでのCodeStyle作成 のプロトタイプは既にできていて、次のEAPで利用できるようになるらしいです。(Live Templateは?)

次のEAPが待ち遠しいですね。

終わりに

以上、Riderの紹介でした。現在RiderはPublic EAPであり、正式リリースはまだまだ先です(2017年第2四半期になるらしい?)。また細かなところでバグいですが、現時点でもReSharperの恩恵を多大に受けることができます。ぜひ使ってみて下さい!!

なお学生の皆さんは今回出てきたReSharperIntelliJなどのJetBrains製品が在学期間中ずっと無料で使えます!
詳細は以下

www.jetbrains.com

人気の言語は一通り網羅しているので大学の講義などでプログラミングをやるときに使ってみてはいかがでしょうか?

明日の担当はmmmmmiya - Qiitaさんです。よろしくお願いします(((o(゚▽゚)o)))♡

RiderのHeap Allocations Viewerについて

コーディング規則をみていると「フィールドにアンスコつけるな!」「privateは冗長だ!」とReSharperにコーディング規則を支配された私には哀しみしかないのですが、ふと「全員がReSharperを使えば問題ないんじゃね」と思ったのでRiderを使ってもらうべく記事書きたいと思います。

というわけで次回のビルドからPublic EAP(になったらいいな)らしいですが、その前にRiderに新しいPluginができました。

f:id:crocus7724:20161113111108j:plain

ほとんどの人は真ん中のReSharper Unityに目が行くと思いますが、残念ながら私はUnityやってないので今回は一番右の紹介です。(まあHeap Allocations ViewerもどちらかというとUnity向け)

なお私はメモリ等については詳しくないので解説部分とかは軽く読み流してください

Heap Allocations Viewerとは

直訳すると「ヒープ割り当てビューア」(訳:Google先生)

ようするにヒープに割り当てられる処理をわかりやすく表示してくれる拡張機能です。

ヒープに割り当てられるとGCゴミが発生して場合によってはパフォーマンスに大きく影響するのでなるべく表示されなくしたいですね。

まあHeap Allocations Viewerを入れるとすぐわかるのですが、表示される例を出していきたいと思います。

new

一番わかりやすいヒープ確保する処理はnewです。つまり参照型のインスタンス作成。

f:id:crocus7724:20161113112014p:plain

なおintやdoubleなどの構造体はnewしても表示されません。まあ構造体はスタックなので当たり前ですが。

f:id:crocus7724:20161113112524p:plain

LINQ

次はみんな大好きLINQです。LINQはメソッドチェインで連続して処理を書けるのでとても見やすく書きやすいですが、実行性能は・・・どうなんでしょう? WhereやSelectなどよく使われるメソッドは最適化がかけられていると風のうわさで耳にしましたがよくわかりません。

f:id:crocus7724:20161113112856p:plain

Heap Allocations ViewerですとLINQメソッドというだけで表示されます。(ちなみにToList()やFirstOrDefault()などのよく終端で使われるメソッドは表示されません。)

まあLINQは繋げた分だけEnumeratorを撒き散らかしてこれがGCゴミになるとどこかで読んだ気がしますが出典不明なので「LINQはなるべく繋げないほうがいいよー」とだけ覚えておけばいいと思います。

デリゲート

デリゲートというかメソッドグループというかなんというか。ようするにメソッドの引数にメソッドを渡すやつです。 具体的に見てみましょう。

private int InvokeSampleMethod(Func<int,int> func)=>func.Invoke(10);

private int OnSampleMethod(int i) => ++i;

というメソッド(例なので全く意味のないメソッドです)に対して、

InvokeSampleMethod(x=>++i);
InvokeSampleMethod(OnSampleMethod);
InvokeSampleMethod(i=>OnSampleMethod(i));

という3つの書き方をします。メソッドの実行結果としてはほぼ同じですが、この中に1つだけHeap Allocations Viewerで表示されないものがあります。

それは・・・

f:id:crocus7724:20161113115508p:plain

です。どうやら正解は自己完結しているラムダ式の模様。詳しくは

neue cc - Unityでのボクシングの殺し方、或いはラムダ式における見えないnewの見極め方

をお読みください。

なおメソッドを直接引き渡すやりかたは他にイベントがあります。ということはイベントの購読も自己完結しているラムダ式で書くことで無駄なGCゴミを生成しないと思いきやラムダ式だとイベントの購読を解除できません!残念無念。

クロージャ

デリゲートやったのでついでによくあるパターンとしてこんなのがあると思います。

int i=0;

InvokeSampleMethod(x=>x*i);

これはHeap Allocations Viewerだとこうなります。

f:id:crocus7724:20161113131105p:plain

f:id:crocus7724:20161113131115p:plain

上の大先生のブログにも書いてありましたが、外の変数をキャプチャする場合、クラスが新しく作られるのでGCゴミが生まれる模様。ただこのパターンはよく見かけるというか、このパターンが便利すぎるので大人しく諦めましょう。しょせんクラス1個分(でもクラス1個分・・・)

見た感じ外の変数を取り込むほどクラスにフィールドが生成されるのでなるべく外の変数を取り込まないようにすると幸せになれるかもしれません。

可変長引数

他にHeap Allocations Viewerが表示される例として可変長引数(params)があります。 例としてDebug.WriteLine(string format, params object[] args)を書いてみると、

f:id:crocus7724:20161113122829p:plain

こうなります。

省略可能ですしnew object[]{"hoge","bar"}などと書かなくてよいので個人的には好きですが、結局配列を生成しちゃうので引数が少ない想定のときはオーバーロードで対応するのがスピードアップへの近道ですかね。(でも配列1個分なら別にゴニョゴニョ)

ボックス化

ところでさっきのスクショを見ていると、引数のところに赤いアンダーラインが引かれてると思います。

わざと赤いラインが引かれるように書いたのですが、objectの引数に構造体を渡すと表示されます。 ようするに構造体(Value Type)からobject(Reference Type)に変更されてせっかくスタックのはずがヒープになってしまってGCゴミガーということです。

ボックス化もパフォーマンスに大きく影響するので(なんとボックス化するのとしないのでは1億回ループを回したときに0.2秒の差がつく!らしい?)できるだけ避けていきたいですね。

他のボックス化の例として、構造体でGetType()を使ったり、自分で定義した構造体でToString()をオーバーライドしないで使ったり、””+1と書くとボックス化が発生します。

まとめ

以上、Riderの新しいプラグインの解説(?)でした。このプラグインを使ったからといって別にコーディングが楽になったりしないし、表示されるのを気にしてコードを複雑にするのは個人的にアンチパターンだと思います。ただ、チームでやっている場合、誰かがこれを使っていれば、もしかしたら無駄な処理に気付けるかもしれません。なのでMacC#やっている人は積極的に使ってみてほしいですね!Riderも一緒に!!

Xamarin SutdioでNuGetパッケージを簡単に作る

NuGetパッケージは依存関係を自動(?)で解消してくれたりリポジトリを検索してインストールしたりで利用する分には簡単(??)なのですが、いざ作成しようとすると.nuspecを編集したりコマンド叩かなきゃいけなかったりで結構めんどくさいです。

なので簡単にNuGetパッケージを作成するXamarin Studio Addinを作成しました。

なお簡単っていっても個人運用向けで、ちゃんと公開する場合はしっかり.nuspecを編集しないといけないので結局面倒くさいです。

使い方

一番簡単な使い方。

1
からdllをダウンロードして

/Applications/Xamarin Studio.app/Contents/Resources/lib/monodevelop/AddIns

とかに入れる。

2 Xamarin Studio起動してプロジェクト開く。

3 ソリューションダブルクリックしてDescriptionに適当な文字を入れる。(ビルドしてなかったらビルドする)

f:id:crocus7724:20161018193706p:plain

4 MainMenu→Edit→Make Nuspecで.nuspecファイル作成

f:id:crocus7724:20161018193908p:plain

5 MainMenu→Edit→Make PackageでNuGetパッケージ作成

f:id:crocus7724:20161018193948p:plain

もっと詳しく

一応、上記のやり方でパッケージは作れるのですが大抵残念仕様です。なのでしっかり.nuspecを編集します。

ソリューションに追加された.nuspecファイルを見てみましょう。

<?xml version="1.0" encoding="utf-8"?>
<package>
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <authors>$author$</authors>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>$copyright$</copyright>
    <tags>Tag1 Tag2</tags>
    <dependencies>
      <dependency id="Xamarin.Forms" version="2.3.1.114" />
      <dependency id="Xamarin.Android.Support.Animated.Vector.Drawable" version="23.3.0" />
      <dependency id="Xamarin.Android.Support.Design" version="23.3.0" />
      <dependency id="Xamarin.Android.Support.v4" version="23.3.0" />
      <dependency id="Xamarin.Android.Support.v7.AppCompat" version="23.3.0" />
      <dependency id="Xamarin.Android.Support.v7.CardView" version="23.3.0" />
      <dependency id="Xamarin.Android.Support.v7.MediaRouter" version="23.3.0" />
      <dependency id="Xamarin.Android.Support.v7.RecyclerView" version="23.3.0" />
      <dependency id="Xamarin.Android.Support.Vector.Drawable" version="23.3.0" />
    </dependencies>
  </metadata>
  <files>
    <file src="../Sample/bin/$Configuration$/Sample.dll" target="lib/" />
    <file src="../Sample.iOS/bin/$Configuration$/Sample.iOS.dll" target="lib/" />
    <file src="../Sample.Android/bin/$Configuration$/Sample.Android.dll" target="lib/" />
  </files>
</package>

Xamarin Studioで開くとシンタックスハイライトが全く効かないのでつらいですが見てみると$id$とか$$で囲われたのがあると思います。 これはMake Packageを実行すると対応した値に変換されます。

以下がその対応表になります。

From To Description
$id$ solution.Name ソリューションの名前
$title$ solution.Name ソリューションの名前
$version$ solution.Version ソリューションの名前
$author$ solution.AuthorInformation.Name ソリューションの製作者情報の名前
$description$ solution.Description ソリューションの詳細
$copyright$ solution.AuthorInformation.Copyright ソリューションの製作者情報のコピーライト
$Configuration$ IdeApp.Workspace.ActiveConfigurationId 現在のコンフィグ(DebugとかReleaseとか)

ただし、$hoge$はdependenciesでは使えません。そこで使うことを想定してないので書くととても残念な事になります。

また、dependencyがいっぱいありますがこれは各プロジェクトのpackages.configの中身をそのまま持ってきた感じになります。

こんな感じ↓

private static IEnumerable<XElement> GetDependencies()
            => ProjectService.CurrentSolution.GetAllProjects()
                .Where(x => File.Exists(x.BaseDirectory.Combine("packages.config")))
                .SelectMany(x => XElement.Load(x.BaseDirectory.Combine("packages.config")).Elements("package"))
                .Select(x => new XElement("dependency",
                    new XAttribute("id", x.Attribute("id").Value),
                    new XAttribute("version", x.Attribute("version").Value)))
                .Distinct(x => x.Attribute("id")?.Value);

また、filesも同じくプロジェクトをごそっと持ってきた感じになります。 こんな感じ↓

private static IEnumerable<XElement> GetFiles()
            => ProjectService.CurrentSolution.GetAllProjects()
                .Select(x => new XElement("file",
                    new XAttribute("src",
                        Path.Combine("..",
                            x.GetOutputFileName(IdeApp.Workspace.ActiveConfiguration)
                                .ToRelative(ProjectService.CurrentSolution.BaseDirectory)).Replace(
                            IdeApp.Workspace.ActiveConfigurationId, "$Configuration$")),
                    new XAttribute("target", "lib/")));

テストプロジェクトがあった場合はfilesに含まれてしまったり、全部lib/なので全プラットフォーム対象になってしまったりなのでfileは要編集です。

そしてそれぞれよしなに編集した.nuspecファイルがこちらになります。

<?xml version="1.0" encoding="utf-8"?>
<package>
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <authors>$author$</authors>
    <licenseUrl>https://opensource.org/licenses/MIT</licenseUrl>
    <projectUrl>https://github.com/crocus7724</projectUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <releaseNotes>First Release.</releaseNotes>
    <copyright>$copyright$</copyright>
    <tags>Xamarin, Xamarin.Forms</tags>
    <dependencies>
      <dependency id="Xamarin.Forms" version="2.3.1.114" />
    </dependencies>
  </metadata>
  <files>
    <file src="../Sample/bin/$Configuration$/Sample.dll" target="lib/portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10" />
    <file src="../Sample.iOS/bin/$Configuration$/Sample.iOS.dll" target="lib/Xamarin.iOS10" />
    <file src="../Sample.Android/bin/$Configuration$/Sample.Android.dll" target="lib/MonoAndroid10" />
  </files>
</package>

.nuspecファイルを編集した場合は⌘+Sで保存してください。残念ながらオートセーブは未実装です。

また、一応申し訳程度の設定があります。

f:id:crocus7724:20161020020910p:plain

適当英語で申し訳ないのですが、

  • 出力先ディレクトリ(Defaultだと.slnと同じ階層とか)
  • Releaseビルドを使うか($Configuration$が常時ReleaseになりますDebugって直接書いてたら意味ないオプション)
  • Make Package前にビルドするか
  • 作ったパッケージをnuget pushするか

を設定できます。

ただ、Auto Publishをする場合は事前にTerminalでnuget setapikey <key> -source <url>をする必要があります。 今回はローカルのサーバーにDockerでNuGet ServerをApiKey=nugetPublish URL=http://192.168.1.11:5001で立ててそれを使ってみました。

この場合のAPIキーの設定はこんな感じ。

nuget setapikey nuget -source http://192.168.1.11:5001

それではMake Packageをしてみましょう。

f:id:crocus7724:20161020025746p:plain

上記のようにエラーっぽいメッセージがなければ成功です。 あとはNuGetのSourcesにURLを足して

f:id:crocus7724:20161020024151p:plain

NuGetパッケージマネージャーを見てみると

f:id:crocus7724:20161020025924p:plain

追加するとちゃんとクラスも表示されているので大成功です!(もっと特徴的な名前にすればよかった)

f:id:crocus7724:20161020023311p:plain

最後に

実はこれソースコードを見ればわかるのですが裏で結構がちゃがちゃやってます(だいたいnugetのせい)。

なので結構バギーです。もしよろしければ使ってみて動かなかった場合は@crocus7724までお知らせください。

Rider Build 11でソリューションが読み込めない

追記

10/22のBuild 12にて日本語でも問題なくソリューションを開けることを確認致しました。

追記ここまで

現在(2016/9/27)Riderの最新のバージョンであるビルド11でソリューションが開けなくなるバグがあります。

具体的に書くとソリューションを開こうとするとエラーっぽいのが表示されてその後もう一度開こうとすると永遠にソリューションの読み込みをします。初期の頃を思い出す・・・

このバグに対する対処が下記に載っています。

https://youtrack.jetbrains.com/issue/RIDER-2431

対処法はなんと・・・

_人人人人人人人人人人人人人人人人人_
> システム言語を英語にする!!! <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄

私は英語苦手マンなのでOSの言語はもちろん日本語なのですがこれが原因でした・・・。
あと中国語もアウトっぽいですね。

この手のバグはいつになったら駆逐されるのでしょうか・・・。

Public EAP!?

そして上記のyoutrackを見て気づきました。

なんとラベルに Public EAPが!!!!!!!!!!

EAP 12の横にPublic EAPのタグがあります!

他のやつ見てみるとついていたりついてなかったりまちまちで判断に困るのですがもうすぐPublic EAPがくると思うと感慨深いですね。。

とりあえずBug FixされたBuild 12の公開はよ

macOS SierraでKarabinerが使えないときの応急処置

9/21にmacOS Sierraが正式リリースされました。

私も勇んでアップデートしたのですがやはりいろいろ問題があったり(ログインパスワード勝手に変えられたりGoogle Chromeがバグっぽい挙動したり)

その中でも特に困ったのが Karabinerが使えない

macOSのUSキーボードユーザーにとっては致命的です。

これの回避方法は他のアプリを使うなりすればいいのですがKarabinerの公式サイトを見たら単純なキーの変更を行えるKarabiner-Elementsというものを開発中らしい。

今回はそのKarabiner-Elementsを使ってとりあえずかなを使えるようにしてみました。

インストール

まずはインストール。

https://github.com/tekezo/Karabiner-Elements

のページにある

https://pqrs.org/latest/karabiner-elements-latest.dmg

からイメージファイルを落としてきます。

インストール自体は他と変わらなくハイハイ押せばいいのですが、最後に外付けキーボード使ってないのにキーボードが見つかりません的なウィンドウが出たら何も押さず閉じちゃって大丈夫です。

設定ファイル

インストールが終了したら設定ファイルを書きます。

設定ファイルの置き場所は~/.karabiner.d/configurationです。なかったらたぶんKarabiner-Elementを起動すれば作られるはず。

最初はconfigurationの中身は空っぽなので適当にターミナルから

vi ~/.karabiner.d/configuration/karabiner.json

で設定ファイルを作成します。そして試しに

{
    "profiles": [
        {
            "name": "Default profile",
            "selected": true,
            "simple_modifications": {
                "caps_lock": "japanese_kana",
                "right_shift":"japanese_eisuu"
            }
        }
    ]
}

と編集して保存してみてください。

そうするとcaps_lockで日本語入力が、右Shiftキーで英字入力ができると思います。

現在はまだ開発途中で単純なキーの入れ替えしかできないようなのでKarabinerのようにCommandキー1回押すと日本語入力みたいな器用な真似はできません(たぶん)。

なので個人的に使わないキーであるcaps_lockと右Shiftキーに英語日本語キーを割り当てました。

他のキーに割り当てたい場合は

https://github.com/tekezo/Karabiner-Elements/blob/master/src/share/types.hpp

にキーの割当一覧が乗っているので適宜変更してください。

MacでC#ユーザーのRider入門〜便利機能〜

今回はRiderの便利機能の紹介

getonlyから変更通知プロパティへの変換

Xamarin.Formsをやっていると変更通知プロパティが結構出てくるのですが、もしもともとあるプロパティを変更通知可能にしようとする場合バッキングフィールド書いて〜プロパティのsettergetter書いて〜は結構手間だと思います。

Riderならそんな面倒な変換も一瞬でやってくれます! 例としてgetonlyプロパティをregion付きの変更通知プロパティに変えてみました。

f:id:crocus7724:20160918141140g:plain

Autoプロパティからバッキングフィールドのプロパティへの変換がAlt+Enterで簡単にできます!しかもバッキングフィールドの名前はプロパティの名前のアンダーバー+ロワーキャメルケースへ自動的に変換。めっちゃ便利。

Currentメソッド作成

また、よくあるかわからないけどシングルトンパターンを作るときに初回はインスタンス作成して次回以降はそれを使いまわすみたいな感じになると思いますがこれもRiderならスラスラ書けます。
Sample Current{get;}=new Sample();でいいだろという声は聞こえません

f:id:crocus7724:20160918141236g:plain

なんとnullチェックで冗長だった場合短い構文に書き換えてくれます!!素晴らしい。

Linqサポート

冗長だったやつを短いのに変えるのはnullチェックだけではありません。もしforeachで長い文を書いていた場合Linqに変換してくれます。

f:id:crocus7724:20160918141350g:plain

個人的に+=じゃなくて=が嬉しいですがまあ問題ないんでしょう。

リネーム

リネームのためだけにRiderを開いてもいいほど強力です。どのくらい強力かというと条件があうと別プロジェクトのコメントアウトした部分もリネームするか聞いてきます。

例としてバッキングフィールド付きプロパティをリネームしたとき

f:id:crocus7724:20160918141407g:plain

ちゃんとバッキングフィールドも一緒にリネームするか聞いてきます。地味に凄いですね。

Search Everywhere

これはIntelliJを使っている人ならよく知っていると思いますがShiftキーを2回押すことでいろんなものを検索します。

なんとこれクラスやシンボルだけでなく設定まで検索できます。

f:id:crocus7724:20160918142328g:plain

これでいちいちあの設定はどこだっけと悩む必要はなくなりますね!

ほかにもいろいろ便利な機能がありますがこの辺で。

とりあえずAlt+EnterとSearch Everywhereが便利すぎです。

MacでC#ユーザーのRider入門〜インストール〜

RiderとはJetBrainsが開発中のCross-platform C# IDEです。 詳しくはこちらを御覧ください。

Project Rider – 新しい C# IDE #jetbrainsrider | JetBrains ブログ

ReSharpermacOSで使えます。

ReSharpermacOS で使えます!!

(あとIntelliJなどのプラグインも使えます)

これは使うしかありません。さっそくインストールしましょう!!

注意

まずRiderは2016/9/17現在Private EAPです。上のリンクにはリリースは8月を予定と書いてある通り、当初の予定では2月にPrivate EAP、6月ごろにPublic EAP、8月か9月ころに正式リリースだった記憶があるのですが、Private EAPもギリギリまで遅れ(日本時間で2/29の24時頃だったのでギリギリセーフ(?))それから未だにPrivate EAPです。なので

  • Xamarinのプロジェクトは作れません。Xamarin Studioをお使いください。
  • Xamarinのプロジェクトを実行できません。Xamarin Studioをお使いください。
  • プロジェクト操作がかなり怪しいです(ファイル削除してもファイルが残る)。Xamarin Studioでも怪しいです。

ただし、現在のPrivate EAP10ではだいぶ使い勝手もよくC#でコーディングする分にはほぼ問題ありません。むしろReSharperが素敵すぎます。

インストール手順

まずはPrivate EAPのサブスクライバーに登録します。

以下のページの下の方で申し込みが出来ます。

www.jetbrains.com

入力が終わったらSubscribeを押します。すると2-3分以内にメールがくるのでそのメールにあるOS Xのダウンロードリンクを押します。

するとdmgファイルが落っこちてくるのでインストールします。

f:id:crocus7724:20160917200425p:plain

インストールが終了したら早速起動してみましょう。

最初にこんな画面が出てきました。

f:id:crocus7724:20160917200505p:plain

以前のバージョンなんて無いので下を選択します。

次にどちらのUIを使うかの選択肢が出てきました。

f:id:crocus7724:20160917200535p:plain

LightかDarkですね。私は断然Dark派です。

次にどのエディターカラーを使うかを選択します。左がReSharper(違和感あるけど)、真ん中がVisualStudio(違和感あるけど)、右がDarcula(というかIntelliJ)ですね。

f:id:crocus7724:20160917200555p:plain

私は初期のRiderがReSharper一択で慣れてしまったのでReSharperです。

お次はKeymapです。

f:id:crocus7724:20160917201014p:plain

Visual StudioライクかReSharperライクかIntelliJIDEAライクかが選択できます。個人的にはあとで設定から変えられるReSharper(macOS)が好きですが初期設定でも結構キーが衝突しているのでmacOSユーザーならIntelliJのキーマップがいいのかな?

お次はターミナルからRiderを起動できるようにするかです。

f:id:crocus7724:20160917201123p:plain

私は結構ターミナルを使うことがあるのでとりあえずチェックを付けときました。

最後はチュートリアルやバグ報告する場所などのリンクです。

f:id:crocus7724:20160917201141p:plain

では早速Start using Riderを押しましょう!

f:id:crocus7724:20160917201230p:plain

IntelliJプラットフォームユーザーなら見慣れた画面が出てきました。

これで準備は完了です。お疲れ様でした!!