{"id":16014652,"url":"https://github.com/pmonks/spinner","last_synced_at":"2025-12-12T01:15:07.698Z","repository":{"id":17073442,"uuid":"19838374","full_name":"pmonks/spinner","owner":"pmonks","description":"Progress indicators for command line Clojure apps, including support for indeterminate and determinate tasks.","archived":false,"fork":false,"pushed_at":"2025-03-27T19:18:12.000Z","size":11591,"stargazers_count":38,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"dev","last_synced_at":"2025-04-02T21:11:12.511Z","etag":null,"topics":["ansi","clojure","clojure-library","command-line","progress-bars","spinner"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pmonks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","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":"2014-05-15T23:22:14.000Z","updated_at":"2025-03-27T19:18:15.000Z","dependencies_parsed_at":"2023-01-13T19:08:59.197Z","dependency_job_id":"6381c7a0-e516-45f2-82e1-2ca405b2ca13","html_url":"https://github.com/pmonks/spinner","commit_stats":{"total_commits":188,"total_committers":2,"mean_commits":94.0,"dds":"0.010638297872340385","last_synced_commit":"52e32bca6f9f46f9a35e33c491ee89058f0c1677"},"previous_names":["clj-commons/spinner"],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmonks%2Fspinner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmonks%2Fspinner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmonks%2Fspinner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmonks%2Fspinner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pmonks","download_url":"https://codeload.github.com/pmonks/spinner/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248125710,"owners_count":21051787,"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":["ansi","clojure","clojure-library","command-line","progress-bars","spinner"],"created_at":"2024-10-08T15:04:31.881Z","updated_at":"2025-12-12T01:15:07.692Z","avatar_url":"https://github.com/pmonks.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# spinner\n\n[![CI](https://github.com/pmonks/spinner/actions/workflows/ci.yml/badge.svg?branch=dev)](https://github.com/pmonks/spinner/actions?query=workflow%3ACI+branch%3Adev)\n[![Dependencies](https://github.com/pmonks/spinner/actions/workflows/dependencies.yml/badge.svg?branch=dev)](https://github.com/pmonks/spinner/actions?query=workflow%3Adependencies+branch%3Adev)\n\u003cbr/\u003e\n[![Latest Version](https://img.shields.io/clojars/v/com.github.pmonks/spinner)](https://clojars.org/com.github.pmonks/spinner/)\n[![Open Issues](https://img.shields.io/github/issues/pmonks/spinner.svg)](https://github.com/pmonks/spinner/issues)\n[![License](https://img.shields.io/github/license/pmonks/spinner.svg)](https://github.com/pmonks/spinner/blob/release/LICENSE)\n![Maintained](https://badges.ws/badge/?label=maintained\u0026value=yes,+at+author's+discretion)\n\nProgress indicators for command line Clojure apps, including support for indeterminate tasks (those where progress _cannot_ be measured) and determinate tasks (those where progress _can_ be measured).  The former are represented using \"spinners\", while the latter are represented using \"progress bars\".\n\n#### Why?\n\nTo give the user of a command line app a visual progress indicator during long running processes.\n\nHere it is in action (from the [demo script](https://github.com/pmonks/spinner/blob/dev/demo.clj)):\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Spinner example screenshot\" src=\"https://raw.githubusercontent.com/pmonks/spinner/dev/spinner-demo.gif\"/\u003e\n\u003c/p\u003e\n\nNote that using Unicode characters in progress indicators may be unreliable, depending on your OS, terminal, font, encoding, etc.\n\n## Installation\n\n`spinner` is available as a Maven artifact from [Clojars](https://clojars.org/com.github.pmonks/spinner).\n\n## Usage\n\n[API documentation is available here](https://pmonks.github.io/spinner/).  The [unit](https://github.com/pmonks/spinner/blob/release/test/progress/indeterminate_test.clj) [tests](https://github.com/pmonks/spinner/blob/release/test/progress/determinate_test.clj) provide comprehensive usage examples (alternative animation sets, formatting, etc.).\n\n### Trying it Out\n\n**Important Notes:**\n\n1. If you're using leiningen, your REPL **must** be run in a trampoline (`lein trampoline repl`) in order for the ANSI escape sequences emitted by `spinner` to function.\n\n2. If you're using the Clojure CLI tools, you **must** use the `clojure` binary, as the `clj` binary wraps the JVM in `rlwrap` which then incorrectly interprets some of the ANSI escape sequences emitted by `spinner`. Some other readline alternatives (notably [Rebel Readline](https://github.com/bhauman/rebel-readline)) have been reported to work correctly.\n\n#### Clojure CLI\n\n```shell\n$ clojure -Sdeps '{:deps {com.github.pmonks/spinner {:mvn/version \"RELEASE\"}}}'\n```\n\n#### Leiningen\n\n```shell\n$ lein trampoline try com.github.pmonks/spinner\n```\n\n#### deps-try\n\nDoesn't work properly, for the same reason the `clj` command line doesn't work properly (`rlwrap` intercepts the ANSI escape sequences emitted by this library and misinterprets them).\n\n### [Demo](https://github.com/pmonks/spinner/blob/dev/demo.clj)\n\n```clojure\n;; Indeterminate Task (aka \"spinner\")\n\n(require '[progress.indeterminate :as spinner])\n\n(print \"Something uncountably slow is happening... \")\n(spinner/animate! :opts {:frames (:clocks spinner/styles)}\n  (Thread/sleep 5000))\n(println)\n\n\n;; Determinate Task (aka \"progress bar\")\n\n(require '[progress.determinate :as progress-bar])\n\n(println \"And now something countably slow is happening...\")\n(let [a (atom 0)]\n  (progress-bar/animate! a :opts {:total 1000000\n                                  :redraw-rate 60  ; Use 60 fps for the demo\n                                  :style (:coloured-ascii-boxes progress-bar/styles)}  ; :emoji-boxes is also fun to try\n    (run! (fn [_] (Thread/sleep 0 10) (swap! a inc)) (range 1000000))))  ; Count up to a million, slowly\n(println)\n```\n\n## Contributor Information\n\n[Contributing Guidelines](https://github.com/pmonks/spinner/blob/release/.github/CONTRIBUTING.md)\n\n[Bug Tracker](https://github.com/pmonks/spinner/issues)\n\n[Code of Conduct](https://github.com/pmonks/spinner/blob/release/.github/CODE_OF_CONDUCT.md)\n\n### Developer Workflow\n\nThis project uses the [git-flow branching strategy](https://nvie.com/posts/a-successful-git-branching-model/), and the permanent branches are called `release` and `dev`.  Any changes to the `release` branch are considered a release and auto-deployed (JARs to Clojars, API docs to GitHub Pages, etc.).\n\nFor this reason, **all development must occur either in branch `dev`, or (preferably) in temporary branches off of `dev`.**  All PRs from forked repos must also be submitted against `dev`; the `release` branch is **only** updated from `dev` via PRs created by the core development team.  All other changes submitted to `release` will be rejected.\n\n### Build Tasks\n\n`spinner` uses [`tools.build`](https://clojure.org/guides/tools_build). You can get a list of available tasks by running:\n\n```\nclojure -A:deps -T:build help/doc\n```\n\nOf particular interest are:\n\n* `clojure -T:build test` - run the unit tests\n* `clojure -T:build lint` - run the linters (clj-kondo and eastwood)\n* `clojure -T:build ci` - run the full CI suite (check for outdated dependencies, run the unit tests, run the linters)\n* `clojure -T:build install` - build the JAR and install it locally (e.g. so you can test it with downstream code)\n\nPlease note that the `deploy` task is restricted to the core development team (and will not function if you run it yourself).\n\n### Why are there so many different groupIds on Clojars for this project?\n\nThe project was originally developed under my personal GitHub account.  In early 2018 it was transferred to the `clj-commons` GitHub organisation, but then, as that group refined their scope and mission, it was determined that it no longer belonged there, and the project were transferred back in late 2021.  During this time the build tooling for the project also changed from Leiningen to tools.build, which created further groupId churn (tools.build introduced special, useful semantics for `com.github.username` groupIds that don't exist with Leiningen or Clojars).\n\n### Why is it called \"spinner\", when it offers more than just spinners?\n\ntl;dr - historical reasons and naming is hard.\n\nThe library started life providing a single hardcoded animation sequence (the classic \"/-\\\\|\" sequence), and then organically grew from there.  Because the name \"spinner\" appears in various places where changing it would break things (the GitHub repo, Maven artifact ids, etc.), I decided to stick with the name even though it's no longer very accurate.\n\n## License\n\nCopyright © 2014 Peter Monks\n\nDistributed under the [Mozilla Public License, version 2.0](https://www.mozilla.org/en-US/MPL/2.0/).\n\nSPDX-License-Identifier: [`MPL-2.0`](https://spdx.org/licenses/MPL-2.0)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmonks%2Fspinner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpmonks%2Fspinner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmonks%2Fspinner/lists"}