{"id":22371430,"url":"https://github.com/eagleoutice/texchr","last_synced_at":"2026-07-27T11:31:11.475Z","repository":{"id":211166153,"uuid":"728386064","full_name":"EagleoutIce/TeXCHR","owner":"EagleoutIce","description":"A fun implementation of FreeCHR in plain TeX","archived":false,"fork":false,"pushed_at":"2023-12-10T10:13:45.000Z","size":88,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-21T03:56:59.503Z","etag":null,"topics":["chr","constraint-handling-rules","latex","plain-tex","tex"],"latest_commit_sha":null,"homepage":"","language":"TeX","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc-by-sa-4.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EagleoutIce.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"zenodo":null}},"created_at":"2023-12-06T20:41:45.000Z","updated_at":"2026-01-24T10:14:58.000Z","dependencies_parsed_at":"2023-12-10T10:38:23.465Z","dependency_job_id":null,"html_url":"https://github.com/EagleoutIce/TeXCHR","commit_stats":null,"previous_names":["eagleoutice/texchr"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/EagleoutIce/TeXCHR","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EagleoutIce%2FTeXCHR","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EagleoutIce%2FTeXCHR/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EagleoutIce%2FTeXCHR/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EagleoutIce%2FTeXCHR/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EagleoutIce","download_url":"https://codeload.github.com/EagleoutIce/TeXCHR/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EagleoutIce%2FTeXCHR/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35950362,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-27T02:00:06.776Z","response_time":101,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["chr","constraint-handling-rules","latex","plain-tex","tex"],"created_at":"2024-12-04T20:19:59.694Z","updated_at":"2026-07-27T11:31:11.447Z","avatar_url":"https://github.com/EagleoutIce.png","language":"TeX","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TeXCHR\n\n![plain TeX](https://img.shields.io/badge/made_with-plain_TeX-purple) [![CC BY-SA 4.0][cc-by-sa-shield]][cc-by-sa] [![latest tag](https://badgen.net/github/tag/EagleoutIce/TeXCHR?label=latest\u0026color=blue)](https://github.com/EagleoutIce/TeXCHR/releases/latest)\n\n\nWelcome to TeXCHR (spoken as \"tech-cher\")! To run the example you just need plain, good-old TeX. Run:\n\n```shell\ntex example.tex\n```\n\n## Origins\n\nThis is based on the [Python FreeCHR implementation](https://gist.github.com/SRechenberger/739683a23f8a9978ae601c6c815d61c4) by Sascha Rechenberger.\n\nI've written this more as a joke than a real piece of good TeX software, you could do a lot better and several macros are now over-generalized (most do not need arguments, as we could just lock a name like `\\constraints` for each program).\nThe main file is [`chr.tex`](chr.tex), which includes everything desired to get chr for your (_plain_) TeX project.\n\nFeel free to improve it or to criticize it, I'm open to suggestions.\n\n## How Does It Work?\n\nAllows to use FreeCHR in plain TeX. Every program must be wrapped in `\\chr{name}{program}` (results can be printed directly or stored using `\\gdef`/`\\xdef`).\n\nBasic `\\Rule{name}{kept-heads,...}{removed-heads,...}{guard}{body}`, `\\Compose{rules,...}`, and `\\Run{constraints,...}` with FreeCHR semantics.[^1]\n\nWithin the heads, you can use `\\c` to access the current constraint! For example, if your constraints are just numbers,  you can use `{\\ifnum\\c\u003e2}` to only allow numbers that are greater than `2` (in general, your heads have to each expand to or behave equivalently to either `\\iftrue` or `\\iffalse`).\nWithin the guard you can access all matched constraints using `\\c` as a list (i.e., access them with `\\c{0}`, `\\c{1}`, ...) based on the order of your heads (additionally, you can name them using `\\def\\n{\\c0}`, ...).\nSimilarly, in your body, you can access all matched constraints as `\\c{i}` with i being their 0-based index.\nAll heads, the guard, and the body can have side effects, given that they still expand to a conditional/update the constraint list `chr@constraint`  in the case of the `body` (for this, you can use `\\body` and `\\ebody`, see below).\n\nAdditionally, there are helper functions like\n\n* `\\true` and `\\false` for constant true and false guards or heads\n* `\\log{text...}` to output information during the execution. You have to call `\\enablelog` so that logging works.\n* `\\body{constraints,...}` and `\\ebody{constraints,...}` (expands with `\\edef`) can be used in the `body` argument of `\\Rule` (and `\\rule`) to add new constraints more easily (to the main list `chr@constraints`). They are best used at the tail of the body.\n* `\\LimitCycles{number}` can be used to halt the execution after a maximum of `number` cycles (e.g. if your Rules have no guaranteed fixpoint).\n* `\\makelist{list-name}{elements,...}` to construct lists (using them as `\\name{index}` to access elements, setter and modifications functions are currently not exposed and live under the `\\chr@...` namespace), see the [`list.tex`](https://github.com/EagleoutIce/TeXCHR/blob/main/list.tex).\n* `\\listequal{list-name1}{list-name2}` to compare lists element-wise, expands to `\\iftrue`/`\\iffalse` respectively\n* `\\permute{list-name}{length}` which creates all permutations of the given length from the list (using a modified version of [heap's algorithm](https://en.wikipedia.org/wiki/Heap%27s_algorithm)) - currently it does not do fingerprinting (to avoid a problem with otherwise equal constraints) and therefore can produce the same combinations multiple times if `|list-name| \u003c length`. For each combination, this expands the `\\chr@@output` macro, which has access to the `list-name` with the current permutation and a shortened `\\chr@list@coll` list-presentation (which can be used to copy the list with `\\makelist{list-name}{\\chr@list@coll}`.\n* `\\makeatletter` and `\\makeatother` help you to access all internal macros (which use the `\\chr@` namespace).\n* Corresponding to `\\Rule`, `\\Compose`, and `\\Run`, there are lowercase variants `\\rule`, `\\compose`, and `\\run` which take the names of lists (created with `\\makelist` instead of the lists directly.\n\n### Fibonacci Example\n\nYou want fibonacci? You can have fibonacci!\n\n```tex\n\\chr{fib test}{%\n   \\LimitCycles{25}\n   \\Compose{\n      \\Rule{main}%\n      {} % empty kept head\n      {{\\true}} % removed head\n      {\\true}\n      {% poor man's tuple\n         \\tuple{\\c{0}}%\n         \\add{\\fst}{\\snd}%\n         % ebody expands its argument to replace\n         \\ebody{\\snd:\\res}%\n      }\n   }\n   \\Run{{0:1}}\n}\n```\n\nTo work with tuples you need some helpers:\n\n```tex\n\\def\\tuplehelper#1:#2\\@nil{\\def\\fst{#1}\\def\\snd{#2}}\n\\def\\tuple#1{\\edef\\@tmp{#1}\\expandafter\\tuplehelper\\@tmp\\@nil}\n\\def\\add#1#2{\\chr@tempcount=#1\\relax\\advance\\chr@tempcount by #2\\relax\\edef\\res{\\the\\chr@tempcount}}\n```\n\nSee the [`example.tex`](example.tex) for a full example or the [`playground.tex`](playground.tex) for more.\n\nPlease note, that integer arithmetic is limited by TeX.\n\n[^1]: For the time being, `compose` is limited to once-per-program (I was too lazy to implement proper nesting).\n\n[cc-by-sa]: http://creativecommons.org/licenses/by-sa/4.0/\n[cc-by-sa-shield]: https://img.shields.io/badge/License-CC%20BY--SA%204.0-lightgrey.svg","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feagleoutice%2Ftexchr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feagleoutice%2Ftexchr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feagleoutice%2Ftexchr/lists"}