Skip to content

Commit

Permalink
feat: add cli fraemwork
Browse files Browse the repository at this point in the history
  • Loading branch information
krzko committed Nov 4, 2024
1 parent 2ce128d commit 0f31dc7
Show file tree
Hide file tree
Showing 15 changed files with 519 additions and 108 deletions.
100 changes: 69 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
Here's the updated README.md that reflects the new CLI structure:

```markdown
# codemap

`codemap` is a tool that helps annotate code files with structural information to provide better context for LLMs (Large Language Models). It adds a single line of metadata at the top of each file containing the file path, package name and language information.
Expand All @@ -19,37 +22,71 @@ make build
Or use docker:

```bash
docker run -v $(pwd):/app krzko/codemap
docker run -v $(pwd):/app ghcr.io/krzko/codemap apply --dry-run
```

## Usage
## Commands

### Apply Annotations

Basic usage:
```bash
# Process files in current directory
codemap
# Add annotations to files in current directory
codemap apply

# Process files in a specific directory
codemap -dir=/path/to/your/project
# Add annotations with dry-run (show what would change)
codemap apply --dry-run

# Remove annotations
codemap -clean
# Add annotations to specific directory
codemap apply -d /path/to/project

# Enable verbose logging
codemap -verbose
# Add annotations with verbose output
codemap apply -V
```

### Command Line Options
### Clean Annotations

```bash
# Remove annotations from files in current directory
codemap clean

# Remove annotations with dry-run
codemap clean --dry-run

# Clean specific directory
codemap clean -d /path/to/project
```

### List Files

```bash
# List files that would be processed
codemap list
# or
codemap ls

# List files in specific directory
codemap list -d /path/to/project
```

### Show Statistics

```bash
# Show annotation statistics for current directory
codemap stats

# Show stats for specific directory
codemap stats -d /path/to/project
```

- `-dir`: Directory to process (default: current directory)
- `-clean`: Remove existing annotations
- `-verbose`: Enable verbose logging
- `-types`: Comma-separated list of file extensions to process (default: "go,py,js,jsx,ts,tsx")
- `-version`: Print version information
### Common Options

### Example
All commands support these options:
- `-d, --dir`: Directory to process (default: current directory)
- `-t, --types`: Comma-separated list of file extensions (default: "go,py,js,jsx,ts,tsx")
- `-V, --verbose`: Enable verbose logging
- `-v, --version`: Display version information

Processing a file will add a single line annotation at the top:
### Example Annotation

Before:
```go
Expand Down Expand Up @@ -80,6 +117,7 @@ func main() {
- Python (.py)
- JavaScript (.js, .jsx)
- TypeScript (.ts, .tsx)
- Dockerfile

### Default Exclusions

Expand Down Expand Up @@ -112,21 +150,21 @@ Files:
## Examples

```bash
# Process all supported files in current directory
codemap
# Add annotations with dry-run
codemap apply --dry-run

# Process only Go files in current directory
codemap -types=go
# Process only Go files
codemap apply -t go

# Process Python and JavaScript files in a specific directory
codemap -dir=/path/to/project -types=py,js
# Clean TypeScript files with dry-run
codemap clean -t ts,tsx --dry-run

# Clean annotations from all files in current directory
codemap -clean
# List all Python and JavaScript files
codemap list -t py,js

# Clean annotations from TypeScript files
codemap -clean -types=ts,tsx
# Show stats for Go files
codemap stats -t go

# Process all supported files with verbose logging
codemap -verbose
# Process all files with verbose output
codemap apply -V
```
72 changes: 14 additions & 58 deletions cmd/codemap/main.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package main

import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"runtime"

"github.com/krzko/codemap/internal/processor"
"github.com/krzko/codemap/internal/cli"
ucli "github.com/urfave/cli/v2"
)

