Consolidate common model properties to reduce duplication

This commit is contained in:
Christian Rocha 2020-11-17 17:37:52 -05:00 committed by Christian Rocha
parent ae4c85e97d
commit 4e6460682e
6 changed files with 93 additions and 105 deletions

View file

@ -6,8 +6,8 @@ import "path/filepath"
func ignorePatterns(m model) []string {
return []string{
filepath.Join(m.cfg.HomeDir, "Library"),
m.cfg.Gopath,
filepath.Join(m.general.cfg.HomeDir, "Library"),
m.general.cfg.Gopath,
"node_modules",
".*",
}

View file

@ -4,7 +4,7 @@ package ui
func ignorePatterns(m model) []string {
return []string{
m.cfg.Gopath,
m.general.cfg.Gopath,
"node_modules",
".*",
}

View file

@ -65,16 +65,12 @@ const (
)
type pagerModel struct {
cfg *Config
cc *charm.Client
authStatus authStatus
viewport viewport.Model
state pagerState
width int
height int
showHelp bool
textInput textinput.Model
spinner spinner.Model
general *general
viewport viewport.Model
state pagerState
showHelp bool
textInput textinput.Model
spinner spinner.Model
statusMessage string
statusMessageTimer *time.Timer
@ -88,7 +84,7 @@ type pagerModel struct {
stashedDocument *markdown
}
func newPagerModel(cfg *Config, as authStatus) pagerModel {
func newPagerModel(general *general) pagerModel {
// Init viewport
vp := viewport.Model{}
vp.YPosition = 0
@ -114,18 +110,15 @@ func newPagerModel(cfg *Config, as authStatus) pagerModel {
sp.MinimumLifetime = time.Millisecond * 180
return pagerModel{
cfg: cfg,
state: pagerStateBrowse,
authStatus: as,
textInput: ti,
viewport: vp,
spinner: sp,
general: general,
state: pagerStateBrowse,
textInput: ti,
viewport: vp,
spinner: sp,
}
}
func (m *pagerModel) setSize(w, h int) {
m.width = w
m.height = h
m.viewport.Width = w
m.viewport.Height = h - statusBarHeight
m.textInput.Width = w -
@ -146,7 +139,7 @@ func (m *pagerModel) setContent(s string) {
func (m *pagerModel) toggleHelp() {
m.showHelp = !m.showHelp
m.setSize(m.width, m.height)
m.setSize(m.general.width, m.general.height)
if m.viewport.PastBottom() {
m.viewport.GotoBottom()
}
@ -198,7 +191,7 @@ func (m pagerModel) Update(msg tea.Msg) (pagerModel, tea.Cmd) {
var cmd tea.Cmd
if m.textInput.Value() != m.currentDocument.Note { // don't update if the note didn't change
m.currentDocument.Note = m.textInput.Value() // update optimistically
cmd = saveDocumentNote(m.cc, m.currentDocument.ID, m.currentDocument.Note)
cmd = saveDocumentNote(m.general.cc, m.currentDocument.ID, m.currentDocument.Note)
}
m.state = pagerStateBrowse
m.textInput.Reset()
@ -246,7 +239,7 @@ func (m pagerModel) Update(msg tea.Msg) (pagerModel, tea.Cmd) {
return m, textinput.Blink
case "s":
if m.authStatus != authOK {
if m.general.authStatus != authOK {
break
}
@ -256,7 +249,7 @@ func (m pagerModel) Update(msg tea.Msg) (pagerModel, tea.Cmd) {
m.spinner.Start()
cmds = append(
cmds,
stashDocument(m.cc, m.currentDocument),
stashDocument(m.general.cc, m.currentDocument),
spinner.Tick,
)
}
@ -402,7 +395,7 @@ func (m pagerModel) statusBarView(b *strings.Builder) {
}
}
note = truncate(" "+note+" ", max(0,
m.width-
m.general.width-
ansi.PrintableRuneWidth(logo)-
ansi.PrintableRuneWidth(statusIndicator)-
ansi.PrintableRuneWidth(scrollPercent)-
@ -416,7 +409,7 @@ func (m pagerModel) statusBarView(b *strings.Builder) {
// Empty space
padding := max(0,
m.width-
m.general.width-
ansi.PrintableRuneWidth(logo)-
ansi.PrintableRuneWidth(statusIndicator)-
ansi.PrintableRuneWidth(note)-
@ -447,7 +440,7 @@ func (m pagerModel) setNoteView(b *strings.Builder) {
func (m pagerModel) helpView() (s string) {
memoOrStash := "m set memo"
if m.authStatus == authOK && m.currentDocument.markdownType == localMarkdown {
if m.general.authStatus == authOK && m.currentDocument.markdownType == localMarkdown {
memoOrStash = "s stash this document"
}
@ -479,11 +472,11 @@ func (m pagerModel) helpView() (s string) {
s = indent(s, 2)
// Fill up empty cells with spaces for background coloring
if m.width > 0 {
if m.general.width > 0 {
lines := strings.Split(s, "\n")
for i := 0; i < len(lines); i++ {
l := runewidth.StringWidth(lines[i])
n := max(m.width-l, 0)
n := max(m.general.width-l, 0)
lines[i] += strings.Repeat(" ", n)
}
@ -516,13 +509,13 @@ func glamourRender(m pagerModel, markdown string) (string, error) {
// initialize glamour
var gs glamour.TermRendererOption
if m.cfg.GlamourStyle == "auto" {
if m.general.cfg.GlamourStyle == "auto" {
gs = glamour.WithAutoStyle()
} else {
gs = glamour.WithStylePath(m.cfg.GlamourStyle)
gs = glamour.WithStylePath(m.general.cfg.GlamourStyle)
}
width := max(0, min(int(m.cfg.GlamourMaxWidth), m.viewport.Width))
width := max(0, min(int(m.general.cfg.GlamourMaxWidth), m.viewport.Width))
r, err := glamour.NewTermRenderer(
gs,
glamour.WithWordWrap(width),

View file

@ -69,18 +69,13 @@ const (
)
type stashModel struct {
cc *charm.Client
cfg *Config
cwd string
authStatus authStatus
general *general
state stashState
err error
markdowns []*markdown
spinner spinner.Model
noteInput textinput.Model
filterInput textinput.Model
terminalWidth int
terminalHeight int
stashFullyLoaded bool // have we loaded all available stashed documents from the server?
loadingFromNetwork bool // are we currently loading something from the network?
loaded DocumentType // load status for news, stash and local files loading; we find out exactly with bitmasking
@ -110,33 +105,33 @@ type stashModel struct {
}
func (m stashModel) localOnly() bool {
return m.cfg.DocumentTypes == LocalDocuments
return m.general.cfg.DocumentTypes == LocalDocuments
}
func (m stashModel) stashedOnly() bool {
return m.cfg.DocumentTypes&LocalDocuments == 0
return m.general.cfg.DocumentTypes&LocalDocuments == 0
}
func (m stashModel) loadingDone() bool {
// Do the types loaded match the types we want to have?
return m.loaded == m.cfg.DocumentTypes
return m.loaded == m.general.cfg.DocumentTypes
}
func (m *stashModel) setSize(width, height int) {
m.terminalWidth = width
m.terminalHeight = height
m.general.width = width
m.general.height = height
// Update the paginator
m.setTotalPages()
m.noteInput.Width = m.terminalWidth - stashViewHorizontalPadding*2 - ansi.PrintableRuneWidth(m.noteInput.Prompt)
m.filterInput.Width = m.terminalWidth - stashViewHorizontalPadding*2 - ansi.PrintableRuneWidth(m.filterInput.Prompt)
m.noteInput.Width = width - stashViewHorizontalPadding*2 - ansi.PrintableRuneWidth(m.noteInput.Prompt)
m.filterInput.Width = width - stashViewHorizontalPadding*2 - ansi.PrintableRuneWidth(m.filterInput.Prompt)
}
// Sets the total paginator pages according to the amount of markdowns for the
// current state.
func (m *stashModel) setTotalPages() {
m.paginator.PerPage = max(1, (m.terminalHeight-stashViewTopPadding-stashViewBottomPadding)/stashViewItemHeight)
m.paginator.PerPage = max(1, (m.general.height-stashViewTopPadding-stashViewBottomPadding)/stashViewItemHeight)
if pages := len(m.getNotes()); pages < 1 {
m.paginator.SetTotalPages(1)
@ -298,7 +293,7 @@ func (m *stashModel) moveCursorDown() {
// INIT
func newStashModel(cfg *Config, as authStatus) stashModel {
func newStashModel(general *general) stashModel {
sp := spinner.NewModel()
sp.Spinner = spinner.Line
sp.ForegroundColor = common.SpinnerColor.String()
@ -323,8 +318,7 @@ func newStashModel(cfg *Config, as authStatus) stashModel {
si.Focus()
m := stashModel{
cfg: cfg,
authStatus: as,
general: general,
spinner: sp,
noteInput: ni,
filterInput: si,
@ -475,7 +469,7 @@ func stashUpdate(msg tea.Msg, m stashModel) (stashModel, tea.Cmd) {
if md.markdownType == localMarkdown {
cmds = append(cmds, loadLocalMarkdown(md))
} else {
cmds = append(cmds, loadRemoteMarkdown(m.cc, md.ID, md.markdownType))
cmds = append(cmds, loadRemoteMarkdown(m.general.cc, md.ID, md.markdownType))
}
cmds = append(cmds, spinner.Tick)
@ -530,7 +524,7 @@ func stashUpdate(msg tea.Msg, m stashModel) (stashModel, tea.Cmd) {
// Stash
case "s":
if pages == 0 || m.authStatus != authOK || m.selectedMarkdown() == nil {
if pages == 0 || m.general.authStatus != authOK || m.selectedMarkdown() == nil {
break
}
@ -553,7 +547,7 @@ func stashUpdate(msg tea.Msg, m stashModel) (stashModel, tea.Cmd) {
// Checks passed; perform the stash
m.filesStashing[md.localPath] = struct{}{}
cmds = append(cmds, stashDocument(m.cc, *md))
cmds = append(cmds, stashDocument(m.general.cc, *md))
if m.loadingDone() && !m.spinner.Visible() {
m.spinner.Start()
@ -635,7 +629,7 @@ func stashUpdate(msg tea.Msg, m stashModel) (stashModel, tea.Cmd) {
// If document was stashed during this session, convert it
// back to a local file.
md.markdownType = localMarkdown
md.Note = stripAbsolutePath(m.markdowns[i].localPath, m.cwd)
md.Note = stripAbsolutePath(m.markdowns[i].localPath, m.general.cwd)
} else {
// Delete optimistically and remove the stashed item
// before we've received a success response.
@ -651,7 +645,7 @@ func stashUpdate(msg tea.Msg, m stashModel) (stashModel, tea.Cmd) {
// Update pagination
m.setTotalPages()
return m, deleteStashedItem(m.cc, smd.ID)
return m, deleteStashedItem(m.general.cc, smd.ID)
default:
m.state = stashStateReady
@ -729,7 +723,7 @@ func stashUpdate(msg tea.Msg, m stashModel) (stashModel, tea.Cmd) {
// Set new note
md := m.selectedMarkdown()
newNote := m.noteInput.Value()
cmd := saveDocumentNote(m.cc, md.ID, newNote)
cmd := saveDocumentNote(m.general.cc, md.ID, newNote)
md.Note = newNote
m.noteInput.Reset()
m.state = stashStateReady
@ -775,7 +769,7 @@ func stashView(m stashModel) string {
// We need to fill any empty height with newlines so the footer reaches
// the bottom.
numBlankLines := max(0, (m.terminalHeight-stashViewTopPadding-stashViewBottomPadding)%stashViewItemHeight)
numBlankLines := max(0, (m.general.height-stashViewTopPadding-stashViewBottomPadding)%stashViewItemHeight)
blankLines := ""
if numBlankLines > 0 {
blankLines = strings.Repeat("\n", numBlankLines)
@ -812,7 +806,7 @@ func stashView(m stashModel) string {
// If the dot pagination is wider than the width of the window
// switch to the arabic paginator.
if ansi.PrintableRuneWidth(pagination) > m.terminalWidth-stashViewHorizontalPadding {
if ansi.PrintableRuneWidth(pagination) > m.general.width-stashViewHorizontalPadding {
m.paginator.Type = paginator.Arabic
pagination = common.Subtle(m.paginator.View())
}
@ -848,12 +842,12 @@ func stashHeaderView(m stashModel) string {
loading := !m.loadingDone()
noMarkdowns := len(m.markdowns) == 0
if m.authStatus == authFailed && m.stashedOnly() {
if m.general.authStatus == authFailed && m.stashedOnly() {
return common.Subtle("Cant load stash. Are you offline?")
}
var maybeOffline string
if m.authStatus == authFailed {
if m.general.authStatus == authFailed {
maybeOffline = " " + offlineHeaderNote
}
@ -976,7 +970,7 @@ func stashHelpView(m stashModel) string {
}
if isStashed {
h = append(h, "x: delete", "m: set memo")
} else if isLocal && m.authStatus == authOK {
} else if isLocal && m.general.authStatus == authOK {
h = append(h, "s: stash")
}
if m.err != nil {
@ -985,7 +979,7 @@ func stashHelpView(m stashModel) string {
h = append(h, "/: filter")
h = append(h, "q: quit")
}
return stashHelpViewBuilder(m.terminalWidth, h...)
return stashHelpViewBuilder(m.general.width, h...)
}
// builds the help view from various sections pieces, truncating it if the view

View file

@ -20,7 +20,7 @@ const (
func stashItemView(b *strings.Builder, m stashModel, index int, md *markdown) {
var (
truncateTo = m.terminalWidth - stashViewHorizontalPadding*2
truncateTo = m.general.width - stashViewHorizontalPadding*2
gutter string
title = md.Note
date = relativeTime(md.CreatedAt)

View file

@ -134,18 +134,25 @@ const (
keygenFinished
)
// General stuff we'll need to access in all models
type general struct {
cfg Config
cc *charm.Client
cwd string
authStatus authStatus
width int
height int
}
type model struct {
cfg *Config
cc *charm.Client
authStatus authStatus
keygenState keygenState
state state
fatalErr error
stash stashModel
pager pagerModel
terminalWidth int
terminalHeight int
cwd string // directory from which we're running Glow
general *general
keygenState keygenState
state state
fatalErr error
// Sub-models
stash stashModel
pager pagerModel
// Channel that receives paths to local markdown files
// (via the github.com/muesli/gitcha package)
@ -176,12 +183,6 @@ func (m *model) unloadDocument() []tea.Cmd {
return batch
}
func (m *model) setAuthStatus(as authStatus) {
m.authStatus = as
m.stash.authStatus = as
m.pager.authStatus = as
}
func newModel(cfg Config) tea.Model {
if cfg.GlamourStyle == "auto" {
dbg := te.HasDarkBackground()
@ -196,28 +197,31 @@ func newModel(cfg Config) tea.Model {
cfg.DocumentTypes = LocalDocuments | StashedDocuments | NewsDocuments
}
as := authConnecting
general := general{
cfg: cfg,
authStatus: authConnecting,
}
return model{
cfg: &cfg,
general: &general,
state: stateShowStash,
authStatus: as,
keygenState: keygenUnstarted,
pager: newPagerModel(&cfg, as),
stash: newStashModel(&cfg, as),
pager: newPagerModel(&general),
stash: newStashModel(&general),
}
}
func (m model) Init() tea.Cmd {
var cmds []tea.Cmd
if m.cfg.DocumentTypes&StashedDocuments != 0 || m.cfg.DocumentTypes&NewsDocuments != 0 {
if m.general.cfg.DocumentTypes&StashedDocuments != 0 || m.general.cfg.DocumentTypes&NewsDocuments != 0 {
cmds = append(cmds,
newCharmClient,
spinner.Tick,
)
}
if m.cfg.DocumentTypes&LocalDocuments != 0 {
if m.general.cfg.DocumentTypes&LocalDocuments != 0 {
cmds = append(cmds, findLocalFiles(m))
}
@ -306,8 +310,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// Window size is received when starting up and on every resize
case tea.WindowSizeMsg:
m.terminalWidth = msg.Width
m.terminalHeight = msg.Height
m.general.width = msg.Width
m.general.height = msg.Height
m.stash.setSize(msg.Width, msg.Height)
m.pager.setSize(msg.Width, msg.Height)
@ -316,12 +320,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case initLocalFileSearchMsg:
m.localFileFinder = msg.ch
m.cwd = msg.cwd
m.stash.cwd = msg.cwd
m.general.cwd = msg.cwd
cmds = append(cmds, findNextLocalFile(m))
case foundLocalFileMsg:
newMd := localFileToMarkdown(m.cwd, gitcha.SearchResult(msg))
newMd := localFileToMarkdown(m.general.cwd, gitcha.SearchResult(msg))
m.stash.addMarkdowns(newMd)
cmds = append(cmds, findNextLocalFile(m))
@ -331,7 +334,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
cmds = append(cmds, generateSSHKeys)
} else {
// The keygen ran but things still didn't work and we can't auth
m.setAuthStatus(authFailed)
m.general.authStatus = authFailed
m.stash.err = errors.New("SSH authentication failed; we tried ssh-agent, loading keys from disk, and generating SSH keys")
if debug {
log.Println("entering offline mode;", m.stash.err)
@ -344,7 +347,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case keygenFailedMsg:
// Keygen failed. That sucks.
m.setAuthStatus(authFailed)
m.general.authStatus = authFailed
m.stash.err = errors.New("could not authenticate; could not generate SSH keys")
if debug {
log.Println("entering offline mode;", m.stash.err)
@ -362,14 +365,12 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
cmds = append(cmds, newCharmClient)
case newCharmClientMsg:
m.cc = msg
m.setAuthStatus(authOK)
m.stash.cc = msg
m.pager.cc = msg
m.general.cc = msg
m.general.authStatus = authOK
cmds = append(cmds, loadStash(m.stash), loadNews(m.stash))
case stashLoadErrMsg:
m.setAuthStatus(authFailed)
m.general.authStatus = authFailed
case fetchedMarkdownMsg:
m.pager.currentDocument = *msg
@ -465,7 +466,7 @@ func findLocalFiles(m model) tea.Cmd {
}
var ignore []string
if !m.cfg.ShowAllFiles {
if !m.general.cfg.ShowAllFiles {
ignore = ignorePatterns(m)
}
@ -521,14 +522,14 @@ func newCharmClient() tea.Msg {
func loadStash(m stashModel) tea.Cmd {
return func() tea.Msg {
if m.cc == nil {
if m.general.cc == nil {
err := errors.New("no charm client")
if debug {
log.Println("error loading stash:", err)
}
return stashLoadErrMsg{err}
}
stash, err := m.cc.GetStash(m.page)
stash, err := m.general.cc.GetStash(m.page)
if err != nil {
if debug {
if _, ok := err.(charm.ErrAuthFailed); ok {
@ -545,14 +546,14 @@ func loadStash(m stashModel) tea.Cmd {
func loadNews(m stashModel) tea.Cmd {
return func() tea.Msg {
if m.cc == nil {
if m.general.cc == nil {
err := errors.New("no charm client")
if debug {
log.Println("error loading news:", err)
}
return newsLoadErrMsg{err}
}
news, err := m.cc.GetNews(1) // just fetch the first page
news, err := m.general.cc.GetNews(1) // just fetch the first page
if err != nil {
if debug {
log.Println("error loading news:", err)