PEEE802.11

モバイルソフトウェアエンジニアの備忘録

Mac用MarkdownエディタMacDownを使い始めた

開発しながらメモを気軽にとりたい、それならMarkdownのほうが見やすいし割と書き慣れてるし、ということでMac用のMarkdownエディタを探している。自分にとって重要な点は以下。

  • リアルタイムプレビュー
  • Macネイティブのシェルライクな編集エリアのキーバインドが使える
    • Ctrl + f, b, n, pで前後上下カーソル移動、Ctrl + a, eで行頭行末移動等
  • Evernoteと連携できる
  • できれば無料

これだけ、割とシンプルだしあるだろうと思っていたら全部満たすのは意外に見つからない。微妙にどれか欠けていたりする。

調べてみた&使ってみたアプリは以下。

metanota


Metanota

Evernoteと連携して直接Evernote上のファイルを編集でき、フォルダ分け等の階層もそのまま扱える。UI気に入ったし、動作も軽いし、使いやすそう。最初にこれだ!と思ったのだが、Ctrl + fが検索に割り当てられていて、キーバインドがカスタマイズできず。無料だし、キーバインド以外はほぼ理想的なアプリなのだが…

Marxico


Marxico - Markdown Editor for Evernote

ChromeアプリのMarkdownエディタ。リアルタイムプレビューとEvernote連携OK。無料。UIも好き。ただしこれもキーバインドが固定で、Ctrl + bが強調編集機能に割り当てられてたりで馴染まず。

Byword


Byword • Simple and efficient text editor for Mac, iPhone and iPad.

こちらはけっこうユーザが多そうなアプリ。ウインドウを2つ開けばリアルタイムでプレビューが見れるようだ。Evernoteと連携可、iPhone向けにアプリがある等いろいろ興味深いアプリなのだが、有料である。

Haroopad


Haroopad - The Next Document processor based on Markdown

最近はてブで話題になってたエディタ。リアルタイムプレビュー、キーバインド、無料の面ではよい。Evernoteと連携できないのと、デフォルトで日本語フォントがしょぼい(修正可能らしい)。
割と使いやすいが、寄付の吹き出しが出続ける。


MacDown


MacDown: The open source Markdown editor for OS X.

Mac用Markdownエディタ。Mac用だけあってUIが馴染むし、なにより編集エリアのキーバインドがシェルライクに使える。軽い。無料。リアルタイムプレビュー付き。ただし、Evernote連携ができない。


まとめ

以上のように、どれも完璧に自分のニーズを満たさないのだが、編集時のストレスが一番少ないものということでMacDownをメインに使ってみることにした。metanotaがキーバインド設定可能になれば使いたいなー

mac mini 2014 late + Yosemiteでスリープから復帰できない

今までメインでMacbook Airを使ってたのだけど、Androidアプリ開発でEclipse ADTを動かしてると動きがもっさりしてかなりストレスフルであった。Android Studio使うともうちょいましでストレスはやや軽いが、それでも快適とは言い難い。SSDとは言えノートPC用CPUとメモリ4GBだとIDEは厳しいということがよくわかった。

そこでmac miniを買ってメモリ16GB積んでヒャッハーしようと思ったのだが、最近ずっと出てないので新モデルが出るまで待とうと思い、半年ほど経過。やっとのことでlate 2014が出たので即決。メモリ増設できないので最初から16GB、1TB fusion driveにカスタマイズしてApple online storeで注文。一週間ほどで到着。


フライングで買っておいたWQHDのiiyamaのモニタに繋げて、初期設定して、離席。戻ってくるとスリープ状態になっていたので、適当にキーボードを叩いて復帰させる…はずが、復帰しない。モニタは暗いまま。電源ボタンを押すも効果なし。Thunderbolt経由で画が出ていないだけなのかと思い、HDMIでつないでみるも真っ暗のまま。一応、キーを押すとモニタは何かしらの信号を受け取ってるのかモニタ自体はスリープから復帰する(モニタの電源LEDがオレンジから青に変わる)。その後no signalという表示が出てまたモニタがスリープする。

ちなみに、Apple純正のBluetoothキーボードとTrackpadを使っている。

結局電源ボタン長押しで強制シャットダウン。ウェブ上を見渡すともともとmac miniはスリープ復帰後のフリーズ問題やら復帰しない問題が各所で観測されているぽい。

解決策

システム環境設定 -> 省エネルギー -> 可能な場合はハードディスクをスリープさせる

このチェックを外すと、スリープから復帰するようになった。


