refactor: a lil bit of refactoring

Changes:

- Rename the UI type to App.
- Rename NewUI() to NewApp().
- Move init functions to internal/ui/ui.go.
- Call app's initialisation function from main.
- Move the keymapping functionalities to internal/ui/keymappings.go.
- Add documentation for updateColumn() and updateAllColumns().
- Applied gofmt.

Also:

- Build(mage): optionally include -a and/or -v during go build.
This commit is contained in:
Dan Anglin 2024-01-14 13:46:42 +00:00
parent 43095b9932
commit dbb37a1060
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
9 changed files with 387 additions and 325 deletions

2
.gitignore vendored
View file

@ -1,3 +1,3 @@
/test/databases/*.db
/pelican
/kanban.pelican
/*.pelican

View file

@ -25,12 +25,16 @@ func main() {
log.Fatalf("ERROR: Unexpected number of command-line arguments; want 1; got %d", len(args))
}
pelican, err := ui.NewUI(args[0])
pelican, err := ui.NewApp(args[0])
if err != nil {
log.Fatalf("ERROR: Unable to initialise Pelican; %v", err)
log.Fatalf("ERROR: Unable to create pelican; %v", err)
}
if err := pelican.Init(); 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)
log.Fatalf("ERROR: an error occurred while running pelican, %s", err)
}
}

View file

@ -12,10 +12,10 @@ func (e CardNotExistError) Error() string {
// Card represents a card on a Kanban board.
type Card struct {
ID int
Title string
ID int
Title string
Description string
Created string
Created string
}
// UpdateId updates the ID of the Card value.

View file

@ -58,7 +58,7 @@ func testCreateCard(kanban board.Board, title, content string, expectedCardID, e
t.Log("When the card is created and saved to the database.")
args := board.CardArgs{
NewTitle: title,
NewTitle: title,
NewDescription: content,
}
@ -123,7 +123,7 @@ func testUpdateCard(kanban board.Board, cardID int, newTitle, newContent, timest
args := board.UpdateCardArgs{
CardID: cardID,
CardArgs: board.CardArgs{
NewTitle: newTitle,
NewTitle: newTitle,
NewDescription: newContent,
},
}
@ -138,10 +138,10 @@ func testUpdateCard(kanban board.Board, cardID int, newTitle, newContent, timest
}
want := board.Card{
ID: cardID,
Title: newTitle,
ID: cardID,
Title: newTitle,
Description: newContent,
Created: timestamp,
Created: timestamp,
}
if !reflect.DeepEqual(got, want) {
@ -159,7 +159,7 @@ func testUpdateCardContent(kanban board.Board, cardID int, expectedTitle, newCon
args := board.UpdateCardArgs{
CardID: cardID,
CardArgs: board.CardArgs{
NewTitle: "",
NewTitle: "",
NewDescription: newContent,
},
}
@ -174,10 +174,10 @@ func testUpdateCardContent(kanban board.Board, cardID int, expectedTitle, newCon
}
want := board.Card{
ID: cardID,
Title: expectedTitle,
ID: cardID,
Title: expectedTitle,
Description: newContent,
Created: timestamp,
Created: timestamp,
}
if !reflect.DeepEqual(got, want) {

View file

@ -163,8 +163,8 @@ func TestReadAndWriteCards(t *testing.T) {
}()
singleCard := board.Card{
ID: -1,
Title: "A test task.",
ID: -1,
Title: "A test task.",
Description: "This task should be completed.",
}
@ -173,18 +173,18 @@ func TestReadAndWriteCards(t *testing.T) {
manyCards := []board.Card{
{
ID: -1,
Title: "Test card A.",
ID: -1,
Title: "Test card A.",
Description: "This is test card A.",
},
{
ID: -1,
Title: "Test card B.",
ID: -1,
Title: "Test card B.",
Description: "This is test card B.",
},
{
ID: -1,
Title: "Test card C.",
ID: -1,
Title: "Test card C.",
Description: "This is test card C.",
},
}
@ -223,8 +223,8 @@ func testReadOneCard(t *testing.T, database *bolt.DB, cardID int) {
}
want := board.Card{
ID: 1,
Title: "A test task.",
ID: 1,
Title: "A test task.",
Description: "This task should be completed.",
}
@ -278,18 +278,18 @@ func testReadManyCards(t *testing.T, database *bolt.DB, cardIDs []int) {
want := []board.Card{
{
ID: 2,
Title: "Test card A.",
ID: 2,
Title: "Test card A.",
Description: "This is test card A.",
},
{
ID: 3,
Title: "Test card B.",
ID: 3,
Title: "Test card B.",
Description: "This is test card B.",
},
{
ID: 4,
Title: "Test card C.",
ID: 4,
Title: "Test card C.",
Description: "This is test card C.",
},
}
@ -326,8 +326,8 @@ func TestDeleteOneCard(t *testing.T) {
// Create one card, get card ID.
card := board.Card{
ID: -1,
Title: "Test card",
ID: -1,
Title: "Test card",
Description: "",
}

106
internal/ui/init.go Normal file
View file

@ -0,0 +1,106 @@
package ui
import (
"fmt"
"github.com/gdamore/tcell/v2"
)
// initColumns initialises the columns of the Kanban board.
func (a *App) initColumns() error {
a.columnFlex.Clear()
statusList, err := a.board.StatusList()
if err != nil {
return fmt.Errorf("unable to retrieve the list of statuses; %w", err)
}
columns := make([]*column, len(statusList))
for i := range statusList {
column := newColumn(statusList[i].ID, statusList[i].Name, a.boardMode)
a.columnFlex.AddItem(column, 50, 1, true)
columns[i] = column
}
a.columns = columns
return nil
}
// initCardForm initialises the card form.
func (a *App) initCardForm() {
doneFunc := func(title, description string, success bool, mode cardFormMode) {
if success {
switch mode {
case create:
a.saveCard(title, description)
case edit:
a.editFocusedCard(title, description)
}
}
a.pages.HidePage(cardFormPage)
a.setColumnFocus()
}
a.cardForm.setDoneFunc(doneFunc)
}
// initDeleteCardModal initialises the modal for deleting cards.
func (a *App) initDeleteCardModal() {
doneFunc := func(_ int, buttonLabel string) {
if buttonLabel == "Confirm" {
a.deleteFocusedCard()
a.refresh(true)
}
a.pages.HidePage(deleteCardModalPage)
a.setColumnFocus()
}
a.deleteCardModal.AddButtons([]string{"Confirm", "Cancel"}).SetDoneFunc(doneFunc)
a.deleteCardModal.SetBorder(true).SetBorderColor(tcell.ColorOrangeRed)
a.deleteCardModal.SetBackgroundColor(tcell.ColorBlack.TrueColor())
a.deleteCardModal.SetButtonBackgroundColor(tcell.ColorBlueViolet.TrueColor())
a.deleteCardModal.SetTextColor(tcell.ColorWhite.TrueColor())
}
// initQuitModal initialises the quit modal.
func (a *App) initQuitModal() {
doneFunc := func(_ int, buttonLabel string) {
switch buttonLabel {
case "Quit":
a.shutdown()
default:
a.pages.HidePage(quitPage)
a.setColumnFocus()
}
}
a.quitModal.SetText("Do you want to quit the application?").
AddButtons([]string{"Quit", "Cancel"}).
SetDoneFunc(doneFunc)
}
// initView initialises the view window for displaying the card.
func (a *App) initView() {
doneFunc := func(key tcell.Key) {
if key == tcell.KeyEsc {
a.pages.HidePage(viewPage)
a.view.Clear()
a.setColumnFocus()
}
}
a.view.setDoneFunc(doneFunc)
}
func (a *App) initStatusbar() {
changedFunc := func() {
a.Draw()
}
a.statusbar.SetChangedFunc(changedFunc)
}

131
internal/ui/keymappings.go Normal file
View file

@ -0,0 +1,131 @@
package ui
import (
"fmt"
"github.com/gdamore/tcell/v2"
)
func (a *App) inputCapture() func(event *tcell.EventKey) *tcell.EventKey {
return func(event *tcell.EventKey) *tcell.EventKey {
key, letter := event.Key(), event.Rune()
switch {
case letter == 'h' || key == tcell.KeyLeft:
a.shiftColumnFocus(previous)
case letter == 'l' || key == tcell.KeyRight:
a.shiftColumnFocus(next)
case letter == 'c':
a.create()
case letter == 'm':
a.move()
case letter == 'e':
a.edit()
case key == tcell.KeyCtrlD:
a.delete()
case key == tcell.KeyCtrlQ:
a.quit()
case key == tcell.KeyESC:
a.escape()
case key == tcell.KeyEnter:
a.selected()
}
return event
}
}
func (a *App) create() {
if a.mode == normal {
a.cardForm.mode = create
a.cardForm.updateInputFields("", "")
a.cardForm.frame.SetTitle(" Create Card ")
a.pages.ShowPage(cardFormPage)
a.SetFocus(a.cardForm)
}
}
func (a *App) move() {
if a.mode == normal {
a.statusSelection.cardID = a.focusedCardID()
a.statusSelection.currentStatusID = a.focusedStatusID()
a.mode = selection
}
}
func (a *App) edit() {
if a.mode == normal {
a.cardForm.mode = edit
card, ok := a.getFocusedCard()
if !ok {
return
}
a.cardForm.updateInputFields(card.Title, card.Description)
a.cardForm.frame.SetTitle(" Edit Card ")
a.pages.ShowPage(cardFormPage)
a.SetFocus(a.cardForm)
}
}
func (a *App) delete() {
if a.mode == normal {
card, ok := a.getFocusedCard()
if !ok {
return
}
text := fmt.Sprintf("Do you want to delete '%s'?", card.Title)
a.deleteCardModal.SetText(text)
a.pages.ShowPage(deleteCardModalPage)
a.SetFocus(a.deleteCardModal)
}
}
func (a *App) quit() {
if a.mode == normal {
a.pages.ShowPage(quitPage)
a.SetFocus(a.quitModal)
}
}
func (a *App) selected() {
switch a.mode {
case normal:
card, ok := a.getFocusedCard()
if !ok {
break
}
status := a.focusedStatusName()
a.view.setText(card.ID, card.Title, status, card.Created, card.Description)
a.pages.ShowPage(viewPage)
a.SetFocus(a.view)
case selection:
a.statusSelection.nextStatusID = a.focusedStatusID()
if a.statusSelection.currentStatusID != a.statusSelection.nextStatusID {
if err := a.statusSelection.moveCard(a.board); err != nil {
a.statusbar.displayMessage(
errorLevel,
fmt.Sprintf("Failed to move card: %v", err),
)
} else {
a.statusbar.displayMessage(
infoLevel,
"Card moved successfully.",
)
}
}
a.statusSelection = statusSelection{0, 0, 0}
a.mode = normal
a.refresh(false)
}
}
func (a *App) escape() {
if a.mode != normal {
a.mode = normal
}
}

View file

@ -4,7 +4,6 @@ import (
"fmt"
"codeflow.dananglin.me.uk/apollo/pelican/internal/board"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
@ -31,7 +30,7 @@ const (
viewPage string = "view"
)
type UI struct {
type App struct {
*tview.Application
columns []*column
@ -49,14 +48,14 @@ type UI struct {
statusbar *statusbar
}
// NewUI returns a new UI value.
func NewUI(path string) (UI, error) {
// NewApp returns a new App value.
func NewApp(path string) (App, error) {
kanban, err := board.Open(path)
if err != nil {
return UI{}, fmt.Errorf("unable to open the project's board; %w", err)
return App{}, fmt.Errorf("unable to open the project's board; %w", err)
}
userInterface := UI{
app := App{
Application: tview.NewApplication(),
pages: tview.NewPages(),
baseFlex: tview.NewFlex(),
@ -73,248 +72,66 @@ func NewUI(path string) (UI, error) {
statusbar: newStatusbar(),
}
if err := userInterface.init(); err != nil {
return UI{}, fmt.Errorf("received an error after running the initialisation; %w", err)
}
return userInterface, nil
}
// closeBoard closes the board.
func (u *UI) closeBoard() {
_ = u.board.Close()
return app, nil
}
// init initialises the UI.
func (u *UI) init() error {
if err := u.initColumns(); err != nil {
func (a *App) Init() error {
if err := a.initColumns(); err != nil {
return fmt.Errorf("error initialising the status columns; %w", err)
}
u.columnFlex.SetInputCapture(u.inputCapture())
a.columnFlex.SetInputCapture(a.inputCapture())
u.initStatusbar()
a.initStatusbar()
u.baseFlex.SetDirection(tview.FlexRow)
u.baseFlex.AddItem(u.columnFlex, 0, 1, true)
u.baseFlex.AddItem(u.statusbar, 2, 1, false)
a.baseFlex.SetDirection(tview.FlexRow)
a.baseFlex.AddItem(a.columnFlex, 0, 1, true)
a.baseFlex.AddItem(a.statusbar, 2, 1, false)
u.pages.AddPage(mainPage, u.baseFlex, true, true)
a.pages.AddPage(mainPage, a.baseFlex, true, true)
u.initQuitModal()
u.pages.AddPage(quitPage, u.quitModal, false, false)
a.initQuitModal()
a.pages.AddPage(quitPage, a.quitModal, false, false)
u.initCardForm()
u.pages.AddPage(cardFormPage, u.cardForm, false, false)
a.initCardForm()
a.pages.AddPage(cardFormPage, a.cardForm, false, false)
u.initDeleteCardModal()
u.pages.AddPage(deleteCardModalPage, u.deleteCardModal, false, false)
a.initDeleteCardModal()
a.pages.AddPage(deleteCardModalPage, a.deleteCardModal, false, false)
u.initView()
u.pages.AddPage(viewPage, u.view, false, false)
a.initView()
a.pages.AddPage(viewPage, a.view, false, false)
u.SetRoot(u.pages, true)
a.SetRoot(a.pages, true)
u.refresh(false)
a.refresh(false)
return nil
}
func (u *UI) inputCapture() func(event *tcell.EventKey) *tcell.EventKey {
return func(event *tcell.EventKey) *tcell.EventKey {
key, letter := event.Key(), event.Rune()
switch {
case letter == 'h' || key == tcell.KeyLeft:
u.shiftColumnFocus(previous)
case letter == 'l' || key == tcell.KeyRight:
u.shiftColumnFocus(next)
case letter == 'c':
if u.mode == normal {
u.cardForm.mode = create
u.cardForm.updateInputFields("", "")
u.cardForm.frame.SetTitle(" Create Card ")
u.pages.ShowPage(cardFormPage)
u.SetFocus(u.cardForm)
}
case letter == 'm':
if u.mode == normal {
u.statusSelection.cardID = u.focusedCardID()
u.statusSelection.currentStatusID = u.focusedStatusID()
u.mode = selection
}
case letter == 'e':
if u.mode == normal {
u.cardForm.mode = edit
card, ok := u.getFocusedCard()
if !ok {
break
}
u.cardForm.updateInputFields(card.Title, card.Description)
u.cardForm.frame.SetTitle(" Edit Card ")
u.pages.ShowPage(cardFormPage)
u.SetFocus(u.cardForm)
}
case key == tcell.KeyCtrlD:
if u.mode == normal {
card, ok := u.getFocusedCard()
if !ok {
break
}
text := fmt.Sprintf("Do you want to delete '%s'?", card.Title)
u.deleteCardModal.SetText(text)
u.pages.ShowPage(deleteCardModalPage)
u.SetFocus(u.deleteCardModal)
}
case key == tcell.KeyCtrlQ:
if u.mode == normal {
u.pages.ShowPage(quitPage)
u.SetFocus(u.quitModal)
}
case key == tcell.KeyESC:
if u.mode != normal {
u.mode = normal
}
case key == tcell.KeyEnter:
switch u.mode {
case normal:
card, ok := u.getFocusedCard()
if !ok {
break
}
status := u.focusedStatusName()
u.view.setText(card.ID, card.Title, status, card.Created, card.Description)
u.pages.ShowPage(viewPage)
u.SetFocus(u.view)
case selection:
u.statusSelection.nextStatusID = u.focusedStatusID()
if u.statusSelection.currentStatusID != u.statusSelection.nextStatusID {
if err := u.statusSelection.moveCard(u.board); err != nil {
u.statusbar.displayMessage(
errorLevel,
fmt.Sprintf("Failed to move card: %v", err),
)
} else {
u.statusbar.displayMessage(
infoLevel,
"Card moved successfully.",
)
}
}
u.statusSelection = statusSelection{0, 0, 0}
u.mode = normal
u.refresh(false)
}
}
return event
}
}
// initCardForm initialises the card form.
func (u *UI) initCardForm() {
doneFunc := func(title, description string, success bool, mode cardFormMode) {
if success {
switch mode {
case create:
u.saveCard(title, description)
case edit:
u.editFocusedCard(title, description)
}
}
u.pages.HidePage(cardFormPage)
u.setColumnFocus()
}
u.cardForm.setDoneFunc(doneFunc)
}
// initDeleteCardModal initialises the modal for deleting cards.
func (u *UI) initDeleteCardModal() {
doneFunc := func(_ int, buttonLabel string) {
if buttonLabel == "Confirm" {
u.deleteFocusedCard()
u.refresh(true)
}
u.pages.HidePage(deleteCardModalPage)
u.setColumnFocus()
}
u.deleteCardModal.AddButtons([]string{"Confirm", "Cancel"}).SetDoneFunc(doneFunc)
u.deleteCardModal.SetBorder(true).SetBorderColor(tcell.ColorOrangeRed)
u.deleteCardModal.SetBackgroundColor(tcell.ColorBlack.TrueColor())
u.deleteCardModal.SetButtonBackgroundColor(tcell.ColorBlueViolet.TrueColor())
u.deleteCardModal.SetTextColor(tcell.ColorWhite.TrueColor())
}
// initQuitModal initialises the quit modal.
func (u *UI) initQuitModal() {
doneFunc := func(_ int, buttonLabel string) {
switch buttonLabel {
case "Quit":
u.shutdown()
default:
u.pages.HidePage(quitPage)
u.setColumnFocus()
}
}
u.quitModal.SetText("Do you want to quit the application?").
AddButtons([]string{"Quit", "Cancel"}).
SetDoneFunc(doneFunc)
}
// initView initialises the view window for displaying the card.
func (u *UI) initView() {
doneFunc := func(key tcell.Key) {
if key == tcell.KeyEsc {
u.pages.HidePage(viewPage)
u.view.Clear()
u.setColumnFocus()
}
}
u.view.setDoneFunc(doneFunc)
}
func (u *UI) initStatusbar() {
changedFunc := func() {
u.Draw()
}
u.statusbar.SetChangedFunc(changedFunc)
}
// saveCard creates and saves a new card to the database.
func (u *UI) saveCard(title, description string) {
// saveCard saves a new card to the database.
func (a *App) saveCard(title, description string) {
args := board.CardArgs{
NewTitle: title,
NewDescription: description,
}
_, err := u.board.CreateCard(args)
_, err := a.board.CreateCard(args)
if err != nil {
u.statusbar.displayMessage(errorLevel, fmt.Sprintf("Failed to create card: %v.", err))
a.statusbar.displayMessage(errorLevel, fmt.Sprintf("Failed to create card: %v.", err))
return
}
u.statusbar.displayMessage(infoLevel, "Card created successfully.")
a.statusbar.displayMessage(infoLevel, "Card created successfully.")
u.refresh(false)
a.refresh(false)
}
// editFocusedCard saves and edited card to the database.
func (u *UI) editFocusedCard(title, description string) {
cardID := u.focusedCardID()
// editFocusedCard saves an edited card to the database.
func (a *App) editFocusedCard(title, description string) {
cardID := a.focusedCardID()
args := board.UpdateCardArgs{
CardID: cardID,
@ -324,24 +141,24 @@ func (u *UI) editFocusedCard(title, description string) {
},
}
if err := u.board.UpdateCard(args); err != nil {
u.statusbar.displayMessage(errorLevel, fmt.Sprintf("Failed to edit card: %v.", err))
if err := a.board.UpdateCard(args); err != nil {
a.statusbar.displayMessage(errorLevel, fmt.Sprintf("Failed to edit card: %v.", err))
return
}
u.statusbar.displayMessage(infoLevel, "Card edited successfully.")
a.statusbar.displayMessage(infoLevel, "Card edited successfully.")
u.refresh(true)
a.refresh(true)
}
// getFocusedCard retrieves the details of the focused card.
func (u *UI) getFocusedCard() (board.Card, bool) {
cardID := u.focusedCardID()
// getFocusedCard retrieves the details of the card in focus.
func (a *App) getFocusedCard() (board.Card, bool) {
cardID := a.focusedCardID()
card, err := u.board.Card(cardID)
card, err := a.board.Card(cardID)
if err != nil {
u.statusbar.displayMessage(
a.statusbar.displayMessage(
errorLevel,
fmt.Sprintf("Failed to retrieve the card with card ID %d, %v.", cardID, err),
)
@ -352,47 +169,26 @@ func (u *UI) getFocusedCard() (board.Card, bool) {
return card, true
}
// deleteFocusedCard deletes the focused card from the board.
func (u *UI) deleteFocusedCard() {
// deleteFocusedCard deletes the card in focus from the board.
func (a *App) deleteFocusedCard() {
args := board.DeleteCardArgs{
CardID: u.focusedCardID(),
StatusID: u.focusedStatusID(),
CardID: a.focusedCardID(),
StatusID: a.focusedStatusID(),
}
if err := u.board.DeleteCard(args); err != nil {
u.statusbar.displayMessage(errorLevel, fmt.Sprintf("Failed to delete card: %v.", err))
if err := a.board.DeleteCard(args); err != nil {
a.statusbar.displayMessage(errorLevel, fmt.Sprintf("Failed to delete card: %v.", err))
return
}
u.statusbar.displayMessage(infoLevel, "Card deleted successfully.")
a.statusbar.displayMessage(infoLevel, "Card deleted successfully.")
}
// initColumns initialises the columns of the Kanban board.
func (u *UI) initColumns() error {
u.columnFlex.Clear()
statusList, err := u.board.StatusList()
if err != nil {
return fmt.Errorf("unable to retrieve the list of statuses; %w", err)
}
columns := make([]*column, len(statusList))
for i := range statusList {
column := newColumn(statusList[i].ID, statusList[i].Name, u.boardMode)
u.columnFlex.AddItem(column, 50, 1, true)
columns[i] = column
}
u.columns = columns
return nil
}
func (u *UI) updateAllColumns() error {
for i := range u.columns {
if err := u.updateColumn(i); err != nil {
// updateAllColumns ensures that all columns are up-to-date.
func (a *App) updateAllColumns() error {
for i := range a.columns {
if err := a.updateColumn(i); err != nil {
return err
}
}
@ -400,51 +196,55 @@ func (u *UI) updateAllColumns() error {
return nil
}
func (u *UI) updateColumn(index int) error {
if err := u.columns[index].update(u.board); err != nil {
// updateColumn ensures that the column is up-to-date.
func (a *App) updateColumn(index int) error {
if err := a.columns[index].update(a.board); err != nil {
return fmt.Errorf("unable to update column; %w", err)
}
return nil
}
func (u *UI) shiftColumnFocus(movement boardMovement) {
// shiftColumnFocus shifts the focus to the column to the left or right depending
// on the movement set by the user.
func (a *App) shiftColumnFocus(movement boardMovement) {
switch movement {
case next:
if u.focusedColumn == len(u.columns)-1 {
u.focusedColumn = 0
if a.focusedColumn == len(a.columns)-1 {
a.focusedColumn = 0
} else {
u.focusedColumn++
a.focusedColumn++
}
case previous:
if u.focusedColumn == 0 {
u.focusedColumn = len(u.columns) - 1
if a.focusedColumn == 0 {
a.focusedColumn = len(a.columns) - 1
} else {
u.focusedColumn--
a.focusedColumn--
}
}
u.setColumnFocus()
a.setColumnFocus()
}
func (u *UI) setColumnFocus() {
u.SetFocus(u.columns[u.focusedColumn])
// setColumnFocus sets the focus to the column primitive as specified by focusedColumn.
func (a *App) setColumnFocus() {
a.SetFocus(a.columns[a.focusedColumn])
}
// refresh refreshes the UI.
func (u *UI) refresh(updateFocusedColumnOnly bool) {
func (a *App) refresh(updateFocusedColumnOnly bool) {
if updateFocusedColumnOnly {
if err := u.updateColumn(u.focusedColumn); err != nil {
u.statusbar.displayMessage(
if err := a.updateColumn(a.focusedColumn); err != nil {
a.statusbar.displayMessage(
errorLevel,
fmt.Sprintf("Failed to update status column %q: %v", u.focusedStatusName(), err),
fmt.Sprintf("Failed to update status column %q: %v", a.focusedStatusName(), err),
)
return
}
} else {
if err := u.updateAllColumns(); err != nil {
u.statusbar.displayMessage(
if err := a.updateAllColumns(); err != nil {
a.statusbar.displayMessage(
errorLevel,
fmt.Sprintf("Failed to update status columns: %v", err),
)
@ -453,34 +253,39 @@ func (u *UI) refresh(updateFocusedColumnOnly bool) {
}
}
u.setColumnFocus()
a.setColumnFocus()
}
// shutdown shuts down the application.
func (u *UI) shutdown() {
u.closeBoard()
u.Stop()
func (a *App) shutdown() {
a.closeBoard()
a.Stop()
}
// boardMode returns the current board mode.
func (u *UI) boardMode() boardMode {
return u.mode
func (a *App) boardMode() boardMode {
return a.mode
}
// focusedCardID returns the ID of the card in focus.
func (u *UI) focusedCardID() int {
focusedCard := u.columns[u.focusedColumn].focusedCard
id := u.columns[u.focusedColumn].cards[focusedCard].id
func (a *App) focusedCardID() int {
focusedCard := a.columns[a.focusedColumn].focusedCard
id := a.columns[a.focusedColumn].cards[focusedCard].id
return id
}
// focusedStatusID returns the ID of the status (column) in focus.
func (u *UI) focusedStatusID() int {
return u.columns[u.focusedColumn].statusID
func (a *App) focusedStatusID() int {
return a.columns[a.focusedColumn].statusID
}
// focusedStatusName returns the name of the status (column) in focus.
func (u *UI) focusedStatusName() string {
return u.columns[u.focusedColumn].statusName
func (a *App) focusedStatusName() string {
return a.columns[a.focusedColumn].statusName
}
// closeBoard closes the board.
func (a *App) closeBoard() {
_ = a.board.Close()
}

View file

@ -25,7 +25,7 @@ var Default = Build
// To enable verbose mode set PELICAN_TEST_VERBOSE=1.
// To enable coverage mode set PELICAN_TEST_COVER=1.
func Test() error {
goTest := sh.RunCmd("go", "test")
test := sh.RunCmd("go", "test")
args := []string{"./..."}
@ -37,7 +37,7 @@ func Test() error {
args = append(args, "-cover")
}
return goTest(args...)
return test(args...)
}
// Lint runs golangci-lint against the code.
@ -46,11 +46,27 @@ func Lint() error {
}
// Build build the executable
// To rebuild packages that are already up-to-date set PELICAN_BUILD_REBUILD_ALL=1
// To enable verbose mode set PELICAN_BUILD_VERBOSE=1
func Build() error {
main := "./cmd/" + binary
flags := ldflags()
return sh.Run("go", "build", "-ldflags="+flags, "-a", "-o", binary, main)
build := sh.RunCmd("go", "build")
args := []string{"-ldflags=" + flags, "-o", binary}
if os.Getenv("PELICAN_BUILD_REBUILD_ALL") == "1" {
args = append(args, "-a")
}
if os.Getenv("PELICAN_BUILD_VERBOSE") == "1" {
args = append(args, "-v")
}
args = append(args, main)
return build(args...)
}
func Install() error {