helm-cscope.elをMELPAに登録しました

最近 (遅ればせながら) helmを使い始めました。なぜ使うようになったかというと、Emacs24に移行したから。これまで、ある事情からEmacs23を使い続けていたのですが、Emacs24以降しかサポートしないパッケージが増えてきたため、ついに見切りをつけました。Emacs23ではanythingでしたが、バッファ・ファイル選択程度であまり積極的には使っていませんでした。helmは、MELPAにたくさんパッケージが登録されているのが大きなメリットですね。おかげで簡単に機能を追加していくことができます。

私は、Emacsを使う時間の半分以上はCのプログラム開発なので、タグジャンプ機能は欠かせません。タグジャンプのためのツールと言えば、GNU globalcscopeが二大メジャーです (よね?)。当然ながら、GNU globalのhelm版helm-gtagsはあるのですが、何故かcscopeの方はMELPAに見当たりませんでした。ググってみたところ、

の2つがありましたが、後者は何かエラーで動作せず、前者はanything版 (多分これが元ネタ) をhelm版に書き換えたもののようで、一応普通に動作はしますが若干機能不足ということで、自分で作ってみることにしました。helmの拡張を書く練習にちょうどいいと思ったというのもあります。

helm-cscope.el

リポジトリこちらにあります。一応MELPAに登録するからには、少なくとも上記の2つよりは機能的に整っていないと申し訳ないので、現時点でそれなりに使えるものにはなっていると思います (helm-gtagsには及びませんが...)。特徴的な点としては、以下があります。

データベースリストのサポート

xcscope.elでは、cscope-database-regexpsという変数で検索対象のタグデータベースを複数登録することができますが、helm-cscope.elでもこの変数をそのまま利用できます。helm-cscope.elでは、データベース毎にhelmの1つの情報源として結果が表示されます。

シンボル位置のfuzzyな検索

これもxcscope.elの機能をそのまま拝借したもので、通常編集中 (未保存) のファイルに対して検索すると結果はズレてしまいますが、指定した範囲 (デフォルトは1000文字) の範囲で対象のシンボルをパターンマッチして調整してくれます。コードを書きながら検索するときは、地味に便利な機能です。

GNU global vs cscope

今回helm-cscopeを書くのにあたって、GNU globalとcscopeを改めて比較してみました。元々cscopeを使い始めたのは、数年前にGNU globalしか知らなかったときにcscopeを見つけて、cscopeの方が検索機能が優れていると思ったからです。しかし、GNU globalはPygmentsプラグインパーサの取り込みにより対応言語を大幅に拡張するなど、最近も活発に開発が続けられている一方、cscopeは2012年8月のリリースが最新で、あまり開発が行われていないようです (元々、それまでも3年おきくらいにしかリリースされていないようですが...)。なので、将来性からするとGNU globalを使った方がよいかもしれません。あと、C言語以外の場合も。

ただ、C言語に限って言うと、今でもcscopeの方が優れていると思います。そもそもシステム的な違いなのかもしれませんが、GNU globalはグローバル変数の宣言位置にジャンプすることができません (シンボル検索で見つけることはできますが)。これがあるため、私はまだcscopeを使い続けると思います。

あと、変数cscope-programを"gtags-cscope"に設定することで、helm-cscopeでGNU globalのタグファイルを利用することもできます。まぁ、GNU globalしか使わない人は素直にhelm-gtagsを使えばいいですが、cscopeと併用する場合はこの方法でhelm-cscopeにUIを統一できるので、一応選択肢としてありますということで。

git-gutter.elのSubversionサポート

git管理されているファイルをEmacsで編集する際に、変更箇所の表示などができるgit-gutter.el (作者のsyohexさん自身の紹介記事) を使っています。最近になってgit以外にもMercurialやBazzarがサポートされるようになったのですが、個人的にSubversionがまだ仕事では必要です (git svnという選択肢もありますが、もうメンテナンスフェーズに入っているプロジェクトには今更面倒だったりするので)。

diff-hlを使うとSubversionにも対応できるので、今まではSubversionのときだけdiff-hlを使うようにしていたのですが、使い慣れているgit-gutterにUIを統一したいと思い、git-gutterにSubversionサポートを追加してマージしてもらいました。既にMercurialやBazzar等の別のbackendに対応できるようにコードが書かれていたので、Subversionの対応も割と簡単でした。