前述の通り本現象が観測されたマシンは1TBのFusion driveにカスタマイズしている。これがSSDやHDDモデルで起こるかどうかはわからない。もしくは実はiiyamaモニタとの相性なのかもしれない。根本原因ははっきりとしないが、これでしばらく使ってみることにする。

init.rcの実行順番

Androidが起動する際、kernel起動後にinit.rcに記述した通りにファイルシステムパーミッション設定やら各種サービス起動やらが実行される。

rootdir/init.rc - platform/system/core - Git at Google

ここで、on early-initだとかon initだとかいくつか起動の段階がある。init.rcは別のinit*rcファイルをimportできるようになっていて、init.usb.rcだとかinit.trace.rcだとかいくつもファイルが分かれており、on init等はそれらのファイルに分散している。

init.rcを解釈して実行していくのは、system/core/initである。on initだとかon bootだとかon fsがどういった順番で起動されるか、どこかに公式ドキュメントがないかと探してみたのだがどうも簡単に見つからなかった。なので直接ソースを見てみた。

init/init.c - platform/system/core - Git at Google

このmain()に、

action_for_each_trigger("early-init", action_add_queue_tail);

というコードがある。これがon early-initを実行する関数のはず。この関数に着目すると以下の順番で実行されるようだ(is_charger == falseの場合)。

  1. on early-init
  2. on init
  3. on early-fs
  4. on fs
  5. on post-fs
  6. on post-fs-data
  7. on early-boot
  8. on boot


このon hogeは以前のAndroidリリースから現在のKitkatに至るまでにけっこう追加されている。gingerbreadではpost-fs-dataが無いし、eclairまで遡ればon early-fs、on fs、on post-fsが無い。今後変わるかもしれないが、init.rcに見慣れないon fugaが出てきてもソースをチェックすればわかるだろう。

XMLを編集してレイアウトを変更するとエミュレータ上で例外が発生する

ADTでレイアウトを調整するためにXMLを直接編集していたら、レイアウトエディタ上では問題なく表示されているのにGenyMotion上で実行すると以下のエラーを吐いて実行できなかった。

03-31 13:34:34.416: W/dalvikvm(1475): threadid=1: thread exiting with uncaught exception (group=0xa4cefb20)
03-31 13:34:34.420: E/AndroidRuntime(1475): FATAL EXCEPTION: main
03-31 13:34:34.420: E/AndroidRuntime(1475): Process: com.example.mobiledatamanager, PID: 1475
03-31 13:34:34.420: E/AndroidRuntime(1475): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.mobiledatamanager/com.example.mobiledatamanager.MainActivity}: java.lang.ClassCastException: android.widget.TextView cannot be cast to android.widget.Button
03-31 13:34:34.420: E/AndroidRuntime(1475): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
03-31 13:34:34.420: E/AndroidRuntime(1475): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
03-31 13:34:34.420: E/AndroidRuntime(1475): at android.app.ActivityThread.access$800(ActivityThread.java:135)
03-31 13:34:34.420: E/AndroidRuntime(1475): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
03-31 13:34:34.420: E/AndroidRuntime(1475): at android.os.Handler.dispatchMessage(Handler.java:102)
03-31 13:34:34.420: E/AndroidRuntime(1475): at android.os.Looper.loop(Looper.java:136)
03-31 13:34:34.420: E/AndroidRuntime(1475): at android.app.ActivityThread.main(ActivityThread.java:5017)
03-31 13:34:34.420: E/AndroidRuntime(1475): at java.lang.reflect.Method.invokeNative(Native Method)
03-31 13:34:34.420: E/AndroidRuntime(1475): at java.lang.reflect.Method.invoke(Method.java:515)
03-31 13:34:34.420: E/AndroidRuntime(1475): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
03-31 13:34:34.420: E/AndroidRuntime(1475): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
03-31 13:34:34.420: E/AndroidRuntime(1475): at dalvik.system.NativeStart.main(Native Method)
03-31 13:34:34.420: E/AndroidRuntime(1475): Caused by: java.lang.ClassCastException: android.widget.TextView cannot be cast to android.widget.Button
03-31 13:34:34.420: E/AndroidRuntime(1475): at com.example.mobiledatamanager.MainActivity.onCreate(MainActivity.java:64)
03-31 13:34:34.420: E/AndroidRuntime(1475): at android.app.Activity.performCreate(Activity.java:5231)
03-31 13:34:34.420: E/AndroidRuntime(1475): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
03-31 13:34:34.420: E/AndroidRuntime(1475): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
03-31 13:34:34.420: E/AndroidRuntime(1475): ... 11 more
03-31 13:34:37.456: I/Process(1475): Sending signal. PID: 1475 SIG: 9
03-31 13:37:44.804: D/AndroidRuntime(1528): Shutting down VM