var (
Expand All @@ -17,62 +15,20 @@ var (
date = "unknown"
)

func init() {
log.SetFlags(log.Ltime)
}

func displayVersion() {
fmt.Printf("codemap version %s\n", version)
fmt.Printf(" Build date: %s\n", date)
fmt.Printf(" Git commit: %s\n", commit)
fmt.Printf(" Go version: %s\n", runtime.Version())
fmt.Printf(" OS/Arch: %s/%s\n", runtime.GOOS, runtime.GOARCH)
}

func main() {
showVersion := flag.Bool("version", false, "Display version information")

dir := flag.String("dir", ".", "Directory to process (defaults to current directory)")
clean := flag.Bool("clean", false, "Remove existing annotations")
verbose := flag.Bool("verbose", false, "Enable verbose logging")
fileTypes := flag.String("types", "go,py,js,jsx,ts,tsx", "Comma-separated list of file types to process")

versionShort := flag.Bool("v", false, "Display version information")

flag.Parse()

// Check for version flag
if *showVersion || *versionShort {
displayVersion()
os.Exit(0)
app := &ucli.App{
Name: "codemap",
Usage: "Annotate code files with structural information for LLMs",
Version: version,
Metadata: map[string]interface{}{
"commit": commit,
"buildDate": date,
"goVersion": runtime.Version(),
},
Commands: cli.Commands(),
}

if *verbose {
log.SetFlags(log.Ltime | log.Lshortfile)
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}

absPath, err := filepath.Abs(*dir)
if err != nil {
log.Printf("Warning: Could not resolve absolute path for %s: %v", *dir, err)
absPath = *dir
}

log.Printf("Processing directory: %s", absPath)
log.Printf("Looking for file types: %s", *fileTypes)

opts := processor.DefaultOptions()
opts.Directory = *dir
opts.Clean = *clean

proc, err := processor.New(opts)
if err != nil {
log.Fatalf("Failed to initialise processor: %v", err)
}

if err := proc.Process(); err != nil {
log.Fatalf("Failed to process directory: %v", err)
os.Exit(1)
}

log.Println("Processing completed successfully")
}
11 changes: 10 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,13 @@ module github.com/krzko/codemap

go 1.23.2

require github.com/gobwas/glob v0.2.3
require (
github.com/gobwas/glob v0.2.3
github.com/urfave/cli/v2 v2.27.5
)

require (
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
)
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
55 changes: 55 additions & 0 deletions internal/cli/apply.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cli

import (
"fmt"
"log"

"github.com/urfave/cli/v2"
)

func ApplyCommand() *cli.Command {
return &cli.Command{
Name: "apply",
Usage: "Add annotations to files",
Flags: append(commonFlags,
&cli.BoolFlag{
Name: "dry-run",
Aliases: []string{"n"},
Usage: "Show what would be done without making changes",
},
&cli.BoolFlag{
Name: "recursive",
Aliases: []string{"r"},
Usage: "Process directories recursively",
Value: true,
},
),
Action: runApply,
}
}

func runApply(c *cli.Context) error {
proc, err := createProcessor(c)
if err != nil {
return fmt.Errorf("failed to initialize processor: %w", err)
}

files, err := proc.ListFiles()
if err != nil {
return fmt.Errorf("failed to list files: %w", err)
}

if c.Bool("dry-run") {
log.Printf("Would process %d files in %s", len(files), c.String("dir"))
for _, file := range files {
log.Printf("Would annotate: %s", file)
}
return nil
}

if err := proc.Process(); err != nil {
return fmt.Errorf("failed to process files: %w", err)
}

return nil
}
49 changes: 49 additions & 0 deletions internal/cli/clean.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package cli

import (
"fmt"
"log"

"github.com/urfave/cli/v2"
)

func CleanCommand() *cli.Command {
return &cli.Command{
Name: "clean",
Usage: "Remove annotations from files",
Flags: append(commonFlags,
&cli.BoolFlag{
Name: "dry-run",
Aliases: []string{"n"},
Usage: "Show what would be done without making changes",
},
),
Action: runClean,
}
}

func runClean(c *cli.Context) error {
proc, err := createProcessor(c)
if err != nil {
return fmt.Errorf("failed to initialize processor: %w", err)
}

files, err := proc.ListFiles()
if err != nil {
return fmt.Errorf("failed to list files: %w", err)
}

if c.Bool("dry-run") {
log.Printf("Would clean %d files in %s", len(files), c.String("dir"))
for _, file := range files {
log.Printf("Would clean: %s", file)
}
return nil
}

if err := proc.Clean(); err != nil {
return fmt.Errorf("failed to clean files: %w", err)
}

return nil
}
34 changes: 34 additions & 0 deletions internal/cli/commands.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cli

import (
"github.com/urfave/cli/v2"
)

func Commands() []*cli.Command {
return []*cli.Command{
ApplyCommand(),
CleanCommand(),
ListCommand(),
StatsCommand(),
}
}

var commonFlags = []cli.Flag{
&cli.StringFlag{
Name: "dir",
Aliases: []string{"d"},
Usage: "Directory to process",
Value: ".",
},
&cli.StringFlag{
Name: "types",
Aliases: []string{"t"},
Usage: "Comma-separated list of file types to process",
Value: "go,py,js,jsx,ts,tsx",
},
&cli.BoolFlag{
Name: "verbose",
Aliases: []string{"V"},
Usage: "Enable verbose logging",
},
}
Loading

0 comments on commit 0f31dc7

Please sign in to comment.