Blank identifier discarding results; verify intentional ignoring of return values
_, _ = fmt.Fprintf(os.Stderr, "The most similar flags of --%s are:\n", unknownFlag)
1// SPDX-License-Identifier: MIT23package main45import (6 "errors"7 "fmt"8 "os"9 "slices"10 "strings"1112 "github.com/boyter/scc/v4/processor"13 "github.com/spf13/cobra"14 "github.com/spf13/pflag"15)1617func printShellCompletion(cmd *cobra.Command, command string) error {18 switch command {19 case "bash":20 return cmd.GenBashCompletionV2(os.Stdout, true)21 case "zsh":22 return cmd.GenZshCompletion(os.Stdout)23 case "fish":24 return cmd.GenFishCompletion(os.Stdout, true)25 case "powershell":26 return cmd.GenPowerShellCompletion(os.Stdout)27 default:28 return errors.New("Unknown shell: " + command)29 }30}3132func printFlagSuggestion(flagSet *pflag.FlagSet, unknownFlag string) {33 flags := processor.GetMostSimilarFlags(flagSet, unknownFlag)34 if len(flags) == 0 {35 return36 }3738 if len(flags) > 1 {39 _, _ = fmt.Fprintf(os.Stderr, "The most similar flags of --%s are:\n", unknownFlag)40 } else {41 _, _ = fmt.Fprintf(os.Stderr, "The most similar flag of --%s is:\n", unknownFlag)42 }4344 for _, flag := range flags {45 _, _ = fmt.Fprintf(os.Stderr, "\t--%s\n", flag)46 }47}4849//go:generate go run scripts/include.go50func main() {51 // f, _ := os.Create("scc.pprof")52 // pprof.StartCPUProfile(f)53 // defer pprof.StopCPUProfile()5455 // Handle --mcp flag before cobra to avoid interfering with stdio. Match both56 // the bare boolean form and the explicit --mcp=true form pflag accepts, so the57 // server starts consistently however the flag is spelled.58 if slices.ContainsFunc(os.Args[1:], func(a string) bool {59 return a == "--mcp" || a == "--mcp=true"60 }) {61 startMCPServer()62 return63 }6465 // handle "scc @flags.txt" syntax. The sole-argument trigger is preserved;66 // only the splitter is swapped for the shared tokenizer, which adds comment67 // stripping, quote-aware tokenization and drops the old blank-line empty-arg68 // bug.69 if len(os.Args) == 2 && strings.HasPrefix(os.Args[1], "@") {70 filename := strings.TrimPrefix(os.Args[1], "@")71 b, err := os.ReadFile(filename)72 if err != nil {73 fmt.Fprintf(os.Stderr, "Error reading flags from a file: %s\n", err)74 os.Exit(1)75 }76 os.Args = append([]string{os.Args[0]}, parseConfigArgs(string(b), true)...)77 }7879 // What the user actually specified80 genuineCLI := slices.Clone(os.Args[1:])8182 // Cobra's completion machinery must see the genuine argv. The shell invokes83 // the hidden __complete / __completeNoDesc commands on every TAB, and the84 // user-facing `completion` command generates the scripts; both key on the85 // subcommand sitting in args[0]. Prepending discovered config tokens would86 // shift it and break dynamic completion in any directory containing a ./.sccconfig.87 // Config never influences completion output anyway, so skip discovery for it.88 var globalTokens, projectTokens []string89 if !isCompletionInvocation(os.Args) {90 noConfig, findRoot, explicitPath := preScanConfig(os.Args)91 var discoverErr error92 globalTokens, projectTokens, discoverErr = discoverConfigArgs(noConfig, findRoot, explicitPath)93 if discoverErr != nil {94 processor.PrintError(discoverErr.Error())95 os.Exit(1)96 }97 }9899 // Fast path when no config was discovered: the merged list *is* the genuine100 // CLI, so bind write flags directly to the real vars and parse once, exactly101 // as scc does today. The discard / CLI-only split engages only when config is102 // actually present.103 // Ensures we follow old scc logic without config104 configPresent := len(globalTokens) != 0 || len(projectTokens) != 0105106 // Build the merged argument list N.B. ORDER MATTERS HERE! CLI MUST COME LAST!107 var merged []string108 merged = append(merged, os.Args[0])109 merged = append(merged, globalTokens...)110 merged = append(merged, projectTokens...)111 merged = append(merged, genuineCLI...)112113 // Write-flag bindings for the merged parse114 var discardOutput, discardReport, discardFormatMulti string115 bindings := &flagBindings{116 output: &processor.FileOutput,117 report: &processor.ReportOut,118 formatMulti: &processor.FormatMulti,119 }120121 // if we use config, we NEVER allow writing to disk because someone could use that as122 // an attack vector, so we reset these options to ensure this is not a risk123 if configPresent {124 bindings.output = &discardOutput125 bindings.report = &discardReport126 bindings.formatMulti = &discardFormatMulti127 }128129 rootCmd := &cobra.Command{130 Use: "scc [flags] [files or directories]",131 Short: "scc [files or directories]",132 Long: fmt.Sprintf("Sloc, Cloc and Code. Count lines of code in a directory with complexity estimation.\nVersion %s\nBen Boyter <ben@boyter.org> + Contributors\nhttps://github.com/boyter/scc", processor.Version),133 Example: ` Count the current directory:134 scc135136 Count a specific folder or file:137 scc myproject/138 scc main.go139140 Count several paths at once:141 scc src/ docs/ README.md142143 Show a per-file breakdown instead of the per-language summary:144 scc --by-file145146 Output as CSV or JSON (e.g. for further processing):147 scc --format csv148 scc --format json -o counts.json149150 Count an unrecognised extension as a known language:151 scc --count-as jsp:html152153 Count files matching a path pattern as a new category (glob by default):154 scc --count-as-pattern '*_spec.rb:Ruby Spec:Ruby'155156 Generate a self-contained HTML infographic report:157 scc --report158 scc --report=out.html --report-title "myrepo" --report-skip cocomo159160 Use a project config file (./.sccconfig) or a global one (precedence: global < project < CLI):161 export SCC_CONFIG_PATH=~/.sccconfig162 scc --config team.sccconfig163164 Tune the COCOMO cost estimate, or turn it off (see https://en.wikipedia.org/wiki/COCOMO):165 scc --avg-wage 75000 --cocomo-project-type semi-detached166 scc --no-cocomo`,167 Version: processor.Version,168 Run: func(cmd *cobra.Command, args []string) {169 processor.DirFilePaths = args170 processor.ConfigureGc()171 processor.ConfigureLazy(true)172173 // Detect if LOCOMO price/tps flags were explicitly set. Their default174 // is 0, which is ambiguous (unset vs. an explicit 0), so the processor175 // needs the "was it set?" bit to decide between the preset value and the176 // user override. Only pflag's Changed() knows this, hence here not there.177 processor.LocomoInputPriceSet = cmd.PersistentFlags().Changed("locomo-input-price")178 processor.LocomoOutputPriceSet = cmd.PersistentFlags().Changed("locomo-output-price")179 processor.LocomoTPSSet = cmd.PersistentFlags().Changed("locomo-tps")180 processor.LocomoCyclesSet = cmd.PersistentFlags().Changed("locomo-cycles")181182 if v, err := cmd.PersistentFlags().GetBool("no-fold-authors"); err == nil && v {183 processor.FoldAuthors = false184 }185186 // Source the write vars from the genuine CLI alone (file output is a187 // CLI-only capability), then warn if config tried to set one.188 if configPresent {189 cliSet := resolveWriteFlags(genuineCLI)190 warnIfConfigWrote(cmd.PersistentFlags(), cliSet)191 }192193 // Merge the built-in defaults back into the empty-defaulted slice194 // flags, then flush any buffered config trace/debug.195 applySliceDefaults()196 flushConfigTrace()197198 processor.Process()199 },200 }201202 flags := rootCmd.PersistentFlags()203 registerFlags(flags, bindings)204 registerConfigControlFlags(flags)205206 // If invoked in the format of "scc completion --shell [name of shell]", generate command line completions instead.207 // With the --shell option, unintentionally triggering shell completions should be highly unlikely. This reads the208 // genuine os.Args (config tokens are handed to cobra via SetArgs below, never prepended into os.Args), so a ./.sccconfig209 // in the working directory cannot shift args[1] and break completion.210 args := os.Args211 if len(args) == 4 && args[1] == "completion" && args[2] == "--shell" {212 err := printShellCompletion(rootCmd, args[3])213 if err != nil {214 _, _ = fmt.Fprintf(os.Stderr, "Error printing shell completion: %s\n", err)215 }216 return217 }218219 // Hand the merged list to cobra without mutating os.Args.220 rootCmd.SetArgs(merged[1:])221222 if err := rootCmd.Execute(); err != nil {223 // If a flag does not exist and is not a shorthand, it may be a spelling error. Search for and print possible options.224 if notExistError, ok := err.(*pflag.NotExistError); ok && len(notExistError.GetSpecifiedName()) > 1 {225 name := notExistError.GetSpecifiedName()226 // Best-effort: attribute the unknown flag to the config file it came.227 if src := attributeConfigFlag(name); src != "" {228 _, _ = fmt.Fprintf(os.Stderr, "in %s: unknown flag --%s\n", src, name)229 }230 printFlagSuggestion(flags, name)231 }232 os.Exit(1)233 }234}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.