(追記:2013-11-01) DirFriendのバージョンアップについての記事を書きました。

あなたはファイルシステムに美を見るか?


プロジェクトにおけるディレクトリ構造をさっと把握したいという欲求があります。そういうときは通常treeします。

% bundle gem gem_project -bt
% tree gem_project
gem_project
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── bin
│   └── gem_project
├── gem_project.gemspec
├── lib
│   ├── gem_project
│   │   └── version.rb
│   └── gem_project.rb
└── spec
    ├── gem_project_spec.rb
    └── spec_helper.rb

4 directories, 10 files

極めて簡易ですが色気がありません。プレゼンに使うにはちょっと躊躇します。プレゼンしませんが。

一方で前回の記事で示したように、Graphvizを使えばディレクトリ構造を美しく視覚化することができます。

Rubyのソースディレクトリも視覚化してみる

しかしそのためには相応の手間が掛かります。

どうしたらいいでしょうか。もっと簡単に美しくプロジェクトをビジュアライズする方法はないのでしょうか。


DirFriendがあります。」



そんなわけで…

DirFriendというディレクトリ構造を簡単に視覚化できるツールを作りましたので紹介します:-)

dir_friend | RubyGems.org | your community gem host

melborne/dir_friend

なお、DirFriendで生成されるDOTファイルを見るにはGraphvizが必要です。

Download. | Graphviz - Graph Visualization Software

対象Rubyバージョンは>= 2.0.0です。最新のMac OS(Mavericks)を使っているならgem install dir_friendで準備は完了です。

DirFriendのターミナルでの使い方

DirFriendにはコマンドdir_friendが用意されています。早速使ってみます。引数なしで実行するとヘルプが表示されます。

% dir_friend
DirFriend is a tool for visualizing file directory.
Commands:
  dir_friend dot PATH        # Create a graphviz dot file for PATH
  dir_friend help [COMMAND]  # Describe available commands or one specific command
  dir_friend info PATH       # Show PATH info
  dir_friend version         # Show DirFriend version

プロジェクトのディレクトリでinfoすると簡単な情報が出力されます。

% dir_friend info gem_project
{:directories=>4, :files=>10, :depth=>3}

何の役にも立たないので、次にdotしてみます。

% dir_friend dot gem_project
Dot file created: `a.dot`

カレントディレクトリにa.dotというDOTファイルが生成されました。開いてみます。

% open a.dot

Graphvizが起動してそのWindowに以下が表示されます。

(追記:version0.0.4よりMac OSでは自動でGraphvizが起動するようになりました。)

dir_friend noshadow

dotサブコマンドは色々なオプションを取れます。まずはヘルプで確認します。

% dir_friend help dot
Usage:
  dir_friend dot PATH

Options:
  -l, [--layout=LAYOUT]
  -c, [--colorscheme=COLORSCHEME]
      [--dir-shape=DIR_SHAPE]
      [--file-shape=FILE_SHAPE]
  -g, [--global=GLOBAL]
  -n, [--nodes=NODES]
  -e, [--edges=EDGES]
  -s, [--save=SAVE]
                                   # Default: a
  -d, [--depth=DEPTH]
                                   # Default: 9
  -o, [--with-open]
                                   # Default: true

Description:
  ex.

  `dir_friend dot path/ -l fdp -c blues, -e "arrowhead:none"`

  `dir_friend dot path/ -c greens -g "bgcolor:azure,rankdir:LR,splines:ortho"`

まずは--colorschemeオプションで色を付けてみます。

% dir_friend dot gem_project -c blues
Dot file created: `a.dot`

Alt title noshadow

ディレクトリの深さに応じて色がグラデーションします。colorschemeにセットできる色は以下で確認できます。

Color Names | Graphviz - Graph Visualization Software

このとき色数を表す末尾の数字を省略するとDirFriend側でよしなに処理します。DirFriendと一緒にインストールされるGvizのコマンドを使っても色を知ることができます。

