checkpoint: created the printer and began refactoring and redesigning

This commit is contained in:
Dan Anglin 2024-06-16 20:17:07 +01:00
parent f73f1f5872
commit 947b1b8c46
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
18 changed files with 424 additions and 222 deletions

View file

@ -11,6 +11,7 @@ import (
"strconv" "strconv"
"codeflow.dananglin.me.uk/apollo/enbas/internal/executor" "codeflow.dananglin.me.uk/apollo/enbas/internal/executor"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
) )
var ( var (
@ -87,39 +88,52 @@ func run() error {
command := flag.Arg(0) command := flag.Arg(0)
args := flag.Args()[1:] args := flag.Args()[1:]
enbasPrinter := printer.NewPrinter(
*topLevelFlags.NoColor,
topLevelFlags.Pager,
80,
)
executorMap := map[string]executor.Executor{ executorMap := map[string]executor.Executor{
executor.CommandAccept: executor.NewAcceptOrRejectExecutor( executor.CommandAccept: executor.NewAcceptOrRejectExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandAccept, executor.CommandAccept,
executor.CommandSummaryLookup(executor.CommandAccept), executor.CommandSummaryLookup(executor.CommandAccept),
), ),
executor.CommandAdd: executor.NewAddExecutor( executor.CommandAdd: executor.NewAddExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandAdd, executor.CommandAdd,
executor.CommandSummaryLookup(executor.CommandAdd), executor.CommandSummaryLookup(executor.CommandAdd),
), ),
executor.CommandBlock: executor.NewBlockOrUnblockExecutor( executor.CommandBlock: executor.NewBlockOrUnblockExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandBlock, executor.CommandBlock,
executor.CommandSummaryLookup(executor.CommandBlock), executor.CommandSummaryLookup(executor.CommandBlock),
), ),
executor.CommandCreate: executor.NewCreateExecutor( executor.CommandCreate: executor.NewCreateExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandCreate, executor.CommandCreate,
executor.CommandSummaryLookup(executor.CommandCreate), executor.CommandSummaryLookup(executor.CommandCreate),
), ),
executor.CommandDelete: executor.NewDeleteExecutor( executor.CommandDelete: executor.NewDeleteExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandDelete, executor.CommandDelete,
executor.CommandSummaryLookup(executor.CommandDelete), executor.CommandSummaryLookup(executor.CommandDelete),
), ),
executor.CommandEdit: executor.NewEditExecutor( executor.CommandEdit: executor.NewEditExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandEdit, executor.CommandEdit,
executor.CommandSummaryLookup(executor.CommandEdit), executor.CommandSummaryLookup(executor.CommandEdit),
), ),
executor.CommandFollow: executor.NewFollowOrUnfollowExecutor( executor.CommandFollow: executor.NewFollowOrUnfollowExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandFollow, executor.CommandFollow,
executor.CommandSummaryLookup(executor.CommandFollow), executor.CommandSummaryLookup(executor.CommandFollow),
), ),
@ -129,7 +143,8 @@ func run() error {
executor.CommandSummaryLookup(executor.CommandLogin), executor.CommandSummaryLookup(executor.CommandLogin),
), ),
executor.CommandReject: executor.NewAcceptOrRejectExecutor( executor.CommandReject: executor.NewAcceptOrRejectExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandReject, executor.CommandReject,
executor.CommandSummaryLookup(executor.CommandReject), executor.CommandSummaryLookup(executor.CommandReject),
), ),
@ -139,26 +154,31 @@ func run() error {
executor.CommandSummaryLookup(executor.CommandRemove), executor.CommandSummaryLookup(executor.CommandRemove),
), ),
executor.CommandSwitch: executor.NewSwitchExecutor( executor.CommandSwitch: executor.NewSwitchExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandSwitch, executor.CommandSwitch,
executor.CommandSummaryLookup(executor.CommandSwitch), executor.CommandSummaryLookup(executor.CommandSwitch),
), ),
executor.CommandUnfollow: executor.NewFollowOrUnfollowExecutor( executor.CommandUnfollow: executor.NewFollowOrUnfollowExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandUnfollow, executor.CommandUnfollow,
executor.CommandSummaryLookup(executor.CommandUnfollow), executor.CommandSummaryLookup(executor.CommandUnfollow),
), ),
executor.CommandUnblock: executor.NewBlockOrUnblockExecutor( executor.CommandUnblock: executor.NewBlockOrUnblockExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandUnblock, executor.CommandUnblock,
executor.CommandSummaryLookup(executor.CommandUnblock), executor.CommandSummaryLookup(executor.CommandUnblock),
), ),
executor.CommandShow: executor.NewShowExecutor( executor.CommandShow: executor.NewShowExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandShow, executor.CommandShow,
executor.CommandSummaryLookup(executor.CommandShow), executor.CommandSummaryLookup(executor.CommandShow),
), ),
executor.CommandVersion: executor.NewVersionExecutor( executor.CommandVersion: executor.NewVersionExecutor(
enbasPrinter,
executor.CommandVersion, executor.CommandVersion,
executor.CommandSummaryLookup(executor.CommandVersion), executor.CommandSummaryLookup(executor.CommandVersion),
binaryVersion, binaryVersion,
@ -167,7 +187,8 @@ func run() error {
gitCommit, gitCommit,
), ),
executor.CommandWhoami: executor.NewWhoAmIExecutor( executor.CommandWhoami: executor.NewWhoAmIExecutor(
topLevelFlags, enbasPrinter,
topLevelFlags.ConfigDir,
executor.CommandWhoami, executor.CommandWhoami,
executor.CommandSummaryLookup(executor.CommandWhoami), executor.CommandSummaryLookup(executor.CommandWhoami),
), ),

View file

@ -17,7 +17,7 @@ const (
listPath string = "/api/v1/lists" listPath string = "/api/v1/lists"
) )
func (g *Client) GetAllLists() (model.Lists, error) { func (g *Client) GetAllLists() ([]model.List, error) {
url := g.Authentication.Instance + listPath url := g.Authentication.Instance + listPath
var lists []model.List var lists []model.List

View file

@ -9,23 +9,26 @@ import (
"fmt" "fmt"
"codeflow.dananglin.me.uk/apollo/enbas/internal/client" "codeflow.dananglin.me.uk/apollo/enbas/internal/client"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
) )
type AcceptOrRejectExecutor struct { type AcceptOrRejectExecutor struct {
*flag.FlagSet *flag.FlagSet
topLevelFlags TopLevelFlags printer *printer.Printer
resourceType string configDir string
accountName string resourceType string
command string accountName string
command string
} }
func NewAcceptOrRejectExecutor(tlf TopLevelFlags, name, summary string) *AcceptOrRejectExecutor { func NewAcceptOrRejectExecutor(enbasPrinter *printer.Printer, configDir, name, summary string) *AcceptOrRejectExecutor {
acceptExe := AcceptOrRejectExecutor{ acceptExe := AcceptOrRejectExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError), FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
topLevelFlags: tlf, printer: enbasPrinter,
command: name, configDir: configDir,
command: name,
} }
acceptExe.StringVar(&acceptExe.resourceType, flagType, "", "Specify the type of resource to accept or reject") acceptExe.StringVar(&acceptExe.resourceType, flagType, "", "Specify the type of resource to accept or reject")
@ -46,7 +49,7 @@ func (a *AcceptOrRejectExecutor) Execute() error {
return UnsupportedTypeError{resourceType: a.resourceType} return UnsupportedTypeError{resourceType: a.resourceType}
} }
gtsClient, err := client.NewClientFromConfig(a.topLevelFlags.ConfigDir) gtsClient, err := client.NewClientFromConfig(a.configDir)
if err != nil { if err != nil {
return fmt.Errorf("unable to create the GoToSocial client: %w", err) return fmt.Errorf("unable to create the GoToSocial client: %w", err)
} }
@ -55,7 +58,7 @@ func (a *AcceptOrRejectExecutor) Execute() error {
} }
func (a *AcceptOrRejectExecutor) acceptOrRejectFollowRequest(gtsClient *client.Client) error { func (a *AcceptOrRejectExecutor) acceptOrRejectFollowRequest(gtsClient *client.Client) error {
accountID, err := getAccountID(gtsClient, false, a.accountName, a.topLevelFlags.ConfigDir) accountID, err := getAccountID(gtsClient, false, a.accountName, a.configDir)
if err != nil { if err != nil {
return fmt.Errorf("received an error while getting the account ID: %w", err) return fmt.Errorf("received an error while getting the account ID: %w", err)
} }
@ -75,7 +78,7 @@ func (a *AcceptOrRejectExecutor) acceptFollowRequest(gtsClient *client.Client, a
return fmt.Errorf("unable to accept the follow request: %w", err) return fmt.Errorf("unable to accept the follow request: %w", err)
} }
fmt.Println("Successfully accepted the follow request.") a.printer.PrintSuccess("Successfully accepted the follow request.")
return nil return nil
} }
@ -85,7 +88,7 @@ func (a *AcceptOrRejectExecutor) rejectFollowRequest(gtsClient *client.Client, a
return fmt.Errorf("unable to reject the follow request: %w", err) return fmt.Errorf("unable to reject the follow request: %w", err)
} }
fmt.Println("Successfully rejected the follow request.") a.printer.PrintSuccess("Successfully rejected the follow request.")
return nil return nil
} }