一度R.javaを削除して自動生成し直すと実行できるようになった。

どうもButtonやらTextViewやらの上下関係をXML内で入れ替える等大幅にXMLを書き換えてしまうと、自動生成されるR.javaが自動調整できずにおかしなことになるようだ。

UbuntuのChrome上にSynergy経由でクリップボードからペーストするとフリーズする

Ubuntu 12.04 (server) + WIndows7 (client) でSynergyを使っているのだけど、Windows7クリップボードにコピーしたテキストをUbuntuChrome上でペーストしようとすると、Chromeがフリーズする現象に悩まされている。Ctrl+vでもミドルクリックでも起こる。タブ切り替えは動くのだけど、テキスト選択やタブ閉じはできない。数分後忘れた頃にフリーズから復帰する。

Chromiumでも報告されていて、#62にWorkaroundが2つ提示されてた。

https://code.google.com/p/chromium/issues/detail?id=131863

  1. geditにペーストしてからChromeにペースト
  2. まずアドレスバーで一度ミドルクリックする。見た目何も起こらないように見えるけどクリップボードの状態は変化する。その後15秒〜1分以内に目的の場所でミドルクリックする。目的の場所がアドレスバーの場合は単純にアドレスバーで2回ミドルクリックする。

2.についてはミドルクリックとしか言及されてないけど、自分の場合はCtrl+vでも動作してると思う。

geditを常にスタンバっとくのもめんどいので、Workaround 2.を使おうと思っている。でもたまに間違ってやってしまうんだろうなー。フリーズさせてしまった時の絶望感は果てしないので早く直らないかな…

2014.9 追記

最新版のChromeでは直っているぽい。
ここ一ヶ月くらい、Linux - Windows間でクリップボードのやりとりができなくなったりすることもなくなっている。

ARM上でBoost::shared_ptrがリンクエラー

armでlibgnustl_shared.soをSTLとしてリンクし、boost_1_55_0でshared_ptrを使うと、undefined referenceのエラーが出る。AndroidGNU STLAndroid NDK標準のSTLと違って基本的にほぼx86用同等だと思っていたけど…と思っていたら以下に解決策があった。

https://legacy.madewithmarmalade.com/jp/node/52963

コンパイルするコードのどこかに、

namespace boost {
  void throw_exception( std::exception const & e ) { }
}

と書けばOK。自分のAndroid環境では上記URLに書いてあるBOOST_NO_EXCEPTIONSをdefineしなくてもOKだった。これでshared_ptrが使える。もちろん他のboostの便利機能splitとかlexical_castとかtrimとかも。

そもそもC++11でビルドすればstd::shared_ptrが使えるはずなんだけど、-std=c++0x 付けると::uint64_tがundefinedだのなんだのたくさんエラーが出てきた。g++ 4.6ではC++11の機能が全部カバーされてるわけではないようなので(下記URL)、とりあえず当面はC++11はDisableにしておく。

http://gcc.gnu.org/gcc-4.6/cxx0x_status.html

C++でBoost使わずに文字列を分解する

boost::splitを使うと文字列をデリミタで分解してコンテナに格納することができるのだけど、boostが無い環境で同等の機能が欲しくなったので書いてみた。find_first_of()とsubstr()を使う。

void split(std::vector<std::string> &v, const std::string &input_string, const std::string &delimiter)
{
  std::string::size_type index = input_string.find_first_of(delimiter);

  if (index != std::string::npos) {
    v.push_back(input_string.substr(0, index));
    split(v, input_string.substr(index + 1), delimiter);
  } else {
    v.push_back(input_string);
  }
}

int main(int argc, const char * argv[])
{
  std::string input_string, delimiter;
  std::vector<std::string> v;

  std::cout << "input string to split: ";
  std::cin >> input_string;

  std::cout << "specify delimiter: ";
  std::cin >> delimiter;

  split(v, input_string, delimiter);

  for (auto &s : v) {
    std::cout << s << std::endl;
  }

  return 0;
}


結果

input string to split: first,second,third,forth
specify delimiter: ,
first
second
third
forth


再帰で割りとシンプルに書けた。

追記 2014.10

実はのstd::getline()で普通にデリミタ指定ができる模様。無知を恥じます。


getlineはsplitに使える - Faith and Brave - C++で遊ぼう