% gviz man color_schemes
Color schemes:
  accent, blues, brbg, bugn, bupu, dark, gnbu, greens,
  greys, oranges, orrd, paired, pastel, piyg, pubu,
  pubugn, puor, purd, purples, rdbu, rdgy, rdpu, rdylbu,
  rdylgn, reds, set, spectral, ylgn, ylorbr, ylorrd

赤系の色を使ってみます。

% dir_friend dot gem_project -c ylorrd
Dot file created: `a.dot`

Alt title noshadow

ylorrdはyellow-redの略ですね。


他のオプションも使ってみます。

% dir_friend dot gem_project -c greens -l fdp --dir_shape box -g "bgcolor:azure" -e "arrowhead:none,color:violet"
Dot file created: `a.dot`

–global, –edges, –nodesのオプションは属性名と値を:で結合して渡します。複数ある場合は,で区切ります。

出力です。

Alt title noshadow

もう一つ。

% dir_friend dot gem_project -c purd -g "rankdir:LR,splines:ortho" -e "color:violet" --dir_shape diamond --file_shape egg
Dot file created: `a.dot`

rankdir:LRはグラフの向きをLeft->Rightにし、splines:orthoはエッジのカーブを直交(orthogonal)にします。Graphvizで指定可能な属性は以下を参考にします。

attrs | Graphviz - Graph Visualization Software

出力です。

Alt title noshadow

Rubyスクリプトでの使い方

次にスクリプトとしての使い方を見ます。ここでは先ほどのgem_projectディレクトリでirbします。

dir_friendをrequireしてDirFriend::D.newでディレクトリオブジェクトを生成します。

/gem_project% irb -rdir_friend
IRB on Ruby2.0.0
>> d = DirFriend::D.new('.')
>> d.class.instance_methods(false) #=> [:entries, :each, :info, :up, :down, :depth, :to_s, :to_dot]

このオブジェクトに対し、entries, each, info, up, down, to_dotといったメソッドが使えます。

info, entriesは説明は不要ですね。

>> d.info #=> {:directories=>4, :files=>10, :depth=>3}
>> puts d.entries
D: bin
F: gem_project.gemspec
F: Gemfile
D: lib
F: LICENSE.txt
F: Rakefile
F: README.md
D: spec           #=> nil

各エントリはディレクトリDのインスタンスまたはファイルFのインスタンスです。よって一応それぞれが固有の情報を持っています。

>> bin = d.entries.first
>> bin.class #=> DirFriend::D
>> bin.directory? #=> true
>> bin.size #=> 102
>>
>> gemspec = d.entries[1]
>> gemspec.class #=> DirFriend::F
>> gemspec.file? #=> true
>> gemspec.info #=> {:mode=>33188, :nlink=>1, :uid=>501, :gid=>20, :size=>869, :mtime=>2013-10-28 18:12:56 +0900}

eachは対象ディレクトリ以下のすべてのファイルおよびディレクトリをトラバースします。Enumerableモジュールをincludeしているので、map, selectなどの便利なメソッドがディレクトリエントリに対して使えます。

>> d.map {|ent| "%d:%s" % [ent.size, ent.name]}
=> ["102:bin", "43:gem_project", "869:gem_project.gemspec", "96:Gemfile", "136:lib", "102:gem_project", "42:version.rb", "80:gem_project.rb", "1064:LICENSE.txt", "117:Rakefile", "508:README.md", "136:spec", "206:gem_project_spec.rb", "81:spec_helper.rb"]
>> puts d.select {|ent| ent.file? }
F: gem_project
F: gem_project.gemspec
F: Gemfile
F: version.rb
F: gem_project.rb
F: LICENSE.txt
F: Rakefile
F: README.md
F: gem_project_spec.rb
F: spec_helper.rb                   #=> nil

up, downはディレクトリの階層を移動します。

>> lib = d.down('lib')
>> lib.info #=> {:directories=>1, :files=>2, :depth=>2}
>> puts lib.entries
D: gem_project
F: gem_project.rb   #=> nil

で、to_dotです。to_dotは基本的にGvizのオブジェクトを返します。Gvizオブジェクトはputsすると生成されたDOTデータを吐きます。