View file

@ -10,12 +10,14 @@ import (
"fmt" "fmt"
"codeflow.dananglin.me.uk/apollo/enbas/internal/client" "codeflow.dananglin.me.uk/apollo/enbas/internal/client"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
) )
type AddExecutor struct { type AddExecutor struct {
*flag.FlagSet *flag.FlagSet
topLevelFlags TopLevelFlags printer *printer.Printer
configDir string
resourceType string resourceType string
toResourceType string toResourceType string
listID string listID string
@ -26,13 +28,15 @@ type AddExecutor struct {
content string content string
} }
func NewAddExecutor(tlf TopLevelFlags, name, summary string) *AddExecutor { func NewAddExecutor(printer *printer.Printer, configDir, name, summary string) *AddExecutor {
emptyArr := make([]string, 0, 3) emptyArr := make([]string, 0, 3)
addExe := AddExecutor{ addExe := AddExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError), FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
accountNames: MultiStringFlagValue(emptyArr),
topLevelFlags: tlf, printer: printer,
configDir: configDir,
accountNames: MultiStringFlagValue(emptyArr),
} }
addExe.StringVar(&addExe.resourceType, flagType, "", "Specify the resource type to add (e.g. account, note)") addExe.StringVar(&addExe.resourceType, flagType, "", "Specify the resource type to add (e.g. account, note)")
@ -67,7 +71,7 @@ func (a *AddExecutor) Execute() error {
return UnsupportedTypeError{resourceType: a.toResourceType} return UnsupportedTypeError{resourceType: a.toResourceType}
} }
gtsClient, err := client.NewClientFromConfig(a.topLevelFlags.ConfigDir) gtsClient, err := client.NewClientFromConfig(a.configDir)
if err != nil { if err != nil {
return fmt.Errorf("unable to create the GoToSocial client: %w", err) return fmt.Errorf("unable to create the GoToSocial client: %w", err)
} }
@ -124,7 +128,7 @@ func (a *AddExecutor) addAccountsToList(gtsClient *client.Client) error {
return fmt.Errorf("unable to add the accounts to the list: %w", err) return fmt.Errorf("unable to add the accounts to the list: %w", err)
} }
fmt.Println("Successfully added the account(s) to the list.") a.printer.PrintSuccess("Successfully added the account(s) to the list.")
return nil return nil
} }
@ -150,7 +154,7 @@ func (a *AddExecutor) addNoteToAccount(gtsClient *client.Client) error {
return fmt.Errorf("unexpected number of accounts specified: want 1, got %d", len(a.accountNames)) return fmt.Errorf("unexpected number of accounts specified: want 1, got %d", len(a.accountNames))
} }
accountID, err := getAccountID(gtsClient, false, a.accountNames[0], a.topLevelFlags.ConfigDir) accountID, err := getAccountID(gtsClient, false, a.accountNames[0], a.configDir)
if err != nil { if err != nil {
return fmt.Errorf("received an error while getting the account ID: %w", err) return fmt.Errorf("received an error while getting the account ID: %w", err)
} }
@ -166,7 +170,7 @@ func (a *AddExecutor) addNoteToAccount(gtsClient *client.Client) error {
return fmt.Errorf("unable to add the private note to the account: %w", err) return fmt.Errorf("unable to add the private note to the account: %w", err)
} }
fmt.Println("Successfully added the private note to the account.") a.printer.PrintSuccess("Successfully added the private note to the account.")
return nil return nil
} }
@ -196,7 +200,7 @@ func (a *AddExecutor) addStatusToBookmarks(gtsClient *client.Client) error {
return fmt.Errorf("unable to add the status to your bookmarks: %w", err) return fmt.Errorf("unable to add the status to your bookmarks: %w", err)
} }
fmt.Println("Successfully added the status to your bookmarks.") a.printer.PrintSuccess("Successfully added the status to your bookmarks.")
return nil return nil
} }
@ -228,7 +232,7 @@ func (a *AddExecutor) addStarToStatus(gtsClient *client.Client) error {
return fmt.Errorf("unable to add the %s to the status: %w", a.resourceType, err) return fmt.Errorf("unable to add the %s to the status: %w", a.resourceType, err)
} }
fmt.Printf("Successfully added a %s to the status.\n", a.resourceType) a.printer.PrintSuccess("Successfully added a " + a.resourceType + " to the status.\n")
return nil return nil
} }
@ -238,7 +242,7 @@ func (a *AddExecutor) addBoostToStatus(gtsClient *client.Client) error {
return fmt.Errorf("unable to add the boost to the status: %w", err) return fmt.Errorf("unable to add the boost to the status: %w", err)
} }
fmt.Println("Successfully added the boost to the status.") a.printer.PrintSuccess("Successfully added the boost to the status.")
return nil return nil
} }
@ -285,7 +289,7 @@ func (a *AddExecutor) addVoteToPoll(gtsClient *client.Client) error {
return fmt.Errorf("unable to add your vote(s) to the poll: %w", err) return fmt.Errorf("unable to add your vote(s) to the poll: %w", err)
} }
fmt.Println("Successfully added your vote(s) to the poll.") a.printer.PrintSuccess("Successfully added your vote(s) to the poll.")
return nil return nil
} }

