forEachでインデックスを使いたい

配列をすべて舐めるような処理をする時はforEachを使うけど、この時indexを使うことができない

let array = ["a", "b", "c", "d"]
array.forEach { string in
  debugPrint(string)
}

そんなときはArray#enumerated() を使えばindexも使うことができる

let array = ["a", "b", "c", "d"]
array.enumerated().forEach({ index, string in
    debugPrint("\(index): \(string)")
})

// "0: a"
// "1: b"
// "2: c"
// "3: d"

UITextFieldで入力文字を制限する

UITextFieldDelegate を使う

textField(_:shouldChangeCharactersIn:replacementString:) - UITextFieldDelegate | Apple Developer Documentation

例えばIntにパースできる値だけにしたければ、次のようなコードになる

class ViewController: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        return Int(string) != nil
    }
}

ただ、このdelegateメソッドの引数である string は入力された値だけなので、UITextFieldに入る値を数値だけに制限したい場合は、これだけでは不十分。 range 引数に、UITextField のキャレットなどの文字選択位置が渡されるので、それで置換してあげればいい。

class ViewController: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if let currentString = textField.text, let _range = Range(range, in: currentString) {
            let newString = currentString.replacingCharacters(in: _range, with: string)
            return Int(newString) != nil
        } else {
            return false
        }
    }
}

コマンドラインの実行結果を監視する

コマンドラインの実行結果を監視したいんだと

  • watchだと履歴が見れない
  • whileだと全部垂れ流しで全部のデータを見るのがだるい

コマンドラインの実行結果が変わったときだけに表示してほしい〜〜って思ったんだけど、watchもwhileも微妙だったのでチョコチョコかいた そういうコマンドありそうなんだけど知らないなあ

while do
  sleep 1
  c=`date +"%Y-%m-%d %H:%M"`
  if [ $c != $d ]; then
    date
    echo $c
    echo '-------------------------------------------------------------------'
  fi
  d=$c
done

こんな感じに標準出力が変わったときに表示される

2018年 3月13日 火曜日 07時40分00秒 JST
2018-03-13 07:40
-------------------------------------------------------------------
2018年 3月13日 火曜日 07時41分00秒 JST
2018-03-13 07:41
-------------------------------------------------------------------
2018年 3月13日 火曜日 07時42分00秒 JST
2018-03-13 07:42
-------------------------------------------------------------------
2018年 3月13日 火曜日 07時43分00秒 JST
2018-03-13 07:43
-------------------------------------------------------------------
2018年 3月13日 火曜日 07時44分00秒 JST
2018-03-13 07:44
-------------------------------------------------------------------

ImageMagickを使って画像の種類を判別する

ImageMagickidentifyコマンドを使って画像の判定ができる。

拡張子はJPGと言いながら実はPNGだった例

$ identify -format %m ./path/to/image-file.jpg
PNG

特定のディレクトリ以下のすべてのファイルの種類を表示するならこんな感じ

for imagefile in $(find ./ -name *.jpg); do
  format=$(identify -format %m $imagefile)
  echo "${format} ${imagefile}"
done

jpg以外のファイルを探すならこんな感じ

for imagefile in $(find ./ -name *.jpg); do
  format=$(identify -format %m $imagefile)
  if [ $format != 'JPEG' ]; then
    echo "${format} ${imagefile}"
  fi
done

magic numberの確認

例えばカメラのRAWファイルの場合、ImageMagickはデフォルトで判別することはできない*1 どういう画像なのかはたいていマジクナンバーを見れば分かる

$ od -c ./path/to/raw-file.jpg | head -4
0000000    I   I   R   O  \b  \0  \0  \0 027  \0  \0 001 004  \0 001  \0
0000020   \0  \0 360 017  \0  \0 001 001 004  \0 001  \0  \0  \0 340  \v
0000040   \0  \0 002 001 003  \0 001  \0  \0  \0 020  \0  \0  \0 003 001
0000060  003  \0 001  \0  \0  \0 001  \0  \0  \0 006 001 003  \0 001  \0

IIRO magic number で検索するとOlympusのORFファイルだということが分かった。

参考

*1:ufrawをインストールすれば扱うことができる

Androidプロジェクトをシュッと開く

Androidプロジェクトを開く時、Android Studioのメニューから開くのはとてもめんどうくさい。File -> Open... と選択してからプロジェクトの在り処を選択する必要がある。めんどうだ。マウス操作めんどう。

実はコマンドラインからプロジェクトをAndroid Studioで開くコマンドラインツールがAndroid Studioに備わっている。なんかしらのプロジェクトを開いている状態でTools -> Create Command-line Launcher... を選んでコマンドを作るだけだ。

f:id:tomorrowkey:20160731142409p:plain

コマンドが作られると、プロジェクトがカレントディレクトリの状態で次のコマンドを実行するだけでプロジェクトを開くことができる。

studio .

楽ちん〜。

この機能はすべてのJetBrains系のIDEについているみたいなので、例えばRubyMineとかでも使えます。

さらにAlfredを使っている人は次のworkflowもオススメ

github.com

studioと入力すると開くプロジェクトがでてくるので素早くプロジェクトを開くことができる。

f:id:tomorrowkey:20160731143152p:plain

ここにでてくるプロジェクトはAndroid Studioで開いたことがあるものだけなので注意が必要。

adb-pecoを書き直しました

複数デバイスが接続されていたときにデバイスを選択する支援をしてくれる adb-peco ですが、この度、Rubyでコードを書き直しました。 通常だとmore than one device/emulator と出力されるようなシチュエーションでも、こんな風にコマンド実行時にデバイス選択することができます。

f:id:tomorrowkey:20160731134935g:plain

書き直したことにより次の2つの改善がなされました。

  • インストールの簡素化
  • バイス指定の必要のないコマンドではデバイス指定なしに

インストールの簡素化

Ruby Gemで作っているためインストールがコマンド1つで完結するようになりました。

gem install adb-peco

バイス指定の必要のないコマンドではデバイス指定なしに

以前のshell版ではdeviceskill-serverなどでもデバイス指定が必要でした。これらのコマンドでは本来デバイス指定は必要ないので、なくしました。ホワイトリスト形式で除外しているので、デバイス指定が必要ないコマンドが他にありましたらissue立てて貰えると対応します。

最後に

ソースコードGitHubで公開していますので、うまく動かないなどありましたらissue立ててもらえると助かります。

github.com