Skip to content

Commit b273ee0

Browse files
committed
Improve --raw and add to README
1 parent 79731ad commit b273ee0

File tree

2 files changed

+60
-54
lines changed

2 files changed

+60
-54
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Then run `ari` for a REPL or `ari --help` to see CLI options.
2828
- Replace default REPL printing by setting a function value for the `ari.print` global (function receives a single Goal value to print)
2929
- Configure the output format with `--output-format` or using one of the `)output.` system commands at the REPL. Formats include CSV/TSV, JSON, Markdown, and LaTeX.
3030
- `ari.p` is bound to the previous result (value from last evaluation at the REPL)
31+
- Alternatively run `ari` with `--raw` for a simpler, raw REPL that lacks line editing, history, and auto-complete, but is better suited for interaction via an editor like (Neo)Vim, or if you prefer rlwrap or another line editor to the one that ships with ari.
3132
- Extensible help system
3233
- `help"help"` for an overview
3334
- `help"TOPIC"` similar to Goal's CLI help
@@ -53,7 +54,6 @@ Non-exhaustive list:
5354

5455
- TODO: Test coverage.
5556
- TODO: Correct usage of `goal.NewError` vs. `goal.NewPanicError`
56-
- TODO: Option for raw REPL (modeled on Goal's) with better input performance, no auto-complete etc.
5757
- TODO: Functions to conveniently populate SQL tables with Goal values.
5858
- TODO: Support plots/charts (consider https://github.com/wcharczuk/go-chart)
5959
- TODO: User commands (as found in [APL](https://aplwiki.com/wiki/User_command)), executable from Goal or SQL modes

cmd/ari/root.go

Lines changed: 59 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type CliSystem struct {
6363
debug bool
6464
outputFormat outputFormat
6565
programName string
66+
rawREPL bool
6667
}
6768

6869
func (cliSystem *CliSystem) switchMode(cliMode cliMode, args []string) error {
@@ -79,12 +80,14 @@ func (cliSystem *CliSystem) switchMode(cliMode cliMode, args []string) error {
7980

8081
func (cliSystem *CliSystem) switchModeToGoal() error {
8182
cliSystem.cliMode = cliModeGoal
82-
cliSystem.cliEditor.Prompt = cliModeGoalPrompt
83-
cliSystem.cliEditor.NextPrompt = cliModeGoalNextPrompt
84-
cliSystem.detectAriPrompt()
85-
cliSystem.cliEditor.AutoComplete = cliSystem.autoCompleter.goalAutoCompleteFn()
86-
cliSystem.cliEditor.CheckInputComplete = modeGoalCheckInputComplete
87-
cliSystem.cliEditor.SetExternalEditorEnabled(true, "goal")
83+
if !cliSystem.rawREPL {
84+
cliSystem.cliEditor.Prompt = cliModeGoalPrompt
85+
cliSystem.cliEditor.NextPrompt = cliModeGoalNextPrompt
86+
cliSystem.detectAriPrompt()
87+
cliSystem.cliEditor.AutoComplete = cliSystem.autoCompleter.goalAutoCompleteFn()
88+
cliSystem.cliEditor.CheckInputComplete = modeGoalCheckInputComplete
89+
cliSystem.cliEditor.SetExternalEditorEnabled(true, "goal")
90+
}
8891
return nil
8992
}
9093

@@ -110,11 +113,13 @@ func (cliSystem *CliSystem) switchModeToSQLReadOnly(args []string) error {
110113
}
111114
}
112115
cliSystem.cliMode = cliModeSQLReadOnly
113-
cliSystem.cliEditor.CheckInputComplete = modeSQLCheckInputComplete
114-
cliSystem.cliEditor.AutoComplete = cliSystem.autoCompleter.sqlAutoCompleteFn()
115-
cliSystem.cliEditor.SetExternalEditorEnabled(true, "sql")
116-
cliSystem.cliEditor.Prompt = cliModeSQLReadOnlyPrompt
117-
cliSystem.cliEditor.NextPrompt = cliModeSQLReadOnlyNextPrompt
116+
if !cliSystem.rawREPL {
117+
cliSystem.cliEditor.CheckInputComplete = modeSQLCheckInputComplete
118+
cliSystem.cliEditor.AutoComplete = cliSystem.autoCompleter.sqlAutoCompleteFn()
119+
cliSystem.cliEditor.SetExternalEditorEnabled(true, "sql")
120+
cliSystem.cliEditor.Prompt = cliModeSQLReadOnlyPrompt
121+
cliSystem.cliEditor.NextPrompt = cliModeSQLReadOnlyNextPrompt
122+
}
118123
return nil
119124
}
120125

@@ -135,11 +140,13 @@ func (cliSystem *CliSystem) switchModeToSQLReadWrite(args []string) error {
135140
}
136141
}
137142
cliSystem.cliMode = cliModeSQLReadOnly
138-
cliSystem.cliEditor.CheckInputComplete = modeSQLCheckInputComplete
139-
cliSystem.cliEditor.AutoComplete = cliSystem.autoCompleter.sqlAutoCompleteFn()
140-
cliSystem.cliEditor.SetExternalEditorEnabled(true, "sql")
141-
cliSystem.cliEditor.Prompt = cliModeSQLReadWritePrompt
142-
cliSystem.cliEditor.NextPrompt = cliModeSQLReadWriteNextPrompt
143+
if !cliSystem.rawREPL {
144+
cliSystem.cliEditor.CheckInputComplete = modeSQLCheckInputComplete
145+
cliSystem.cliEditor.AutoComplete = cliSystem.autoCompleter.sqlAutoCompleteFn()
146+
cliSystem.cliEditor.SetExternalEditorEnabled(true, "sql")
147+
cliSystem.cliEditor.Prompt = cliModeSQLReadWritePrompt
148+
cliSystem.cliEditor.NextPrompt = cliModeSQLReadWriteNextPrompt
149+
}
143150
return nil
144151
}
145152

@@ -193,16 +200,12 @@ func ariMain(cmd *cobra.Command, args []string) int {
193200
ariContext: ariContext,
194201
debug: viper.GetBool("debug"),
195202
programName: programName,
203+
rawREPL: viper.GetBool("raw"),
196204
}
197205

198206
// MUST COME FIRST
199207
// Engage detailed print on panic.
200-
debug, err := cmd.Flags().GetBool("debug")
201-
if err != nil {
202-
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
203-
return 1
204-
}
205-
if debug {
208+
if mainCliSystem.debug {
206209
defer debugPrintStack(ariContext.GoalContext, programName)
207210
}
208211

@@ -293,8 +296,10 @@ func ariMain(cmd *cobra.Command, args []string) int {
293296
// With files loaded (which might adjust the prompt via Goal code)
294297
// and knowing we're not executing and exiting immediately,
295298
// set up the CLI REPL.
296-
mainCliSystem.cliEditor = cliEditorInitialize()
297-
mainCliSystem.autoCompleter = &AutoCompleter{ariContext: ariContext}
299+
if !mainCliSystem.rawREPL {
300+
mainCliSystem.cliEditor = cliEditorInitialize()
301+
mainCliSystem.autoCompleter = &AutoCompleter{ariContext: ariContext}
302+
}
298303
startupCliModeString := viper.GetString("mode")
299304
startupCliMode, err := cliModeFromString(startupCliModeString)
300305
if err != nil {
@@ -309,11 +314,10 @@ func ariMain(cmd *cobra.Command, args []string) int {
309314
}
310315

311316
// REPL
312-
useRawREPL := viper.GetBool("raw")
313-
if useRawREPL {
314-
rawREPL(mainCliSystem)
317+
if mainCliSystem.rawREPL {
318+
rawREPL(&mainCliSystem)
315319
} else {
316-
editorREPL(mainCliSystem)
320+
editorREPL(&mainCliSystem)
317321
}
318322
return 0
319323
}
@@ -325,11 +329,35 @@ func registerCliGoalBindings(ariContext *ari.Context) {
325329
goalContext.RegisterDyad("tui.render", VFTuiRender)
326330
}
327331

328-
func rawREPL(cliSystem CliSystem) {
329-
runStdin(cliSystem.ariContext.GoalContext, cliSystem.outputFormat)
332+
func rawREPL(cliSystem *CliSystem) {
333+
sc := &scanner{r: bufio.NewReader(os.Stdin)}
334+
for {
335+
fmt.Fprint(os.Stdout, " ")
336+
line, err := sc.readLine()
337+
line = strings.TrimRight(line, "\n\r")
338+
if err != nil && line == "" {
339+
return
340+
}
341+
if matchesSystemCommand(line) {
342+
err = cliSystem.replEvalSystemCommand(line)
343+
if err != nil {
344+
fmt.Fprintf(os.Stderr, "Failed to execute system command %q with error: %v\n", line, err)
345+
}
346+
continue
347+
}
348+
349+
switch cliSystem.cliMode {
350+
case cliModeGoal:
351+
cliSystem.replEvalGoal(line)
352+
case cliModeSQLReadOnly:
353+
cliSystem.replEvalSQLReadOnly(line)
354+
case cliModeSQLReadWrite:
355+
cliSystem.replEvalSQLReadWrite(line)
356+
}
357+
}
330358
}
331359

332-
func editorREPL(cliSystem CliSystem) {
360+
func editorREPL(cliSystem *CliSystem) {
333361
cliEditor := cliSystem.cliEditor
334362
for {
335363
line, err := cliEditor.GetLine()
@@ -658,28 +686,6 @@ func runSource(cliSystem *CliSystem, source, loc string) (goal.V, error) {
658686
return value, nil
659687
}
660688

661-
// Adapted from Goal's implementation.
662-
func runStdin(ctx *goal.Context, outputFormat outputFormat) {
663-
sc := &scanner{r: bufio.NewReader(os.Stdin)}
664-
for {
665-
fmt.Fprint(os.Stdout, " ")
666-
s, err := sc.readLine()
667-
s = strings.TrimRight(s, "\n\r")
668-
if err != nil && s == "" {
669-
return
670-
}
671-
value, err := ctx.Eval(s)
672-
if err != nil {
673-
formatREPLError(err)
674-
continue
675-
}
676-
assigned := ctx.AssignedLast()
677-
if !assigned && value != (goal.V{}) {
678-
printInOutputFormat(ctx, outputFormat, value)
679-
}
680-
}
681-
}
682-
683689
// printProgram prints debug information about the context and any compiled
684690
// source.
685691
//

0 commit comments

Comments
 (0)