{"id":13507619,"url":"https://github.com/henrik/progress_bar","last_synced_at":"2026-02-18T09:42:17.282Z","repository":{"id":48778666,"uuid":"42768940","full_name":"henrik/progress_bar","owner":"henrik","description":"Command-line progress bars and spinners for Elixir.","archived":false,"fork":false,"pushed_at":"2025-07-22T10:30:14.000Z","size":107,"stargazers_count":337,"open_issues_count":4,"forks_count":20,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-08T11:52:58.305Z","etag":null,"topics":["cli","progress-bar","progressbar","spinner","spinners","terminal"],"latest_commit_sha":null,"homepage":"","language":"Elixir","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/henrik.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","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":"2015-09-19T10:29:12.000Z","updated_at":"2025-10-02T22:48:36.000Z","dependencies_parsed_at":"2024-05-01T16:19:36.523Z","dependency_job_id":"4d558eeb-69fd-4e59-a431-b29793901dc2","html_url":"https://github.com/henrik/progress_bar","commit_stats":{"total_commits":161,"total_committers":9,"mean_commits":17.88888888888889,"dds":0.09316770186335399,"last_synced_commit":"123536f5af4c86f332a77e027fe7c489731eafea"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/henrik/progress_bar","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrik%2Fprogress_bar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrik%2Fprogress_bar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrik%2Fprogress_bar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrik%2Fprogress_bar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/henrik","download_url":"https://codeload.github.com/henrik/progress_bar/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrik%2Fprogress_bar/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29575115,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-18T08:38:15.585Z","status":"ssl_error","status_checked_at":"2026-02-18T08:38:14.917Z","response_time":162,"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":["cli","progress-bar","progressbar","spinner","spinners","terminal"],"created_at":"2024-08-01T02:00:37.088Z","updated_at":"2026-02-18T09:42:12.268Z","avatar_url":"https://github.com/henrik.png","language":"Elixir","readme":"**2025-07-22: Not actively maintained.** Want to take over maintenance? [Let me know.](https://henrik.nyh.se)\n\n---\n\n# ProgressBar for Elixir\n\n[![Build Status](https://travis-ci.org/henrik/progress_bar.svg?branch=master)](https://travis-ci.org/henrik/progress_bar)\n[![Module Version](https://img.shields.io/hexpm/v/progress_bar.svg)](https://hex.pm/packages/progress_bar)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/progress_bar/)\n[![Total Download](https://img.shields.io/hexpm/dt/progress_bar.svg)](https://hex.pm/packages/progress_bar)\n[![License](https://img.shields.io/hexpm/l/progress_bar.svg)](https://github.com/henrik/progress_bar/blob/master/LICENSE.md)\n[![Last Updated](https://img.shields.io/github/last-commit/henrik/progress_bar.svg)](https://github.com/henrik/progress_bar/commits/master)\n\nCommand-line progress bars and spinners.\n\n![Screenshot](https://s3.amazonaws.com/f.cl.ly/items/2N3n440S0d2S2n371j0G/progress_bar.gif)\n\n* [Usage](#usage)\n* [Examples](#examples)\n* [Installation](#installation)\n* [License](#license)\n\n\n## Usage\n\nYou can render:\n  * [progress bars](#progress-bars),\n  * [indeterminate bars](#indeterminate-progress-bars) that animate but don't\n    indicate the current progress,\n  * and [indeterminate spinners](#spinners).\n\nDo you have a use case not listed below? Please open an issue or pull request!\n\n\n### Progress bars\n\nSpecify the current value and the total value, and a bar will be rendered to STDOUT.\n\n``` elixir\nProgressBar.render(2, 3)\n```\n\nOutput:\n\n    |==================================                |  67%\n\nCall the function again and it will overwrite the previous bar with the new value:\n\n``` elixir\nProgressBar.render(2, 3)\nProgressBar.render(3, 3)\n```\n\nOutput:\n\n    |==================================================| 100%\n\nThis basically works by printing \"\\r[===…\" each time, without a newline. The text cursor will return to the beginning of the line and overwrite the previous value.\n\nWhen the bar becomes full, a newline is automatically printed, so any subsequent output gets its own line.\n\nIt's up to you to re-render the bar when something changes. Here's a trivial example of an animated progress bar:\n\n``` elixir\nEnum.each 1..100, fn (i) -\u003e\n  ProgressBar.render(i, 100)\n  :timer.sleep 25\nend\n```\n\n#### Width\n\nThe bar will automatically set its width to fit the terminal. If the terminal width can't be determined automatically, an 80 column width will be assumed.\n\nIf you really want to, you may specify an explicit terminal column width to fit inside:\n\n``` elixir\nProgressBar.render(97, 100, width: 30)\n```\n\nEven with a wide terminal, note that the bar proper maxes out at 100 characters wide (one per percentage point) and will not go wider.\n\n#### Customize format\n\nReplace the `bar`, `blank`, `left` or `right` values.\n\n``` elixir\nformat = [\n  bar: \"X\",   # default: \"=\"\n  blank: \".\", # default: \" \"\n  left: \"(\",  # default: \"|\"\n  right: \")\", # default: \"|\"\n]\n\nProgressBar.render(97, 100, format)\n```\n\nOutput:\n\n    …XXXXXXXXX...)  97%\n\n`bar` and `blank` don't have to be single characters. They can be any-length strings and will repeat and truncate as appropriate.\n\nYou can provide empty-string values to remove `left` and `right` entirely.\n\nYou can also provide `left` or `right` as chardata lists with [IO.ANSI values](http://elixir-lang.org/docs/v1.0/elixir/IO.ANSI.html):\n\n``` elixir\nformat = [\n  left: [IO.ANSI.magenta, \"PROGRESS:\", IO.ANSI.reset, \" |\"],\n]\n```\n\n#### Customize color\n\nSpecify [IO.ANSI values](http://elixir-lang.org/docs/v1.0/elixir/IO.ANSI.html) as `bar_color` or `blank_color`. Use lists for multiple values.\n\n``` elixir\nformat = [\n  bar_color: [IO.ANSI.white, IO.ANSI.green_background],\n  blank_color: IO.ANSI.red_background,\n]\n\nProgressBar.render(97, 100, format)\n```\n\n#### `percent: false`\n\nHides the percentage shown after the bar.\n\n``` elixir\nProgressBar.render(1, 1, percent: false)\n```\n\nOutput:\n\n    …============|\n\nInstead of:\n\n    …============| 100%\n\n#### `suffix: :count`\n\nThis option causes the values to be printed on the suffix of your progress bar.\n\n``` elixir\nProgressBar.render(9_751, 10_000, suffix: :count)\n```\n\nOutput:\n\n    …=========   |  97% (9751/10000)\n\n\n#### `suffix: :bytes`\n\nThis option causes the values to be treated as bytes of data, showing those amounts next to the bar.\n\n``` elixir\nProgressBar.render(2_034_237, 2_097_152, suffix: :bytes)\n```\n\nOutput:\n\n    …=========   |  97% (1.94/2.00 MB)\n\nThe unit (KB or MB) is determined automatically.\n\nThis is great with [progressive downloads](https://gist.github.com/henrik/108e5fc23b66131fc3aa).\n\n\n### Indeterminate progress bars\n\nIndeterminate progress bars will animate on their own for the duration of a function you pass to it.\n\n``` elixir\nProgressBar.render_indeterminate fn -\u003e\n  # Do something for an indeterminate amount of time…\n  :timer.sleep 2000\nend\n```\n\nIt will alternate between four forms by default:\n\n    |=---=---=---=---=---=---=---=---=---=---=---…\n    |-=---=---=---=---=---=---=---=---=---=---=--…\n    |--=---=---=---=---=---=---=---=---=---=---=-…\n    |---=---=---=---=---=---=---=---=---=---=---=…\n\nAnd then show as done:\n\n    |============================================…\n\nThe return value of the function is passed through, if you want it:\n\n``` elixir\ndata = ProgressBar.render_indeterminate fn -\u003e\n  ApiClient.painstakingly_retrieve_data\nend\n\nIO.puts \"Finally got the data: #{inspect data}\"\n```\n\n#### Customize format\n\nYou can customize the forms it alternates between, as well as the done state, and the `left` and `right` bookends.\n\n``` elixir\nProgressBar.render_indeterminate [\n  bars: [ \"Oo\", \"oO\" ],\n  done: \"X\",\n  left: \"\",\n  right: \"\",\n], fn -\u003e end\n```\n\nThe `bars` list can be any length. Each string in that list is a \"frame\" in the animation. The bar will alternate between these strings, and then start over.\n\nEach string in the list can be any length and will repeat to fit the bar.\n\n\n#### Customize color\n\nYou can customize the color of the bar, and of the completed state.\n\n``` elixir\nProgressBar.render_indeterminate [\n  bars_color: IO.ANSI.yellow,\n  done_color: IO.ANSI.green,\n], fn -\u003e end\n```\n\nYou can pass multiple `IO.ANSI` values, just as with a regular progress bar. The indeterminate bar intentionally doesn't alternate between colors, so as not to trigger epileptic seizures…\n\n#### Interval\n\nYou can customize the millisecond interval at which it alternates. The default is 500 milliseconds.\n\n``` elixir\nProgressBar.render_indeterminate([interval: 10], fn -\u003e end)\n```\n\n\n### Spinners\n\nA spinner is similar to an indeterminate progress bar. But instead of a bar, it shows a \"spinning\" animation next to some text.\n\n``` elixir\nProgressBar.render_spinner [text: \"Loading…\", done: \"Loaded.\"], fn -\u003e\n  # Do something for an indeterminate amount of time…\n  :timer.sleep 2000\nend\n```\n\nThis is the default animation and text:\n\n    / Loading…\n    - Loading…\n    \\ Loading…\n    | Loading…\n\nThen it shows as done:\n\n    Loaded.\n\nYou can customize some things:\n\n``` elixir\nformat = [\n  frames: [\"/\" , \"-\", \"\\\\\", \"|\"],  # Or an atom, see below\n  text: \"Loading…\",\n  done: \"Loaded.\",\n  spinner_color: IO.ANSI.magenta,\n  interval: 100,  # milliseconds between frames\n]\n\nProgressBar.render_spinner format, my_function\n```\n\nColors can be lists just like with other progress bars.\n\nIf you want the done state to also be some colored symbol, just use chardata lists:\n\n``` elixir\nformat = [\n  done: [IO.ANSI.green, \"✓\", IO.ANSI.reset, \" Loaded.\"],\n]\n```\n\nOr you can pass `done: :remove` to stop showing this line of text entirely when it completes.\n\nAs with indeterminate progress bars, the return value of the function is passed through if you want it:\n\n``` elixir\ndata = ProgressBar.render_spinner fn -\u003e\n  ApiClient.painstakingly_retrieve_data\nend\n\nIO.puts \"Finally got the data: #{inspect data}\"\n```\n\n#### Predefined spinners\n\nInstead of specifying the frames as a list, you can assign one of the predefined styles as an atom:\n\n``` elixir\nProgressBar.render_spinner([frames: :braille], fn -\u003e end)\n```\n\nName                 | Frames\n-------------------- | ---------------------------\n`:strokes` (default) | `/ - \\ \\|`\n`:braille`           | `⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏`\n`:bars`              | `▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▇ ▆ ▅ ▄ ▃`\n\n\n## Examples\n\nTo see these bad boys in action, clone this repo and run the example scripts:\n\n    # Run all examples.\n    mix run examples/all.exs\n\n    # See what's available.\n    ls examples\n\n    # Run a single example.\n    mix run examples/02-color.exs\n\nOr to see them in a real project, try [Sipper](https://github.com/henrik/sipper).\n\n\n## Installation\n\nAdd the dependency to your project's `mix.exs`:\n\n``` elixir\ndefp deps do\n  [\n    {:progress_bar, \"\u003e 0.0.0\"},\n  ]\nend\n```\n\nThen fetch it:\n\n    mix deps.get\n\n\n## See Also\n\n* [simple_bar](https://github.com/jeffreybaird/simple_bar)\n\n\n## License\n\nReleased under [the MIT License](./LICENSE.md).\n","funding_links":[],"categories":["Command Line Applications"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenrik%2Fprogress_bar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhenrik%2Fprogress_bar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenrik%2Fprogress_bar/lists"}