Skip to content

Commit 09fef75

Browse files
authored
Merge pull request #22 from semperos/revamp-help-system
Use Goal's help
2 parents cd96174 + eabe714 commit 09fef75

File tree

20 files changed

+252
-915
lines changed

20 files changed

+252
-915
lines changed

.golangci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ linters:
330330

331331

332332
issues:
333+
exclude-dirs:
334+
- vendored
333335
# Maximum count of issues with the same text.
334336
# Set to 0 to disable.
335337
# Default: 3

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# v "next"
22

3+
- Removed Ari's `glob` and `abspath` now that Goal has them.
4+
- Replaced custom `help` with Goal's default `help`. Tabling a more extensible help offering for future development.
35
- `pp.tbl` and `pp.dict` which invoke `fmt.tbl` and `fmt.dict` with default values (all rows/columns; `"%.2f"` float format)
46
- `time.utc` to set location of a time value to UTC
57
- `time.format` to format a time with a given format. Format constants from Go's `time` package are already defined.

README.md

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Then run `ari` for a REPL or `ari --help` to see CLI options.
1919
- [Goal] is the core language
2020
- Goal's `lib` files are loaded by default, with prefix matching their file names (see [vendor-goal](vendor-goal) folder in this repo)
2121
- Extensible CLI REPL with:
22-
- Auto-completion for:
22+
- Auto-completion with documentation for:
2323
- Built-in keywords
2424
- Built-in syntax aliases (e.g., typing "first" and TAB will show `*` and `¿` in auto-complete results)
2525
- User-defined globals
@@ -29,21 +29,14 @@ Then run `ari` for a REPL or `ari --help` to see CLI options.
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)
3131
- 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.
32-
- Extensible help system
33-
- `help"help"` for an overview
34-
- `help"TOPIC"` similar to Goal's CLI help
35-
- `help rx/search/` to use regular expression matching to find help entries that match
36-
- `"myvar" help "My Var Help"` to extend the help system with new documentation
37-
- `help""` returns entire help dictionary (including non-Goal help for the SQL mode; use `(help"")"goal"` for just the Goal help)
38-
- Auto-complete shows abbreviated help for each result.
32+
- `help` based on Goal's, but allows adding help strings when used dyadically (e.g.,`"sql.q"help"Run SQL query"`)
3933
- New Goal functions:
4034
- `http.` functions for HTTP requests using [Resty]
4135
- `sql.` functions for SQL queries and commands
4236
- `tt.` test framework
4337
- `csv.tbl` and `json.tbl` to make Goal tables from the output of `csv` and `json` respectively
4438
- _(WIP)_ `time.` functions for more extensive date/time handling
4539
- `tui.` functions for basic terminal UI styling (colors, padding/margin, borders)
46-
- `glob` and `abspath` wrapping Go's `path/filepath.Glob` and `path/filepath.Abs` functions respectively
4740
- Dedicated SQL mode
4841
- The ari CLI uses DuckDB, but the `github.com/semperos/ari` Go package doesn't directly depend on a specific SQL database driver, so you can BYODB.
4942
- Activate with `)sql` for read-only, `)sql!` for read/write modes. Execute `)goal` to return to the default Goal mode.
@@ -57,8 +50,9 @@ See [CHANGES.md](CHANGES.md) for recent changes.
5750

5851
Non-exhaustive list:
5952

60-
- TODO: Test coverage (Go reports 14% coverage, currently minimal Goal-level testing as well)
61-
- TODO: Calculate help just in time; leverage Goal's new `HelpFunc`
53+
- TODO: Test coverage
54+
- TODO: System functions to switch between rich and raw REPL `)repl.rich` and `)repl.raw`
55+
- TODO: System function for cross-mode extensible `)help`
6256
- TODO: Consider which of ari's functions should be pervasive; review Goal's approach and implement
6357
- TODO: BUG When using `-l` flag, loaded files aren't completely evaluated. Evaluation stops partway through and it's not immediately clear why.
6458
- TODO: BUG `json.tbl` produces improper zero values when keys are missing. Where possible, column lists should be of uniform type and not generic if the data allows for it.

