{"id":34627764,"url":"https://github.com/werf/wormatter","last_synced_at":"2026-01-13T20:32:35.412Z","repository":{"id":330299319,"uuid":"1122289985","full_name":"werf/wormatter","owner":"werf","description":"Comprehensive opinionated formatter for Go","archived":false,"fork":false,"pushed_at":"2026-01-13T15:17:24.000Z","size":65,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-13T18:06:07.981Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/werf.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-24T12:34:40.000Z","updated_at":"2026-01-13T15:17:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/werf/wormatter","commit_stats":null,"previous_names":["werf/wormatter"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/werf/wormatter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/werf%2Fwormatter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/werf%2Fwormatter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/werf%2Fwormatter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/werf%2Fwormatter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/werf","download_url":"https://codeload.github.com/werf/wormatter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/werf%2Fwormatter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28399849,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-24T16:11:11.393Z","updated_at":"2026-01-13T20:32:35.401Z","avatar_url":"https://github.com/werf.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Wormatter\n\nA DST-based Go source code formatter. Highly opinionated, but very comprehensive. Gofumpt and gci built-in.\n\n## Installation\n\nDownload the latest binary from [GitHub Releases](https://github.com/werf/wormatter/releases).\n\n## Usage\n\n```bash\nwormatter \u003cfile.go|directory\u003e\n```\n\nFormats Go files in place. Recursively processes directories.\n\n### Options\n\n- `-c, --check` — Check if files need formatting without modifying them. Exits with code 1 if any file needs formatting.\n- `-e, --exclude \u003cpattern\u003e` — Exclude files matching glob pattern (can be specified multiple times).\n\n### Examples\n\n```bash\n# Format a single file\nwormatter main.go\n\n# Format all Go files in a directory\nwormatter ./pkg/\n\n# Check if files are formatted (useful for CI)\nwormatter --check .\n\n# Exclude test files\nwormatter --exclude \"*_test.go\" .\n\n# Exclude multiple patterns\nwormatter --exclude \"*.pb.go\" --exclude \"vendor/*\" .\n```\n\n### Generated Files\n\nFiles starting with any of these comments are automatically skipped:\n- `// Code generated`\n- `// DO NOT EDIT`\n- `// GENERATED`\n- `// Autogenerated`\n- `// auto-generated`\n- `// Automatically generated`\n\n## Building\n\n```bash\ntask build\n```\n\n## Formatting Rules\n\n### File-Level Declaration Order\n\nDeclarations are reordered top to bottom:\n\n| Order | Declaration | Notes |\n|-------|-------------|-------|\n| 1 | Imports | Unchanged |\n| 2 | `init()` functions | Preserved in original order |\n| 3 | Constants | Merged into single `const()` block |\n| 4 | Variables | Merged into single `var()` block |\n| 5 | Types | Grouped by category, each followed by its constructors and methods |\n| 6 | Standalone functions | Sorted by exportability, then by architectural layer |\n| 7 | `main()` function | Always last |\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\n// Before\nfunc helper() {}\nvar name = \"app\"\ntype Config struct{}\nfunc main() {}\nconst version = \"1.0\"\nfunc init() { setup() }\nfunc NewConfig() *Config { return \u0026Config{} }\n\n// After\nconst version = \"1.0\"\n\nvar name = \"app\"\n\nfunc init() { setup() }\n\ntype Config struct{}\n\nfunc NewConfig() *Config { return \u0026Config{} }\n\nfunc helper() {}\n\nfunc main() {}\n```\n\n\u003c/details\u003e\n\n---\n\n### Constants and Variables\n\n**Block format:**\n- Single declaration → inline: `const X = 1`\n- Multiple declarations → parenthesized block: `const ( ... )`\n\n**Grouping** (separated by empty lines):\n\n| Priority | Group | Sub-grouping |\n|----------|-------|--------------|\n| 1 | Blank identifiers (`var _ Interface = ...`) | None |\n| 2 | Public (uppercase) | By custom type |\n| 3 | Private (lowercase) | By custom type |\n\n**Within each group:** sorted alphabetically, no empty lines.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\n// Before\nconst (\n    maxRetries = 3\n    StatusOK StatusCode = \"ok\"\n    AppName = \"myapp\"\n    StatusError StatusCode = \"error\"\n    defaultTimeout = 30\n    Version = \"1.0\"\n)\n\n// After\nconst (\n    AppName = \"myapp\"\n    Version = \"1.0\"\n\n    StatusError StatusCode = \"error\"\n    StatusOK    StatusCode = \"ok\"\n\n    defaultTimeout = 30\n    maxRetries     = 3\n)\n```\n\n\u003c/details\u003e\n\n---\n\n### Types\n\n**Category order:**\n\n| Order | Category | Example |\n|-------|----------|---------|\n| 1 | Simple types | `type MyString string`, function types |\n| 2 | Function interfaces | Interfaces with exactly 1 method |\n| 3 | Other interfaces | Interfaces with 0 or 2+ methods |\n| 4 | Structs | — |\n\nTypes within each category preserve their original order.\n\n**After each type definition:**\n1. Constructors (functions starting with `New`/`new` that return the type)\n2. Methods (functions with receiver of that type)\n\n**Constructor matching** for type `T`:\n- Name starts with `New` (exported) or `new` (unexported)\n- Returns `T`, `*T`, `(T, error)`, `(*T, error)`, etc.\n- Name suffix matches `T` case-insensitively, or starts with `T` + non-lowercase char\n\n| Function | Type `Foo` | Match? |\n|----------|------------|--------|\n| `NewFoo` | `Foo` | ✓ |\n| `newFoo` | `foo` | ✓ |\n| `NewFooWithOptions` | `Foo` | ✓ |\n| `NewFoobar` | `Foo` | ✗ (matches `Foobar`) |\n\n**Sorting:**\n- Constructors: alphabetically\n- Methods: exported first, then unexported; each group sorted by architectural layer\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\n// Before\ntype Server struct {\n    port int\n}\nfunc (s *Server) Start() {}\nfunc (s *Server) stop() {}\ntype Handler func(r Request)\nfunc NewServer(port int) *Server { return \u0026Server{port: port} }\nfunc NewServerWithTLS(port int, cert string) *Server { return \u0026Server{port: port} }\nfunc (s *Server) Listen() {}\ntype Reader interface {\n    Read(p []byte) (n int, err error)\n}\n\n// After\ntype Handler func(r Request)\n\ntype Reader interface {\n    Read(p []byte) (n int, err error)\n}\n\ntype Server struct {\n    port int\n}\n\nfunc NewServer(port int) *Server { return \u0026Server{port: port} }\n\nfunc NewServerWithTLS(port int, cert string) *Server { return \u0026Server{port: port} }\n\nfunc (s *Server) Listen() {}\n\nfunc (s *Server) Start() {}\n\nfunc (s *Server) stop() {}\n```\n\n\u003c/details\u003e\n\n---\n\n### Struct Fields\n\nFields are grouped (separated by empty lines):\n\n| Order | Group | Sorting |\n|-------|-------|---------|\n| 1 | Embedded | Alphabetically by type name |\n| 2 | Public | Alphabetically |\n| 3 | Private | Alphabetically |\n\n**Struct literals** with named fields are reordered to match the struct definition.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\n// Before\ntype Server struct {\n    port     int\n    Logger\n    Name     string\n    host     string\n    Timeout  int\n    io.Reader\n}\n\n// After\ntype Server struct {\n    io.Reader\n    Logger\n\n    Name    string\n    Timeout int\n\n    host string\n    port int\n}\n```\n\n```go\n// Struct literal — before\ncfg := \u0026Config{debug: true, Timeout: 30, Name: \"app\"}\n\n// Struct literal — after (matches struct field order)\ncfg := \u0026Config{Name: \"app\", Timeout: 30, debug: true}\n```\n\n\u003c/details\u003e\n\n---\n\n### Functions\n\n**Standalone functions sorting:**\n1. Exported first, then unexported\n2. Within each group: by architectural layer (high-level first)\n\n**Architectural layer** — determined by call depth to local functions:\n- Layer 0: calls no local functions (utilities)\n- Layer N: calls functions from layer N-1 or lower\n- Cyclic calls share the same layer\n\nHigher layers appear first (orchestrators → utilities).\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\n// Before\nfunc validate(s string) bool { return len(s) \u003e 0 }\nfunc process(s string) string { return transform(s) }\nfunc transform(s string) string { return strings.ToUpper(s) }\nfunc Run(input string) {\n    if validate(input) {\n        result := process(input)\n        fmt.Println(result)\n    }\n}\n\n// After — exported first, then by layer (high to low)\nfunc Run(input string) {          // Layer 2: calls validate, process\n    if validate(input) {\n        result := process(input)\n        fmt.Println(result)\n    }\n}\n\nfunc process(s string) string {   // Layer 1: calls transform\n    return transform(s)\n}\n\nfunc transform(s string) string { // Layer 0: no local calls\n    return strings.ToUpper(s)\n}\n\nfunc validate(s string) bool {    // Layer 0: no local calls\n    return len(s) \u003e 0\n}\n```\n\n\u003c/details\u003e\n\n**Body formatting:**\n- Empty body stays one line: `func foo() {}`\n- Non-empty body expands to multiple lines\n- Empty line before `return` (unless it's the first statement)\n- Empty line before line comments (unless first in block)\n- No empty lines between `case` clauses in `switch`/`select`\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\n// Before\nfunc process(x int) int {\n    result := x * 2\n    return result\n}\n\n// After — empty line before return\nfunc process(x int) int {\n    result := x * 2\n\n    return result\n}\n```\n\n```go\n// Before\nswitch x {\ncase 1:\n    return \"one\"\n\ncase 2:\n    return \"two\"\n}\n\n// After — no empty lines between cases\nswitch x {\ncase 1:\n    return \"one\"\ncase 2:\n    return \"two\"\n}\n```\n\n\u003c/details\u003e\n\n---\n\n### Spacing\n\n- Single blank line between major sections, type definitions, and functions\n- Double blank lines compacted to single\n- No blank lines within const/var groups (only between groups)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwerf%2Fwormatter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwerf%2Fwormatter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwerf%2Fwormatter/lists"}