src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/cli/examples/e3bc/main.go (about)

     1  // Command e3bc ("Elvish-editor-enhanced bc") is a wrapper for the bc command
     2  // that uses Elvish's cli library for an enhanced CLI experience.
     3  package main
     4  
     5  import (
     6  	"fmt"
     7  	"io"
     8  	"unicode"
     9  
    10  	"src.elv.sh/pkg/cli"
    11  	"src.elv.sh/pkg/cli/examples/e3bc/bc"
    12  	"src.elv.sh/pkg/cli/modes"
    13  	"src.elv.sh/pkg/cli/term"
    14  	"src.elv.sh/pkg/cli/tk"
    15  	"src.elv.sh/pkg/diag"
    16  	"src.elv.sh/pkg/ui"
    17  )
    18  
    19  // A highlighter for bc code. Currently this just makes all digits green.
    20  //
    21  // TODO: Highlight more syntax of bc.
    22  type highlighter struct{}
    23  
    24  func (highlighter) Get(code string) (ui.Text, []ui.Text) {
    25  	t := ui.Text{}
    26  	for _, r := range code {
    27  		var style ui.Styling
    28  		if unicode.IsDigit(r) {
    29  			style = ui.FgGreen
    30  		}
    31  		t = append(t, ui.T(string(r), style)...)
    32  	}
    33  	return t, nil
    34  }
    35  
    36  func (highlighter) LateUpdates() <-chan struct{} { return nil }
    37  
    38  func main() {
    39  	var app cli.App
    40  	app = cli.NewApp(cli.AppSpec{
    41  		Prompt:      cli.NewConstPrompt(ui.T("bc> ")),
    42  		Highlighter: highlighter{},
    43  		CodeAreaBindings: tk.MapBindings{
    44  			term.K('D', ui.Ctrl): func(tk.Widget) { app.CommitEOF() },
    45  			term.K(ui.Tab): func(w tk.Widget) {
    46  				codearea := w.(tk.CodeArea)
    47  				if codearea.CopyState().Buffer.Content != "" {
    48  					// Only complete with an empty buffer
    49  					return
    50  				}
    51  				w, err := modes.NewCompletion(app, modes.CompletionSpec{
    52  					Replace: diag.Ranging{From: 0, To: 0}, Items: candidates(),
    53  				})
    54  				if err == nil {
    55  					app.PushAddon(w)
    56  				}
    57  			},
    58  		},
    59  		GlobalBindings: tk.MapBindings{
    60  			term.K('[', ui.Ctrl): func(tk.Widget) { app.PopAddon() },
    61  		},
    62  	})
    63  
    64  	bc := bc.Start()
    65  	defer bc.Quit()
    66  
    67  	for {
    68  		code, err := app.ReadCode()
    69  		if err != nil {
    70  			if err != io.EOF {
    71  				fmt.Println("error:", err)
    72  			}
    73  			break
    74  		}
    75  		bc.Exec(code)
    76  	}
    77  }