View file

@ -9,23 +9,26 @@ import (
"fmt" "fmt"
"codeflow.dananglin.me.uk/apollo/enbas/internal/client" "codeflow.dananglin.me.uk/apollo/enbas/internal/client"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
) )
type BlockOrUnblockExecutor struct { type BlockOrUnblockExecutor struct {
*flag.FlagSet *flag.FlagSet
topLevelFlags TopLevelFlags printer *printer.Printer
resourceType string configDir string
accountName string resourceType string
command string accountName string
command string
} }
func NewBlockOrUnblockExecutor(tlf TopLevelFlags, name, summary string) *BlockOrUnblockExecutor { func NewBlockOrUnblockExecutor(printer *printer.Printer, configDir, name, summary string) *BlockOrUnblockExecutor {
blockExe := BlockOrUnblockExecutor{ blockExe := BlockOrUnblockExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError), FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
topLevelFlags: tlf, printer: printer,
command: name, configDir: configDir,
command: name,
} }
blockExe.StringVar(&blockExe.resourceType, flagType, "", "Specify the type of resource to block or unblock") blockExe.StringVar(&blockExe.resourceType, flagType, "", "Specify the type of resource to block or unblock")
@ -46,7 +49,7 @@ func (b *BlockOrUnblockExecutor) Execute() error {
return UnsupportedTypeError{resourceType: b.resourceType} return UnsupportedTypeError{resourceType: b.resourceType}
} }
gtsClient, err := client.NewClientFromConfig(b.topLevelFlags.ConfigDir) gtsClient, err := client.NewClientFromConfig(b.configDir)
if err != nil { if err != nil {
return fmt.Errorf("unable to create the GoToSocial client: %w", err) return fmt.Errorf("unable to create the GoToSocial client: %w", err)
} }
@ -55,7 +58,7 @@ func (b *BlockOrUnblockExecutor) Execute() error {
} }
func (b *BlockOrUnblockExecutor) blockOrUnblockAccount(gtsClient *client.Client) error { func (b *BlockOrUnblockExecutor) blockOrUnblockAccount(gtsClient *client.Client) error {
accountID, err := getAccountID(gtsClient, false, b.accountName, b.topLevelFlags.ConfigDir) accountID, err := getAccountID(gtsClient, false, b.accountName, b.configDir)
if err != nil { if err != nil {
return fmt.Errorf("received an error while getting the account ID: %w", err) return fmt.Errorf("received an error while getting the account ID: %w", err)
} }
@ -75,7 +78,7 @@ func (b *BlockOrUnblockExecutor) blockAccount(gtsClient *client.Client, accountI
return fmt.Errorf("unable to block the account: %w", err) return fmt.Errorf("unable to block the account: %w", err)
} }
fmt.Println("Successfully blocked the account.") b.printer.PrintSuccess("Successfully blocked the account.")
return nil return nil
} }
@ -85,7 +88,7 @@ func (b *BlockOrUnblockExecutor) unblockAccount(gtsClient *client.Client, accoun
return fmt.Errorf("unable to unblock the account: %w", err) return fmt.Errorf("unable to unblock the account: %w", err)
} }
fmt.Println("Successfully unblocked the account.") b.printer.PrintSuccess("Successfully unblocked the account.")
return nil return nil
} }

View file

