|
@@ -11,11 +11,13 @@
|
|
package tool
|
|
package tool
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
+ "encoding/json"
|
|
"flag"
|
|
"flag"
|
|
"fmt"
|
|
"fmt"
|
|
"io"
|
|
"io"
|
|
"io/ioutil"
|
|
"io/ioutil"
|
|
"os"
|
|
"os"
|
|
|
|
+ "path/filepath"
|
|
"strings"
|
|
"strings"
|
|
|
|
|
|
"devt.de/krotik/common/fileutil"
|
|
"devt.de/krotik/common/fileutil"
|
|
@@ -54,7 +56,8 @@ type CLIInterpreter struct {
|
|
CustomWelcomeMessage string
|
|
CustomWelcomeMessage string
|
|
CustomHelpString string
|
|
CustomHelpString string
|
|
|
|
|
|
- EntryFile string // Entry file for the program
|
|
|
|
|
|
+ EntryFile string // Entry file for the program
|
|
|
|
+ LoadPlugins bool // Flag if stdlib plugins should be loaded
|
|
|
|
|
|
// Parameter these can either be set programmatically or via CLI args
|
|
// Parameter these can either be set programmatically or via CLI args
|
|
|
|
|
|
@@ -75,7 +78,8 @@ type CLIInterpreter struct {
|
|
NewCLIInterpreter creates a new commandline interpreter for ECAL.
|
|
NewCLIInterpreter creates a new commandline interpreter for ECAL.
|
|
*/
|
|
*/
|
|
func NewCLIInterpreter() *CLIInterpreter {
|
|
func NewCLIInterpreter() *CLIInterpreter {
|
|
- return &CLIInterpreter{scope.NewScope(scope.GlobalScope), nil, nil, "", "", "", nil, nil, nil, nil, os.Stdout}
|
|
|
|
|
|
+ return &CLIInterpreter{scope.NewScope(scope.GlobalScope), nil, nil, "", "", "",
|
|
|
|
+ true, nil, nil, nil, nil, os.Stdout}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -225,63 +229,105 @@ func (i *CLIInterpreter) Interpret(interactive bool) error {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
- err := i.CreateTerm()
|
|
|
|
|
|
+ err := i.LoadStdlibPlugins(interactive)
|
|
|
|
|
|
- if interactive {
|
|
|
|
- fmt.Fprintln(i.LogOut, fmt.Sprintf("ECAL %v", config.ProductVersion))
|
|
|
|
- }
|
|
|
|
|
|
+ if err == nil {
|
|
|
|
+ err = i.CreateTerm()
|
|
|
|
|
|
- // Create Runtime Provider
|
|
|
|
|
|
+ if interactive {
|
|
|
|
+ fmt.Fprintln(i.LogOut, fmt.Sprintf("ECAL %v", config.ProductVersion))
|
|
|
|
+ }
|
|
|
|
|
|
- if err == nil {
|
|
|
|
|
|
+ // Create Runtime Provider
|
|
|
|
|
|
- if err = i.CreateRuntimeProvider("console"); err == nil {
|
|
|
|
|
|
+ if err == nil {
|
|
|
|
|
|
- tid := i.RuntimeProvider.NewThreadID()
|
|
|
|
|
|
+ if err = i.CreateRuntimeProvider("console"); err == nil {
|
|
|
|
|
|
- if interactive {
|
|
|
|
- if lll, ok := i.RuntimeProvider.Logger.(*util.LogLevelLogger); ok {
|
|
|
|
- fmt.Fprint(i.LogOut, fmt.Sprintf("Log level: %v - ", lll.Level()))
|
|
|
|
- }
|
|
|
|
|
|
+ tid := i.RuntimeProvider.NewThreadID()
|
|
|
|
|
|
- fmt.Fprintln(i.LogOut, fmt.Sprintf("Root directory: %v", *i.Dir))
|
|
|
|
|
|
+ if interactive {
|
|
|
|
+ if lll, ok := i.RuntimeProvider.Logger.(*util.LogLevelLogger); ok {
|
|
|
|
+ fmt.Fprint(i.LogOut, fmt.Sprintf("Log level: %v - ", lll.Level()))
|
|
|
|
+ }
|
|
|
|
|
|
- if i.CustomWelcomeMessage != "" {
|
|
|
|
- fmt.Fprintln(i.LogOut, fmt.Sprintf(i.CustomWelcomeMessage))
|
|
|
|
|
|
+ fmt.Fprintln(i.LogOut, fmt.Sprintf("Root directory: %v", *i.Dir))
|
|
|
|
+
|
|
|
|
+ if i.CustomWelcomeMessage != "" {
|
|
|
|
+ fmt.Fprintln(i.LogOut, fmt.Sprintf(i.CustomWelcomeMessage))
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
|
|
- // Execute file if given
|
|
|
|
|
|
+ // Execute file if given
|
|
|
|
|
|
- if err = i.LoadInitialFile(tid); err == nil {
|
|
|
|
|
|
+ if err = i.LoadInitialFile(tid); err == nil {
|
|
|
|
|
|
- // Drop into interactive shell
|
|
|
|
|
|
+ // Drop into interactive shell
|
|
|
|
|
|
- if interactive {
|
|
|
|
|
|
+ if interactive {
|
|
|
|
|
|
- // Add history functionality without file persistence
|
|
|
|
|
|
+ // Add history functionality without file persistence
|
|
|
|
|
|
- i.Term, err = termutil.AddHistoryMixin(i.Term, "",
|
|
|
|
- func(s string) bool {
|
|
|
|
- return i.isExitLine(s)
|
|
|
|
- })
|
|
|
|
|
|
+ i.Term, err = termutil.AddHistoryMixin(i.Term, "",
|
|
|
|
+ func(s string) bool {
|
|
|
|
+ return i.isExitLine(s)
|
|
|
|
+ })
|
|
|
|
|
|
- if err == nil {
|
|
|
|
|
|
+ if err == nil {
|
|
|
|
|
|
- if err = i.Term.StartTerm(); err == nil {
|
|
|
|
- var line string
|
|
|
|
|
|
+ if err = i.Term.StartTerm(); err == nil {
|
|
|
|
+ var line string
|
|
|
|
|
|
- defer i.Term.StopTerm()
|
|
|
|
|
|
+ defer i.Term.StopTerm()
|
|
|
|
|
|
- fmt.Fprintln(i.LogOut, "Type 'q' or 'quit' to exit the shell and '?' to get help")
|
|
|
|
|
|
+ fmt.Fprintln(i.LogOut, "Type 'q' or 'quit' to exit the shell and '?' to get help")
|
|
|
|
|
|
- line, err = i.Term.NextLine()
|
|
|
|
- for err == nil && !i.isExitLine(line) {
|
|
|
|
- trimmedLine := strings.TrimSpace(line)
|
|
|
|
|
|
+ line, err = i.Term.NextLine()
|
|
|
|
+ for err == nil && !i.isExitLine(line) {
|
|
|
|
+ trimmedLine := strings.TrimSpace(line)
|
|
|
|
|
|
- i.HandleInput(i.Term, trimmedLine, tid)
|
|
|
|
|
|
+ i.HandleInput(i.Term, trimmedLine, tid)
|
|
|
|
|
|
- line, err = i.Term.NextLine()
|
|
|
|
|
|
+ line, err = i.Term.NextLine()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+LoadStdlibPlugins load plugins from .ecal.json.
|
|
|
|
+*/
|
|
|
|
+func (i *CLIInterpreter) LoadStdlibPlugins(interactive bool) error {
|
|
|
|
+ var err error
|
|
|
|
+
|
|
|
|
+ if i.LoadPlugins {
|
|
|
|
+ confFile := filepath.Join(*i.Dir, ".ecal.json")
|
|
|
|
+ if ok, _ := fileutil.PathExists(confFile); ok {
|
|
|
|
+
|
|
|
|
+ if interactive {
|
|
|
|
+ fmt.Fprintln(i.LogOut, fmt.Sprintf("Loading stdlib plugins from %v", confFile))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var content []byte
|
|
|
|
+ if content, err = ioutil.ReadFile(confFile); err == nil {
|
|
|
|
+ var conf map[string]interface{}
|
|
|
|
+ if err = json.Unmarshal(content, &conf); err == nil {
|
|
|
|
+ if stdlibPlugins, ok := conf["stdlibPlugins"]; ok {
|
|
|
|
+ err = fmt.Errorf("Config stdlibPlugins should be a list")
|
|
|
|
+ if plugins, ok := stdlibPlugins.([]interface{}); ok {
|
|
|
|
+ err = nil
|
|
|
|
+ if errs := stdlib.LoadStdlibPlugins(plugins); len(errs) > 0 {
|
|
|
|
+ for _, e := range errs {
|
|
|
|
+ fmt.Fprintln(i.LogOut, fmt.Sprintf("Error loading plugins: %v", e))
|
|
|
|
+ }
|
|
|
|
+ err = fmt.Errorf("Could not load plugins defined in .ecal.json")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|