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 "runtime"10 "strings"1112 "github.com/boyter/scc/v3/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 stdio56 for _, arg := range os.Args[1:] {57 if arg == "--mcp" {58 startMCPServer()59 return60 }61 }6263 if len(os.Args) == 2 && strings.HasPrefix(os.Args[1], "@") {64 // handle "scc @flags.txt" syntax65 filepath := strings.TrimPrefix(os.Args[1], "@")66 b, err := os.ReadFile(filepath)67 if err != nil {68 fmt.Printf("Error reading flags from a file: %s\n", err)69 os.Exit(1)70 }7172 args := strings.Split(string(b), "\n")73 newArgs := make([]string, 0, len(args))74 for _, x := range args {75 newArgs = append(newArgs, strings.TrimSpace(x))76 }77 os.Args = append([]string{os.Args[0]}, newArgs...)78 }7980 rootCmd := &cobra.Command{81 Use: "scc [flags] [files or directories]",82 Short: "scc [files or directories]",83 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", processor.Version),84 Version: processor.Version,85 Run: func(cmd *cobra.Command, args []string) {86 processor.DirFilePaths = args87 processor.ConfigureGc()88 processor.ConfigureLazy(true)8990 // Detect if LOCOMO price/tps flags were explicitly set91 processor.LocomoInputPriceSet = cmd.PersistentFlags().Changed("locomo-input-price")92 processor.LocomoOutputPriceSet = cmd.PersistentFlags().Changed("locomo-output-price")93 processor.LocomoTPSSet = cmd.PersistentFlags().Changed("locomo-tps")94 processor.LocomoCyclesSet = cmd.PersistentFlags().Changed("locomo-cycles")9596 processor.Process()97 },98 }99100 flags := rootCmd.PersistentFlags()101102 flags.BoolVarP(103 &processor.MaxMean,104 "character",105 "m",106 false,107 "calculate max and mean characters per line",108 )109 flags.BoolVarP(110 &processor.Percent,111 "percent",112 "p",113 false,114 "include percentage values in output",115 )116 flags.BoolVarP(117 &processor.UlocMode,118 "uloc",119 "u",120 false,121 "calculate the number of unique lines of code (ULOC) for the project",122 )123 flags.BoolVarP(124 &processor.Dryness,125 "dryness",126 "a",127 false,128 "calculate the DRYness of the project (implies --uloc)",129 )130 flags.BoolVar(131 &processor.DisableCheckBinary,132 "binary",133 false,134 "disable binary file detection",135 )136 flags.BoolVar(137 &processor.Files,138 "by-file",139 false,140 "display output for every file",141 )142 flags.BoolVar(143 &processor.Ci,144 "ci",145 false,146 "enable CI output settings where stdout is ASCII",147 )148 flags.BoolVar(149 &processor.Ignore,150 "no-ignore",151 false,152 "disables .ignore file logic",153 )154 flags.BoolVar(155 &processor.SccIgnore,156 "no-scc-ignore",157 false,158 "disables .sccignore file logic",159 )160 flags.BoolVar(161 &processor.GitIgnore,162 "no-gitignore",163 false,164 "disables .gitignore file logic",165 )166 flags.BoolVar(167 &processor.GitModuleIgnore,168 "no-gitmodule",169 false,170 "disables .gitmodules file logic",171 )172 flags.BoolVar(173 &processor.CountIgnore,174 "count-ignore",175 false,176 "set to allow .gitignore and .ignore files to be counted",177 )178 flags.BoolVar(179 &processor.Debug,180 "debug",181 false,182 "enable debug output",183 )184 flags.StringSliceVar(185 &processor.PathDenyList,186 "exclude-dir",187 []string{".git", ".hg", ".svn"},188 "directories to exclude",189 )190 flags.IntVar(191 &processor.GcFileCount,192 "file-gc-count",193 10000,194 "number of files to parse before turning the GC on",195 )196 flags.IntVar(197 &processor.FileListQueueSize,198 "file-list-queue-size",199 runtime.NumCPU(),200 "the size of the queue of files found and ready to be read into memory",201 )202 flags.IntVar(203 &processor.FileProcessJobWorkers,204 "file-process-job-workers",205 runtime.NumCPU(),206 "number of goroutine workers that process files collecting stats",207 )208 flags.IntVar(209 &processor.FileSummaryJobQueueSize,210 "file-summary-job-queue-size",211 runtime.NumCPU(),212 "the size of the queue used to hold processed file statistics before formatting",213 )214 flags.IntVar(215 &processor.DirectoryWalkerJobWorkers,216 "directory-walker-job-workers",217 8,218 "controls the maximum number of workers which will walk the directory tree",219 )220 flags.StringVarP(221 &processor.Format,222 "format",223 "f",224 "tabular",225 "set output format [tabular, wide, json, json2, csv, csv-stream, cloc-yaml, html, html-table, sql, sql-insert, openmetrics]",226 )227 flags.StringSliceVarP(228 &processor.AllowListExtensions,229 "include-ext",230 "i",231 []string{},232 "limit to file extensions [comma separated list: e.g. go,java,js]",233 )234 flags.StringSliceVarP(235 &processor.ExcludeListExtensions,236 "exclude-ext",237 "x",238 []string{},239 "ignore file extensions (overrides include-ext) [comma separated list: e.g. go,java,js]",240 )241 flags.StringSliceVarP(242 &processor.ExcludeFilename,243 "exclude-file",244 "n",245 []string{"package-lock.json", "Cargo.lock", "yarn.lock", "pubspec.lock", "Podfile.lock", "pnpm-lock.yaml"},246 "ignore files with matching names",247 )248 flags.BoolVarP(249 &processor.Languages,250 "languages",251 "l",252 false,253 "print supported languages and extensions",254 )255 flags.Int64Var(256 &processor.AverageWage,257 "avg-wage",258 56286,259 "average wage value used for basic COCOMO calculation",260 )261 flags.Float64Var(262 &processor.Overhead,263 "overhead",264 2.4,265 "set the overhead multiplier for corporate overhead (facilities, equipment, accounting, etc.)",266 )267 flags.Float64Var(268 &processor.EAF,269 "eaf",270 1.0,271 "the effort adjustment factor derived from the cost drivers (1.0 if rated nominal)",272 )273 flags.BoolVar(274 &processor.SLOCCountFormat,275 "sloccount-format",276 false,277 "print a more SLOCCount like COCOMO calculation",278 )279 flags.BoolVar(280 &processor.Cocomo,281 "no-cocomo",282 false,283 "remove COCOMO calculation output",284 )285 flags.StringVar(286 &processor.CocomoProjectType,287 "cocomo-project-type",288 "organic",289 "change COCOMO model type [organic, semi-detached, embedded, \"custom,1,1,1,1\"]",290 )291 flags.BoolVar(292 &processor.Size,293 "no-size",294 false,295 "remove size calculation output",296 )297 flags.BoolVar(298 &processor.HBorder,299 "no-hborder",300 false,301 "remove horizontal borders between sections",302 )303 flags.StringVar(304 &processor.SizeUnit,305 "size-unit",306 "si",307 "set size unit [si, binary, mixed, xkcd-kb, xkcd-kelly, xkcd-imaginary, xkcd-intel, xkcd-drive, xkcd-bakers]",308 )309 flags.BoolVarP(310 &processor.Complexity,311 "no-complexity",312 "c",313 false,314 "skip calculation of code complexity",315 )316 flags.BoolVarP(317 &processor.Duplicates,318 "no-duplicates",319 "d",320 false,321 "remove duplicate files from stats and output",322 )323 flags.BoolVarP(324 &processor.MinifiedGenerated,325 "min-gen",326 "z",327 false,328 "identify minified or generated files",329 )330 flags.BoolVarP(331 &processor.Minified,332 "min",333 "",334 false,335 "identify minified files",336 )337 flags.BoolVarP(338 &processor.Generated,339 "gen",340 "",341 false,342 "identify generated files",343 )344 flags.StringSliceVarP(345 &processor.GeneratedMarkers,346 "generated-markers",347 "",348 []string{"do not edit", "<auto-generated />"},349 "string markers in head of generated files",350 )351 flags.BoolVar(352 &processor.IgnoreMinifiedGenerate,353 "no-min-gen",354 false,355 "ignore minified or generated files in output (implies --min-gen)",356 )357 flags.BoolVar(358 &processor.IgnoreMinified,359 "no-min",360 false,361 "ignore minified files in output (implies --min)",362 )363 flags.BoolVar(364 &processor.IgnoreGenerated,365 "no-gen",366 false,367 "ignore generated files in output (implies --gen)",368 )369 flags.IntVar(370 &processor.MinifiedGeneratedLineByteLength,371 "min-gen-line-length",372 255,373 "number of bytes per average line for file to be considered minified or generated",374 )375 flags.StringArrayVarP(376 &processor.Exclude,377 "not-match",378 `M`,379 []string{},380 "ignore files and directories matching regular expression",381 )382 flags.StringVarP(383 &processor.FileOutput,384 "output",385 "o",386 "",387 "output filename (default stdout)",388 )389 flags.StringVarP(390 &processor.SortBy,391 "sort",392 "s",393 "files",394 "column to sort by [files, name, lines, blanks, code, comments, complexity]",395 )396 flags.BoolVarP(397 &processor.Trace,398 "trace",399 "t",400 false,401 "enable trace output (not recommended when processing multiple files)",402 )403 flags.BoolVarP(404 &processor.Verbose,405 "verbose",406 "v",407 false,408 "verbose output",409 )410 flags.BoolVarP(411 &processor.More,412 "wide",413 "w",414 false,415 "wider output with additional statistics (implies --complexity)",416 )417 flags.BoolVar(418 &processor.NoLarge,419 "no-large",420 false,421 "ignore files over certain byte and line size set by large-line-count and large-byte-count",422 )423 flags.BoolVar(424 &processor.IncludeSymLinks,425 "include-symlinks",426 false,427 "if set will count symlink files",428 )429 flags.Int64Var(430 &processor.LargeLineCount,431 "large-line-count",432 40000,433 "number of lines a file can contain before being removed from output",434 )435 flags.Int64Var(436 &processor.LargeByteCount,437 "large-byte-count",438 1000000,439 "number of bytes a file can contain before being removed from output",440 )441 flags.StringVar(442 &processor.CountAs,443 "count-as",444 "",445 "count extension as language [e.g. jsp:htm,chead:\"C Header\" maps extension jsp to html and chead to C Header]",446 )447 flags.StringVar(448 &processor.FormatMulti,449 "format-multi",450 "",451 "have multiple format output overriding --format [e.g. tabular:stdout,csv:file.csv,json:file.json]",452 )453 flags.StringVar(454 &processor.SQLProject,455 "sql-project",456 "",457 "use supplied name as the project identifier for the current run. Only valid with the --format sql or sql-insert option",458 )459 flags.StringVar(460 &processor.RemapUnknown,461 "remap-unknown",462 "",463 "inspect files of unknown type and remap by checking for a string and remapping the language [e.g. \"-*- C++ -*-\":\"C Header\"]",464 )465 flags.StringVar(466 &processor.RemapAll,467 "remap-all",468 "",469 "inspect every file and remap by checking for a string and remapping the language [e.g. \"-*- C++ -*-\":\"C Header\"]",470 )471 flags.StringVar(472 &processor.CurrencySymbol,473 "currency-symbol",474 "$",475 "set currency symbol",476 )477 flags.BoolVar(478 &processor.Locomo,479 "locomo",480 false,481 "enable LOCOMO (LLM Output COst MOdel) cost estimation",482 )483 flags.BoolVar(484 &processor.CostComparison,485 "cost-comparison",486 false,487 "show both COCOMO and LOCOMO estimates side by side",488 )489 flags.StringVar(490 &processor.LocomoPresetName,491 "locomo-preset",492 "medium",493 "LOCOMO model preset [large, medium, small, local]",494 )495 flags.Float64Var(496 &processor.LocomoReviewMinutesPerLine,497 "locomo-review",498 0.01,499 "human review minutes per line of code for LOCOMO estimate",500 )501 flags.StringVar(502 &processor.LocomoConfig,503 "locomo-config",504 "",505 "LOCOMO power-user config \"tokensPerLine,inputPerLine,complexityWeight,iterations,iterationWeight\"",506 )507 flags.Float64Var(508 &processor.LocomoInputPrice,509 "locomo-input-price",510 0,511 "LOCOMO cost per 1M input tokens in dollars (overrides preset)",512 )513 flags.Float64Var(514 &processor.LocomoOutputPrice,515 "locomo-output-price",516 0,517 "LOCOMO cost per 1M output tokens in dollars (overrides preset)",518 )519 flags.Float64Var(520 &processor.LocomoTPS,521 "locomo-tps",522 0,523 "LOCOMO output tokens per second (overrides preset)",524 )525 flags.Float64Var(526 &processor.LocomoCyclesOverride,527 "locomo-cycles",528 0,529 "override estimated LLM iteration cycles (default: calculated from complexity)",530 )531532 // --mcp is intercepted before cobra runs, but we register it here so it appears in --help533 var mcpDummy bool534 flags.BoolVar(535 &mcpDummy,536 "mcp",537 false,538 "start as an MCP (Model Context Protocol) server over stdio",539 )540541 // If invoked in the format of "scc completion --shell [name of shell]", generate command line completions instead.542 // With the --shell option, unintentionally triggering shell completions should be highly unlikely.543 args := os.Args544 if len(args) == 4 && args[1] == "completion" && args[2] == "--shell" {545 err := printShellCompletion(rootCmd, args[3])546 if err != nil {547 _, _ = fmt.Fprintf(os.Stderr, "Error printing shell completion: %s\n", err)548 }549 return550 }551552 if err := rootCmd.Execute(); err != nil {553 // If a flag does not exist and is not a shorthand, it may be a spelling error. Search for and print possible options.554 if notExistError, ok := err.(*pflag.NotExistError); ok && len(notExistError.GetSpecifiedName()) > 1 {555 printFlagSuggestion(flags, notExistError.GetSpecifiedName())556 }557 os.Exit(1)558 }559}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.