2026-01-30 10:32:05 +00:00
|
|
|
package cli
|
refactor(cli): restructure cmd packages into subdirectories
- Move CLI commands into subdirectories matching command hierarchy:
dev/, go/, php/, build/, ci/, sdk/, pkg/, vm/, docs/, setup/, doctor/, test/, ai/
- Create shared/ package for common styles and utilities
- Add new `core ai` root command with claude subcommand
- Update package declarations and imports across all files
- Create commands.go entry points for each package
- Remove GUI-related files (moved to core-gui repo)
This makes the filesystem structure match the CLI command structure,
improving context capture and code organization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 18:02:43 +00:00
|
|
|
|
|
|
|
|
import (
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
"bufio"
|
refactor(cli): restructure cmd packages into subdirectories
- Move CLI commands into subdirectories matching command hierarchy:
dev/, go/, php/, build/, ci/, sdk/, pkg/, vm/, docs/, setup/, doctor/, test/, ai/
- Create shared/ package for common styles and utilities
- Add new `core ai` root command with claude subcommand
- Update package declarations and imports across all files
- Create commands.go entry points for each package
- Remove GUI-related files (moved to core-gui repo)
This makes the filesystem structure match the CLI command structure,
improving context capture and code organization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 18:02:43 +00:00
|
|
|
"context"
|
|
|
|
|
"fmt"
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
"os"
|
refactor(cli): restructure cmd packages into subdirectories
- Move CLI commands into subdirectories matching command hierarchy:
dev/, go/, php/, build/, ci/, sdk/, pkg/, vm/, docs/, setup/, doctor/, test/, ai/
- Create shared/ package for common styles and utilities
- Add new `core ai` root command with claude subcommand
- Update package declarations and imports across all files
- Create commands.go entry points for each package
- Remove GUI-related files (moved to core-gui repo)
This makes the filesystem structure match the CLI command structure,
improving context capture and code organization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 18:02:43 +00:00
|
|
|
"os/exec"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
|
|
|
|
|
"github.com/host-uk/core/pkg/i18n"
|
refactor(cli): restructure cmd packages into subdirectories
- Move CLI commands into subdirectories matching command hierarchy:
dev/, go/, php/, build/, ci/, sdk/, pkg/, vm/, docs/, setup/, doctor/, test/, ai/
- Create shared/ package for common styles and utilities
- Add new `core ai` root command with claude subcommand
- Update package declarations and imports across all files
- Create commands.go entry points for each package
- Remove GUI-related files (moved to core-gui repo)
This makes the filesystem structure match the CLI command structure,
improving context capture and code organization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 18:02:43 +00:00
|
|
|
)
|
|
|
|
|
|
2026-01-29 18:27:33 +00:00
|
|
|
// GhAuthenticated checks if the GitHub CLI is authenticated.
|
|
|
|
|
// Returns true if 'gh auth status' indicates a logged-in user.
|
refactor(cli): restructure cmd packages into subdirectories
- Move CLI commands into subdirectories matching command hierarchy:
dev/, go/, php/, build/, ci/, sdk/, pkg/, vm/, docs/, setup/, doctor/, test/, ai/
- Create shared/ package for common styles and utilities
- Add new `core ai` root command with claude subcommand
- Update package declarations and imports across all files
- Create commands.go entry points for each package
- Remove GUI-related files (moved to core-gui repo)
This makes the filesystem structure match the CLI command structure,
improving context capture and code organization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 18:02:43 +00:00
|
|
|
func GhAuthenticated() bool {
|
|
|
|
|
cmd := exec.Command("gh", "auth", "status")
|
|
|
|
|
output, _ := cmd.CombinedOutput()
|
|
|
|
|
return strings.Contains(string(output), "Logged in")
|
|
|
|
|
}
|
|
|
|
|
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
// ConfirmOption configures Confirm behaviour.
|
|
|
|
|
type ConfirmOption func(*confirmConfig)
|
|
|
|
|
|
|
|
|
|
type confirmConfig struct {
|
|
|
|
|
defaultYes bool
|
|
|
|
|
required bool
|
2026-01-30 13:11:58 +00:00
|
|
|
timeout time.Duration
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DefaultYes sets the default response to "yes" (pressing Enter confirms).
|
|
|
|
|
func DefaultYes() ConfirmOption {
|
|
|
|
|
return func(c *confirmConfig) {
|
|
|
|
|
c.defaultYes = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Required prevents empty responses; user must explicitly type y/n.
|
|
|
|
|
func Required() ConfirmOption {
|
|
|
|
|
return func(c *confirmConfig) {
|
|
|
|
|
c.required = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-30 13:11:58 +00:00
|
|
|
// Timeout sets a timeout after which the default response is auto-selected.
|
|
|
|
|
// If no default is set (not Required and not DefaultYes), defaults to "no".
|
|
|
|
|
//
|
|
|
|
|
// Confirm("Continue?", Timeout(30*time.Second)) // Auto-no after 30s
|
|
|
|
|
// Confirm("Continue?", DefaultYes(), Timeout(10*time.Second)) // Auto-yes after 10s
|
|
|
|
|
func Timeout(d time.Duration) ConfirmOption {
|
|
|
|
|
return func(c *confirmConfig) {
|
|
|
|
|
c.timeout = d
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-29 18:27:33 +00:00
|
|
|
// Confirm prompts the user for yes/no confirmation.
|
|
|
|
|
// Returns true if the user enters "y" or "yes" (case-insensitive).
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
//
|
|
|
|
|
// Basic usage:
|
|
|
|
|
//
|
|
|
|
|
// if Confirm("Delete file?") { ... }
|
|
|
|
|
//
|
|
|
|
|
// With options:
|
|
|
|
|
//
|
|
|
|
|
// if Confirm("Save changes?", DefaultYes()) { ... }
|
|
|
|
|
// if Confirm("Dangerous!", Required()) { ... }
|
2026-01-30 13:11:58 +00:00
|
|
|
// if Confirm("Auto-continue?", Timeout(30*time.Second)) { ... }
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
func Confirm(prompt string, opts ...ConfirmOption) bool {
|
|
|
|
|
cfg := &confirmConfig{}
|
|
|
|
|
for _, opt := range opts {
|
|
|
|
|
opt(cfg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build the prompt suffix
|
|
|
|
|
var suffix string
|
|
|
|
|
if cfg.required {
|
|
|
|
|
suffix = "[y/n] "
|
|
|
|
|
} else if cfg.defaultYes {
|
|
|
|
|
suffix = "[Y/n] "
|
|
|
|
|
} else {
|
|
|
|
|
suffix = "[y/N] "
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-30 13:11:58 +00:00
|
|
|
// Add timeout indicator if set
|
|
|
|
|
if cfg.timeout > 0 {
|
|
|
|
|
suffix = fmt.Sprintf("%s(auto in %s) ", suffix, cfg.timeout.Round(time.Second))
|
|
|
|
|
}
|
|
|
|
|
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
reader := bufio.NewReader(os.Stdin)
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
fmt.Printf("%s %s", prompt, suffix)
|
2026-01-30 13:11:58 +00:00
|
|
|
|
|
|
|
|
var response string
|
|
|
|
|
|
|
|
|
|
if cfg.timeout > 0 {
|
|
|
|
|
// Use timeout-based reading
|
|
|
|
|
resultChan := make(chan string, 1)
|
|
|
|
|
go func() {
|
|
|
|
|
line, _ := reader.ReadString('\n')
|
|
|
|
|
resultChan <- line
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
case response = <-resultChan:
|
|
|
|
|
response = strings.ToLower(strings.TrimSpace(response))
|
|
|
|
|
case <-time.After(cfg.timeout):
|
|
|
|
|
fmt.Println() // New line after timeout
|
|
|
|
|
return cfg.defaultYes
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
response, _ = reader.ReadString('\n')
|
|
|
|
|
response = strings.ToLower(strings.TrimSpace(response))
|
|
|
|
|
}
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
|
|
|
|
|
// Handle empty response
|
|
|
|
|
if response == "" {
|
|
|
|
|
if cfg.required {
|
|
|
|
|
continue // Ask again
|
|
|
|
|
}
|
|
|
|
|
return cfg.defaultYes
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check for yes/no responses
|
|
|
|
|
if response == "y" || response == "yes" {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
if response == "n" || response == "no" {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Invalid response
|
|
|
|
|
if cfg.required {
|
|
|
|
|
fmt.Println("Please enter 'y' or 'n'")
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Non-required: treat invalid as default
|
|
|
|
|
return cfg.defaultYes
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
refactor(i18n): remove C() and move intents to test-only
Breaking change: Remove C() semantic intent composition API.
- Remove C() global function and Service.C() method
- Remove IntentBuilder fluent API (I(), For(), Compose(), etc.)
- Move coreIntents from intents.go to intents_test.go (test data only)
- Remove C() from Translator interface
Replace intent-based CLI helpers with grammar composition:
- ConfirmIntent → ConfirmAction(verb, subject)
- ConfirmDangerous → ConfirmDangerousAction(verb, subject)
- QuestionIntent → QuestionAction(verb, subject)
- ChooseIntent → ChooseAction(verb, subject, items)
- ChooseMultiIntent → ChooseMultiAction(verb, subject, items)
The intent definitions now serve purely as test data to verify
the grammar engine can compose identical strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:50:08 +00:00
|
|
|
// ConfirmAction prompts for confirmation of an action using grammar composition.
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
//
|
refactor(i18n): remove C() and move intents to test-only
Breaking change: Remove C() semantic intent composition API.
- Remove C() global function and Service.C() method
- Remove IntentBuilder fluent API (I(), For(), Compose(), etc.)
- Move coreIntents from intents.go to intents_test.go (test data only)
- Remove C() from Translator interface
Replace intent-based CLI helpers with grammar composition:
- ConfirmIntent → ConfirmAction(verb, subject)
- ConfirmDangerous → ConfirmDangerousAction(verb, subject)
- QuestionIntent → QuestionAction(verb, subject)
- ChooseIntent → ChooseAction(verb, subject, items)
- ChooseMultiIntent → ChooseMultiAction(verb, subject, items)
The intent definitions now serve purely as test data to verify
the grammar engine can compose identical strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:50:08 +00:00
|
|
|
// if ConfirmAction("delete", "config.yaml") { ... }
|
|
|
|
|
// if ConfirmAction("save", "changes", DefaultYes()) { ... }
|
|
|
|
|
func ConfirmAction(verb, subject string, opts ...ConfirmOption) bool {
|
|
|
|
|
question := i18n.Title(verb) + " " + subject + "?"
|
|
|
|
|
return Confirm(question, opts...)
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
}
|
|
|
|
|
|
refactor(i18n): remove C() and move intents to test-only
Breaking change: Remove C() semantic intent composition API.
- Remove C() global function and Service.C() method
- Remove IntentBuilder fluent API (I(), For(), Compose(), etc.)
- Move coreIntents from intents.go to intents_test.go (test data only)
- Remove C() from Translator interface
Replace intent-based CLI helpers with grammar composition:
- ConfirmIntent → ConfirmAction(verb, subject)
- ConfirmDangerous → ConfirmDangerousAction(verb, subject)
- QuestionIntent → QuestionAction(verb, subject)
- ChooseIntent → ChooseAction(verb, subject, items)
- ChooseMultiIntent → ChooseMultiAction(verb, subject, items)
The intent definitions now serve purely as test data to verify
the grammar engine can compose identical strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:50:08 +00:00
|
|
|
// ConfirmDangerousAction prompts for double confirmation of a dangerous action.
|
|
|
|
|
// Shows initial question, then a "Really verb subject?" confirmation.
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
//
|
refactor(i18n): remove C() and move intents to test-only
Breaking change: Remove C() semantic intent composition API.
- Remove C() global function and Service.C() method
- Remove IntentBuilder fluent API (I(), For(), Compose(), etc.)
- Move coreIntents from intents.go to intents_test.go (test data only)
- Remove C() from Translator interface
Replace intent-based CLI helpers with grammar composition:
- ConfirmIntent → ConfirmAction(verb, subject)
- ConfirmDangerous → ConfirmDangerousAction(verb, subject)
- QuestionIntent → QuestionAction(verb, subject)
- ChooseIntent → ChooseAction(verb, subject, items)
- ChooseMultiIntent → ChooseMultiAction(verb, subject, items)
The intent definitions now serve purely as test data to verify
the grammar engine can compose identical strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:50:08 +00:00
|
|
|
// if ConfirmDangerousAction("delete", "config.yaml") { ... }
|
|
|
|
|
func ConfirmDangerousAction(verb, subject string) bool {
|
|
|
|
|
question := i18n.Title(verb) + " " + subject + "?"
|
|
|
|
|
if !Confirm(question, Required()) {
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
refactor(i18n): remove C() and move intents to test-only
Breaking change: Remove C() semantic intent composition API.
- Remove C() global function and Service.C() method
- Remove IntentBuilder fluent API (I(), For(), Compose(), etc.)
- Move coreIntents from intents.go to intents_test.go (test data only)
- Remove C() from Translator interface
Replace intent-based CLI helpers with grammar composition:
- ConfirmIntent → ConfirmAction(verb, subject)
- ConfirmDangerous → ConfirmDangerousAction(verb, subject)
- QuestionIntent → QuestionAction(verb, subject)
- ChooseIntent → ChooseAction(verb, subject, items)
- ChooseMultiIntent → ChooseMultiAction(verb, subject, items)
The intent definitions now serve purely as test data to verify
the grammar engine can compose identical strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:50:08 +00:00
|
|
|
confirm := "Really " + verb + " " + subject + "?"
|
|
|
|
|
return Confirm(confirm, Required())
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// QuestionOption configures Question behaviour.
|
|
|
|
|
type QuestionOption func(*questionConfig)
|
|
|
|
|
|
|
|
|
|
type questionConfig struct {
|
|
|
|
|
defaultValue string
|
|
|
|
|
required bool
|
|
|
|
|
validator func(string) error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithDefault sets the default value shown in brackets.
|
|
|
|
|
func WithDefault(value string) QuestionOption {
|
|
|
|
|
return func(c *questionConfig) {
|
|
|
|
|
c.defaultValue = value
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithValidator adds a validation function for the response.
|
|
|
|
|
func WithValidator(fn func(string) error) QuestionOption {
|
|
|
|
|
return func(c *questionConfig) {
|
|
|
|
|
c.validator = fn
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RequiredInput prevents empty responses.
|
|
|
|
|
func RequiredInput() QuestionOption {
|
|
|
|
|
return func(c *questionConfig) {
|
|
|
|
|
c.required = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Question prompts the user for text input.
|
|
|
|
|
//
|
|
|
|
|
// name := Question("Enter your name:")
|
|
|
|
|
// name := Question("Enter your name:", WithDefault("Anonymous"))
|
|
|
|
|
// name := Question("Enter your name:", RequiredInput())
|
|
|
|
|
func Question(prompt string, opts ...QuestionOption) string {
|
|
|
|
|
cfg := &questionConfig{}
|
|
|
|
|
for _, opt := range opts {
|
|
|
|
|
opt(cfg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reader := bufio.NewReader(os.Stdin)
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
// Build prompt with default
|
|
|
|
|
if cfg.defaultValue != "" {
|
|
|
|
|
fmt.Printf("%s [%s] ", prompt, cfg.defaultValue)
|
|
|
|
|
} else {
|
|
|
|
|
fmt.Printf("%s ", prompt)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
response, _ := reader.ReadString('\n')
|
|
|
|
|
response = strings.TrimSpace(response)
|
|
|
|
|
|
|
|
|
|
// Handle empty response
|
|
|
|
|
if response == "" {
|
|
|
|
|
if cfg.required {
|
|
|
|
|
fmt.Println("Response required")
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
response = cfg.defaultValue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validate if validator provided
|
|
|
|
|
if cfg.validator != nil {
|
|
|
|
|
if err := cfg.validator(response); err != nil {
|
|
|
|
|
fmt.Printf("Invalid: %v\n", err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
refactor(i18n): remove C() and move intents to test-only
Breaking change: Remove C() semantic intent composition API.
- Remove C() global function and Service.C() method
- Remove IntentBuilder fluent API (I(), For(), Compose(), etc.)
- Move coreIntents from intents.go to intents_test.go (test data only)
- Remove C() from Translator interface
Replace intent-based CLI helpers with grammar composition:
- ConfirmIntent → ConfirmAction(verb, subject)
- ConfirmDangerous → ConfirmDangerousAction(verb, subject)
- QuestionIntent → QuestionAction(verb, subject)
- ChooseIntent → ChooseAction(verb, subject, items)
- ChooseMultiIntent → ChooseMultiAction(verb, subject, items)
The intent definitions now serve purely as test data to verify
the grammar engine can compose identical strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:50:08 +00:00
|
|
|
// QuestionAction prompts for text input using grammar composition.
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
//
|
refactor(i18n): remove C() and move intents to test-only
Breaking change: Remove C() semantic intent composition API.
- Remove C() global function and Service.C() method
- Remove IntentBuilder fluent API (I(), For(), Compose(), etc.)
- Move coreIntents from intents.go to intents_test.go (test data only)
- Remove C() from Translator interface
Replace intent-based CLI helpers with grammar composition:
- ConfirmIntent → ConfirmAction(verb, subject)
- ConfirmDangerous → ConfirmDangerousAction(verb, subject)
- QuestionIntent → QuestionAction(verb, subject)
- ChooseIntent → ChooseAction(verb, subject, items)
- ChooseMultiIntent → ChooseMultiAction(verb, subject, items)
The intent definitions now serve purely as test data to verify
the grammar engine can compose identical strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:50:08 +00:00
|
|
|
// name := QuestionAction("rename", "old.txt")
|
|
|
|
|
func QuestionAction(verb, subject string, opts ...QuestionOption) string {
|
|
|
|
|
question := i18n.Title(verb) + " " + subject + "?"
|
|
|
|
|
return Question(question, opts...)
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ChooseOption configures Choose behaviour.
|
|
|
|
|
type ChooseOption[T any] func(*chooseConfig[T])
|
|
|
|
|
|
|
|
|
|
type chooseConfig[T any] struct {
|
|
|
|
|
displayFn func(T) string
|
2026-01-30 13:11:58 +00:00
|
|
|
defaultN int // 0-based index of default selection
|
|
|
|
|
filter bool // Enable fuzzy filtering
|
|
|
|
|
multi bool // Allow multiple selection
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithDisplay sets a custom display function for items.
|
|
|
|
|
func WithDisplay[T any](fn func(T) string) ChooseOption[T] {
|
|
|
|
|
return func(c *chooseConfig[T]) {
|
|
|
|
|
c.displayFn = fn
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithDefaultIndex sets the default selection index (0-based).
|
|
|
|
|
func WithDefaultIndex[T any](idx int) ChooseOption[T] {
|
|
|
|
|
return func(c *chooseConfig[T]) {
|
|
|
|
|
c.defaultN = idx
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-30 13:11:58 +00:00
|
|
|
// Filter enables type-to-filter functionality.
|
|
|
|
|
// Users can type to narrow down the list of options.
|
|
|
|
|
// Note: This is a hint for interactive UIs; the basic CLI Choose
|
|
|
|
|
// implementation uses numbered selection which doesn't support filtering.
|
|
|
|
|
func Filter[T any]() ChooseOption[T] {
|
|
|
|
|
return func(c *chooseConfig[T]) {
|
|
|
|
|
c.filter = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Multi allows multiple selections.
|
|
|
|
|
// Use ChooseMulti instead of Choose when this option is needed.
|
|
|
|
|
func Multi[T any]() ChooseOption[T] {
|
|
|
|
|
return func(c *chooseConfig[T]) {
|
|
|
|
|
c.multi = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Display sets a custom display function for items.
|
|
|
|
|
// Alias for WithDisplay for shorter syntax.
|
|
|
|
|
//
|
|
|
|
|
// Choose("Select:", items, Display(func(f File) string { return f.Name }))
|
|
|
|
|
func Display[T any](fn func(T) string) ChooseOption[T] {
|
|
|
|
|
return WithDisplay[T](fn)
|
|
|
|
|
}
|
|
|
|
|
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
// Choose prompts the user to select from a list of items.
|
|
|
|
|
// Returns the selected item. Uses simple numbered selection for terminal compatibility.
|
|
|
|
|
//
|
|
|
|
|
// choice := Choose("Select a file:", files)
|
|
|
|
|
// choice := Choose("Select a file:", files, WithDisplay(func(f File) string { return f.Name }))
|
|
|
|
|
func Choose[T any](prompt string, items []T, opts ...ChooseOption[T]) T {
|
|
|
|
|
var zero T
|
|
|
|
|
if len(items) == 0 {
|
|
|
|
|
return zero
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cfg := &chooseConfig[T]{
|
|
|
|
|
displayFn: func(item T) string { return fmt.Sprint(item) },
|
|
|
|
|
}
|
|
|
|
|
for _, opt := range opts {
|
|
|
|
|
opt(cfg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Display options
|
|
|
|
|
fmt.Println(prompt)
|
|
|
|
|
for i, item := range items {
|
|
|
|
|
marker := " "
|
|
|
|
|
if i == cfg.defaultN {
|
|
|
|
|
marker = "*"
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf(" %s%d. %s\n", marker, i+1, cfg.displayFn(item))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reader := bufio.NewReader(os.Stdin)
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
fmt.Printf("Enter number [1-%d]: ", len(items))
|
|
|
|
|
response, _ := reader.ReadString('\n')
|
|
|
|
|
response = strings.TrimSpace(response)
|
|
|
|
|
|
|
|
|
|
// Empty response uses default
|
|
|
|
|
if response == "" {
|
|
|
|
|
return items[cfg.defaultN]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parse number
|
|
|
|
|
var n int
|
|
|
|
|
if _, err := fmt.Sscanf(response, "%d", &n); err == nil {
|
|
|
|
|
if n >= 1 && n <= len(items) {
|
|
|
|
|
return items[n-1]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fmt.Printf("Please enter a number between 1 and %d\n", len(items))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
refactor(i18n): remove C() and move intents to test-only
Breaking change: Remove C() semantic intent composition API.
- Remove C() global function and Service.C() method
- Remove IntentBuilder fluent API (I(), For(), Compose(), etc.)
- Move coreIntents from intents.go to intents_test.go (test data only)
- Remove C() from Translator interface
Replace intent-based CLI helpers with grammar composition:
- ConfirmIntent → ConfirmAction(verb, subject)
- ConfirmDangerous → ConfirmDangerousAction(verb, subject)
- QuestionIntent → QuestionAction(verb, subject)
- ChooseIntent → ChooseAction(verb, subject, items)
- ChooseMultiIntent → ChooseMultiAction(verb, subject, items)
The intent definitions now serve purely as test data to verify
the grammar engine can compose identical strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:50:08 +00:00
|
|
|
// ChooseAction prompts for selection using grammar composition.
|
feat(i18n): implement semantic i18n system with grammar engine
Add semantic intent system for natural language CLI interactions:
- Mode system (Normal/Strict/Collect) for missing key handling
- Subject type with fluent builder for typed subjects
- Composed type with Question/Confirm/Success/Failure forms
- 30+ core.* intents (delete, create, commit, push, etc.)
- Grammar engine: verb conjugation, noun pluralization, articles
- Template functions: title, lower, upper, past, plural, article
- Enhanced CLI: Confirm with options, Question, Choose functions
- Collect mode handler for QA testing
Usage:
i18n.T("core.delete", i18n.S("file", "config.yaml"))
result := i18n.C("core.delete", subject)
cli.ConfirmIntent("core.delete", subject)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:29:44 +00:00
|
|
|
//
|
refactor(i18n): remove C() and move intents to test-only
Breaking change: Remove C() semantic intent composition API.
- Remove C() global function and Service.C() method
- Remove IntentBuilder fluent API (I(), For(), Compose(), etc.)
- Move coreIntents from intents.go to intents_test.go (test data only)
- Remove C() from Translator interface
Replace intent-based CLI helpers with grammar composition:
- ConfirmIntent → ConfirmAction(verb, subject)
- ConfirmDangerous → ConfirmDangerousAction(verb, subject)
- QuestionIntent → QuestionAction(verb, subject)
- ChooseIntent → ChooseAction(verb, subject, items)
- ChooseMultiIntent → ChooseMultiAction(verb, subject, items)
The intent definitions now serve purely as test data to verify
the grammar engine can compose identical strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:50:08 +00:00
|
|
|
// file := ChooseAction("select", "file", files)
|
|
|
|
|
func ChooseAction[T any](verb, subject string, items []T, opts ...ChooseOption[T]) T {
|
|
|
|
|
question := i18n.Title(verb) + " " + subject + ":"
|
|
|
|
|
return Choose(question, items, opts...)
|
refactor(cli): restructure cmd packages into subdirectories
- Move CLI commands into subdirectories matching command hierarchy:
dev/, go/, php/, build/, ci/, sdk/, pkg/, vm/, docs/, setup/, doctor/, test/, ai/
- Create shared/ package for common styles and utilities
- Add new `core ai` root command with claude subcommand
- Update package declarations and imports across all files
- Create commands.go entry points for each package
- Remove GUI-related files (moved to core-gui repo)
This makes the filesystem structure match the CLI command structure,
improving context capture and code organization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 18:02:43 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-30 13:11:58 +00:00
|
|
|
// ChooseMulti prompts the user to select multiple items from a list.
|
|
|
|
|
// Returns the selected items. Uses space-separated numbers or ranges.
|
|
|
|
|
//
|
|
|
|
|
// choices := ChooseMulti("Select files:", files)
|
|
|
|
|
// choices := ChooseMulti("Select files:", files, WithDisplay(func(f File) string { return f.Name }))
|
|
|
|
|
//
|
|
|
|
|
// Input format:
|
|
|
|
|
// - "1 3 5" - select items 1, 3, and 5
|
|
|
|
|
// - "1-3" - select items 1, 2, and 3
|
|
|
|
|
// - "1 3-5" - select items 1, 3, 4, and 5
|
|
|
|
|
// - "" (empty) - select none
|
|
|
|
|
func ChooseMulti[T any](prompt string, items []T, opts ...ChooseOption[T]) []T {
|
|
|
|
|
if len(items) == 0 {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cfg := &chooseConfig[T]{
|
|
|
|
|
displayFn: func(item T) string { return fmt.Sprint(item) },
|
|
|
|
|
}
|
|
|
|
|
for _, opt := range opts {
|
|
|
|
|
opt(cfg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Display options
|
|
|
|
|
fmt.Println(prompt)
|
|
|
|
|
for i, item := range items {
|
|
|
|
|
fmt.Printf(" %d. %s\n", i+1, cfg.displayFn(item))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reader := bufio.NewReader(os.Stdin)
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
fmt.Printf("Enter numbers (e.g., 1 3 5 or 1-3) or empty for none: ")
|
|
|
|
|
response, _ := reader.ReadString('\n')
|
|
|
|
|
response = strings.TrimSpace(response)
|
|
|
|
|
|
|
|
|
|
// Empty response returns no selections
|
|
|
|
|
if response == "" {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parse the selection
|
|
|
|
|
selected, err := parseMultiSelection(response, len(items))
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Printf("Invalid selection: %v\n", err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build result
|
|
|
|
|
result := make([]T, 0, len(selected))
|
|
|
|
|
for _, idx := range selected {
|
|
|
|
|
result = append(result, items[idx])
|
|
|
|
|
}
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// parseMultiSelection parses a multi-selection string like "1 3 5" or "1-3 5".
|
|
|
|
|
// Returns 0-based indices.
|
|
|
|
|
func parseMultiSelection(input string, maxItems int) ([]int, error) {
|
|
|
|
|
selected := make(map[int]bool)
|
|
|
|
|
parts := strings.Fields(input)
|
|
|
|
|
|
|
|
|
|
for _, part := range parts {
|
|
|
|
|
// Check for range (e.g., "1-3")
|
|
|
|
|
if strings.Contains(part, "-") {
|
|
|
|
|
rangeParts := strings.Split(part, "-")
|
|
|
|
|
if len(rangeParts) != 2 {
|
|
|
|
|
return nil, fmt.Errorf("invalid range: %s", part)
|
|
|
|
|
}
|
|
|
|
|
var start, end int
|
|
|
|
|
if _, err := fmt.Sscanf(rangeParts[0], "%d", &start); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("invalid range start: %s", rangeParts[0])
|
|
|
|
|
}
|
|
|
|
|
if _, err := fmt.Sscanf(rangeParts[1], "%d", &end); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("invalid range end: %s", rangeParts[1])
|
|
|
|
|
}
|
|
|
|
|
if start < 1 || start > maxItems || end < 1 || end > maxItems || start > end {
|
|
|
|
|
return nil, fmt.Errorf("range out of bounds: %s", part)
|
|
|
|
|
}
|
|
|
|
|
for i := start; i <= end; i++ {
|
|
|
|
|
selected[i-1] = true // Convert to 0-based
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Single number
|
|
|
|
|
var n int
|
|
|
|
|
if _, err := fmt.Sscanf(part, "%d", &n); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("invalid number: %s", part)
|
|
|
|
|
}
|
|
|
|
|
if n < 1 || n > maxItems {
|
|
|
|
|
return nil, fmt.Errorf("number out of range: %d", n)
|
|
|
|
|
}
|
|
|
|
|
selected[n-1] = true // Convert to 0-based
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert map to sorted slice
|
|
|
|
|
result := make([]int, 0, len(selected))
|
|
|
|
|
for i := 0; i < maxItems; i++ {
|
|
|
|
|
if selected[i] {
|
|
|
|
|
result = append(result, i)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result, nil
|
|
|
|
|
}
|
|
|
|
|
|
refactor(i18n): remove C() and move intents to test-only
Breaking change: Remove C() semantic intent composition API.
- Remove C() global function and Service.C() method
- Remove IntentBuilder fluent API (I(), For(), Compose(), etc.)
- Move coreIntents from intents.go to intents_test.go (test data only)
- Remove C() from Translator interface
Replace intent-based CLI helpers with grammar composition:
- ConfirmIntent → ConfirmAction(verb, subject)
- ConfirmDangerous → ConfirmDangerousAction(verb, subject)
- QuestionIntent → QuestionAction(verb, subject)
- ChooseIntent → ChooseAction(verb, subject, items)
- ChooseMultiIntent → ChooseMultiAction(verb, subject, items)
The intent definitions now serve purely as test data to verify
the grammar engine can compose identical strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:50:08 +00:00
|
|
|
// ChooseMultiAction prompts for multiple selections using grammar composition.
|
2026-01-30 13:11:58 +00:00
|
|
|
//
|
refactor(i18n): remove C() and move intents to test-only
Breaking change: Remove C() semantic intent composition API.
- Remove C() global function and Service.C() method
- Remove IntentBuilder fluent API (I(), For(), Compose(), etc.)
- Move coreIntents from intents.go to intents_test.go (test data only)
- Remove C() from Translator interface
Replace intent-based CLI helpers with grammar composition:
- ConfirmIntent → ConfirmAction(verb, subject)
- ConfirmDangerous → ConfirmDangerousAction(verb, subject)
- QuestionIntent → QuestionAction(verb, subject)
- ChooseIntent → ChooseAction(verb, subject, items)
- ChooseMultiIntent → ChooseMultiAction(verb, subject, items)
The intent definitions now serve purely as test data to verify
the grammar engine can compose identical strings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:50:08 +00:00
|
|
|
// files := ChooseMultiAction("select", "files", files)
|
|
|
|
|
func ChooseMultiAction[T any](verb, subject string, items []T, opts ...ChooseOption[T]) []T {
|
|
|
|
|
question := i18n.Title(verb) + " " + subject + ":"
|
|
|
|
|
return ChooseMulti(question, items, opts...)
|
2026-01-30 13:11:58 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-29 18:27:33 +00:00
|
|
|
// GitClone clones a GitHub repository to the specified path.
|
|
|
|
|
// Prefers 'gh repo clone' if authenticated, falls back to SSH.
|
refactor(cli): restructure cmd packages into subdirectories
- Move CLI commands into subdirectories matching command hierarchy:
dev/, go/, php/, build/, ci/, sdk/, pkg/, vm/, docs/, setup/, doctor/, test/, ai/
- Create shared/ package for common styles and utilities
- Add new `core ai` root command with claude subcommand
- Update package declarations and imports across all files
- Create commands.go entry points for each package
- Remove GUI-related files (moved to core-gui repo)
This makes the filesystem structure match the CLI command structure,
improving context capture and code organization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 18:02:43 +00:00
|
|
|
func GitClone(ctx context.Context, org, repo, path string) error {
|
|
|
|
|
if GhAuthenticated() {
|
|
|
|
|
httpsURL := fmt.Sprintf("https://github.com/%s/%s.git", org, repo)
|
|
|
|
|
cmd := exec.CommandContext(ctx, "gh", "repo", "clone", httpsURL, path)
|
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
|
|
|
if err == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
errStr := strings.TrimSpace(string(output))
|
|
|
|
|
if strings.Contains(errStr, "already exists") {
|
|
|
|
|
return fmt.Errorf("%s", errStr)
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-29 18:27:33 +00:00
|
|
|
// Fall back to SSH clone
|
refactor(cli): restructure cmd packages into subdirectories
- Move CLI commands into subdirectories matching command hierarchy:
dev/, go/, php/, build/, ci/, sdk/, pkg/, vm/, docs/, setup/, doctor/, test/, ai/
- Create shared/ package for common styles and utilities
- Add new `core ai` root command with claude subcommand
- Update package declarations and imports across all files
- Create commands.go entry points for each package
- Remove GUI-related files (moved to core-gui repo)
This makes the filesystem structure match the CLI command structure,
improving context capture and code organization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 18:02:43 +00:00
|
|
|
cmd := exec.CommandContext(ctx, "git", "clone", fmt.Sprintf("git@github.com:%s/%s.git", org, repo), path)
|
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("%s", strings.TrimSpace(string(output)))
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|