ただ、pull requestした後issueを見たところ既にfeature requestを出している方がいて、syohexさんがもう使っていないのでサポートの予定はないと書かれていたので、余計なことをしてしまったかなと思ってます。pull requestする前にissueはきちんと見ないとダメですね。

Subversionのバージョンについて

READMEには、Subversion 1.8以上を使ってねと書いてありますが、実際には1.6等の古いバージョンでも問題ありません (少なくとも、CentOS 6.6付属の1.6.11では動作を確認)。Subversionを使い続けている方は、事情によりバージョンが古いままというケースも多いと思いますので (とは言っても、git-gutter自体はEmacs 24を要求するわけですが)。

simplenote2.elをリリースしました

Emacs用の Simplenote クライアント simplenote.el の新バージョン simplenote2.el をリリースしました。

simplenote.elの改良 では、互換性を保てる範囲で簡単に改善できるところだけ改善したのですが、他にも色々改善したいことが出てきて全面的に書き直しました。ただ、simplenote.el はオリジナルの作者の方がもうメンテしておらず長い間放置状態になっており、今さら大きな変更を入れるのもどうかと思ったので、今回新バージョンとしてリリースすることになった次第です。

新バージョンの主な特徴は以下の2点になります。

  • Simplenote API ver.2を使用することによる、タグ・自動マージ等のサポート
  • サーバーへのアクセスを非同期かつ並列に行うことによる、同期の高速化とブロックしないUIの実現

前者は、旧バージョンはAPI ver.1を使用していたのでノート本体以外の情報が取得できなかったのですが、今回API ver.2を使用するように書き直したことで、タグ、"Pinned to top"、"Markdowned" 等の付属情報が取得できるようになります。また、ノート更新時に他のクライアントからの変更が行われていた時に、サーバー側で (可能な限り) 自動でマージしてくれるようになります (ver.1だと、サーバ側の変更を無視して強制上書きしてしまう)。

後者については、前回やりたいと言っていたことですが、同期時のHTTPアクセスをできる限り非同期かつ並列化しています。ノート数とネットワーク環境にもよりますが、私のケースでは最初の同期にかかる時間が半分程度になりました。ただ、最初の同期以降はほとんどノート単独で同期する場合が多いので、前回の改良だけで実使用上はそれほど問題はありませんでした。なので、どちらかというと技術的興味の側面が強いです。

インストールと基本的な使用方法

こちら から手動で git clone or ダウンロードして頂いてもよいですが、MELPAにも登録されたので M-x package-install でインストール可能です。

使い方は、基本的には旧バージョンと変わりません。M-x simplenote2-browse で一覧画面を呼び出し、[Sync with server] ボタンで同期、各ノートのリンクをクリックして編集、となります。単独のノート同期も旧バージョンと変わらず、M-x simplenote2-create-from-buffer, M-x simplenote2-push-buffer, M-x simplenote2-pull-buffer が使用可能です (simplenote.elの改良 を参照)。

新規機能について

タグのサポート

各ノートのタグは、ノートの一覧画面に表示されます。M-x simplenote2-filter-note-by-tag コマンドでタグによるノートのフィルタリングができます (タグは複数指定可能)。C-u M-x simplenote2-filter-note-by-tag でフィルタを解除します。

simplenote2.elからのタグの追加・編集は、今のところできません。

Pinned to top

Pinned to topがセットされたノートは、自動的に一覧画面の一番上に表示されます。

今後の予定

とりあえずリリースしましたが、しばらくは細かい機能追加や改善を行うと思います。まずは、タグ等の付属情報の編集への対応を予定しています。UI周りも、今のところ旧バージョンを流用したやっつけになっていて改善したいと思いますが、私自身もどんな感じにすれば使いやすくなるのかよく分からないところもあるので、何か要望などありましたらこのページにコメントを入れて頂ければと思います。

最小限の初期投資で始めるiOSアプリ開発

