普通すぎるエディタ「micro」

f:id:y_d:20160902012300p:plain

go言語(termbox-goではなくtcell)で実装されたmicroというターミナルベースのテキストエディタの version1.0 がリリースされたようで、試しにちょっとだけつかってみたのですが、なかなか使い心地がよいです。

というわけで(個人的に)使い心地が(いい意味で逆に)普通すぎるエディタ「micro」の紹介になります。

github.com

microの特徴

microはターミナルベースのエディタであるものの、マウス操作がサポートされていたり、GUIアプリケーション風のキーバインドが設定されていたりと、いたって普通なGUIテキストエディタを使っているかのように直感的な使い心地を実現しているのが最大の特徴だと思います。

  • いけてる特徴
  • 残念なところ
    • 日本語表示は問題なさそうだが、日本語入力すると挙動がおかしくなる
    • 使うターミナルによってちょっと動きがおかしいことが多々ある

多少残念なところもあるけど、 Nightly build があったりするようで、今後の改善に期待が持てそうです。

ダウンロード

  1. とりあえず使ってみるだけなら、ここのリリースページからダウンロード(macOSなら micro-1.0.1-osx.tar.gz )。
  2. ダウンロードしたら ~/Downloads/micro-1.0.1/micro にコマンドがあるはずなので、そのようにターミナル上で叩くとmicroエディタが起動する(macOSの場合)。
  3. ~/Downloads/micro-1.0.1/micro /path/to/file.txt のようにコマンドに続けてファイルパスを指定すればそのファイルが開かれる。

使い方

メモレベルだけど具体的な使い方は以下の通り。

基本操作

  1. 矢印キーもしくはマウスクリックでキャレット移動
  2. Shit+矢印キー もしくはマウスドラッグで領域選択
  3. マウスホイールで表示領域の移動(キャレットはそのまま)
  4. Vimの入力モードのようなものはなく、キーボード操作でそのままテキストが入力される
  5. esc で何かしらの入力待ち状態をキャンセル
  6. 終了したいときはCtrl-q 。編集内容を保存しなくて良ければ続けて y を入力で終了。

※マウスを使った操作を行う際は「マウスレポーティングを許可」する(macOSのターミナルの場合)

f:id:y_d:20160902011222g:plain

コピペ

  1. 下記のいずれかで領域を選択
    • Shif+矢印キー
    • Ctrl-a
    • マウスでテキストをドラッグ
  2. Ctrl-c でコピー ( Ctrl-x で切り取り)
  3. Ctrl-v で貼り付け

ヒストリー

  1. Ctrl-z で戻す
  2. Ctrl-y でやり直し

検索

  1. Ctrl-fFinding: と聞かれるので、検索したい文字を入力してEnter(正規表現も使える)
  2. Ctrl-n で次にマッチする箇所に移動
  3. Ctrl-p で前にマッチする箇所に移動
  4. esc で検索を抜ける

置換

  1. Ctrl-e でコマンド入力欄表示
  2. replace {{検索文字列}} {{置換文字列}} とうつ

例: replace "A" "B"

コマンド実行

  1. Ctrl-e でコマンド入力欄表示
  2. run {{コマンド}} とうつ

例: run ls

テーマの変更

  1. Ctrl-e でコマンド入力欄表示
  2. set colorscheme {{テーマ名}}

例: set colorscheme monokai

使えるテーマは今のところ下記がある

default
simple
solarized
solarized-tc
atom-dark-tc
monokai
gruvbox
zenburn
bubblegum

f:id:y_d:20160902011208g:plain

画面分割

  1. Ctrl-e でコマンド入力欄表示
  2. vsplit or hsplit を入力して Enter(既存ファイルを開くときは vsplit file.txtといった感じ)
  3. アクティブのパネルを切り替えるのは Ctrl-w もしくはアクティブにしたい領域をクリック
  4. Ctrl-q でアクティブ状態の分割パネルを閉じる
  5. 編集済みのタブを閉じる際は、yで編集内容破棄、nでキャンセル、sで保存(ファイル名入力)

※タブと組み合わせると、挙動がおかしくなる?

f:id:y_d:20160902011211g:plain

タブ

  1. Ctrl-t で新規タブ作成&新しいタブを表示 (画面上部にタブができる)
  2. Ctrl-¥ で次のタブに移動
  3. Ctrl-] で前のタブに移動
  4. 上部タブをクリックでもタブ移動可能
  5. Ctrl-q でタブを閉じる
  6. 編集済みのタブを閉じる際は、yで編集内容破棄、nでキャンセル、sで保存(ファイル名入力)

※画面分割と組み合わせると、挙動がおかしくなる?

