Documentation
¶
Overview ¶
Package format provides the command to auto-format project source code.
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var FormatCmd = &cobra.Command{ Use: "format [paths...]", Example: ` contextvibes product format # Format entire project contextvibes product format --strict # Format using strict rules contextvibes product format --remove-directives # Remove //nolint comments contextvibes product format cmd/factory/scrub # Format specific package`, Args: cobra.ArbitraryArgs, RunE: func(cmd *cobra.Command, args []string) error { presenter := ui.NewPresenter(cmd.OutOrStdout(), cmd.ErrOrStderr()) ctx := cmd.Context() presenter.Summary("Applying code formatting and auto-fixes.") cwd, err := os.Getwd() if err != nil { return fmt.Errorf("failed to get working directory: %w", err) } gitCfg := git.GitClientConfig{ Logger: globals.AppLogger, Executor: globals.ExecClient.UnderlyingExecutor(), } gitClient, err := git.NewClient(ctx, cwd, gitCfg) if err != nil { presenter.Warning("Could not initialize Git client. Safety checks and smart reporting will be disabled.") } projType, err := project.Detect(cwd) if err != nil { return fmt.Errorf("failed to detect project type: %w", err) } presenter.Info("Detected project type: %s", presenter.Highlight(string(projType))) // --- Report Buffer Initialization --- var reportBuffer bytes.Buffer fmt.Fprintf(&reportBuffer, "# Format Report (%s)\n\n", time.Now().Format(time.RFC3339)) fmt.Fprintf(&reportBuffer, "> **AI Instruction:** This report details the results of the `format` command. Review the 'Execution Log' for errors. If files are listed under 'Updated File Content', treat that content as the new Ground Truth, superseding previous context. If no files are listed there, no changes were made.\n\n") fmt.Fprintf(&reportBuffer, "## Execution Log\n\n") var formatErrors []error switch projType { case project.Go: if removeDirectives { modified, err := runStripDirectives(ctx, presenter, gitClient, cwd, args) if err != nil { return err } if len(modified) > 0 { fmt.Fprintf(&reportBuffer, "### Strip Directives\n") for _, f := range modified { fmt.Fprintf(&reportBuffer, "- Cleaned: %s\n", f) } fmt.Fprintf(&reportBuffer, "\n") } } presenter.Header("Go Formatting & Lint Fixes") if globals.ExecClient.CommandExists("go") { out, err := runFormatCommand(ctx, presenter, globals.ExecClient, cwd, "go", []string{"mod", "tidy"}) logOutput(&reportBuffer, "go mod tidy", out, err) if err != nil { formatErrors = append(formatErrors, err) } else { presenter.Success("✓ go mod tidy applied.") } } if globals.ExecClient.CommandExists("goimports") { goimportsArgs := []string{"-l", "-w"} if len(args) > 0 { goimportsArgs = append(goimportsArgs, args...) } else { goimportsArgs = append(goimportsArgs, ".") } out, err := runFormatCommand(ctx, presenter, globals.ExecClient, cwd, "goimports", goimportsArgs) logOutput(&reportBuffer, "goimports", out, err) if err != nil { formatErrors = append(formatErrors, err) } else { if len(out) > 0 { lines := strings.SplitSeq(strings.TrimSpace(out), "\n") for line := range lines { presenter.Detail("Updated: %s", line) } } presenter.Success("✓ goimports applied.") } } else { presenter.Warning("goimports not found. Install 'gotools' for better import management.") } gofmtArgs := []string{"-l", "-s", "-w"} if len(args) > 0 { gofmtArgs = append(gofmtArgs, args...) } else { gofmtArgs = append(gofmtArgs, ".") } out, err := runFormatCommand(ctx, presenter, globals.ExecClient, cwd, "gofmt", gofmtArgs) logOutput(&reportBuffer, "gofmt", out, err) if err != nil { formatErrors = append(formatErrors, err) } else { if len(out) > 0 { lines := strings.SplitSeq(strings.TrimSpace(out), "\n") for line := range lines { presenter.Detail("Updated: %s", line) } } presenter.Success("✓ gofmt -s applied.") } lintArgs := []string{"run", "--fix"} if strictMode { presenter.Info("Using strict configuration for linter fixes.") configBytes, err := config.GetLanguageAsset("go", config.AssetLintStrict) if err != nil { return fmt.Errorf("failed to load strict config asset: %w", err) } tmpFile, err := os.CreateTemp(".", ".golangci-strict-*.yml") if err != nil { return fmt.Errorf("failed to create temp strict config: %w", err) } defer os.Remove(tmpFile.Name()) if _, err := tmpFile.Write(configBytes); err != nil { return fmt.Errorf("failed to write strict config: %w", err) } tmpFile.Close() lintArgs = append(lintArgs, "-c", tmpFile.Name()) } if len(args) > 0 { lintArgs = append(lintArgs, args...) } lintOut, lintErr := runFormatCommand(ctx, presenter, globals.ExecClient, cwd, "golangci-lint", lintArgs) if strictMode { lintOut = strings.ReplaceAll(lintOut, ".golangci-strict-*.yml", ".golangci-strict.yml") } logOutput(&reportBuffer, "golangci-lint", lintOut, lintErr) if lintErr != nil { presenter.Warning("'golangci-lint --fix' completed but may have found unfixable issues.") } else { presenter.Success("✓ golangci-lint --fix applied.") } default: presenter.Info("No formatters configured for %s", projType) } presenter.Newline() if len(formatErrors) > 0 { return errFormattingFailed } presenter.Success("All formatting and auto-fixing tools completed.") if gitClient != nil { statusOut, _, err := gitClient.GetStatusShort(ctx) if err == nil && len(statusOut) > 0 { dirtyFiles := parseGitStatus(statusOut) filesToDump := filterFiles(dirtyFiles, args) if len(filesToDump) > 0 { fmt.Fprintf(&reportBuffer, "\n## Updated File Content (Ground Truth)\n") for _, path := range filesToDump { info, err := os.Stat(path) if err == nil && !info.IsDir() { content, err := os.ReadFile(path) if err == nil { tools.AppendFileMarkerHeader(&reportBuffer, path) reportBuffer.Write(content) tools.AppendFileMarkerFooter(&reportBuffer, path) } } } } } } if err := tools.WriteBufferToFile("_contextvibes.md", &reportBuffer); err != nil { presenter.Error("Failed to write report to _contextvibes.md: %v", err) } else { presenter.Success("Full context written to %s", presenter.Highlight("_contextvibes.md")) } return nil }, }
FormatCmd represents the format command.
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.