新しい開発言語Swiftも使えるようになり (ちょうど日経ソフトウェア2015年1月号で特集もしているようです)、この機会にiOSアプリ開発を始めてみようかという方も多いのではないかと思いますが、開発にはOS Xが動作するMacが必須で、さらに実機で動作を確認しようと思うとiOSアプリ開発用ライセンス (年間8,000円程度) が必要と分かり、大抵の人は断念してしまうのではないでしょうか?そこで、Windows PCとiPhoneしか持っていない (私のような) 人でも最小限の初期費用 (2,000円) だけでiOSアプリ開発ができる方法についてまとめてみました。

とは言っても、ここに書いてあることはほとんど以下のページのものまねです。意味があるとすれば、2014/11/22時点の最新環境でも、この方法がそのまま使えるということだけでしょう。

なお、最初に書いておきますが、この方法は

  1. 仮想マシンOS Xをインストールする
  2. iOSデバイスを脱獄 (jailbreak) する

というAppleのライセンス規約的にグレーなことをやることになりますので、その点は留意して下さい。

それと、これを見てそのうちやってみようと思った方は、iOSデバイスの脱獄だけは今すぐにやっておくことをお勧めします。 脱獄が可能な最新バージョンiOS 8.1へのアップデートは11/24現在では可能ですが、既にiOS 8.1.1がリリースされており、いつAppleのサーバ側でアップデートが許可されなくなってもおかしくない状況です。脱獄の方法は、Pangu for iOS8 - Tools 4 Hack等を参照すれば簡単にできます。 12/6現在、iOS 8.1へのアップデートはできなくなりましたが、iOS 8.1.1で脱獄が可能になりました。脱獄方法は、[iOS] iOS 8.1.1対応!iOS 8.0~8.1.1を完全脱獄する方法!『TaiG』を参照。 また、一度脱獄してもiOSの復元を行えば基本的に元に戻せますので、その点はご安心下さい。

動作確認した環境


WMwareにMac OS Xをインストール

細かく書こうかと思いましたが、前述したMac本体が無くてもWindowsだけでOS Xをインストールする方法 (いちたそさんのページ) そのままなので、そちらを参照して下さい。Mac OS X 10.6 (Snow Leopard) の購入 (2,000円程度) が必要になります。インストール後、無償で 10.9 (Yosemite) にアップグレードできます。

少しだけ補足すると、最初の新しい仮想マシンウィザードのゲストOSの選択に注意して下さい。通常、Linux 等をインストールする際は適当に選んでも問題ありませんが、Mac OS Xの場合は違うようです。私の場合、"Mac OS Server 10.6 64ビット" を選ばないと仮想マシンが正常に起動しませんでした。それと、サウンドドライバはSnow Leopardの間は動作していましたが、Yosemiteに上げたら音が出なくなりました。まぁ開発には支障はないので、気にしていません。

Yosemiteにアップグレードしたら、AppStoreからXcode (6.1) をインストールして適当なアプリを作成し、iOSシミュレーターで動作させてみるところまでやっておいて下さい。その状態から、作成したアプリを実機に転送して動作させるまでが以下の説明になります。

証明書の作成

アプリに署名を行うための証明書を作成します。いわゆるオレオレ証明書です。

  1. Dockの「アプリケーション」=>「ユーティリティ」フォルダにある「キーチェインアクセス」を起動します。
  2. メニューの "キーチェーンアクセス" => "証明書アシスタント" => "証明書を作成..."
  3. ダイアログの最初で、
    • 名前: 適当に入力 (ここでは "alpha22jp")
    • 証明書のタイプ: コード署名
    • "デフォルトを無効化" にチェック (これはどちらでもいいかも?) f:id:alpha22jp:20141124233839p:plain
  4. 後の画面は全部デフォルトで [続ける] を連打します。
  5. 以下のように「自分の証明書」に証明書が作成されたことを確認します。 f:id:alpha22jp:20141125000618p:plain

Xcodeのコード署名設定の変更

Xocdeが起動中の場合は一旦終了させて下さい。OS Xに不慣れな方 (私もですが...) のために書いておきますが、単にウィンドウを閉じるだけでは終了しておらず、Dockのアイコンから終了させる必要があります。

  1. Finderで以下のフォルダをを開きます。(メニューの "移動" => "フォルダへ移動...")
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk
  2. SDKSettings.plist をデスクトップなどの適当な場所にコピーして開きます。
  3. 以下のように、CODE_SIGNING_REQUIRED を NO に変更して保存します。 f:id:alpha22jp:20141125001909p:plain
  4. 変更したファイルをFinderで元の場所に上書きします。
    (このとき、警告が出るので管理者のパスワードを入力します)

