{"id":16579982,"url":"https://github.com/tfausak/cabal-gild","last_synced_at":"2026-04-02T22:02:16.378Z","repository":{"id":138840628,"uuid":"585234477","full_name":"tfausak/cabal-gild","owner":"tfausak","description":":crown: Format Haskell package descriptions.","archived":false,"fork":false,"pushed_at":"2026-03-31T14:17:39.000Z","size":527,"stargazers_count":67,"open_issues_count":9,"forks_count":5,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-03-31T16:10:42.772Z","etag":null,"topics":["cabal","formatter","haskell"],"latest_commit_sha":null,"homepage":"https://hackage.haskell.org/package/cabal-gild","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"phadej/cabal-fmt","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tfausak.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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":"2023-01-04T16:51:16.000Z","updated_at":"2026-03-05T16:17:29.000Z","dependencies_parsed_at":"2024-05-17T13:54:14.167Z","dependency_job_id":"7f2b3ded-a718-436c-b5c6-d89db2f416fa","html_url":"https://github.com/tfausak/cabal-gild","commit_stats":null,"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"purl":"pkg:github/tfausak/cabal-gild","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfausak%2Fcabal-gild","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfausak%2Fcabal-gild/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfausak%2Fcabal-gild/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfausak%2Fcabal-gild/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tfausak","download_url":"https://codeload.github.com/tfausak/cabal-gild/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfausak%2Fcabal-gild/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31317831,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T21:35:00.834Z","status":"ssl_error","status_checked_at":"2026-04-02T21:34:59.806Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["cabal","formatter","haskell"],"created_at":"2024-10-11T22:19:46.357Z","updated_at":"2026-04-02T22:02:16.372Z","avatar_url":"https://github.com/tfausak.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gild\n\n[![CI](https://github.com/tfausak/cabal-gild/actions/workflows/ci.yml/badge.svg)](https://github.com/tfausak/cabal-gild/actions/workflows/ci.yml)\n[![Hackage](https://badgen.net/hackage/v/cabal-gild)](https://hackage.haskell.org/package/cabal-gild)\n\nGild is an opinionated command line utility that formats Haskell package\ndescriptions, which are also known as `*.cabal` files. Gild can also be used to\nautomatically discover `exposed-modules`; see [the pragmas section][] for more\nabout that.\n\n[the pragmas section]: #pragmas\n\nGild started as a fork of [phadej/cabal-fmt][], but is now totally separate.\nFor a brief summary of the differences between Gild and `cabal-fmt`, read [the\nannouncement post][].\n\n[phadej/cabal-fmt]: https://github.com/phadej/cabal-fmt\n[the announcement post]: https://taylor.fausak.me/2024/02/17/gild/\n\n## Summary\n\nGiven a package description like this:\n\n``` cabal\nCABAL-VERSION : 3.0\nname          : example\nversion       : 0.0.0.0\n\nlibrary\n  build-depends: mtl\u003e=2.3, base\n  ghc-options:-Wall\n  if impl(ghc\u003e=9.8)\n    ghc-options: -Wmissing-role-annotations\n```\n\nGild will produce output like this:\n\n``` cabal\ncabal-version: 3.0\nname: example\nversion: 0.0.0.0\n\nlibrary\n  build-depends:\n    base,\n    mtl \u003e=2.3,\n\n  ghc-options: -Wall\n\n  if impl(ghc \u003e= 9.8)\n    ghc-options: -Wmissing-role-annotations\n```\n\nSee [the installation section][] for how to get Gild and [the usage section][]\nfor how to use it.\n\n[the installation section]: #installation\n[the usage section]: #usage\n\n## Goals\n\n- There should be no configuration options. As long as the output format is\n  reasonable, the specifics should not matter too much. This means the amount\n  of indentation cannot be changed, for example.\n\n- The output should be diff friendly. This means things generally go on their\n  own line, trailing commas are used when possible, and elements are sorted\n  where it makes sense.\n\n- The output should be semantically the same as the input. This means no\n  normalization or canonicalization. For example, separate `build-depends`\n  fields are not merged together.\n\n- It should be possible to format other files that use the same format as\n  package descriptions. This means `cabal.project` files can be formatted as\n  well.\n\n- The focus should be mostly on formatting. There should be no effort made to\n  validate input or provide any checks or lints. However some quality of life\n  features, like automatic module discovery, are desireable.\n\n- Formatting should be as regular as possible. Special cases for particular\n  fields or sections should be avoided unless it improves quality of life. For\n  example, interpreting the `build-depends` field to pretty print it is okay.\n\n- The command line utility should be fast enough to run on every save. It\n  should not need network access.\n\n## Installation\n\nGo to [the latest release page][] and download the binary for your platform.\n\n[the latest release page]: https://github.com/tfausak/cabal-gild/releases/latest\n\nTo run Gild in a GitHub Actions workflow, consider using [cabal-gild-setup-action][].\n\n[cabal-gild-setup-action]: https://github.com/marketplace/actions/setup-gild\n\n### From Source\n\nIn general you should prefer downloading the appropriate binary for you\nplatform. However it is possible to build Gild from source. It supports Linux,\nmacOS, and Windows along with the three most recent versions of GHC. Any other\nconfigurations are unsupported.\n\nWith Cabal:\n\n``` sh\n$ cabal install cabal-gild\n```\n\nWith Stack:\n\n``` sh\n$ stack install cabal-gild\n```\n\n## Usage\n\nGild is a command line utility named `cabal-gild`. Pass one or more files as\narguments to format them in-place:\n\n``` sh\n$ cabal-gild p.cabal\n$ cabal-gild a.cabal b.cabal\n```\n\nWhen no files are given, Gild reads from standard input (STDIN) and writes to\nstandard output (STDOUT):\n\n``` sh\n$ cabal-gild \u003c p.cabal \u003e q.cabal\n```\n\nWhen run interactively with no arguments, Gild will look for a `*.cabal` file\nin the current directory and format it in-place.\n\n### Options\n\nRun `cabal-gild --help` to see the options that Gild supports. They are:\n\n- `--help`: Prints the help message to STDOUT then exits successfully.\n\n- `--version`: Prints the version number to STDOUT then exits successfully.\n\n- `--crlf=LENIENCY`: Sets the CRLF handling mode, which must be either\n  `lenient` (the default) or `strict`. When checking if the input is formatted,\n  setting this to `lenient` will treat CRLF line endings the same as LF.\n  Setting this to `strict` will require the input to be byte-for-byte identical\n  to the expected output. (Note that Gild will never produce CRLF line endings\n  when formatting.)\n\n- `--mode=MODE`: Sets the mode to `MODE`, which must be either `format` (the\n  default) or `check`. When the mode is `format`, Gild will output the\n  formatted package description. When the mode is `check`, Gild will exit\n  successfully if the input is already formatted, otherwise it will exit\n  unsuccessfully. When checking multiple files, all files are checked before\n  exiting.\n\n- `--stdin=FILE`: When reading input from STDIN, use `FILE` as the effective\n  input file. This is useful when a file's contents are already available, like\n  in an editor. For example:\n\n  ``` sh\n  $ cabal-gild --stdin p.cabal \u003c p.cabal\n  ```\n\n  It is an error to provide a value for this option when a file argument is\n  given.\n\n### Deprecated Options\n\nThe following options are deprecated and will be removed in a future version.\nUse positional file arguments instead.\n\n- `--input=FILE`: Uses `FILE` as the input. Use a positional argument instead.\n\n- `--output=FILE`: Uses `FILE` as the output. Use piping instead.\n\n- `--io=FILE`: Shortcut for setting both `--input` and `--output`. Use a\n  positional argument instead.\n\nIt is an error to combine these options with positional file arguments.\n\n### Pragmas\n\nGild supports special comments in package descriptions that act as pragmas.\nEach pragma starts with `-- cabal-gild:`. Pragmas must be the last comment\nbefore a field.\n\n#### `discover`\n\n```\n-- cabal-gild: discover [DIRECTORY ...] [--include=PATTERN ...] [--exclude=PATTERN ...]\n```\n\nThis pragma will discover files in any of the given directories. If no\ndirectories are given, defaults to `.` (the directory of the package\ndescription). For example, given this input:\n\n``` cabal\nlibrary\n  -- cabal-gild: discover\n  exposed-modules: ...\n```\n\nAssuming there is a single Haskell file at `Example.hs`, Gild will produce this\noutput:\n\n``` cabal\nlibrary\n  -- cabal-gild: discover\n  exposed-modules: Example\n```\n\nThis pragma works with the following fields:\n\n- `asm-sources`\n- `c-sources`\n- `cxx-sources`\n- `data-files`\n- `exposed-modules`\n- `extra-doc-files`\n- `extra-source-files`\n- `includes`\n- `install-includes`\n- `js-sources`\n- `license-files`\n- `other-modules`\n- `signatures`\n\nIt will be ignored on all other fields. For the `exposed-modules`,\n`other-modules`, and `signatures` fields, only files with the following\nextensions will be discovered:\n\n- `*.chs`\n- `*.cpphs`\n- `*.gc`\n- `*.hs`\n- `*.hsc`\n- `*.hsig`\n- `*.lhs`\n- `*.lhsig`\n- `*.ly`\n- `*.x`\n- `*.y`\n\nFor all other fields, files with any extension will be discovered.\n\nAny existing files, modules, or signatures in the field will be ignored. The\nentire field will be replaced. This means adding, removing, and renaming files\nshould be handled automatically.\n\nDirectories can be quoted if they contain spaces. For example:\n\n``` cabal\nlibrary\n  -- cabal-gild: discover \"my modules\"\n  exposed-modules: ...\n```\n\nBy default, all files in any of the given directories are considered for\ndiscovery. To explicitly include only certain files, use the\n`--include=PATTERN` option. For example:\n\n``` cabal\nlibrary\n  -- cabal-gild: discover --include=**/*Spec.hs\n  other-modules: ...\n```\n\nFiles can be excluded from discovery by using the `--exclude=PATTERN` option.\nFor example:\n\n``` cabal\nlibrary\n  -- cabal-gild: discover --exclude=**/*Spec.hs\n  exposed-modules: ...\n```\n\nIf a file would match both the `--include` pattern and the `--exclude` pattern,\nit will be excluded.\n\n#### `version`\n\n```\n-- cabal-gild: version\n```\n\nThis pragma will insert a comment below it indicating which version of Gild\nproduced the output. For example, given this input:\n\n``` cabal\n-- cabal-gild: version\nname: my-package\n```\n\nGild will produce this output:\n\n``` cabal\n-- cabal-gild: version\n-- Generated with cabal-gild version 1.8.0.0\nname: my-package\n```\n\nOn subsequent runs, the generated comment will be updated to reflect the\ncurrent version of Gild. The pragma itself is left unchanged. This pragma can\nbe used on any field or section.\n\n#### `fragment`\n\n```\n-- cabal-gild: fragment FILE\n```\n\nThis pragma will replace the contents of a field or section with the contents\nof the given file. The file path is resolved relative to the directory of the\npackage description. This is useful for sharing configuration between multiple\npackages. For example, given this input:\n\n``` cabal\n-- cabal-gild: fragment common.fragment\ncommon warnings\n```\n\nAnd a file called `common.fragment` with this content:\n\n``` cabal\ncommon warnings\n  ghc-options:\n    -Wall\n    -Wcompat\n```\n\nGild will produce this output:\n\n``` cabal\n-- cabal-gild: fragment common.fragment\ncommon warnings\n  ghc-options:\n    -Wall\n    -Wcompat\n```\n\nThis pragma works on both fields and sections. For fields, the fragment file\nmust contain a field with the same name. For sections, it must contain a\nsection with the same name and arguments. For example:\n\n``` cabal\nlibrary\n  -- cabal-gild: fragment build-deps.fragment\n  build-depends: ...\n```\n\nWith a `build-deps.fragment` file containing:\n\n``` cabal\nbuild-depends:\n  base,\n  containers,\n```\n\nOn subsequent runs, the field or section contents will be replaced again with\nthe contents of the fragment file, making the operation idempotent. The pragma\nitself is left unchanged.\n\nIf the fragment file cannot be read or parsed, or if the field or section name\ndoes not match, a warning is emitted and the field or section is left\nunchanged. Recursive fragment expansion is not supported.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftfausak%2Fcabal-gild","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftfausak%2Fcabal-gild","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftfausak%2Fcabal-gild/lists"}