f:id:y_d:20160902011204g:plain

ファイルオープン

  1. Ctrl-o 押下
  2. 編集中データがあればyで編集内容破棄、nでキャンセル、sで保存(ファイル名入力)
  3. File to open: と聞かれるのでファイル名を入力(絶対パス相対パスを入力。入力中にTab押下で入力補完が効く)

ファイル保存

  1. Ctrl-s 押下
  2. Filename: と聞かれるのでファイル名を入力(絶対パス相対パスを入力。入力中にTab押下で入力補完が効く)

行番号

  1. Ctrl-r で行番号表示、非表示切り替え

行番号に移動

  1. Ctrl-l の後に行番号入力で、その行に移動

タブサイズ変更

  1. Ctrl-e でコマンド入力欄表示
  2. set tabsize 4 ※4は例

※ファイルの拡張子ごとに設定することも可能らしい

ソフトタブ

※tabキー押下で、半角スペースを入力する設定

  1. Ctrl-e でコマンド入力欄表示
  2. set tabstospaces on で有効化
  3. set tabstospaces off で無効化

タブの可視化

  1. Ctrl-e でコマンド入力欄表示
  2. 例: set indentchar >

※設定を解除する方法がわからないが、 ~/.config/micro/setting.json を編集して indentchar" " を設定すると良さそう。

その他オプション変更

  1. Ctrl-e でコマンド入力欄表示
  2. set {{オプション名}} {{設定値}}
  3. ~/.config/micro/setting.json に設定が書き出される
  4. ファイルの拡張子ごとに設定することも可能らしい

詳しくは下記 https://github.com/zyedidia/micro/blob/master/runtime/help/options.md

その他キーバインディング

下記に詳しく書いていある https://github.com/zyedidia/micro/blob/master/runtime/help/keybindings.md

さいごに

以上のように、普通のGUIテキストエディタのように使えるので、学習コストが低いエディタだと思います。 機会があれば使ってみてはいかがでしょうか。

君はもう見たか!php.netの走る象を

なんとやくタイトルに倒置法を使ってみましたが、深い意味はありません。
というのはおいといて、

コアラのマーチには眉毛コアラがたまに入っていて、見つけるとちょっと嬉しいですが、php.netにもそんな遊びが仕掛けられているようです。
先日先輩から、php.netの右上のロゴが走る象になっている人が隣の席にいるという話をされ、気になったので調べてみました。

通常これが表示されているけど、これが走る象になっていたらしいです。
f:id:y_d:20140611231629p:plain

調査

htmlを読んでみると、この画像のURLは下記となっていて、phpのプログラムから画像を返す作りになっていました。
http://www.php.net/images/logo.php

ググってみたところ、どうやらソースは下記のようです。
https://github.com/php/web-php/blob/master/images/logo.php

このソースを読むとどうやら、およそ64回に1回の確率(実際にはもっと確率は低い)、さらに1日キャッシュが効くので64日に1回以下の確率といったところでしょうか。
私は走る象が表示されているところを見たことがありませんが、ちょくちょくphp.netは覗いているので、確率的に今までに走る象を見ていてもおかしくなさそうに思えます。といっても左上のロゴをまじまじと見ることはないので、もしかしたら見逃していただけでしょうか。

※とりあえず象の画像だけ見たい方はこちらでみれます
http://php.net/images/logos/elephpant-running-78x48.gif
f:id:y_d:20140611231910g:plain

実際に表示してみる

仕組みは分かったものの、どうしても実際に走る象が表示されているところを見てみたい気持ちが抑えられないので、無理やり表示してみようと思います。

手順:
f:id:y_d:20140611231303g:plain

  1. phpのロゴ画像URLに「?refresh」を付けたURLを何度か叩いて、走る象の画像を表示する。
  2. php.netを表示して、右上の画像URLもまた同じく「?refresh」をつける。

※URLは http://www.php.net/images/logo.php?refresh になる
php.netさん、リロード何度もしてごめんなさい

これで走る象の画像になりました!
f:id:y_d:20140611231347g:plain

いつかインチキなしで見てみたいです。

Gifアニメを作るChrome拡張Animated Gif Captureを公開しました

f:id:y_d:20140511200605p:plain

「Animated Gif Capture」というアニメーションGifを作るChrome拡張を公開しました。
Chromeに表示中のWebページをアニメーションGifに変換します。また、オプションページから設定を変更すると、デスクトップやChrome以外のウィンドウもアニメーションGifにすることが出来ます。

Chrome Web Storeに登録してあるので、ここからインストールできます。
Chrome Web Store - Animated Gif Capture - アニメーションGifキャプチャ