@ -11,39 +11,42 @@ import (
"codeflow.dananglin.me.uk/apollo/enbas/internal/client" "codeflow.dananglin.me.uk/apollo/enbas/internal/client"
"codeflow.dananglin.me.uk/apollo/enbas/internal/model" "codeflow.dananglin.me.uk/apollo/enbas/internal/model"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities" "codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
) )
type CreateExecutor struct { type CreateExecutor struct {
*flag.FlagSet *flag.FlagSet
topLevelFlags TopLevelFlags printer *printer.Printer
addPoll bool addPoll bool
boostable bool boostable bool
federated bool federated bool
likeable bool likeable bool
pollAllowsMultipleChoices bool pollAllowsMultipleChoices bool
pollHidesVoteCounts bool pollHidesVoteCounts bool
replyable bool replyable bool
sensitive *bool sensitive *bool
content string configDir string
contentType string content string
fromFile string contentType string
language string fromFile string
resourceType string language string
listTitle string resourceType string
listRepliesPolicy string listTitle string
spoilerText string listRepliesPolicy string
visibility string spoilerText string
pollExpiresIn TimeDurationFlagValue visibility string
pollOptions MultiStringFlagValue pollExpiresIn TimeDurationFlagValue
pollOptions MultiStringFlagValue
} }
func NewCreateExecutor(tlf TopLevelFlags, name, summary string) *CreateExecutor { func NewCreateExecutor(printer *printer.Printer, configDir, name, summary string) *CreateExecutor {
createExe := CreateExecutor{ createExe := CreateExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError), FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
topLevelFlags: tlf, printer: printer,
configDir: configDir,
} }
createExe.BoolVar(&createExe.boostable, flagEnableReposts, true, "Specify if the status can be reposted/boosted by others") createExe.BoolVar(&createExe.boostable, flagEnableReposts, true, "Specify if the status can be reposted/boosted by others")
@ -87,7 +90,7 @@ func (c *CreateExecutor) Execute() error {
return FlagNotSetError{flagText: flagType} return FlagNotSetError{flagText: flagType}
} }
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.ConfigDir) gtsClient, err := client.NewClientFromConfig(c.configDir)
if err != nil { if err != nil {
return fmt.Errorf("unable to create the GoToSocial client: %w", err) return fmt.Errorf("unable to create the GoToSocial client: %w", err)
} }
@ -125,8 +128,8 @@ func (c *CreateExecutor) createList(gtsClient *client.Client) error {
return fmt.Errorf("unable to create the list: %w", err) return fmt.Errorf("unable to create the list: %w", err)
} }
fmt.Println("Successfully created the following list:") c.printer.PrintSuccess("Successfully created the following list:")
utilities.Display(list, *c.topLevelFlags.NoColor, c.topLevelFlags.Pager) c.printer.PrintList(list)
return nil return nil
} }
@ -217,13 +220,13 @@ func (c *CreateExecutor) createStatus(gtsClient *client.Client) error {
form.Poll = &poll form.Poll = &poll
} }
status, err := gtsClient.CreateStatus(form) _, err = gtsClient.CreateStatus(form)
if err != nil { if err != nil {
return fmt.Errorf("unable to create the status: %w", err) return fmt.Errorf("unable to create the status: %w", err)
} }
fmt.Println("Successfully created the following status:") c.printer.PrintSuccess("Successfully created the following status:")
utilities.Display(status, *c.topLevelFlags.NoColor, c.topLevelFlags.Pager) //utilities.Display(status, *c.topLevelFlags.NoColor, c.topLevelFlags.Pager)
return nil return nil
} }

View file

@ -9,20 +9,24 @@ import (
"fmt" "fmt"
"codeflow.dananglin.me.uk/apollo/enbas/internal/client" "codeflow.dananglin.me.uk/apollo/enbas/internal/client"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
) )
type DeleteExecutor struct { type DeleteExecutor struct {
*flag.FlagSet *flag.FlagSet
topLevelFlags TopLevelFlags printer *printer.Printer
resourceType string configDir string
listID string resourceType string
listID string
} }
func NewDeleteExecutor(tlf TopLevelFlags, name, summary string) *DeleteExecutor { func NewDeleteExecutor(printer *printer.Printer, configDir, name, summary string) *DeleteExecutor {
deleteExe := DeleteExecutor{ deleteExe := DeleteExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError), FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
topLevelFlags: tlf,
printer: printer,
configDir: configDir,
} }
deleteExe.StringVar(&deleteExe.resourceType, flagType, "", "Specify the type of resource to delete") deleteExe.StringVar(&deleteExe.resourceType, flagType, "", "Specify the type of resource to delete")
@ -47,7 +51,7 @@ func (d *DeleteExecutor) Execute() error {
return UnsupportedTypeError{resourceType: d.resourceType} return UnsupportedTypeError{resourceType: d.resourceType}
} }
gtsClient, err := client.NewClientFromConfig(d.topLevelFlags.ConfigDir) gtsClient, err := client.NewClientFromConfig(d.configDir)
if err != nil { if err != nil {
return fmt.Errorf("unable to create the GoToSocial client: %w", err) return fmt.Errorf("unable to create the GoToSocial client: %w", err)
} }
@ -64,7 +68,7 @@ func (d *DeleteExecutor) deleteList(gtsClient *client.Client) error {
return fmt.Errorf("unable to delete the list: %w", err) return fmt.Errorf("unable to delete the list: %w", err)
} }
fmt.Println("The list was successfully deleted.") d.printer.PrintSuccess("The list was successfully deleted.")
return nil return nil
} }

View file

@ -10,23 +10,26 @@ import (
"codeflow.dananglin.me.uk/apollo/enbas/internal/client" "codeflow.dananglin.me.uk/apollo/enbas/internal/client"
"codeflow.dananglin.me.uk/apollo/enbas/internal/model" "codeflow.dananglin.me.uk/apollo/enbas/internal/model"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities" "codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
) )
type EditExecutor struct { type EditExecutor struct {
*flag.FlagSet *flag.FlagSet
topLevelFlags TopLevelFlags printer *printer.Printer
configDir string
resourceType string resourceType string
listID string listID string
listTitle string listTitle string
listRepliesPolicy string listRepliesPolicy string
} }
func NewEditExecutor(tlf TopLevelFlags, name, summary string) *EditExecutor { func NewEditExecutor(printer *printer.Printer, configDir, name, summary string) *EditExecutor {
editExe := EditExecutor{ editExe := EditExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError), FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
topLevelFlags: tlf,
printer: printer,
configDir: configDir,
} }
editExe.StringVar(&editExe.resourceType, flagType, "", "Specify the type of resource to update") editExe.StringVar(&editExe.resourceType, flagType, "", "Specify the type of resource to update")
@ -53,7 +56,7 @@ func (e *EditExecutor) Execute() error {
return UnsupportedTypeError{resourceType: e.resourceType} return UnsupportedTypeError{resourceType: e.resourceType}
} }
gtsClient, err := client.NewClientFromConfig(e.topLevelFlags.ConfigDir) gtsClient, err := client.NewClientFromConfig(e.configDir)
if err != nil { if err != nil {
return fmt.Errorf("unable to create the GoToSocial client: %w", err) return fmt.Errorf("unable to create the GoToSocial client: %w", err)
} }
@ -89,8 +92,8 @@ func (e *EditExecutor) editList(gtsClient *client.Client) error {
return fmt.Errorf("unable to update the list: %w", err) return fmt.Errorf("unable to update the list: %w", err)
} }
fmt.Println("Successfully updated the list.") e.printer.PrintSuccess("Successfully updated the list.")
utilities.Display(updatedList, *e.topLevelFlags.NoColor, e.topLevelFlags.Pager) e.printer.PrintList(updatedList)
return nil return nil
} }

