mizdra's blog

ぽよぐらみんぐ

夏のCLI commandsものまね大会 ~ls編~

「そこは〇〇では?」、「ここはこうしたほうがいいんじゃない?」等の優しいマサカリ?は大歓迎です。よろしくお願いします。

仕様

  • ls <dir>を真似る
  • オプションは-a, -Fに対応する
  • 複合オプション-aFに対応する

リポジトリ

github.com

使い方

$ npm install -g mizdra/node-ls
$ node-ls --help

  Usage: node-ls [options] <dir>

  Options:

    -h, --help      output usage information
    -V, --version   output the version number
    -a, --all       include hidden files and directories
    -F, --classify  classify files and directories

$ node-ls -aF sample-dir
./
../
.hidden-dir
.hidden-file
fifo|
sock=
sock-symlink@
visible-dir/
visible-dir-symlink@
visible-file
visible-file-symlink@
x-666-file
x-677-file*
x-767-file*
x-776-file*
x-777-file*
x-777-file-symlink@

感想

  • lsの挙動についてちょっとだけ詳しくなった
  • Unixファイルシステムについてちょっとだけ詳しくなった
  • tj/commanderjsがとにかく便利
    • オプションとか引数を良い感じにパースしてくれる
    • しかしAPI documentationがあまりにも不親切
      • 引数の型が書いてないAPIがある
      • descriptionが分かりにくい
      • サンプルコードがないAPIがある
      • 酷いものに至っては、分かりにくいdescriptionとそのAPIを実装するメソッドのソースコードが貼られただけ
      • 仕様がきちんと決まってないとある挙動がバグなのか判別することすらできないと思うんだけど、どうしてこうなってるんだろう…
      • 散々愚痴を書いてますがtj/commanderjsそのものは素晴らしいライブラリだと思ってます!
  • Array#{filter,map}を使ったら良い感じに書けた
    • 複合オプション-aFにも対応できた
    • Arrayすごい
      • こういうのってStreamって言うんだっけ
  • コマンドのパースをbin/command.js(このプロジェクトではbin/node-ls.js)に集約してみた
    • lib配下はCLI非依存の処理、bin配下はCLI依存の処理に分けたら綺麗そうだなと思ってやってみた
    • 個人的には割りと綺麗にみえる
    • 他のプロジェクトを参考にしつつbin/command.jsの設計についてもう少し考えてみたい
    • 参考になりそうなプロジェクト: babel-cli, webpack/webpack, gulpjs/gulp, mysticatea/npm-run-all, mochajs/mocha, etc.
  • エラーを処理してない(面倒だった)
    • 次回以降はちゃんとエラー処理したい
  • テストを書いてない(面倒だった)
  • 同期メソッド(fs.*Sync)を使って書くと楽だった
    • 最初は非同期メソッドを使って書いていた
    • 1ファイルごとに1つの非同期メソッドを呼び出す === 複数の処理が並列で実行される
    • 制御が難しくなってきた
    • デバッグも難しくなってきた
    • つらくなってきた
    • だいぶ書いてから気づいたけどArray#{filter, map}に上手く非同期メソッドを埋め込めない
      • [..].filter(file => asyncFunc(file)).map(..)できない
      • async/awaitがあれば綺麗に書けそう…な気がする (今回はNode.js v6.4.0を使用しているのでトランスパイラ等を使わない限りasync/await使えません!)
        • イメージ: [..].filter(file => await asyncFunc(file)).map(..)
        • でもこれArray#filterがパラレルじゃないからawaitで1ファイルについて処理している時に他のファイルが待たされることになる。つまり駄目
    • 非同期って難しい…
    • 他のライブラリを組み合わせて上手くできたりしないかな。要調査
      • node-ls-parallelの機運
    • 結果: 非同期メソッドやめた
  • 良い感じにモジュール化できた(個人の感想)
    • ES6 Modulesスタイルで書いたことはあったけどCommonJSスタイルはまだだった
    • ES6 Modulesスタイルと殆ど変わらなかった
    • 綺麗にモジュール化できると気持ちいい
      • 久々にちゃんとしたコードを書いた気がする
    • 正直モジュール化とかあまり詳しくなくてオレオレで書いているのでちゃんと勉強したい
  • インストールのチェックはnpm pack, npm install ./*.tgzでやった

終わりに

コーディング途中の僕のツイートです。

次回は多分catをやります。(難易度的にcatを一番最初にやるべきだった気がする)