キャプチャ例

Flashもキャプチャできます。
http://demouth.net/sketch/016/ 以前私がAS3で作ったやつ
f:id:y_d:20140511224420g:plain


FlashのキャプチャできるのでVimeoでもYouTubeもいけます。
フレームレートを高めると滑らかなアニメーションGifになります。
※これは私のVimeo動画です。著作権違反にはお気をつけください
f:id:y_d:20140511225623g:plain


Chrome拡張ではありますが、Chrome以外のウィンドウや、デスクトップ全体のキャプチャも可能です。
これはフレームレートを落とし、撮影時間を長くして、Illustratorをキャプチャしています。
f:id:y_d:20140511225746g:plain

使い方

詳しい使い方はインストール後のオプションページに書いてありますので、インストール後に拡張アイコンを右クリックしてオプションページを表示してください。

あとYouTubeに動画をアップしてあるので、こっちを見ていただくとだいたいわかると思います。
個人的にChrome拡張を使う時一番心配なのは勝手に個人情報にアクセスしてWebにアップしたりしないかという事なのですが、この拡張はWebアクセスはしませんし余計な事は何もしません(当たり前だけど一応)。


How to use Animated Gif Capture - YouTube



以上がアプリの紹介になります。
以降、作った時の技術的な感想をだらだらと書きます。

技術的なこと

Chrome ExtensionはJavaScriptなので、インストールすればソース見られますが、一応Githubにもソースを公開してます。リファクタリングの時間が取れずにソース汚くなっていますが、ソースを公開することで誰かのお役に立てれば幸いです。
demouth/AnimatedGifCapture

基本的に Chrome Extension APIs にすべて必要な情報はあるので、こちらを見ます。

この拡張はキャプチャする方法を3種類の中から選んで設定出来ます。
今回使ったキャプチャを出来るAPIは下記です(あまり確認してないけど、キャプチャ出来るAPIは多分これ以外には無いと思う)。

  • chrome.tabs.captureVisibleTab(integer windowId, types.ImageDetails options, function callback)
  • chrome.tabCapture.capture(object options, function callback)
  • chrome.desktopCapture.chooseDesktopMedia(array of DesktopCaptureSourceType sources, tabs.Tab targetTab, function callback)

tabCaptureはChromeのバージョン31、desktopCaptureは34から使えるようになったようなのでなかなかタイムリーでした。

chrome.tabs.captureVisibleTab()

chrome.tabs.captureVisibleTab()を使うと、コールバックで画像のdataURLが返ってきます。
このAPIは一瞬ではありますがブラウザが固まるのが難点です。アニメーションGifを作るために何度もキャプチャするとChromeのレスポンスが悪くなります。
あと、このAPIで返ってくる画像には、マウスカーソルやセレクトボックスの中身などは映りこみません。

chrome.tabCapture.capture()

chrome.tabCapture.capture()を使うとコールバックにタブの内容を動画と音声で返すLocalMediaStreamオブジェクトを返します。これを使ってタブの中身のキャプチャを撮ります。これをURL.createObjectURL();でvideo要素のsrcに入れると動画を再生できます。あとはこれをcanvas要素を使ってcontext2dにdrawImage()すれば画像に変換出来ます。

var video = document.createElement('video');
video.src = window.URL.createObjectURL(stream);
video.addEventListener('canplay', this.handler);
video.play();

video.srcにstreamを入れると動画の再生が始まるのかと最初思っていましたが、play()しないとvideoに表示される内容は更新されませんでした。後から考えると当たり前かと思いましたが。
あと、タブの動画の再生が始まるまで多少タイムラグがあるようで、canplayイベントの後でないと真っ暗な画像になってしまいました。canplayイベントでなくてもいいかも知れません。

キャプチャする動画のサイズをchrome.tabCapture.capture()の引数に渡すと、その通りの画像サイズでキャプチャしてくれます。タブの中身をキャプチャしたいのでタブのサイズを取得してから渡します。タブのサイズよりも大きなサイズを指定するとタブよりも大きい部分は黒く塗りつぶされた動画が返ってきます。
なお、このAPIはタブのサイズが奇数になると、偶数に丸められ、同時に動画の品質が落ちるようです。この問題をどうにかしようと頑張りましたがどうにもなりませんでした。何か情報をお持ちの方は教えて頂ければと思います。

