2019年2月18日月曜日

fff: Fuzzy Finding Filer

go-fuzzyfinderという素敵なライブラリが公開されたので、ファイラを作ってみた。 以前作ったファイラにソート機能を付けた感じ。
package main
import (
  "flag"
  "fmt"
  "log"
  "os/exec"
  "regexp"
  "strings"
  fuzzyfinder "github.com/ktr0731/go-fuzzyfinder"
  // termbox "github.com/nsf/termbox-go"
)

var (
  cmdOpt = flag.String("cmd", "ls -al --time-style=long-iso", "command for filtering")
)

func main() {
  var arr [][]string
  var customCmds = [][]string{
    []string{"sort    by time",  "ls -alt --time-style=long-iso"},
    []string{"reverse by time",  "ls -altr --time-style=long-iso"},
    []string{"sort    by ctime", "ls -alc --time-style=long-iso"},
    []string{"reverse by ctime", "ls -alcr --time-style=long-iso"},
    []string{"sort    by atime", "ls -alu --time-style=long-iso"},
    []string{"reverse by atime", "ls -alur --time-style=long-iso"},
    []string{"sort    by size",  "ls -alS --time-style=long-iso"},
    []string{"reverse by size",  "ls -alSr --time-style=long-iso"},
  }

  flag.Parse()
  cmds := strings.Split(*cmdOpt, " ")


  loop := true
  for {
    if !loop {
      return
    }

    ls, err := exec.Command(cmds[0], cmds[1:]...).Output()
    if err != nil {
      log.Fatal(err)
    }
    rows := strings.Split(string(ls), "\n")[1:]  // 0: header
    rowsLen := len(rows) - 2
    re := regexp.MustCompile(`\s+`)
    for _, row := range rows {
      arr = append(arr, re.Split(row, -1))
    }
    for _, cmd := range customCmds {
      rows = append(rows, cmd[0])
      arr = append(arr, cmd)
    }


    indices, err := fuzzyfinder.FindMulti(
      rows,
      func(i int) string {
        return rows[i]
      })
    // if err != nil {
    //   log.Fatal(err)
    // }
    pos := len(re.Split(rows[1], -1)) - 1
    for _, idx := range indices {
      if idx <= rowsLen {
        fmt.Printf("%v\n", arr[idx][pos])
        loop = false
      } else {
        cmds = strings.Split(arr[idx][1], " ")
      }
    }
  }
}

上記はちょっといい加減な実装してるけど、動くから良しとしておく。

使い方としては fff.go という名前で保存し、go build fff.go してバイナリを作る。 以前作ったファイラの代わりに呼び出しても良いし、外部コマンドの呼び出しに使っても良い。 私は以下のように登録してみたけど、まあまあ使い物にはなってるかな。
alias c='cd "`fff ${1}`"; ls'

一瞬で作れて凄いと思った。

0 件のコメント: