feat(help): Add CLI help command

Fixes #136
This commit is contained in:
Snider 2026-02-02 00:19:10 +00:00
parent 12779ef67c
commit f574cae2a8
8 changed files with 159 additions and 3 deletions

BIN
core-test Executable file

Binary file not shown.

2
go.mod
View file

@ -5,7 +5,6 @@ go 1.25.5
require (
github.com/Snider/Borg v0.1.0
github.com/getkin/kin-openapi v0.133.0
github.com/host-uk/core-gui v0.0.0-20260131214111-6e2460834a87
github.com/leaanthony/debme v1.2.1
github.com/leaanthony/gosod v1.0.4
github.com/minio/selfupdate v0.6.0
@ -58,6 +57,7 @@ require (
github.com/tidwall/match v1.2.0 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/ugorji/go/codec v1.3.0 // indirect
github.com/wI2L/jsondiff v0.7.0 // indirect
github.com/woodsbury/decimal128 v1.4.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect

2
go.sum
View file

@ -59,8 +59,6 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8=
github.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
github.com/host-uk/core-gui v0.0.0-20260131214111-6e2460834a87 h1:gCdRVNxL1GpKhiYhtqJ60xm2ML3zU/UbYR9lHzlAWb8=
github.com/host-uk/core-gui v0.0.0-20260131214111-6e2460834a87/go.mod h1:yOBnW4of0/82O6GSxFl2Pxepq9yTlJg2pLVwaU9cWHo=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=

66
internal/cmd/help/cmd.go Normal file
View file

@ -0,0 +1,66 @@
package help
import (
"fmt"
"github.com/host-uk/core/pkg/cli"
"github.com/host-uk/core/pkg/help"
)
func init() {
cli.RegisterCommands(AddHelpCommands)
}
func AddHelpCommands(root *cli.Command) {
var searchFlag string
helpCmd := &cli.Command{
Use: "help [topic]",
Short: "Display help documentation",
Run: func(cmd *cli.Command, args []string) {
catalog := help.DefaultCatalog()
if searchFlag != "" {
results := catalog.Search(searchFlag)
if len(results) == 0 {
fmt.Println("No topics found.")
return
}
fmt.Println("Search Results:")
for _, res := range results {
fmt.Printf(" %s - %s\n", res.Topic.ID, res.Topic.Title)
}
return
}
if len(args) == 0 {
topics := catalog.List()
fmt.Println("Available Help Topics:")
for _, t := range topics {
fmt.Printf(" %s - %s\n", t.ID, t.Title)
}
return
}
topic, err := catalog.Get(args[0])
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
renderTopic(topic)
},
}
helpCmd.Flags().StringVarP(&searchFlag, "search", "s", "", "Search help topics")
root.AddCommand(helpCmd)
}
func renderTopic(t *help.Topic) {
// Simple ANSI rendering for now
// Use explicit ANSI codes or just print
fmt.Printf("\n\033[1;34m%s\033[0m\n", t.Title) // Blue bold title
fmt.Println("----------------------------------------")
fmt.Println(t.Content)
fmt.Println()
}

View file

@ -11,6 +11,9 @@ import (
"golang.org/x/mod/semver"
)
// PkgVersion is set via ldflags
var PkgVersion = "dev"
// Version holds the current version of the application.
// It is set at build time via ldflags or fallback to the version in package.json.
var Version = PkgVersion

View file

@ -41,5 +41,6 @@ import (
_ "github.com/host-uk/core/internal/cmd/updater"
_ "github.com/host-uk/core/internal/cmd/vm"
_ "github.com/host-uk/core/internal/cmd/workspace"
_ "github.com/host-uk/core/internal/cmd/help"
_ "github.com/host-uk/core/pkg/build/buildcmd"
)

1
issues.json Normal file

File diff suppressed because one or more lines are too long

87
pkg/help/catalog.go Normal file
View file

@ -0,0 +1,87 @@
package help
import (
"fmt"
)
// Catalog manages help topics.
type Catalog struct {
topics map[string]*Topic
index *searchIndex
}
// DefaultCatalog returns a catalog with built-in topics.
func DefaultCatalog() *Catalog {
c := &Catalog{
topics: make(map[string]*Topic),
index: newSearchIndex(),
}
// Add default topics
c.Add(&Topic{
ID: "getting-started",
Title: "Getting Started",
Content: `# Getting Started
Welcome to Core! This CLI tool helps you manage development workflows.
## Common Commands
- core dev: Development workflows
- core setup: Setup repository
- core doctor: Check environment health
- core test: Run tests
## Next Steps
Run 'core help <topic>' to learn more about a specific topic.
`,
})
c.Add(&Topic{
ID: "config",
Title: "Configuration",
Content: `# Configuration
Core is configured via environment variables and config files.
## Environment Variables
- CORE_DEBUG: Enable debug logging
- GITHUB_TOKEN: GitHub API token
## Config Files
Config is stored in ~/.core/config.yaml
`,
})
return c
}
// Add adds a topic to the catalog.
func (c *Catalog) Add(t *Topic) {
c.topics[t.ID] = t
c.index.Add(t)
}
// List returns all topics.
func (c *Catalog) List() []*Topic {
var list []*Topic
for _, t := range c.topics {
list = append(list, t)
}
return list
}
// Search searches for topics.
func (c *Catalog) Search(query string) []*SearchResult {
return c.index.Search(query)
}
// Get returns a topic by ID.
func (c *Catalog) Get(id string) (*Topic, error) {
t, ok := c.topics[id]
if !ok {
return nil, fmt.Errorf("topic not found: %s", id)
}
return t, nil
}