ちなみにcanvas要素のtoDataURL()メソッドですが、これはtoDataURL('image/webp')のように画像フォーマットを指定できますが、jpegが一番早かったです。
計測結果メモっておけばよかったのですが、残していないので、参考までにざっくりとした感覚値を残しておきます。おそらく画像の内容によっても変換時間は変わると思うのであくまで参考ということで。

  • toDataURL('image/webp') -> ダントツで遅い
  • toDataURL('image/png') -> 速い gifと変わらない
  • toDataURL('image/gif') -> 速い pngと変わらない
  • toDataURL('image/jpeg',1) -> 1番速いけど、png,gifとそんなに変わらない

あと、このAPIで返ってくる動画には、マウスカーソルやセレクトボックスの中身などは映りこみません。

chrome.desktopCapture.chooseDesktopMedia()

desktopCapture APIchrome.tabCapture.capture()と似ていて、動画でキャプチャするAPIです。
tabCaptureと違うのは、chooseDesktopMedia()を呼ぶとウィンドウやデスクトップを選択する為の下記のウィンドウを表示します。
f:id:y_d:20140511212849p:plain
これを使ってウィンドウやデスクトップをユーザーが選択すると、コールバックにstreamIdが返ってきます。
このstreamIdを使ってnavigator.webkitGetUserMedia()に渡すと、tabCaptureと同じようにstreamを取得できます(もしかしてwebkitのプリフィックスいらないかも)。あとはtabCaptureと同じ要領です。下記のような感じ。

    chrome.desktopCapture.chooseDesktopMedia(
      ["screen", "window"] , //ウィンドウとデスクトップどちらも
      function(streamId) {
        if (!streamId) { /* error */ }
        
        navigator.webkitGetUserMedia(
          {
            audio: false,
            video: {
              mandatory: {
                chromeMediaSource: 'desktop',
                chromeMediaSourceId: streamId,
                minWidth: 10,
                maxWidth: 1920,
                minHeight: 10,
                maxHeight: 1080
              }
            }
          },
          function(stream){
            var video = document.createElement('video');
            video.src = window.URL.createObjectURL(stream);
            video.play();
          }
        );
      }
    );

あと、このAPIで返ってくる動画にはマウスカーソルやセレクトボックスの中身は映りこみます。

アニメーションGIFの変換ライブラリ

antimatter15/jsgif を使いました。
※bytearray.orgのAS3の移植!

さすがにGIF画像を作るのは処理時間がかかります。このライブラリの中でWebWorkerを使っているので対象早くなっているかもしれませんが、さすがに画像サイズやアニメーション枚数が多いと数十秒間処理時間がかかります。WebWorkerについてあまり調べていませんが、ライブラリの中を少し覗いてみたところ1スレッドにGIF生成の処理を流し込んでいるようなのでこの辺を書き換えればマルチコアのCPUの時に多少早くなるのかも知れません(たぶん)。

jsgifを使うとgifのdataURLを取得できます。
しかしdataURLは大変重く、ファイルサイズが大きくなった場合ブラウザが死んでしまうこともあるので、バイナリに変換してダウンロードさせています。

http://blog.agektmr.com/2013/09/canvas-png-blob.html
こちらを参考に下記のようなコードでBlobに変換し、ブラウザにダウンロードさせています。

// 空の Uint8Array ビューを作る
var buffer = new Uint8Array(rawData.length);
// Uint8Array ビューに 1 バイトずつ値を埋める
for (var i = 0; i < rawData.length; i++) {
  buffer[i] = rawData.charCodeAt(i);
}
// Uint8Array ビューのバッファーを抜き出し、それを元に Blob を作る
var blob = new Blob([buffer.buffer], {type: 'image/gif'});

var a = document.createElement('A');
a.href = window.URL.createObjectURL(blob);
a.setAttribute('download', filename);
a.click();

Chrome拡張の公開にあたって

f:id:y_d:20140511214654p:plain

Chrome拡張の公開

Chrome拡張をChromeウェブストアに公開する手順は下記を参考にしました。
アイコンの作り方などが紹介されていました(あまり読んでいない)。
https://developer.chrome.com/webstore/publish

デベロッパー ダッシュボードでは言語毎に説明文や画像を設定したり出来ます。

画像について

アプリの画像は下記があると良いです。
試していませんが、おそらく最低限アイコン用の128x128の画像と、ストア用のスクリーンショットが1枚あればいいと思います。

  • アプリ内のアイコン画像 16,19,32,48,128の正方形。manifest.jsonで設定する。
  • ストア用のアイコン画像 128x128である必要がありますが、96x96のアイコンを作って、上下左右に16pxの透明な領域をつける必要があるそうです。
  • ストア用のスクリーンショット1280x800 または 640x400を最大5枚、もしくはYouTube動画。
  • ストア用のプロモーションタイル画像 440x280,920x680,1400x560を1枚ずつ。



以上です。