feat(BREAKING): specify project path #8

Manually merged
dananglin merged 1 commit from 4-support-opening-projects-from-any-path into main 2023-12-12 12:55:01 +00:00
5 changed files with 94 additions and 45 deletions

View file

@ -1,21 +1,77 @@
= Pelican = 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. Pelican is a simple Kanban board for your terminal.
== Storage
Data is stored in a https://github.com/etcd-io/bbolt[BoltDB] database. 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 Pelican does not make any assumptions to the path of the database file;
If $XDG\_DATA\_HOME is not set then the default location is $HOME/.local/share/canal/canal.db by default. instead the user is expected to specify the path when running the application.
For all other operating systems the default location is $HOME/.canal/canal.db.
== 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 == 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 == Inspiration

View file

@ -2,12 +2,20 @@ package main
import ( import (
"log" "log"
"os"
"codeflow.dananglin.me.uk/apollo/pelican/internal/ui" "codeflow.dananglin.me.uk/apollo/pelican/internal/ui"
) )
func main() { 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 { if err := pelican.Run(); err != nil {
log.Fatalf("Error: an error occurred while running pelican, %s", err) log.Fatalf("Error: an error occurred while running pelican, %s", err)

View file

@ -1,8 +1,8 @@
package board package board
import ( import (
"sort"
"fmt" "fmt"
"sort"
) )
type StatusListEmptyError struct{} type StatusListEmptyError struct{}

View file

@ -5,7 +5,6 @@ import (
"strconv" "strconv"
"codeflow.dananglin.me.uk/apollo/pelican/internal/board" "codeflow.dananglin.me.uk/apollo/pelican/internal/board"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview" "github.com/rivo/tview"
) )
@ -37,7 +36,12 @@ type UI struct {
} }
// NewUI returns a new UI value. // 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{ ui := UI{
Application: tview.NewApplication(), Application: tview.NewApplication(),
pages: tview.NewPages(), pages: tview.NewPages(),
@ -47,13 +51,15 @@ func NewUI() UI {
focusedColumn: 0, focusedColumn: 0,
columns: nil, columns: nil,
move: nil, move: nil,
board: board.Board{}, board: b,
deleteCardModal: tview.NewModal(), 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. // closeBoard closes the board.
@ -78,7 +84,7 @@ func (u *UI) deleteCard() {
} }
// init initialises the UI. // init initialises the UI.
func (u *UI) init() { func (u *UI) init() error {
u.pages.AddPage(mainPageName, u.flex, true, true) u.pages.AddPage(mainPageName, u.flex, true, true)
u.initQuitModal() u.initQuitModal()
@ -90,18 +96,13 @@ func (u *UI) init() {
u.initDeleteCardModal() u.initDeleteCardModal()
u.pages.AddPage(deleteCardPageName, u.deleteCardModal, false, false) 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) 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. // initAddInputModal initialises the add input modal.
@ -168,22 +169,6 @@ func (u *UI) newCard(title, content string) error {
return nil 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. // refresh refreshes the UI.
func (u *UI) refresh() error { func (u *UI) refresh() error {
statusList, err := u.board.StatusList() statusList, err := u.board.StatusList()

View file

@ -41,7 +41,7 @@ func Lint() error {
// Build build the executable // Build build the executable
func Build() error { func Build() error {
main := "./cmd/"+binary+"/main.go" main := "./cmd/" + binary + "/main.go"
return sh.Run("go", "build", "-o", binary, main) return sh.Run("go", "build", "-o", binary, main)
} }