View file

@ -9,25 +9,28 @@ import (
"fmt" "fmt"
"codeflow.dananglin.me.uk/apollo/enbas/internal/client" "codeflow.dananglin.me.uk/apollo/enbas/internal/client"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
) )
type FollowOrUnfollowExecutor struct { type FollowOrUnfollowExecutor struct {
*flag.FlagSet *flag.FlagSet
topLevelFlags TopLevelFlags printer *printer.Printer
resourceType string configDir string
accountName string resourceType string
showReposts bool accountName string
notify bool showReposts bool
action string notify bool
action string
} }
func NewFollowOrUnfollowExecutor(tlf TopLevelFlags, name, summary string) *FollowOrUnfollowExecutor { func NewFollowOrUnfollowExecutor(printer *printer.Printer, configDir, name, summary string) *FollowOrUnfollowExecutor {
command := FollowOrUnfollowExecutor{ command := FollowOrUnfollowExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError), FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
topLevelFlags: tlf, printer: printer,
action: name, configDir: configDir,
action: name,
} }
command.StringVar(&command.resourceType, flagType, "", "Specify the type of resource to follow") command.StringVar(&command.resourceType, flagType, "", "Specify the type of resource to follow")
@ -50,7 +53,7 @@ func (f *FollowOrUnfollowExecutor) Execute() error {
return UnsupportedTypeError{resourceType: f.resourceType} return UnsupportedTypeError{resourceType: f.resourceType}
} }
gtsClient, err := client.NewClientFromConfig(f.topLevelFlags.ConfigDir) gtsClient, err := client.NewClientFromConfig(f.configDir)
if err != nil { if err != nil {
return fmt.Errorf("unable to create the GoToSocial client: %w", err) return fmt.Errorf("unable to create the GoToSocial client: %w", err)
} }
@ -59,7 +62,7 @@ func (f *FollowOrUnfollowExecutor) Execute() error {
} }
func (f *FollowOrUnfollowExecutor) followOrUnfollowAccount(gtsClient *client.Client) error { func (f *FollowOrUnfollowExecutor) followOrUnfollowAccount(gtsClient *client.Client) error {
accountID, err := getAccountID(gtsClient, false, f.accountName, f.topLevelFlags.ConfigDir) accountID, err := getAccountID(gtsClient, false, f.accountName, f.configDir)
if err != nil { if err != nil {
return fmt.Errorf("received an error while getting the account ID: %w", err) return fmt.Errorf("received an error while getting the account ID: %w", err)
} }
@ -85,7 +88,7 @@ func (f *FollowOrUnfollowExecutor) followAccount(gtsClient *client.Client, accou
return fmt.Errorf("unable to follow the account: %w", err) return fmt.Errorf("unable to follow the account: %w", err)
} }
fmt.Println("The follow request was sent successfully.") f.printer.PrintSuccess("Successfully sent the follow request.")
return nil return nil
} }
@ -95,7 +98,7 @@ func (f *FollowOrUnfollowExecutor) unfollowAccount(gtsClient *client.Client, acc
return fmt.Errorf("unable to unfollow the account: %w", err) return fmt.Errorf("unable to unfollow the account: %w", err)
} }
fmt.Println("Successfully unfollowed the account.") f.printer.PrintSuccess("Successfully unfollowed the account.")
return nil return nil
} }

View file