ari.goal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ json.tbl:{ / table from parsing json array of like objects
3838
?[istbl x;:x;:error"dict is not a table: $x"]
3939
[ks:!*x; vs:@[;ks]'x; ks!+vs]]}
4040
/ Interactive Tools
41-
ac:{[s] gs:!rt.get"g"; r:rx s; ms:(..p.r@'p.gs)#gs; ms@<_ms } / auto-complete
41+
ac:{gs:,/rtnames"";ms:?["s"=@x;(..p.x%p.gs)#gs;[(..p.x@p.gs)#gs]]; ms@<_ms } / auto-complete
4242
/ Test Framework
4343
tt.suite:"global"; tt.suitestate:..[es:();fs:();ps:();ss:()]; tt.state:..[global:tt.suitestate]
4444
tt.st:tt.state; tt.ffast:0; tt.clear:{tt.st::tt.state}

cmd/ari/input.go

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ import (
2020
type AutoCompleter struct {
2121
ariContext *ari.Context
2222
sqlKeywords []string
23-
goalKeywordsHelp map[string]string
2423
goalKeywordsKeys []string
2524
goalSyntaxAliases map[string]string
26-
goalSyntaxHelp map[string]string
2725
goalSyntaxKeys []string
2826
systemCommandsHelp map[string]string
2927
systemCommandsKeys []string
@@ -317,19 +315,15 @@ func (autoCompleter *AutoCompleter) goalAutoCompleteFn() func(v [][]rune, line,
317315
}
318316

319317
func autoCompleteGoalSyntax(autoCompleter *AutoCompleter, lword string, perCategory map[string][]acEntry) {
318+
helpFunc := autoCompleter.ariContext.Help.Func
320319
category := "Syntax"
321320
syntaxSet := make(map[string]bool, 0)
322321
for _, name := range autoCompleter.goalSyntaxKeys {
323322
chstr := autoCompleter.goalSyntaxAliases[name]
324323
if strings.HasPrefix(strings.ToLower(name), lword) {
325324
if _, ok := syntaxSet[chstr]; !ok {
326325
syntaxSet[chstr] = true
327-
var help string
328-
if val, ok := autoCompleter.goalSyntaxHelp[chstr]; ok {
329-
help = val
330-
} else {
331-
help = "Goal syntax"
332-
}
326+
help := helpFunc(chstr)
333327
perCategory[category] = append(perCategory[category], acEntry{chstr, help})
334328
}
335329
}
@@ -341,35 +335,26 @@ func autoCompleteGoalKeywords(autoCompleter *AutoCompleter, lword string, perCat
341335
if autoCompleter.goalKeywordsKeys == nil {
342336
autoCompleter.cacheGoalKeywords(autoCompleter.ariContext.GoalContext)
343337
}
338+
helpFunc := autoCompleter.ariContext.Help.Func
344339
category := "Keyword"
345340
for _, goalKeyword := range autoCompleter.goalKeywordsKeys {
346341
if strings.HasPrefix(strings.ToLower(goalKeyword), lword) {
347-
var help string
348-
if val, ok := autoCompleter.goalKeywordsHelp[goalKeyword]; ok {
349-
help = val
350-
} else {
351-
help = "A Goal keyword"
352-
}
342+
help := helpFunc(goalKeyword)
353343
perCategory[category] = append(perCategory[category], acEntry{goalKeyword, help})
354344
}
355345
}
356346
}
357347

358348
func autoCompleteGoalGlobals(autoCompleter *AutoCompleter, lword string, perCategory map[string][]acEntry) {
359349
goalContext := autoCompleter.ariContext.GoalContext
350+
helpFunc := autoCompleter.ariContext.Help.Func
360351
// Globals cannot be cached; this is what assignment in Goal creates.
361352
goalGlobals := goalContext.GlobalNames(nil)
362353
sort.Strings(goalGlobals)
363-
goalHelp := autoCompleter.ariContext.Help["goal"]
364354
category := "Global"
365355
for _, goalGlobal := range goalGlobals {
366356
if strings.HasPrefix(strings.ToLower(goalGlobal), lword) {
367-
var help string
368-
if val, ok := goalHelp[goalGlobal]; ok {
369-
help = val
370-
} else {
371-
help = "A Goal global binding"
372-
}
357+
help := helpFunc(goalGlobal)
373358
perCategory[category] = append(perCategory[category], acEntry{goalGlobal, help})
374359
}
375360
}
@@ -406,10 +391,8 @@ func (autoCompleter *AutoCompleter) sqlAutoCompleteFn() func(v [][]rune, line, c
406391

407392
func (autoCompleter *AutoCompleter) cacheGoalKeywords(goalContext *goal.Context) {
408393
goalKeywords := goalContext.Keywords(nil)
409-
goalKeywordsHelp := ari.GoalKeywordsHelp()
410394
sort.Strings(goalKeywords)
411395
autoCompleter.goalKeywordsKeys = goalKeywords
412-
autoCompleter.goalKeywordsHelp = goalKeywordsHelp
413396
}
414397

415398
func (autoCompleter *AutoCompleter) cacheGoalSyntax() {
@@ -421,7 +404,6 @@ func (autoCompleter *AutoCompleter) cacheGoalSyntax() {
421404
sort.Strings(keys)
422405
autoCompleter.goalSyntaxKeys = keys
423406
autoCompleter.goalSyntaxAliases = goalSyntax
424-
autoCompleter.goalSyntaxHelp = ari.GoalSyntaxHelp()
425407
}
426408

427409
func (autoCompleter *AutoCompleter) cacheSQL() {

context.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@ import (
44
"os"
55

66
"codeberg.org/anaseto/goal"
7+
"github.com/semperos/ari/vendored/help"
78
)
89

9-
type Help map[string]map[string]string
10+
type Help struct {
11+
Dictionary map[string]map[string]string
12+
Func func(string) string
13+
}
1014

1115
type Context struct {
1216
// GoalContext is needed to evaluate Goal programs and introspect the Goal execution environment.
@@ -43,20 +47,7 @@ func NewSQLDatabase(dataSourceName string) (*SQLDatabase, error) {
4347

4448
func NewHelp() map[string]map[string]string {
4549
defaultSQLHelp := "A SQL keyword"
46-
// defaultGoalHelp := "A Goal keyword"
47-
goalGlobalsHelp := GoalGlobalsHelp()
48-
goalKeywordsHelp := GoalKeywordsHelp()
49-
goalSyntaxHelp := GoalSyntaxHelp()
50-
goalHelp := make(map[string]string, len(goalGlobalsHelp)+len(goalKeywordsHelp)+len(goalSyntaxHelp))
51-
for k, v := range goalGlobalsHelp {
52-
goalHelp[k] = v
53-
}
54-
for k, v := range goalKeywordsHelp {
55-
goalHelp[k] = v
56-
}
57-
for k, v := range goalSyntaxHelp {
58-
goalHelp[k] = v
59-
}
50+
goalHelp := GoalKeywordsHelp()
6051
sqlKeywords := SQLKeywords()
6152
sqlHelp := make(map[string]string, len(sqlKeywords))
6253
for _, x := range sqlKeywords {
@@ -71,7 +62,20 @@ func NewHelp() map[string]map[string]string {
7162
// Initialize a new Context without connecting to the database.
7263
func NewContext(dataSourceName string) (*Context, error) {
7364
ctx := Context{}
74-
help := NewHelp()
65+
helpDictionary := NewHelp()
66+
ariHelpFunc := func(s string) string {
67+
goalHelp, ok := helpDictionary["goal"]
68+
if !ok {
69+
panic(`Developer Error: Dictionary in Help must have a \"goal\" entry.`)
70+
}
71+
help, found := goalHelp[s]
72+
if found {
73+
return help
74+
}
75+
return ""
76+
}
77+
helpFunc := help.Wrap(ariHelpFunc, help.HelpFunc())
78+
help := Help{Dictionary: helpDictionary, Func: helpFunc}
7579
sqlDatabase, err := NewSQLDatabase(dataSourceName)
7680
if err != nil {
7781
return nil, err

export_test.go

Lines changed: 0 additions & 98 deletions
This file was deleted.

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.21
55
toolchain go1.22.0
66

77
require (
8-
codeberg.org/anaseto/goal v0.44.1-0.20241004131139-2c29db7014a9
8+
codeberg.org/anaseto/goal v0.44.1-0.20241008170026-f3932b3869c0
99
github.com/charmbracelet/lipgloss v0.13.0
1010
github.com/go-resty/resty/v2 v2.15.3
1111
github.com/jarcoal/httpmock v1.3.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
codeberg.org/anaseto/goal v0.44.1-0.20241004131139-2c29db7014a9 h1:cab2Z5qLhcwjKf8StkIcdhVbCJjtePfXlbg0DsUEBmI=
2-
codeberg.org/anaseto/goal v0.44.1-0.20241004131139-2c29db7014a9/go.mod h1:oipi4mkQiwXW9Td2IxNhuMV0Ewq4obs6EvkqpyZ6qMs=
1+
codeberg.org/anaseto/goal v0.44.1-0.20241008170026-f3932b3869c0 h1:qZ6JnuiGQvSePnZGzuiR5ZvFf0SG7r9HADB3dGXmu98=
2+
codeberg.org/anaseto/goal v0.44.1-0.20241008170026-f3932b3869c0/go.mod h1:oipi4mkQiwXW9Td2IxNhuMV0Ewq4obs6EvkqpyZ6qMs=
33
github.com/apache/arrow/go/v17 v17.0.0 h1:RRR2bdqKcdbss9Gxy2NS/hK8i4LDMh23L6BbkN5+F54=
44
github.com/apache/arrow/go/v17 v17.0.0/go.mod h1:jR7QHkODl15PfYyjM2nU+yTLScZ/qfj7OSUZmJ8putc=
55
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=

0 commit comments

Comments
 (0)