Files
wen/internal/editor/run.go
T
2026-10-26 02:32:03 +00:00

120 lines
2.3 KiB
Go

package editor
import (
"context"
"errors"
"fmt"
"log/slog"
"runtime/debug"
"code.chimeric.al/dwrz/wen/internal/editor/event"
)
func (e *Editor) Run(ctx context.Context, files []string) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
if err := e.terminal.SetRaw(); err != nil {
return fmt.Errorf("failed to set raw mode: %w", err)
}
e.canvas.Reset()
// Log build info.
var commit, time string
bi, ok := debug.ReadBuildInfo()
if ok {
for _, s := range bi.Settings {
switch s.Key {
case "vcs.revision":
commit = s.Value
case "vcs.time":
time = s.Value
}
}
}
e.log.Debug(
"文 version",
slog.String("commit", commit),
slog.String("time", time),
)
// Reset the terminal before exiting.
defer func() {
e.canvas.Reset()
if err := e.terminal.Reset(); err != nil {
e.log.Error(
"failed to reset terminal attributes",
slog.Any("error", err),
)
}
}()
// Start reading user input.
// The reader may be blocked in a read when the editor ends.
// The reader stops when the process stops.
go func() {
if err := e.reader.Run(ctx); err != nil && !errors.Is(err, context.Canceled) {
e.events <- event.NewError(err)
}
}()
// Open the files and render the initial state.
e.load(files)
if err := e.canvas.Render(e.active, e.prompt); err != nil {
return fmt.Errorf("failed to render: %w", err)
}
// Main loop.
for {
select {
case <-ctx.Done():
e.log.DebugContext(ctx, "context done: stopping")
return nil
case ev := <-e.events:
switch t := ev.(type) {
case *event.Error:
return t
case *event.Message:
e.prompt.SetText(t.Text())
if err := e.canvas.Render(
e.active, e.prompt,
); err != nil {
return fmt.Errorf(
"failed to render: %w", err,
)
}
case *event.Quit:
return nil
}
case event := <-e.input:
if e.prompt.IsPrompt() {
if err := e.promptInput(event); err != nil {
return fmt.Errorf(
"failed to process input: %w",
err,
)
}
} else {
if err := e.bufferInput(event); err != nil {
return fmt.Errorf(
"failed to process input: %w",
err,
)
}
}
if err := e.canvas.Render(
e.active, e.prompt,
); err != nil {
return fmt.Errorf("failed to render: %w", err)
}
}
}
}