Run initializes the program and runs its event loops, blocking until it gets terminated by either [Program.Quit], [Program.Kill], or its signal handler. Returns the final model.
()
| 989 | // terminated by either [Program.Quit], [Program.Kill], or its signal handler. |
| 990 | // Returns the final model. |
| 991 | func (p *Program) Run() (returnModel Model, returnErr error) { |
| 992 | if p.initialModel == nil { |
| 993 | return nil, errors.New("bubbletea: InitialModel cannot be nil") |
| 994 | } |
| 995 | |
| 996 | // Initialize context and teardown channel. |
| 997 | p.handlers = channelHandlers{} |
| 998 | cmds := make(chan Cmd) |
| 999 | |
| 1000 | p.finished = make(chan struct{}) |
| 1001 | defer func() { |
| 1002 | close(p.finished) |
| 1003 | }() |
| 1004 | |
| 1005 | defer p.cancel() |
| 1006 | |
| 1007 | if p.disableInput { |
| 1008 | p.input = nil |
| 1009 | } else if p.input == nil { |
| 1010 | p.input = os.Stdin |
| 1011 | if !term.IsTerminal(os.Stdin.Fd()) { |
| 1012 | ttyIn, _, err := OpenTTY() |
| 1013 | if err != nil { |
| 1014 | return p.initialModel, fmt.Errorf("bubbletea: error opening TTY: %w", err) |
| 1015 | } |
| 1016 | p.input = ttyIn |
| 1017 | } |
| 1018 | } |
| 1019 | |
| 1020 | // Handle signals. |
| 1021 | if !p.disableSignalHandler { |
| 1022 | p.handlers.add(p.handleSignals()) |
| 1023 | } |
| 1024 | |
| 1025 | // Recover from panics. |
| 1026 | if !p.disableCatchPanics { |
| 1027 | defer func() { |
| 1028 | if r := recover(); r != nil { |
| 1029 | returnErr = fmt.Errorf("%w: %w", ErrProgramKilled, ErrProgramPanic) |
| 1030 | p.recoverFromPanic(r) |
| 1031 | } |
| 1032 | }() |
| 1033 | } |
| 1034 | |
| 1035 | // Check if output is a TTY before entering raw mode, hiding the cursor and |
| 1036 | // so on. |
| 1037 | if err := p.initTerminal(); err != nil { |
| 1038 | return p.initialModel, err |
| 1039 | } |
| 1040 | |
| 1041 | // Get the initial window size. |
| 1042 | width, height := p.width, p.height |
| 1043 | if p.ttyOutput != nil { |
| 1044 | // Set the initial size of the terminal. |
| 1045 | w, h, err := term.GetSize(p.ttyOutput.Fd()) |
| 1046 | if err != nil { |
| 1047 | return p.initialModel, fmt.Errorf("bubbletea: error getting terminal size: %w", err) |
| 1048 | } |