kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Go で TODO を管理する CLI を作ろうと思っていて

A Tour of Go を一通り終えたので,実際に何か作ってみようと思っていたときに,会社のデスクの上にタスクをメモった付箋が大量に貼ってあることに気付いて「よし!この TODO を管理する CLI を作ってみよう」と思い立ったのが3日前のこと.

Go ビギナーだから初歩的なところで困ったりもするけど,試行錯誤している過程で学んだことなども多いので,簡単に現状を整理しておこうかと思う.

試作している CLI をチラッと

ザッと以下の基本操作をできるようにした.

  • togoo init
    • SQLite データベースを作成してテーブルを追加する
  • togoo add
    • タスクを追加する
  • togoo list
    • タスクを一覧する
  • togoo done
    • タスクを完了する

タスクを一覧してみると以下のような出力になる.まだ表示できていないけど,データとしては created_atupdated_at を UNIX time で保持している.

$ togoo list
| --- | -------------------------------------------------- | ------- |
| No  | Title                                              | Status  |
| --- | -------------------------------------------------- | ------- |
|   1 | sample_task1                                       | Done    |
|   2 | sample_task2                                       | -       |
| --- | -------------------------------------------------- | ------- |

Go で CLI の雛形を作るには

Ruby で言う Thor のようなものがあるかなとー思って調べたら GitHub - urfave/cli: A simple, fast, and fun package for building command line apps in Go が人気そうだったので,GitHub - tcnksm/gcli: The easy way to build Golang command-line application. を使ってスケルトンを生成した.gcli は本当に便利で,一瞬で CLI が動くようになった.素晴らしすぎる!

$ gcli new -c init -c add -c list -c done togoo
$ cd ${GOPATH}/src/github.com/kakakakakku/togoo
$ go build
$ ./togoo

SQLite を操作する

Go から SQLite を操作するために GitHub - mattn/go-sqlite3: sqlite3 driver for go that using database/sql を使った.サンプルコードが参考になった.

ホームディレクトリを取得する

togoo init を実行するとホームディレクトリに SQLite データベースを作成するようにしている.ホームディレクトリを取得するときに,最初は os/user を使って実装してみたんだけど,GitHub - motemen/gore: Yet another Go REPL that works nicely. Featured with line editing, code completion, and more. のコードを読んでいたら GitHub - mitchellh/go-homedir: Go library for detecting and expanding the user's home directory without cgo. を使っていることに気付いて真似してみた.cgo を必要としないため,クロスコンパイルの観点でメリットがあるとのこと.

UNIX time を取得する

SQLite にはタイムスタンプ型がないため Integer で定義して UNIX time を保持している.取得するには time.Now().Unix() と書く.

package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println(time.Now().Unix())
}

困ってること

日本語(ダブルバイト)のタスク名を登録すると表示がズレてしまう.ちゃんと %-50s として幅固定しているのになぜ?こういうのをすぐ解決できないあたり,ビギナーだなと感じる.悔しー!(誰か指導プルリクを…!)

$ togoo list
| --- | -------------------------------------------------- | ------- |
| No  | Title                                              | Status  |
| --- | -------------------------------------------------- | ------- |
|   1 | sample_task1                                       | Done    |
|   2 | sample_task2                                       | -       |
|   3 | あ                                                  | -       |
| --- | -------------------------------------------------- | ------- |

引き続きやること

楽しそう!

まとめ

メリークリスマス!