Subscribed unsubscribe Subscribe Subscribe

枕を欹てて聴く

香炉峰の雪は簾を撥げて看る

Goでtree

面白そうなのでGoでとりあえずtree command(色なし版)書いてみた.
なぜtreeなのかはちょっとわかりません.
channelも使えて満足です. goroutineもとってつけたように使っています.
http://gist.github.com/231953

package main

import (
  "fmt";
  "flag";
  "path";
  "io";
  "os";
  "container/vector";
)

type Walker struct {
  Floor int;
  List *vector.Vector;
  Out chan string;
}

type Node struct {
  Floor int;
  Last bool;
  Name string;
}

func (w *Walker) VisitDir(p string, d *os.Dir, last bool) bool {
  _, fstr := path.Split(p);
  w.Draw(&Node{w.Floor, last, fstr});
  w.Floor++;
  w.List.Push(last);
  return true;
}

func (w *Walker) VisitFile(p string, d *os.Dir, last bool) {
  _, fstr := path.Split(p);
  w.Draw(&Node{w.Floor, last, fstr});
}

func (w *Walker) Draw(n *Node) {
  for i := 0; i < n.Floor; i++ {
    if w.List.At(i).(bool) {
      w.Out<-"   ";
    } else {
      w.Out<-"|  ";
    }
  }
  if n.Last {
    w.Out<-("`-- "+n.Name+"\n");
  } else {
    w.Out<-("|-- "+n.Name+"\n");
  }
}

func walk(p string, d *os.Dir, w *Walker, last bool) {
  if !d.IsDirectory() {
    w.VisitFile(p, d, last);
    return;
  }

  if !w.VisitDir(p, d, last) {
    return;
  }

  list, _ := io.ReadDir(p);
  lastIndex := len(list)-1;
  for i, e := range(list) {
    walk(path.Join(p, e.Name), e, w, (i == lastIndex));
  }
  w.List.Pop();
  w.Floor--;
}

func walker(root string, w *Walker) {
  d, err := os.Lstat(root);
  if err != nil {
    return;
  }
  walk(root, d, w, true);
  w.Out <- "\n";
}

func start() {
  out := make(chan string);
  go func() {
    for {
      fmt.Print(<-out);
    }
  }();
  walker(flag.Arg(0), &Walker{0, vector.New(0), out});
}

func main() {
  flag.Parse();
  if flag.NArg() > 0 {
    start();
  } else {
    fmt.Println("usage:\n  tree [directory]");
  }
}

これをgoのinstallされている環境で

8g tree.go
8l -o tree tree.8
./tree <DIR>

でdirectoryをtree表示します.
例えば,

./tree ~/work/go > out,txt

でこんな感じで表示されました.

`-- go
   |-- cat
   |  |-- 8.out
   |  |-- cat.8
   |  |-- cat.go
   |  |-- file.8
   |  `-- file.go
   |-- cat_rot
   |  |-- 8.out
   |  |-- cat.go
   |  |-- cat_rot13.8
   |  |-- cat_rot13.go
   |  |-- file.8
   |  `-- file.go
   |-- echo
   |  `-- echo.go
   |-- fib
   |  |-- 8.out
   |  |-- fib.8
   |  `-- fib.go
   |-- file.go
   |-- fizzbuzz
   |  |-- 8.out
   |  |-- fizzbuzz.8
   |  `-- fizzbuzz.go
   |-- hello
   |  |-- 8.out
   |  |-- hello.8
   |  `-- hello.go
   |-- ls
   |  `-- ls.go
   |-- print
   |  |-- 8.out
   |  |-- print.8
   |  `-- print.go
   |-- sieve
   |  |-- 8.out
   |  |-- sieve.8
   |  |-- sieve.go
   |  |-- sieve1.8
   |  `-- sieve1.go
   |-- test
   `-- tree
      |-- o.txt
      |-- tree
      |-- tree.8
      `-- tree.go

みたいになります. tutorialを律儀にやったのがもろばれです.
Go面白い! はじめNative CodeをはくっていうのでてっきりC++みたいなメモリ管理かと思いきや, GC乗っててびっくりしました.

Goは名前がバッティングしているらしく(他の言語と), Issueで問題になっているみたいですが, 実際Issueのなかでそれが一番盛り上がっています.
Issue 9 - go - I have already used the name for *MY* programming language - The Go Programming Language - Google Project Hosting

個人的にはgoo, giggity giggity goo, go2 がお気に入りです(このやっつけ感).

Remove all ads