アプリの作成と署名

Xcodeで作成したアプリのプロジェクトを開き、以下の操作を行います (ここでは、"TestApp" という名前でアプリを作成したとします)。

  1. プロジェクトのBuild Settingsを開き、Code Signingの設定を以下のように全部 "Don't Code Sign" にします。 f:id:alpha22jp:20141125003053p:plain
  2. 動作させたいデバイスをUSB接続し、ターゲットをそれに変更します。(ツールバーデバッグ停止ボタンの右)
  3. ビルドを行います (メニューの "Product" => "Build")。ビルドが成功すると、左側ペインのProductsの下にTestApp.appができます。 f:id:alpha22jp:20141125003937p:plain
  4. 右クリックして "Show in Finder" 等で、アプリのフォルダの所在を確認して下さい。この例では以下の場所となります。
    ~/Library/Developer/Xcode/DerivedData/TestApp-gzmnwhrlrgsdkmexucyaurqfoynl/Build/Products/Debug-iphoneos/TestApp.app
  5. ターミナルから以下を実行します。
$ export CODESIGN_ALLOCATE="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate"
$ cd ~/Library/Developer/Xcode/DerivedData/TestApp-gzmnwhrlrgsdkmexucyaurqfoynl/Build/Products/Debug-iphoneos/
$ codesign -fs "alpha22jp" TestApp.app

1つめの引数は作成した証明書の名前、2つめはアプリのフォルダです。実行すると警告が出るので [許可] を選択します。なお、最初の1行は、毎回実行しなくもよいように、~/.bash_profile等に追加しておくとよいでしょう。

以上で、実機で実行可能なアプリができました。

実機へのアプリの転送と動作確認

転送方法は何でもよいですが、ここではsshを使用しますのでCydiaでopensshをインストールして下さい。(ここも詳細は省略...)

実機をMacと同じネットワークに接続した状態で、Macのターミナルから以下を実行します。ここでは、実機のIPアドレスが192.168.1.11として説明します。上の操作でアプリを署名したところからの続きです。

$ scp -r TestApp.app root@192.168.1.11:/Applications/
$ ssh root@192.168.1.11 chmod -R 775 /Applications/TestApp.app
$ ssh root@192.168.1.11 killall -HUP SpringBoard

最後の1行は、実機のUI (FlipSwitch等) からリスプリングを実行しても同じです。

これで、以下のようにアイコンが現れ、実際に動作させてみることができます。

f:id:alpha22jp:20141125224531p:plain

(2014/11/27 追記)
どうも、iOS 8 (7も?) では単にリスプリングしてもアプリのアイコンが出てこないことがあるようです。その場合は、Cydiaで何でもよいのでリスプリングが必要となるアプリを再インストールしてみて下さい。

また、アプリの更新時は再ビルドしてファイルをコピーし直すだけでOKです。(署名とリスプリングは不要)


どうでしょうか?若干ターミナルからのコマンドが必要な箇所があり、その辺りの操作に不慣れな方にはちょっと難しく感じるかもしれませんが、やっていること自体は難しいことではありません。

ただ、仮想マシンでは動作が重くXcodeが快適には動きませんし、実際にアプリを配布しようと思うとやはり開発者ライセンスが必要なので、この方法でちょっと試してみて、続けられそうなら本格的に開発環境を整えるのがよいと思います。

Simplenote向けStylishスタイルファイル

昨日に続き、Simplenoteネタでもう一つ。

Simplenoteのブラウザでの表示ですが、デフォルトだと正直あまり綺麗じゃないですよね?フォントも今イチだし、Markdown記法で書くときの各要素の見た目なんかもバラバラです。まぁ好みもあると思いますが。

そこで、私はFirefoxを使っているのでCSSを強制的に設定するアドオンStylishを使って、ある程度まともにしてみました。Markdown記法を使う場合に特化しています。以下のような感じになります。

