github.com/aergoio/aergo@v1.3.1/cmd/brick/brick.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/aergoio/aergo-lib/log"
    10  	"github.com/aergoio/aergo/cmd/brick/context"
    11  	"github.com/aergoio/aergo/cmd/brick/exec"
    12  	prompt "github.com/c-bata/go-prompt"
    13  )
    14  
    15  var logger = log.NewLogger("brick")
    16  
    17  func completerBroker(d prompt.Document) []prompt.Suggest {
    18  	var s []prompt.Suggest
    19  	// parse first word. it is represent a command
    20  	cmd, args := context.ParseFirstWord(d.Lines()[0])
    21  
    22  	// find number of word before a current cursor location
    23  	chunks := context.SplitSpaceAndAccent(args, true)
    24  	chunkNum := len(chunks)
    25  
    26  	// if there is nothing typed text or it is a first word
    27  	if cmd == "" || (cmd != "" && chunkNum == 0 && !strings.HasSuffix(d.TextBeforeCursor(), " ")) {
    28  		// suggest all commands available
    29  		for _, executor := range exec.AllExecutors() {
    30  			s = append(s, prompt.Suggest{Text: executor.Command(), Description: executor.Describe()})
    31  		}
    32  
    33  		return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
    34  	} else if cmd == context.Comment {
    35  		// ignore a special char; comment
    36  		s = append(s, prompt.Suggest{Text: "<comment>"})
    37  
    38  		return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
    39  	}
    40  
    41  	// suggest consequence word using a syntax of command
    42  	executor := exec.GetExecutor(cmd)
    43  	if executor == nil {
    44  		s = append(s, prompt.Suggest{Text: "<error>", Description: fmt.Sprintf("command not found: %s", cmd)})
    45  	} else {
    46  		syntax := executor.Syntax()
    47  		syntaxSplit := strings.Fields(syntax)
    48  		syntaxNum := len(syntaxSplit)
    49  		var symbol string
    50  		var current int
    51  
    52  		// there exist a syntax
    53  		if syntaxNum != 0 {
    54  			// from the syntax, try to find a matched symbol of a current field
    55  			if syntaxNum >= chunkNum {
    56  				// when last char is a space, then skip to next symbol
    57  				takeNextSymbol := strings.HasSuffix(d.TextBeforeCursor(), " ")
    58  				if takeNextSymbol && syntaxNum != chunkNum {
    59  					current = chunkNum
    60  					symbol = syntaxSplit[current]
    61  				} else if !takeNextSymbol {
    62  					current = chunkNum - 1
    63  					symbol = syntaxSplit[current]
    64  				}
    65  			}
    66  
    67  			// search from index using symbol
    68  			for text, descr := range exec.Candidates(cmd, chunks, current, symbol) {
    69  				s = append(s, prompt.Suggest{Text: text, Description: descr})
    70  			}
    71  		}
    72  	}
    73  
    74  	// sort suggestions by text in ascending order
    75  	sort.Slice(s, func(i, j int) bool {
    76  		return strings.Compare(s[i].Text, s[j].Text) < 0
    77  	})
    78  
    79  	return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
    80  }
    81  
    82  func main() {
    83  	if len(os.Args) <= 1 {
    84  		// cli mode
    85  		p := prompt.New(
    86  			exec.Broker,
    87  			completerBroker,
    88  			prompt.OptionPrefix(">"),
    89  			prompt.OptionLivePrefix(context.LivePrefix),
    90  			prompt.OptionTitle("Aergo Brick: Dummy Virtual Machine"),
    91  		)
    92  		p.Run()
    93  	} else {
    94  		// call batch executor
    95  		cmd := "batch"
    96  		args := os.Args[1]
    97  
    98  		// set user-defined log level
    99  		if len(os.Args) > 2 {
   100  			if os.Args[2] == "-v" {
   101  				exec.EnableVerbose()
   102  			} else if os.Args[2] == "-w" {
   103  				exec.EnableWatch()
   104  			} else {
   105  				fmt.Println("Invalid Parameter. Usage: brick filename [-v|-w]\n\t-v\tverbose mode\n\t-w\twatch mode")
   106  				os.Exit(1)
   107  			}
   108  		}
   109  
   110  		exec.Execute(cmd, args)
   111  	}
   112  }