Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: How print output from TODO #7

Closed
abtris opened this issue Oct 13, 2020 · 4 comments
Closed

Question: How print output from TODO #7

abtris opened this issue Oct 13, 2020 · 4 comments

Comments

@abtris
Copy link

abtris commented Oct 13, 2020

I try it example and it's great library, but I can't figure out how you think we can work with output.

Example:

I can just add print for selected output:

for i := range m.selected {
  fmt.Printf("\n%s", m.choices[i])
}

I can put into update function to quit and get ugly output:

What should we buy at the market?

> [x] Buy carrots
  [ ] Buy celery
  [x] Buy kohlrabi

Press q to quit.

Buy kohlrabi
            Buy carrots%

Do I need extra view for that? Or is some simple way how get pass output via program interface to main function to continue for example with other program? I see example with Msg but look overcomplicated for just work with output from CLI.

@meowgorithm
Copy link
Member

Hi! So if I understand correctly, you want to capture the output of a choice, exit Bubble Tea, and then do something with that value?

@abtris
Copy link
Author

abtris commented Oct 13, 2020

Yes, that is simple example of usage.

From interface perspective I think if you have possibility to extend interface func NewProgram(init Init, update Update, view View) *Program to some way that you have access to model via instance of program to process Model outside that will be useful for people using tool for example as input to process.

What I can show download?
- [ ] nodejs 
- [ ] ruby
- [ ] go

press q to quit/continue

and as output will be:

You select nodejs and I'm downloading latest nodejs from ...

in func main can be for example:

func main() {
    p := tea.NewProgram(initialize, update, view)
    if err := p.Start(); err != nil {
        fmt.Printf("Alas, there's been an error: %v", err)
        os.Exit(1)
    } else {
      m := p.GetModel() // whatever make sense
      makeDownload(m.url)
    }
    
}

or

func main() {
    p, model := tea.NewProgram(initialize, update, view)
    if err := p.Start(); err != nil {
        fmt.Printf("Alas, there's been an error: %v", err)
        os.Exit(1)
    } else {     
      makeDownload(model.url)
    }
    
}

@meowgorithm
Copy link
Member

meowgorithm commented Oct 14, 2020

That's a good idea. Since Program.Start() blocks we could potentially do something like:

func main() {
    finalModel, err := tea.NewProgram(myModel).Start()
    if err != nil {
        fmt.Printf("Oh no!: %v\n", err)
        os.Exit(1)
    }

    m, ok := finalModel.(myModel)
    if ok {
        doSomething(model.url)
    }
}

Because the Bubble Tea runtime only knows the type as tea.Model you'd need to assert the model to whatever type you're actually using for the model (same as you'd do in the update function).

Depending on what the rest of your program looks like you could also just perform I/O in a command, which is typically how you’d do I/O in Bubble Tea (quick writeup here incase you haven’t seen it). Something like:

func (m MyModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
    // ...
    switch msg := msg.(type) {
    case tea.KeyMsg:
        switch msg.Type {
        case tea.KeyEnter:
            m.note = "Now downloading!"
            return m, makeDownload(m.url)
        }
    // ...
    }
}

func makeDownload(url string) tea.Cmd {
    return func() tea.Msg {
        // ... download logic
       return downloadStatusMsg{err}
    }
}

But yes, that’s definitely more involved if the goal is to simply use the library to quickly capture some input.

@meowgorithm
Copy link
Member

After thinking about this some more, I think it makes the most sense to send final results back with a channel. Here's an example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants