{"id":29097418,"url":"https://github.com/lambdaisland/ansi","last_synced_at":"2025-06-28T13:42:29.331Z","repository":{"id":32685269,"uuid":"130094654","full_name":"lambdaisland/ansi","owner":"lambdaisland","description":"Parse ANSI color escape sequences to Hiccup syntax","archived":false,"fork":false,"pushed_at":"2022-04-27T14:14:00.000Z","size":48,"stargazers_count":33,"open_issues_count":0,"forks_count":4,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-06-16T11:29:52.304Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/lambdaisland.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}},"created_at":"2018-04-18T16:54:04.000Z","updated_at":"2025-05-01T13:38:45.000Z","dependencies_parsed_at":"2022-08-07T18:00:40.167Z","dependency_job_id":null,"html_url":"https://github.com/lambdaisland/ansi","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/lambdaisland/ansi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaisland%2Fansi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaisland%2Fansi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaisland%2Fansi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaisland%2Fansi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lambdaisland","download_url":"https://codeload.github.com/lambdaisland/ansi/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaisland%2Fansi/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261026945,"owners_count":23099264,"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":[],"created_at":"2025-06-28T13:42:17.925Z","updated_at":"2025-06-28T13:42:29.326Z","avatar_url":"https://github.com/lambdaisland.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lambdaisland/ansi\n\n\u003c!-- badges --\u003e\n[![CircleCI](https://circleci.com/gh/lambdaisland/ansi.svg?style=svg)](https://circleci.com/gh/lambdaisland/ansi) [![cljdoc badge](https://cljdoc.org/badge/lambdaisland/ansi)](https://cljdoc.org/d/lambdaisland/ansi) [![Clojars Project](https://img.shields.io/clojars/v/lambdaisland/ansi.svg)](https://clojars.org/lambdaisland/ansi) [![codecov](https://codecov.io/gh/lambdaisland/ansi/branch/master/graph/badge.svg)](https://codecov.io/gh/lambdaisland/ansi)\n\u003c!-- /badges --\u003e\n\nParse ANSI color codes, optionally convert to Hiccup.\n\n## Features\n\n- Clojure and ClojureScript support (cljc)\n- parses color codes and bold, including 8-bit and 24-bit (rgb) colors\n- Fine-grained building blocks, convert to Hiccup or a format of your choice\n\n## Usage\n\nColors in your terminal work by embedding \"escape codes\" in the text. This\nlibrary contains utilities for parsing and transforming these escape codes.\n\nTerminals are stateful, you can set a property like foreground, background, or\nbold, and it will stay that way until it gets changes or unset (reset).\n\nThe starting point for dealing with a textual stream is `token-stream`. It takes\na string as input, and returns a sequence of \"tokens\", either plain text, or a\nmap of properties that are being set at that point in the stream.\n\n``` clojure\n(require '[lambdaisland.ansi :as ansi])\n\n(ansi/token-stream \"Hello,\\033[1;30;45m world!\")\n;;=\u003e [\"Hello,\" {:bold true, :foreground [:rgb 0 0 0], :background [:rgb 205 0 205]} \" world!\"]\n```\n\nTo convert this to a different format, you need to know which styles apply to\nwhich piece of text, this is what the `apply-props` stateful transducer is for.\nIt keeps track of the \"terminal state\", and returns pairs of style information\nand text.\n\n``` clojure\n(def text \"\\033[1m here \\033[45m we \\033[31m go! \\033[0m done.\")\n\n(sequence ansi/apply-props (ansi/token-stream text))\n;;=\u003e\n([{:bold true} \" here \"]\n [{:bold true\n   :background [:rgb 205 0 205]} \" we \"]\n [{:bold true\n   :background [:rgb 205 0 205]\n   :foreground [:rgb 205 0 0]} \" go! \"]\n [{} \" done.\"])\n```\n\nNow you have all the information available to convert this into Hiccup, you can\nconvert a single one of these pairs with `chunk-\u003ehiccup`.\n\n``` clojure\n(ansi/chunk-\u003ehiccup [{:bold true, :foreground [:rgb 100 200 0]} \"so far...\"])\n;;=\u003e [:span {:style {:color \"rgb(100,200,0)\", :font-weight \"bold\"}} \"so far...\"]\n```\n\nThere's a convenience function to do this in one go, `text-\u003ehiccup`\n\n\n``` clojure\n(ansi/text-\u003ehiccup text)\n;;=\u003e\n([:span {:style {:font-weight \"bold\"}} \" here \"]\n [:span {:style {:background-color \"rgb(205,0,205)\", :font-weight \"bold\"}}\n  \" we \"]\n [:span {:style {:color \"rgb(205,0,0)\",\n                 :background-color \"rgb(205,0,205)\",\n                 :font-weight \"bold\"}}\n  \" go! \"]\n [:span {} \" done.\"])\n```\n\nIf you deal with streaming text, then you need to incrementally apply these\nstate changes, carrying over the old state whenever you receive more input.\n\nIn this case the `hiccup-xform` might be useful.\n\n``` clojure\n(require '[clojure.core.async :as async])\n\n(def channel (chan 1 ansi/hiccup-xform))\n\n(async/go-loop [hiccup-el (async/\u003c! channel)]\n  (append-to-dom hiccup-el))\n\n(async/go (async/\u003e! channel \"\\033[1mhello,\\033[35mworld!\"))\n(async/go (async/\u003e! channel \" life is \\033[0mgreat!\"))\n```\n\n\n## License\n\n\u0026copy; Arne Brasseur 2018\nAvailable under the terms of the Mozilla Public License Version 2.0, see LICENSE.txt\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flambdaisland%2Fansi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flambdaisland%2Fansi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flambdaisland%2Fansi/lists"}