@ -10,16 +10,19 @@ import (
"codeflow.dananglin.me.uk/apollo/enbas/internal/client" "codeflow.dananglin.me.uk/apollo/enbas/internal/client"
"codeflow.dananglin.me.uk/apollo/enbas/internal/model" "codeflow.dananglin.me.uk/apollo/enbas/internal/model"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities" "codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
) )
type ShowExecutor struct { type ShowExecutor struct {
*flag.FlagSet *flag.FlagSet
topLevelFlags TopLevelFlags
printer *printer.Printer
myAccount bool myAccount bool
skipAccountRelationship bool skipAccountRelationship bool
showUserPreferences bool showUserPreferences bool
showInBrowser bool showInBrowser bool
configDir string
resourceType string resourceType string
accountName string accountName string
statusID string statusID string
@ -30,10 +33,12 @@ type ShowExecutor struct {
limit int limit int
} }
func NewShowExecutor(tlf TopLevelFlags, name, summary string) *ShowExecutor { func NewShowExecutor(printer *printer.Printer, configDir, name, summary string) *ShowExecutor {
showExe := ShowExecutor{ showExe := ShowExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError), FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
topLevelFlags: tlf,
printer: printer,
configDir: configDir,
} }
showExe.BoolVar(&showExe.myAccount, flagMyAccount, false, "Set to true to lookup your account") showExe.BoolVar(&showExe.myAccount, flagMyAccount, false, "Set to true to lookup your account")
@ -80,7 +85,7 @@ func (s *ShowExecutor) Execute() error {
return UnsupportedTypeError{resourceType: s.resourceType} return UnsupportedTypeError{resourceType: s.resourceType}
} }
gtsClient, err := client.NewClientFromConfig(s.topLevelFlags.ConfigDir) gtsClient, err := client.NewClientFromConfig(s.configDir)
if err != nil { if err != nil {
return fmt.Errorf("unable to create the GoToSocial client: %w", err) return fmt.Errorf("unable to create the GoToSocial client: %w", err)
} }
@ -94,7 +99,7 @@ func (s *ShowExecutor) showInstance(gtsClient *client.Client) error {
return fmt.Errorf("unable to retrieve the instance details: %w", err) return fmt.Errorf("unable to retrieve the instance details: %w", err)
} }
utilities.Display(instance, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(instance, false, "")
return nil return nil
} }
@ -106,7 +111,7 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
) )
if s.myAccount { if s.myAccount {
account, err = getMyAccount(gtsClient, s.topLevelFlags.ConfigDir) account, err = getMyAccount(gtsClient, s.configDir)
if err != nil { if err != nil {
return fmt.Errorf("received an error while getting the account details: %w", err) return fmt.Errorf("received an error while getting the account details: %w", err)
} }
@ -127,7 +132,7 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
return nil return nil
} }
utilities.Display(account, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(account, false, "")
if !s.myAccount && !s.skipAccountRelationship { if !s.myAccount && !s.skipAccountRelationship {
relationship, err := gtsClient.GetAccountRelationship(account.ID) relationship, err := gtsClient.GetAccountRelationship(account.ID)
@ -135,7 +140,7 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
return fmt.Errorf("unable to retrieve the relationship to this account: %w", err) return fmt.Errorf("unable to retrieve the relationship to this account: %w", err)
} }
utilities.Display(relationship, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(relationship, false, "")
} }
if s.myAccount && s.showUserPreferences { if s.myAccount && s.showUserPreferences {
@ -144,7 +149,7 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
return fmt.Errorf("unable to retrieve the user preferences: %w", err) return fmt.Errorf("unable to retrieve the user preferences: %w", err)
} }
utilities.Display(preferences, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(preferences, false, "")
} }
return nil return nil
@ -166,7 +171,7 @@ func (s *ShowExecutor) showStatus(gtsClient *client.Client) error {
return nil return nil
} }
utilities.Display(status, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(status, false, "")
return nil return nil
} }
@ -210,12 +215,12 @@ func (s *ShowExecutor) showTimeline(gtsClient *client.Client) error {
} }
if len(timeline.Statuses) == 0 { if len(timeline.Statuses) == 0 {
fmt.Println("There are no statuses in this timeline.") s.printer.PrintInfo("There are no statuses in this timeline.\n")
return nil return nil
} }
utilities.Display(timeline, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(timeline, false, "")
return nil return nil
} }
@ -244,7 +249,7 @@ func (s *ShowExecutor) showList(gtsClient *client.Client) error {
list.Accounts = accountMap list.Accounts = accountMap
} }
utilities.Display(list, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) s.printer.PrintList(list)
return nil return nil
} }
@ -256,18 +261,18 @@ func (s *ShowExecutor) showLists(gtsClient *client.Client) error {
} }
if len(lists) == 0 { if len(lists) == 0 {
fmt.Println("You have no lists.") s.printer.PrintInfo("You have no lists.\n")
return nil return nil
} }
utilities.Display(lists, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) s.printer.PrintLists(lists)
return nil return nil
} }
func (s *ShowExecutor) showFollowers(gtsClient *client.Client) error { func (s *ShowExecutor) showFollowers(gtsClient *client.Client) error {
accountID, err := getAccountID(gtsClient, s.myAccount, s.accountName, s.topLevelFlags.ConfigDir) accountID, err := getAccountID(gtsClient, s.myAccount, s.accountName, s.configDir)
if err != nil { if err != nil {
return fmt.Errorf("received an error while getting the account ID: %w", err) return fmt.Errorf("received an error while getting the account ID: %w", err)
} }
@ -278,16 +283,16 @@ func (s *ShowExecutor) showFollowers(gtsClient *client.Client) error {
} }
if len(followers.Accounts) > 0 { if len(followers.Accounts) > 0 {
utilities.Display(followers, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(followers, false, "")
} else { } else {
fmt.Println("There are no followers for this account or the list is hidden.") s.printer.PrintInfo("There are no followers for this account (or the list is hidden).\n")
} }
return nil return nil
} }
func (s *ShowExecutor) showFollowing(gtsClient *client.Client) error { func (s *ShowExecutor) showFollowing(gtsClient *client.Client) error {
accountID, err := getAccountID(gtsClient, s.myAccount, s.accountName, s.topLevelFlags.ConfigDir) accountID, err := getAccountID(gtsClient, s.myAccount, s.accountName, s.configDir)
if err != nil { if err != nil {
return fmt.Errorf("received an error while getting the account ID: %w", err) return fmt.Errorf("received an error while getting the account ID: %w", err)
} }
@ -298,9 +303,9 @@ func (s *ShowExecutor) showFollowing(gtsClient *client.Client) error {
} }
if len(following.Accounts) > 0 { if len(following.Accounts) > 0 {
utilities.Display(following, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(following, false, "")
} else { } else {
fmt.Println("This account is not following anyone or the list is hidden.") s.printer.PrintInfo("This account is not following anyone or the list is hidden.\n")
} }
return nil return nil
@ -313,9 +318,9 @@ func (s *ShowExecutor) showBlocked(gtsClient *client.Client) error {
} }
if len(blocked.Accounts) > 0 { if len(blocked.Accounts) > 0 {
utilities.Display(blocked, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(blocked, false, "")
} else { } else {
fmt.Println("You have no blocked accounts.") s.printer.PrintInfo("You have no blocked accounts.\n")
} }
return nil return nil
@ -328,9 +333,9 @@ func (s *ShowExecutor) showBookmarks(gtsClient *client.Client) error {
} }
if len(bookmarks.Statuses) > 0 { if len(bookmarks.Statuses) > 0 {
utilities.Display(bookmarks, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(bookmarks, false, "")
} else { } else {
fmt.Println("You have no bookmarks.") s.printer.PrintInfo("You have no bookmarks.\n")
} }
return nil return nil
@ -343,9 +348,9 @@ func (s *ShowExecutor) showLiked(gtsClient *client.Client) error {
} }
if len(liked.Statuses) > 0 { if len(liked.Statuses) > 0 {
utilities.Display(liked, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(liked, false, "")
} else { } else {
fmt.Printf("You have no %s statuses.\n", s.resourceType) s.printer.PrintInfo("You have no " + s.resourceType + " statuses.\n")
} }
return nil return nil
@ -358,9 +363,9 @@ func (s *ShowExecutor) showFollowRequests(gtsClient *client.Client) error {
} }
if len(accounts.Accounts) > 0 { if len(accounts.Accounts) > 0 {
utilities.Display(accounts, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(accounts, false, "")
} else { } else {
fmt.Println("You have no follow requests.") s.printer.PrintInfo("You have no follow requests.\n")
} }
return nil return nil
@ -376,7 +381,7 @@ func (s *ShowExecutor) showPoll(gtsClient *client.Client) error {
return fmt.Errorf("unable to retrieve the poll: %w", err) return fmt.Errorf("unable to retrieve the poll: %w", err)
} }
utilities.Display(poll, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager) utilities.Display(poll, false, "")
return nil return nil
} }

