diff --git a/README.asciidoc b/README.asciidoc index b11dff0..ce16d1d 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -1,21 +1,77 @@ = Pelican +:toc: +:toclevels: 1 +:toc-title: Contents -== Summary +== Overview -**This project is WIP and is not meant for production use** +**This project is WIP and is not meant for production use.** Pelican is a simple Kanban board for your terminal. - -== Storage - Data is stored in a https://github.com/etcd-io/bbolt[BoltDB] database. -For Linux the default the database file is located at $XDG\_DATA\_HOME/canal/canal.db -If $XDG\_DATA\_HOME is not set then the default location is $HOME/.local/share/canal/canal.db by default. -For all other operating systems the default location is $HOME/.canal/canal.db. +Pelican does not make any assumptions to the path of the database file; +instead the user is expected to specify the path when running the application. + +== Installation + +=== Requirements + +==== Go + +A minimum version of Go 1.21.0 is required for installing spruce. +Please go https://go.dev/dl/[here] to download the latest version. + +==== Mage (Optional) + +The project includes a https://codeflow.dananglin.me.uk/apollo/pelican/src/branch/main/magefiles/mage.go[magefile] +for automating the build and installation of the binary. +You can visit the https://magefile.org[website] for instructions on how to install Mage. + +=== Install with Mage + +TBC + +=== Install with Go + +If your `GOBIN` directory is included in your `PATH` then you can install Pelican with Go. + +[source,console] +---- +git clone https://codeflow.dananglin.me.uk/apollo/pelican.git +cd pelican +go install ./cmd/pelican +---- + +== Running Pelican + +To create a new Kanban project with Pelican, simply run the following command: +[source,console] +---- +pelican ./project.pelican +---- + +This will create a new BoltDB database file called `project.pelican` in your current directory +and initialises the database with an empty project. == Keybindings -TBC +[%header,cols=2*] +|=== +|Key +|Action + +|CTRL + q +|Quit the application + +|a +|Add card + +|CTRL + d +|Delete card + +|m +|Move card between statuses +|=== == Inspiration diff --git a/cmd/pelican/main.go b/cmd/pelican/main.go index 0243994..cd0d200 100644 --- a/cmd/pelican/main.go +++ b/cmd/pelican/main.go @@ -2,12 +2,20 @@ package main import ( "log" + "os" "codeflow.dananglin.me.uk/apollo/pelican/internal/ui" ) func main() { - pelican := ui.NewUI() + if len(os.Args) != 2 { + log.Fatalf("ERROR: Unexpected number of command-line arguments; want 1; got %d", len(os.Args)-1) + } + + pelican, err := ui.NewUI(os.Args[1]) + if err != nil { + log.Fatalf("ERROR: Unable to initialise Pelican; %v", err) + } if err := pelican.Run(); err != nil { log.Fatalf("Error: an error occurred while running pelican, %s", err) diff --git a/internal/board/status.go b/internal/board/status.go index f46e536..b75f594 100644 --- a/internal/board/status.go +++ b/internal/board/status.go @@ -1,8 +1,8 @@ package board import ( - "sort" "fmt" + "sort" ) type StatusListEmptyError struct{} diff --git a/internal/ui/ui.go b/internal/ui/ui.go index e05d4ca..10f96bd 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -5,7 +5,6 @@ import ( "strconv" "codeflow.dananglin.me.uk/apollo/pelican/internal/board" - "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) @@ -37,7 +36,12 @@ type UI struct { } // NewUI returns a new UI value. -func NewUI() UI { +func NewUI(path string) (UI, error) { + b, err := board.Open(path) + if err != nil { + return UI{}, fmt.Errorf("unable to open the project's board; %w", err) + } + ui := UI{ Application: tview.NewApplication(), pages: tview.NewPages(), @@ -47,13 +51,15 @@ func NewUI() UI { focusedColumn: 0, columns: nil, move: nil, - board: board.Board{}, + board: b, deleteCardModal: tview.NewModal(), } - ui.init() + if err := ui.init(); err != nil { + return UI{}, fmt.Errorf("received an error after running the initialisation; %w", err) + } - return ui + return ui, nil } // closeBoard closes the board. @@ -78,7 +84,7 @@ func (u *UI) deleteCard() { } // init initialises the UI. -func (u *UI) init() { +func (u *UI) init() error { u.pages.AddPage(mainPageName, u.flex, true, true) u.initQuitModal() @@ -90,18 +96,13 @@ func (u *UI) init() { u.initDeleteCardModal() u.pages.AddPage(deleteCardPageName, u.deleteCardModal, false, false) - u.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { - switch event.Rune() { - case 'o': - if u.flex.HasFocus() && len(u.columns) == 0 { - _ = u.openBoard("") - } - } - - return event - }) - u.SetRoot(u.pages, true) + + if err := u.refresh(); err != nil { + return fmt.Errorf("error refreshing the board, %w", err) + } + + return nil } // initAddInputModal initialises the add input modal. @@ -168,22 +169,6 @@ func (u *UI) newCard(title, content string) error { return nil } -// openBoard opens the kanban board. -func (u *UI) openBoard(path string) error { - b, err := board.Open(path) - if err != nil { - return fmt.Errorf("unable to load board, %w", err) - } - - u.board = b - - if err = u.refresh(); err != nil { - return fmt.Errorf("error refreshing the board, %w", err) - } - - return nil -} - // refresh refreshes the UI. func (u *UI) refresh() error { statusList, err := u.board.StatusList() diff --git a/magefiles/mage.go b/magefiles/mage.go index 5de1955..059c5e4 100644 --- a/magefiles/mage.go +++ b/magefiles/mage.go @@ -41,7 +41,7 @@ func Lint() error { // Build build the executable func Build() error { - main := "./cmd/"+binary+"/main.go" + main := "./cmd/" + binary + "/main.go" return sh.Run("go", "build", "-o", binary, main) }