作成したスタイルファイルは、こちらに登録してあります。大したものじゃないですが、よければ使って下さい。フォントはメイリオを指定しているので、WIndowsユーザじゃないときちんと表示されなかったりすると思いますが、好みに合わせて適当に弄って下さい。(見ればすぐわかると思うので...)

ちなみに、JavaScriptを使ってもっと大胆な書き換えができるGreesemonkey用のSimplenote向けスクリプトとして、Simplenote restyledというのがあるみたいなのですが、何故か私の環境ではまともに設定が反映されませんでした。

simplenote.elの改良

クラウドベースの自分用メモツールとして Simplenoteを使っています。

  • 動作が軽い
  • Markdown記法が使える (中途半端だけど...)
  • iPhone用クライアントがある

というのがポイント。正直デザインとかは以前使っていたCatch Noteの方がよかったですが、残念ながら昨年8月でサービス終了 (Simplenoteも同じようにならないことを祈ります)。で、最近これのEmacs用クライアントであるsimplenote.elを使い始めたのですが、いくつか不満な点があったので改良してみました。


1つのノートだけを同期するコマンドがない

ノートの同期を行うコマンドは、基本的に M-x simplenote-sync-notes しかありません。これは全ノートの同期を行うため、1ノートしか更新していなくても無駄に時間がかかります (最初に全ノートの更新状態を取得しに行くため)。M-x simplenote-push-buffer M-x simplenote-pull-buffer という、いかにも1ノートの更新ができそうなコマンドがありますが、READMEに書いてある通りこれらは M-x simplenote-create-note-from-buffer で作成したノート限定のコマンドになっています。これは、同期にはSimplenote上で管理されるノートのIDが必要で、前記コマンドで作成したノートはコメントとして挿入されたローカル変数でIDを保存していますが、通常のノートにはそれがないためです。

そこで、通常のノートでもこれらのコマンドで同期ができるように改良してみました。実は、通常のノートもファイル名がIDになっているので、それを利用しています。動作としては、以下のようになります。

  1. M-x simplenote-create-note-from-buffer で作成されたノートであれば従来通りの動作。
  2. 既存ノート (~/.simplenote/notes/ のファイル) であれば、ファイル名からIDを取得して1を実行。
  3. 新規ノート (~/.simplenote/new/ のファイル) であれば、新規ノートの作成を行い既存ノート置き場に移動。(pushの場合のみ)
  4. それ以外であれば、エラーメッセージを表示して何もしない。

ファイルの保存と同時に同期を行うようなhookを使っている方も多いかと思いますが、呼び出す関数を simplenote-sync-notes から simplenote-push-buffer に変更すれば、少し幸せになれると思います。

本当は、非同期処理にするのが一番いいのですが、そこまでするのは面倒だし、大幅な変更になるので一から書き直した方がいいですね。

全ノートの同期に時間がかかる

M-x simplenote-sync-notes で同期を行う際に、最初の同期など大量のノートの更新が発生するときにやたらと時間がかかります。これは、サーバとの認証用のトークンを各ノートの同期毎に取得し直しているのが原因の1つです。Simplenote APIのドキュメントによると、トークンは発行から24時間有効なので、1回の M-x simplenote-sync-notes では最初に取得したトークンを使い回しても問題ないはず。ということで、そのように修正したところ、自分の環境では半分程度の時間に改善しました。

ノート一覧のヘッダ行の長さがおかしい

些細な点ですが、78文字 (simplenote-note-head-size で設定された文字数) で切るようになっているはずが、日本語が入っていると意図通りに動作しません。文字数のカウントでマルチバイト文字が考慮されていなかったので、修正しました。


以上の改良を行ったsimplenote.elは、こちらから取得できます。なお、1つめの変更はすでに本家に取り込んでもらったので、そちらでも利用可能です (package.elを使用されている方は、アップデートするだけでOK)。残りの2つも取り込んでもらう予定です。 (2014/11/21追記) すべて取り込んで頂きました。

なお、"simplenote.el" でググるこちらが先に出てきますが、(READMEの先頭に書かれている通り) もう古いので使わないようにして下さい。Emacs24だと、ブラウザとsimplenote.elを併用したときにブラウザからの変更分が消えてしまう問題があります (date-to-time関数の挙動のバグ?のせい)。