View file

@ -9,20 +9,23 @@ import (
"fmt" "fmt"
"codeflow.dananglin.me.uk/apollo/enbas/internal/config" "codeflow.dananglin.me.uk/apollo/enbas/internal/config"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
) )
type SwitchExecutor struct { type SwitchExecutor struct {
*flag.FlagSet *flag.FlagSet
topLevelFlags TopLevelFlags configDir string
toResourceType string toResourceType string
accountName string accountName string
printer *printer.Printer
} }
func NewSwitchExecutor(tlf TopLevelFlags, name, summary string) *SwitchExecutor { func NewSwitchExecutor(printer *printer.Printer, configDir, name, summary string) *SwitchExecutor {
switchExe := SwitchExecutor{ switchExe := SwitchExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError), FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
topLevelFlags: tlf, printer: printer,
configDir: configDir,
} }
switchExe.StringVar(&switchExe.toResourceType, flagTo, "", "The account to switch to") switchExe.StringVar(&switchExe.toResourceType, flagTo, "", "The account to switch to")
@ -51,11 +54,11 @@ func (s *SwitchExecutor) switchToAccount() error {
return NoAccountSpecifiedError{} return NoAccountSpecifiedError{}
} }
if err := config.UpdateCurrentAccount(s.accountName, s.topLevelFlags.ConfigDir); err != nil { if err := config.UpdateCurrentAccount(s.accountName, s.configDir); err != nil {
return fmt.Errorf("unable to switch account to the account: %w", err) return fmt.Errorf("unable to switch account to the account: %w", err)
} }
fmt.Printf("The current account is now set to %q.\n", s.accountName) s.printer.PrintSuccess("The current account is now set to '" + s.accountName + "'.")
return nil return nil
} }

View file

@ -6,13 +6,13 @@ package executor
import ( import (
"flag" "flag"
"os"
"strings" "codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
"text/tabwriter"
) )
type VersionExecutor struct { type VersionExecutor struct {
*flag.FlagSet *flag.FlagSet
printer *printer.Printer
showFullVersion bool showFullVersion bool
binaryVersion string binaryVersion string
buildTime string buildTime string
@ -20,9 +20,19 @@ type VersionExecutor struct {
gitCommit string gitCommit string
} }
func NewVersionExecutor(name, summary, binaryVersion, buildTime, goVersion, gitCommit string) *VersionExecutor { func NewVersionExecutor(
enbasPrinter *printer.Printer,
name,
summary,
binaryVersion,
buildTime,
goVersion,
gitCommit string,
) *VersionExecutor {
command := VersionExecutor{ command := VersionExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError), FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
printer: enbasPrinter,
binaryVersion: binaryVersion, binaryVersion: binaryVersion,
buildTime: buildTime, buildTime: buildTime,
goVersion: goVersion, goVersion: goVersion,
@ -38,24 +48,7 @@ func NewVersionExecutor(name, summary, binaryVersion, buildTime, goVersion, gitC
} }
func (v *VersionExecutor) Execute() error { func (v *VersionExecutor) Execute() error {
var builder strings.Builder v.printer.PrintVersion(v.showFullVersion, v.binaryVersion, v.buildTime, v.goVersion, v.gitCommit)
if v.showFullVersion {
builder.WriteString("Enbas\n")
tableWriter := tabwriter.NewWriter(&builder, 0, 8, 0, '\t', 0)
tableWriter.Write([]byte(" Version:\t" + v.binaryVersion + "\n"))
tableWriter.Write([]byte(" Git commit:\t" + v.gitCommit + "\n"))
tableWriter.Write([]byte(" Go version:\t" + v.goVersion + "\n"))
tableWriter.Write([]byte(" Build date:\t" + v.buildTime + "\n"))
tableWriter.Flush()
} else {
builder.WriteString("Enbas " + v.binaryVersion + "\n")
}
os.Stdout.WriteString(builder.String())
return nil return nil
} }

View file

@ -9,18 +9,22 @@ import (
"fmt" "fmt"
"codeflow.dananglin.me.uk/apollo/enbas/internal/config" "codeflow.dananglin.me.uk/apollo/enbas/internal/config"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
) )
type WhoAmIExecutor struct { type WhoAmIExecutor struct {
*flag.FlagSet *flag.FlagSet
topLevelFlags TopLevelFlags printer *printer.Printer
configDir string
} }
func NewWhoAmIExecutor(tlf TopLevelFlags, name, summary string) *WhoAmIExecutor { func NewWhoAmIExecutor(printer *printer.Printer, configDir, name, summary string) *WhoAmIExecutor {
whoExe := WhoAmIExecutor{ whoExe := WhoAmIExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError), FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
topLevelFlags: tlf,
printer: printer,
configDir: configDir,
} }
whoExe.Usage = commandUsageFunc(name, summary, whoExe.FlagSet) whoExe.Usage = commandUsageFunc(name, summary, whoExe.FlagSet)
@ -29,12 +33,12 @@ func NewWhoAmIExecutor(tlf TopLevelFlags, name, summary string) *WhoAmIExecutor
} }
func (c *WhoAmIExecutor) Execute() error { func (c *WhoAmIExecutor) Execute() error {
config, err := config.NewCredentialsConfigFromFile(c.topLevelFlags.ConfigDir) config, err := config.NewCredentialsConfigFromFile(c.configDir)
if err != nil { if err != nil {
return fmt.Errorf("unable to load the credential config: %w", err) return fmt.Errorf("unable to load the credential config: %w", err)
} }
fmt.Printf("You are logged in as %q.\n", config.CurrentAccount) c.printer.PrintInfo("You are logged in as '" + config.CurrentAccount + "'.\n")
return nil return nil
} }

View file

