From fc5fa7b0cace5a401827d7bb802b559cfe818de8 Mon Sep 17 00:00:00 2001 From: Dan Anglin Date: Tue, 12 Dec 2023 12:47:58 +0000 Subject: [PATCH] feat(BREAKING): specify project path This PR allows users to specify the path to the database file Pelican now expects the user to specify the path to the project's database file which allows users to open different projects. This is a breaking change because Pelican no longer opens the default path automatically. If no path is set then Pelican stops with an error message. --- README.asciidoc | 74 +++++++++++++++++++++++++++++++++++----- cmd/pelican/main.go | 10 +++++- internal/board/status.go | 2 +- internal/ui/ui.go | 51 ++++++++++----------------- magefiles/mage.go | 2 +- 5 files changed, 94 insertions(+), 45 deletions(-) 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) }