{"id":17011681,"url":"https://github.com/ruin0x11/kotaro","last_synced_at":"2025-03-22T13:23:13.924Z","repository":{"id":77938883,"uuid":"194807796","full_name":"Ruin0x11/kotaro","owner":"Ruin0x11","description":"A Lua library for rewriting Lua source code.","archived":false,"fork":false,"pushed_at":"2019-12-12T06:10:12.000Z","size":244,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-27T12:49:24.784Z","etag":null,"topics":["ast","formatter","lua","static-analysis"],"latest_commit_sha":null,"homepage":"","language":"Lua","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/Ruin0x11.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}},"created_at":"2019-07-02T07:05:14.000Z","updated_at":"2022-12-04T14:45:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"eece160a-35f7-4958-999a-3b95e577d638","html_url":"https://github.com/Ruin0x11/kotaro","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/Ruin0x11%2Fkotaro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ruin0x11%2Fkotaro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ruin0x11%2Fkotaro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ruin0x11%2Fkotaro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ruin0x11","download_url":"https://codeload.github.com/Ruin0x11/kotaro/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244960629,"owners_count":20538840,"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":["ast","formatter","lua","static-analysis"],"created_at":"2024-10-14T06:07:43.497Z","updated_at":"2025-03-22T13:23:13.911Z","avatar_url":"https://github.com/Ruin0x11.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kotaro\n`kotaro` is a Lua library for rewriting Lua source code. Its primary intended use is for applying repetitive source code rewrites which are difficult to accomplish with editor macros, like adding new fields to a list of tables based on the value of one of each table's fields, or moving a table value to a different table in the same parent.\n\nFor example, if you have this code:\n\n```lua\nreturn {\n   {\n      name = \"lucia\"\n   },\n   {\n      name = \"shizuru\"\n   },\n   {\n      name = \"akane\"\n   },\n}\n```\n\nAnd want to add these table fields to a new field named `quote` on each table based on the value of `name`:\n\n```lua\nlocal quotes = {\n   lucia = \"「死ね死ね変態変態、不潔不潔不潔！」\",\n   shizuru = \"「むぅ」\",\n   akane = \"「ツチノコは手品」\",\n}\n```\n\nThen you can use this code.\n\n```lua\nlocal Codegen = require(\"kotaro.parser.codegen\")\n\nlocal quotes = {\n   lucia = \"「死ね死ね変態変態、不潔不潔不潔！」\",\n   shizuru = \"「むぅ」\",\n   akane = \"「ツチノコは手品」\",\n}\n\nlocal add_table_fields = {}\n\nfunction add_table_fields:new(source_field, target_field, items)\n   return setmetatable({source_field = source_field, target_field = target_field, items = items}, {__index = add_table_fields})\nend\nfunction add_table_fields:applies_to(node)\n   if node:type() ~= \"constructor_expression\" then\n      return false\n   end\n\n   -- index into the AST node as if it were a table.\n   -- equivalent to `tbl[self.source_field]`\n   local target = node:index(self.source_field)\n   if not target or target:type() ~= \"expression\" then\n      return false\n   end\n\n   -- convert the expression AST to an actual Lua value.\n   local value = target:evaluate()\n\n   return self.items[value] ~= nil\nend\nfunction add_table_fields:execute(node)\n   local id = node:index(self.source_field):evaluate()\n   local value = self.items[id]\n\n   -- create a new AST node from scratch representing an expression\n   -- resolving to the actual Lua value `value`.\n   local expr = Codegen.gen_expression(value)\n\n   -- equivalent to `tbl[self.target_field] = value`\n   node:modify_index(self.target_field, value)\n\n   -- mark the contents of this node as changed, which will re-run\n   -- important AST analysis passes like parenting and line numbering.\n   node:changed()\nend\n\nlocal rewrite = {\n    -- these parameters are passed on the command line or from a\n    -- compatible editor.\n    params = {\n        source_field = \"string\",\n        target_field = \"string\",\n    }\n}\n\nfunction rewrite:execute(ast, params, opts)\n   return ast:rewrite(add_table_fields:new(params.source_field, params.target_field, quotes))\nend\n\nreturn rewrite\n```\n\nThe above is a \"rewrite file\" for use in `kotaro`'s batch mode. You can run this rewrite from the command line like this:\n\n```bash\nkotaro rewrite example/add_table_fields.lua example/source.lua -p source_field=name -p target_field=quote\n```\n\nThe resulting code will be printed to standard output.\n\n```lua\nreturn {\n   {\n      name = \"lucia\",\n      quote = \"「死ね死ね変態変態、不潔不潔不潔！」\"\n   },\n   {\n      name = \"shizuru\",\n      quote = \"「むぅ」\"\n   },\n   {\n      name = \"akane\",\n      quote = \"「ツチノコは手品」\"\n   },\n}\n```\n\nYou can also use `kotaro` from an editor by passing `-fedit_list`.\n\n```bash\nkotaro rewrite example/add_table_fields.lua example/source.lua -p source_field=name -p target_field=quote -fedit_list\nexample/source.lua:35:0:,\\n      quote = \"「死ね死ね変態変態、不潔不潔不潔！」\"\nexample/source.lua:69:0:,\\n      quote = \"「むぅ」\"\nexample/source.lua:100:0:\",\\n      quote = \"「ツチノコは手品」\n```\n\nThis will print out a list of edits with format `file:offset:length` to transform the old source into the new source, for each file edited. An example Emacs integration is included which allows the user to interactively confirm the edits in each file.\n\n## Design\n`kotaro` parses Lua source into a custom AST format which will preserve whitespace and the exact contents of all keywords/symbols, similar to `lib2to3`'s parse tree. General inspiration came from the [yapf](https://github.com/google/yapf) Python formatter, which uses `lib2to3` itself. AST manipulation is performed by calling methods on each AST node's metatable and using `kotaro.parser.codegen` to create new AST nodes, which will create the necessary symbols needed for the resulting node to be syntactically valid.\n\n## Note\nThe code is completely alpha-quality. It works well enough for my needs, but it will break if the AST gets into an inconsistent state. Also, the generated code needs to be reformatted manually.\n\n## Wishlist\n- A source code formatter similar in design to `yapf`.\n- File-local scope analysis, to do things like \"extract function from block\" or \"introduce new scope\".\n- Scope analysis across multiple files, to determine targets for a \"rename function\" rewrite.\n- More useful rewrites, like \"move file and update `require` statements\" or \"extract block/expression to function\".\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruin0x11%2Fkotaro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruin0x11%2Fkotaro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruin0x11%2Fkotaro/lists"}