{"id":13681511,"url":"https://github.com/sdiehl/cabal-edit","last_synced_at":"2025-08-22T10:37:23.578Z","repository":{"id":137838819,"uuid":"278071019","full_name":"sdiehl/cabal-edit","owner":"sdiehl","description":"A utility for managing Hackage dependencies and manipulating Cabal files from the command line.","archived":false,"fork":false,"pushed_at":"2023-06-03T09:42:42.000Z","size":82,"stargazers_count":74,"open_issues_count":4,"forks_count":3,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-11-12T00:36:45.258Z","etag":null,"topics":["cabal","cabal-install","cli"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sdiehl.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}},"created_at":"2020-07-08T11:28:26.000Z","updated_at":"2024-02-19T18:41:50.000Z","dependencies_parsed_at":"2024-08-02T13:30:38.122Z","dependency_job_id":null,"html_url":"https://github.com/sdiehl/cabal-edit","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sdiehl%2Fcabal-edit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sdiehl%2Fcabal-edit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sdiehl%2Fcabal-edit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sdiehl%2Fcabal-edit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sdiehl","download_url":"https://codeload.github.com/sdiehl/cabal-edit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225669410,"owners_count":17505387,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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","cabal-install","cli"],"created_at":"2024-08-02T13:01:31.721Z","updated_at":"2024-11-21T04:16:57.485Z","avatar_url":"https://github.com/sdiehl.png","language":"Haskell","funding_links":[],"categories":["Haskell","Cabal Assistants"],"sub_categories":["Talks"],"readme":"cabal-edit\n==========\n\n![Cabal CI](https://github.com/sdiehl/cabal-edit/workflows/Cabal%20CI/badge.svg)\n![Stack CI](https://github.com/sdiehl/cabal-edit/workflows/Stack%20CI/badge.svg)\n\nThis is an extension to Haskell's package manager Cabal to allow you to add,\nremove, and upgrade dependencies by modifying your cabal file from the\ncommand line. This behaves similar to  `install --save` commands in other\npackage managers.\n\n\n* [`cabal-edit add`](#add)\n* [`cabal-edit upgrade`](#upgrade)\n* [`cabal-edit upgradeall`](#upgradeall)\n* [`cabal-edit remove`](#remove)\n* [`cabal-edit list`](#list)\n* [`cabal-edit format`](#format)\n* [`cabal-edit extensions`](#extensions)\n* [`cabal-edit lint`](#lint)\n* [`cabal-edit latest`](#latest)\n* [`cabal-edit rebuild`](#rebuild)\n\nUsage\n-----\n\n### add\n\nFor example to setup a new project one often wants to add common dependencies\nlike `text` and `aeson`. We can use `cabal-edit` to automatically append these\nto our dependency list and deduce the latest versions from Hackage.\n\n```bash\n$ cabal init --lib --cabal-version=3.0    \n\n$ cabal-edit add aeson                \nAdding dependency: aeson ^\u003e=1.5 to sample.cabal\n\n$ cabal-edit add text \nAdding dependency: text ^\u003e=1.2 to sample.cabal\n```\n\nIf we want to depend on a specific version of `aeson`, we can pass this\nexplicitly as an argument.\n\n```bash\n$ cabal-edit add aeson==1.4.0.0\n```\n\nMultiple packages can be passed to the add command at once. For example:\n\n```bash\n$ cabal-edit add base bytestring aeson text process filepath directory mtl transformers protolude\nAdding latest dependency: base ^\u003e=4.14 to sample.cabal\nAdding latest dependency: bytestring ^\u003e=0.10 to sample.cabal\nAdding latest dependency: aeson ^\u003e=1.5 to sample.cabal\nAdding latest dependency: text ^\u003e=1.2 to sample.cabal\nAdding latest dependency: process ^\u003e=1.6 to sample.cabal\nAdding latest dependency: filepath ^\u003e=1.4 to sample.cabal\nAdding latest dependency: directory ^\u003e=1.3 to sample.cabal\nAdding latest dependency: mtl ^\u003e=2.2 to sample.cabal\nAdding latest dependency: transformers ^\u003e=0.5 to sample.cabal\nAdding latest dependency: protolude ^\u003e=0.3 to sample.cabal\n```\n\n*Note: Dependency modification will happen over the library stanza of your Cabal\nfile, and not the executable sections.*\n\n### upgrade\n\nThe upgrade command can be used to safely manipulate the version bounds for a\ngiven library. For instance if one has a simple dependency on `text` for `1.0`\nversion range, like as follows:\n\n\n```haskell\nlibrary\n    exposed-modules:  MyLib\n    default-language: Haskell2010\n    build-depends:\n        base \u003e= 4.14 \u0026\u0026 \u003c=5.0,\n        text ^\u003e= 1.0\n```\n\nWe can bump the bound of this library to upgrade it to allow the latest version\nfrom Hackage. We simply pass the `upgrade` command the name of the package (i.e.\n`text`) and it will automatically figure out the appropriate version range for\nthe upgrade including previously version ranges. The resulting version ranges\nwill always have an upper bound and will conform to Hackage PVP standards.\n\n```bash\n$ cabal-edit upgrade text\nUpgrading bounds for text to 1.3\n```\n\nThis will produce the following modified Cabal file.\n\n```haskell\nlibrary\n    exposed-modules:  MyLib\n    default-language: Haskell2010\n    build-depends:\n        base \u003e=4.14 \u0026\u0026 \u003c=5.0,\n        text \u003e=1.0 \u0026\u0026 \u003c=1.3\n```\n\n### upgradeall\n\n`upgradeall` behaves like `upgrade` but performs the version bound bump for all\navailable dependencies. This sets the upper bounds for all dependencies to the\nlatest available version on Hackage.\n\n```bash\n$ cabal-edit upgradeall\nUpgrading bounds for Cabal to 3.3\nUpgrading bounds for aeson to 1.6\nUpgrading bounds for base to 4.15\nUpgrading bounds for bytestring to 0.11\nUpgrading bounds for ghc to 8.11\nUpgrading bounds for text to 1.3\n```\n\n### remove\n\nRemove will remove a given dependency from the file completely.\n\n```\n$ cabal-edit remove microlens\nRemoving depndency on microlens\n```\n\n### list\n\nThe Hackage database can be queried from the command line to search for all\navailable versions to use with the `list` command.\n\n```bash\n$ cabal-edit list filepath\n1.0\n1.1.0.0\n1.1.0.1\n1.1.0.2\n1.1.0.3\n1.1.0.4\n1.2.0.0\n1.2.0.1\n1.3.0.0\n1.3.0.1\n1.3.0.2\n1.4.0.0\n1.4.1.0\n1.4.1.1\n1.4.1.2\n1.4.2\n1.4.2.1\n```\n\n### format\n\nThe `format` command will canonicalise the Cabal into by parsing it and running\nit through the pretty printer again.\n\n```bash\n$ cabal-edit format\nFormatting: sample.cabal\n```\n\n### extensions\n\nThe `extensions` command will enumerate all the default extensions enabled for\nthe given library. This is useful if you wish to add these headers to files\nwithin the project.\n\n```bash\n$ cabal-edit extensions\n\n{-# LANGUAGE LambdaCase #-}\n{-# LANGUAGE BlockArguments #-}\n{-# LANGUAGE RecordWildCards #-}\n{-# LANGUAGE NoImplicitPrelude #-}\n{-# LANGUAGE FlexibleContexts #-}\n{-# LANGUAGE FlexibleInstances #-}\n{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE RankNTypes #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n```\n\n### lint\n\nThe `lint` command will detect common problems with your version bounds and\nrecommend package upgrades when available.\n\n```bash\n$ cabal-edit lint \naeson : Consider upgrading major bound to latest version 1.6\ntext : Consider upgrading major bound to latest version 1.3\n```\n\n### latest\n\nThe `latest` command will return the dependency string for adding the latest\nversion of a given package.\n\n```bash\n$ cabal-edit latest aeson\naeson ^\u003e=1.5\n```\n\n### rebuild\n\ncabal-edit uses a cache of Hackage package versions internally. This is normally\nbuilt on first run and whenever the package database is older than 30 days. If\nyou wish to manually rebuild it after running `cabal update` then run:\n\n```\n$ cabal-edit rebuild\nDone.\n```\n\nInstallation\n------------\n\nDownload this repository.\n\n```bash\n$ git clone git@github.com:sdiehl/cabal-edit.git\n$ cd cabal-edit\n```\n\nThen install either with Stack, Cabal or Nix.\n\n```bash\n$ stack install \n$ cabal install --installdir=/home/$USER/.local/bin\n$ nix-build -A cabal-edit\n```\n\n*Note: This library links directly against Cabal, so you must be using the same\nversion of Cabal you intend to compile your package against. It is reccomened to\nuse Cabal \u003e 3.0 to support modern versioning schemes.*\n\nShell Completions\n------------------\n\nWe can tab complete on the Hackage package index we install the local\ncompletions for you shell. Run one of the following commands to generate the\nshell completer appropriate to your shell. Then add the output to one of\n`~/.zshrc`, `~/.bashrc` or `~/.config/fish/config.fish`.\n\n```bash\n$ cabal-edit --zsh-completion-script cabal-edit\n$ cabal-edit --bash-completion-script cabal-edit\n$ cabal-edit --fish-completion-script cabal-edit\n```\n\nThis will completion against the Hackage database prefixed by name.\n\n```\n$ cabal-edit add gh\nzsh: do you wish to see all 103 possibilities (15 lines)?\n$ cabal-edit add ghc-pa\nghc-parmake  ghc-parser   ghc-paths\n```\n\n**bash**\n\n```bash\n_cabal-edit()\n{\n    local CMDLINE\n    local IFS=$'\\n'\n    CMDLINE=(--bash-completion-index $COMP_CWORD)\n\n    for arg in ${COMP_WORDS[@]}; do\n        CMDLINE=(${CMDLINE[@]} --bash-completion-word $arg)\n    done\n\n    COMPREPLY=( $(cabal-edit \"${CMDLINE[@]}\") )\n}\n\ncomplete -o filenames -F _cabal-edit cabal-edit\n```\n\n**zsh**\n\n```bash\n#compdef cabal-edit\n\nlocal request\nlocal completions\nlocal word\nlocal index=$((CURRENT - 1))\n\nrequest=(--bash-completion-enriched --bash-completion-index $index)\nfor arg in ${words[@]}; do\n  request=(${request[@]} --bash-completion-word $arg)\ndone\n\nIFS=$'\\n' completions=($( cabal-edit \"${request[@]}\" ))\n\nfor word in $completions; do\n  local -a parts\n\n  # Split the line at a tab if there is one.\n  IFS=$'\\t' parts=($( echo $word ))\n\n  if [[ -n $parts[2] ]]; then\n     if [[ $word[1] == \"-\" ]]; then\n       local desc=(\"$parts[1] ($parts[2])\")\n       compadd -d desc -- $parts[1]\n     else\n       local desc=($(print -f  \"%-019s -- %s\" $parts[1] $parts[2]))\n       compadd -l -d desc -- $parts[1]\n     fi\n  else\n    compadd -f -- $word\n  fi\ndone\n```\n\n**fish**\n\n```bash\n function _cabal-edit\n    set -l cl (commandline --tokenize --current-process)\n    # Hack around fish issue #3934\n    set -l cn (commandline --tokenize --cut-at-cursor --current-process)\n    set -l cn (count $cn)\n    set -l tmpline --bash-completion-enriched --bash-completion-index $cn\n    for arg in $cl\n      set tmpline $tmpline --bash-completion-word $arg\n    end\n    for opt in (cabal-edit $tmpline)\n      if test -d $opt\n        echo -E \"$opt/\"\n      else\n        echo -E \"$opt\"\n      end\n    end\nend\n\ncomplete --no-files --command cabal-edit --arguments '(_cabal-edit)'\n```\n\nLimitations\n-----------\n\nSince this library works directly with the `PackageDescription` data structure\nit cannot handle Cabal files in their full generality. Instead we directly\nmanipulate the internal structure used to represent the Cabal file which is not\ncapable of representing all surface constructs. If your Cabal file currently\nuses:\n\n* Common stanzas\n* Conditional blocks\n* Preprocessor definitions\n\nThese constructs will be compiled into the `PackageDescription` and inlined if\nyou use `cabal-edit`. This makes `cabal-edit` useful for small beginning\nprojects and ones that don't use advanced Cabal features.\n\nLicense\n-------\n\nMIT License\nCopyright (c) 2020, Stephen Diehl\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsdiehl%2Fcabal-edit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsdiehl%2Fcabal-edit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsdiehl%2Fcabal-edit/lists"}