>> d.to_dot.class #=> Gviz
>> puts d.to_dot #=> nil
digraph G {
  layout="dot";
  866200300794894346[label="bin",shape="ellipse",color="3",fontcolor="black"];
  -1429329569930946693[label="gem_project.gemspec",shape="ellipse",color="3",fontcolor="black"];
  2115984733485499187[label="Gemfile",shape="ellipse",color="3",fontcolor="black"];
  -3614298417482850489[label="lib",shape="ellipse",color="3",fontcolor="black"];
  -3184207857630325133[label="LICENSE.txt",shape="ellipse",color="3",fontcolor="black"];
  -4419621440078560366[label="Rakefile",shape="ellipse",color="3",fontcolor="black"];
  -4122678336619934219[label="README.md",shape="ellipse",color="3",fontcolor="black"];
  3938812965865281884[label="spec",shape="ellipse",color="3",fontcolor="black"];
  -836275752370073350[label="gem_project",shape="ellipse",color="4",fontcolor="black"];
  1988668566619024527[label="gem_project",shape="ellipse",color="2",fontcolor="black"];
  -1001180075471808653[label="gem_project",shape="ellipse",color="2",fontcolor="black"];
  3934351981608848895[label="gem_project.rb",shape="ellipse",color="2",fontcolor="black"];
  2453083216909575357[label="version.rb",shape="ellipse",color="1",fontcolor="black"];
  2899348101810456306[label="gem_project_spec.rb",shape="ellipse",color="2",fontcolor="black"];
  3060308287118039450[label="spec_helper.rb",shape="ellipse",color="2",fontcolor="black"];
  -836275752370073350 -> 866200300794894346;
  -836275752370073350 -> -1429329569930946693;
  -836275752370073350 -> 2115984733485499187;
  -836275752370073350 -> -3614298417482850489;
  -836275752370073350 -> -3184207857630325133;
  -836275752370073350 -> -4419621440078560366;
  -836275752370073350 -> -4122678336619934219;
  -836275752370073350 -> 3938812965865281884;
  866200300794894346 -> 1988668566619024527;
  -3614298417482850489 -> -1001180075471808653;
  -3614298417482850489 -> 3934351981608848895;
  -1001180075471808653 -> 2453083216909575357;
  3938812965865281884 -> 2899348101810456306;
  3938812965865281884 -> 3060308287118039450;
}

ファイルに保存したい場合はsaveします。

>> d.to_dot.save(:mydotfile) #=> nil

to_dotは先程の例のようにオプションを取れます。オプションはハッシュで渡します。

Mac限定の機能として、open => trueを渡すとtempfileを生成してGraphvizを自動で起動するといったものがあります。

>> d.to_dot open:true
Graphviz opened tempfile: /var/folders/sk/9h0z77c10g16n_vc0khd_chr0000gn/T/dirfriend20131028-72725-aa866a.dot
=> nil

dir_friend noshadow

残念がらこの機能はコマンドでは実現できていません(泣)help me.

追記:help meと書いたら@rosylillyさんがプルリクで助けてくれました。これによりMac限定ですが、dotコマンドにおいて生成したDotファイルは自動でオープンされるようになりました。スバラシイ!

Add a ‘with_open’ option to a ‘dot’ subcommand by rosylilly · Pull Request #1 · melborne/dir_friend

説明は以上です。

あなたのプロジェクトもDirFriendで視覚化してみませんか?


(追記:2013-10-29) 対象Rubyバージョンなどについて記述を追加しました。

(追記:2013-10-29) MacでDotファイルを自動オープンする記述について追加しました。

(追記:2014-3-3) Gvizについてのまとめ頁を作りました。

Gvizの目次 - Rubyの世界からGraphvizの世界にこんにちは!



=== Ruby関連電子書籍100円で好評発売中! ===

M’ELBORNE BOOKS

ruby_object ruby_tutorial ruby_trivia



blog comments powered by Disqus
ruby_pack8

100円〜で好評発売中!
M'ELBORNE BOOKS