run.go (1937B)
1 package editor 2 3 import ( 4 "context" 5 "fmt" 6 "runtime/debug" 7 8 "code.dwrz.net/src/pkg/editor/event" 9 ) 10 11 func (e *Editor) Run(ctx context.Context, files []string) error { 12 if err := e.terminal.SetRaw(); err != nil { 13 return fmt.Errorf("failed to set raw mode: %w", err) 14 } 15 e.canvas.Reset() 16 17 // Log build info. 18 var commit, time, hostname string 19 bi, ok := debug.ReadBuildInfo() 20 if ok { 21 for _, s := range bi.Settings { 22 switch s.Key { 23 case "vcs.revision": 24 commit = s.Value 25 case "vcs.time": 26 time = s.Value 27 } 28 } 29 } 30 e.log.Debug.Printf( 31 "文 version %s; built at %s on %s", 32 commit, time, hostname, 33 ) 34 35 // Reset the terminal before exiting. 36 defer func() { 37 e.canvas.Reset() 38 39 if err := e.terminal.Reset(); err != nil { 40 e.log.Error.Printf( 41 "failed to reset terminal attributes: %v", err, 42 ) 43 } 44 }() 45 46 // Start reading user input. 47 go func() { 48 if err := e.reader.Run(ctx); err != nil { 49 e.events <- event.NewError(err) 50 } 51 }() 52 53 // Open the files. 54 go e.load(files) 55 56 // Main loop. 57 for { 58 select { 59 case <-ctx.Done(): 60 e.log.Debug.Printf("context done: stopping") 61 return nil 62 63 case ev := <-e.events: 64 switch t := ev.(type) { 65 case *event.Error: 66 return t 67 68 case *event.Message: 69 e.prompt.SetText(t.Text()) 70 71 if err := e.canvas.Render( 72 e.active, e.prompt, 73 ); err != nil { 74 return fmt.Errorf( 75 "failed to render: %w", err, 76 ) 77 } 78 79 case *event.Quit: 80 return nil 81 } 82 83 case event := <-e.input: 84 if e.prompt.IsPrompt() { 85 if err := e.promptInput(event); err != nil { 86 return fmt.Errorf( 87 "failed to process input: %w", 88 err, 89 ) 90 } 91 } else { 92 if err := e.bufferInput(event); err != nil { 93 return fmt.Errorf( 94 "failed to process input: %w", 95 err, 96 ) 97 } 98 } 99 100 if err := e.canvas.Render( 101 e.active, e.prompt, 102 ); err != nil { 103 return fmt.Errorf("failed to render: %w", err) 104 } 105 } 106 } 107 }