@ -7,8 +7,6 @@ package model
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
) )
type ListRepliesPolicy int type ListRepliesPolicy int
@ -107,53 +105,3 @@ type List struct {
Title string `json:"title"` Title string `json:"title"`
Accounts map[string]string Accounts map[string]string
} }
func (l List) Display(noColor bool) string {
format := `
%s
%s
%s
%s
%s
%s
%s`
output := fmt.Sprintf(
format,
utilities.HeaderFormat(noColor, "LIST TITLE:"), l.Title,
utilities.HeaderFormat(noColor, "LIST ID:"), l.ID,
utilities.HeaderFormat(noColor, "REPLIES POLICY:"), l.RepliesPolicy,
utilities.HeaderFormat(noColor, "ADDED ACCOUNTS:"),
)
if len(l.Accounts) > 0 {
for acct, name := range l.Accounts {
output += "\n • " + utilities.FullDisplayNameFormat(noColor, name, acct)
}
} else {
output += "\n None"
}
output += "\n"
return output
}
type Lists []List
func (l Lists) Display(noColor bool) string {
output := "\n" + utilities.HeaderFormat(noColor, "LISTS")
for i := range l {
output += fmt.Sprintf(
"\n • %s (%s)",
l[i].Title,
l[i].ID,
)
}
return output
}

View file

@ -0,0 +1 @@
package printer

45
internal/printer/list.go Normal file
View file

@ -0,0 +1,45 @@
package printer
import (
"strings"
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
)
func (p Printer) PrintList(list model.List) {
var builder strings.Builder
builder.WriteString(p.headerFormat("\n" + "LIST TITLE:") + "\n")
builder.WriteString(list.Title + "\n\n")
builder.WriteString(p.headerFormat("LIST ID:") + "\n")
builder.WriteString(list.ID + "\n\n")
builder.WriteString(p.headerFormat("REPLIES POLICY:") + "\n")
builder.WriteString(list.RepliesPolicy.String() + "\n\n")
builder.WriteString(p.headerFormat("ADDED ACCOUNTS:"))
if len(list.Accounts) > 0 {
for acct, name := range list.Accounts {
builder.WriteString("\n" + p.bullet + p.fullDisplayNameFormat(name, acct))
}
} else {
builder.WriteString("\n" + "None")
}
builder.WriteString("\n")
printToStdout(builder.String())
}
func (p Printer) PrintLists(lists []model.List) {
var builder strings.Builder
builder.WriteString("\n" + p.headerFormat("LISTS"))
for i := range lists {
builder.WriteString("\n" + p.bullet + " " + lists[i].Title + " (" + lists[i].ID + ")")
}
builder.WriteString("\n")
printToStdout(builder.String())
}

126
internal/printer/printer.go Normal file
View file

@ -0,0 +1,126 @@
// SPDX-FileCopyrightText: 2024 Dan Anglin <d.n.i.anglin@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-or-later
package printer
import (
"os"
"regexp"
"strings"
"time"
)
type theme struct {
reset string
boldblue string
boldmagenta string
green string
}
type Printer struct {
theme theme
noColor bool
maxTerminalWidth int
pager string
statusSeparator string
bullet string
pollMeterSymbol string
successSymbol string
failureSymbol string
dateFormat string
dateTimeFormat string
}
func NewPrinter(
noColor bool,
pager string,
maxTerminalWidth int,
) *Printer {
theme := theme{
reset: "\033[0m",
boldblue: "\033[34;1m",
boldmagenta: "\033[35;1m",
green: "\033[32m",
}
return &Printer{
noColor: noColor,
maxTerminalWidth: maxTerminalWidth,
pager: pager,
statusSeparator: strings.Repeat("─", maxTerminalWidth),
bullet: "\u2022",
pollMeterSymbol: "\u2501",
successSymbol: "\u2714",
failureSymbol: "\u2717",
dateFormat: "02 Jan 2006",
dateTimeFormat: "02 Jan 2006, 15:04 (MST)",
theme: theme,
}
}
func (p Printer) PrintSuccess(text string) {
success := p.theme.green + p.successSymbol + p.theme.reset
if p.noColor {
success = p.successSymbol
}
printToStdout(success + " " + text + "\n")
}
func (p Printer) PrintFailure(text string) {
printToStderr(p.failureSymbol + " " + text)
}
func (p Printer) PrintInfo(text string) {
printToStdout(text)
}
func (p Printer) headerFormat(text string) string {
if p.noColor {
return text
}
return p.theme.boldblue + text + p.theme.reset
}
func (p Printer) fieldFormat(text string) string {
if p.noColor {
return text
}
return p.theme.green + text + p.theme.reset
}
func (p Printer) fullDisplayNameFormat(displayName, acct string) string {
// use this pattern to remove all emoji strings
pattern := regexp.MustCompile(`\s:[A-Za-z0-9_]*:`)
var builder strings.Builder
if p.noColor {
builder.WriteString(pattern.ReplaceAllString(displayName, ""))
} else {
builder.WriteString(p.theme.boldmagenta + pattern.ReplaceAllString(displayName, "") + p.theme.reset)
}
builder.WriteString(" (@" + acct + ")")
return builder.String()
}
func (p Printer) formatDate(date time.Time) string {
return date.Local().Format(p.dateFormat)
}
func (p Printer) formatDateTime(date time.Time) string {
return date.Local().Format(p.dateTimeFormat)
}
func printToStdout(text string) {
os.Stdout.WriteString(text)
}
func printToStderr(text string) {
os.Stderr.WriteString(text)
}

View file

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: 2024 Dan Anglin <d.n.i.anglin@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-or-later
package printer
import (
"strings"
"text/tabwriter"
)
func (p Printer) PrintVersion(showFullVersion bool, binaryVersion, buildTime, goVersion, gitCommit string) {
if !showFullVersion {
printToStdout("Enbas " + binaryVersion + "\n")
return
}
var builder strings.Builder
builder.WriteString(p.headerFormat("Enbas") + "\n\n")
tableWriter := tabwriter.NewWriter(&builder, 0, 4, 1, ' ', 0)
_, _ = tableWriter.Write([]byte(p.fieldFormat("Version:") + "\t" + binaryVersion + "\n"))
_, _ = tableWriter.Write([]byte(p.fieldFormat("Git commit:") + "\t" + gitCommit + "\n"))
_, _ = tableWriter.Write([]byte(p.fieldFormat("Go version:") + "\t" + goVersion + "\n"))
_, _ = tableWriter.Write([]byte(p.fieldFormat("Build date:") + "\t" + buildTime + "\n"))
tableWriter.Flush()
printToStdout(builder.String())
}