[
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  pull_request: {}\n  push:\n    branches:\n      - main\n  schedule:\n    - cron: '44 6 * * 0'\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  msrv:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4\n    - uses: dtolnay/rust-toolchain@1.88\n    - run: cargo build --workspace --lib\n    - run: cargo build --workspace --lib --no-default-features --features alloc\n\n  test:\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        rust: [stable, nightly]\n    steps:\n    - uses: actions/checkout@v4\n    - uses: dtolnay/rust-toolchain@master\n      with:\n        toolchain: ${{matrix.rust}}\n    - run: cargo build --workspace --all-targets\n      if: matrix.rust == 'stable'\n    - run: cargo test --workspace --all-targets\n      if: matrix.rust == 'nightly'\n    - run: cargo test --workspace --doc\n      if: matrix.rust == 'nightly'\n\n  clippy:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4\n    - uses: dtolnay/rust-toolchain@stable\n      with:\n        components: clippy\n    - run: cargo clippy --workspace --all-features --all-targets -- -D warnings\n\n  rustfmt:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4\n    - uses: dtolnay/rust-toolchain@stable\n      with:\n        components: rustfmt\n    - run: cargo fmt --check --all\n\n  docs:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: dtolnay/rust-toolchain@nightly\n      - uses: Swatinem/rust-cache@v2\n      - run: cargo doc --lib --no-deps --document-private-items\n        env:\n          RUSTFLAGS: --cfg doc_cfg\n          RUSTDOCFLAGS: --cfg doc_cfg -D warnings\n"
  },
  {
    "path": ".gitignore",
    "content": "/target/\n**/*.rs.bk\nCargo.lock\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n[Unreleased]: https://github.com/udoprog/genco/compare/0.17.3...master\n\n## [0.17.4]\n\n### Changed\n* Update project documentation.\n\n[0.17.4]: https://github.com/udoprog/genco/compare/0.17.3...0.17.4\n\n## [0.17.3]\n\n### Changed\n* Fixed badge in project.\n\n[0.17.3]: https://github.com/udoprog/genco/compare/0.17.2...0.17.3\n\n## [0.17.2]\n\n### Added\n* Added `Copy` and `Clone` implementations for `FromFn` ([#31]).\n\n### Changed\n* Changed internal syntax of doc tests ([#32]).\n\n[#31]: https://github.com/udoprog/genco/issues/31\n[#32]: https://github.com/udoprog/genco/issues/32\n[0.17.2]: https://github.com/udoprog/genco/compare/0.17.1...0.17.2\n\n## [0.17.1]\n### Changed\n* Documentation fixes.\n\n[0.17.1]: https://github.com/udoprog/genco/compare/0.17.0...0.17.1\n## [0.17.0]\n\n### Added\n* Added `FormatInto` implementation for `Arguments<'_>` ([#26]).\n\n### Changed\n* All syntax has been changed from using `#` to `$` ([#27]).\n* `--cfg genco_nightly` has been deprecated in favor of using byte-span hacks to\n  detect whitespace between tokens on the same column.\n\n[#26]: https://github.com/udoprog/genco/issues/26\n[#27]: https://github.com/udoprog/genco/issues/27\n[0.17.0]: https://github.com/udoprog/genco/compare/0.16.0...0.17.0\n\n## [0.16.0]\n\n### Changed\n* Add basic support for using genco to tokenize on stable ([#20]).\n\n## [0.15.1]\n\n### Fixed\n* Fixed typos in documentation.\n* Fixed new Clippy lints.\n\n## [0.15.0]\n\n### Fixed\n* csharp: System must be imported ([#13]).\n\n### Changed\n* Parse match blocks better by ignoring end condition for nested groups ([#13]).\n* Match arms containing parenthesis are now whitespace sensitive ([#13]).\n* Language items are no longer trait objects ([#14]).\n* Use a singly-linked list to improve how quickly we can iterate over language items in token streams ([#16]).\n* Pass formatting configuration by reference instead of by value when constructing a formatter ([#17]).\n\n### Added\n* Patterns are now parsed correctly to support alternatives separated by pipes ([#12]).\n* Added `quote_fn!` macro and added `FormatInto` to the prelude ([#13]).\n\n[#17]: https://github.com/udoprog/genco/issues/17\n[#16]: https://github.com/udoprog/genco/issues/16\n[#14]: https://github.com/udoprog/genco/issues/14\n[#13]: https://github.com/udoprog/genco/issues/13\n[#12]: https://github.com/udoprog/genco/issues/12\n[#20]: https://github.com/udoprog/genco/issues/20\n\n[0.16.0]: https://github.com/udoprog/genco/compare/0.15.0...0.16.0\n[0.15.0]: https://github.com/udoprog/genco/compare/0.14.2...0.15.0\n[0.15.1]: https://github.com/udoprog/genco/compare/0.15.0...0.15.1\n[0.16.0]: https://github.com/udoprog/genco/compare/0.15.1...0.16.0\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nname = \"genco\"\nversion = \"0.19.0\"\nauthors = [\"John-John Tedro <udoprog@tedro.se>\"]\nedition = \"2018\"\nrust-version = \"1.88\"\ndescription = \"A whitespace-aware quasiquoter for beautiful code generation.\"\ndocumentation = \"https://docs.rs/genco\"\nreadme = \"README.md\"\nhomepage = \"https://github.com/udoprog/genco\"\nrepository = \"https://github.com/udoprog/genco\"\nlicense = \"MIT OR Apache-2.0\"\nkeywords = [\"code-generation\", \"template\"]\ncategories = [\"template-engine\"]\n\n[features]\ndefault = [\"std\", \"alloc\"]\nstd = []\nalloc = []\n\n[dependencies]\ngenco-macros = { path = \"./genco-macros\", version = \"0.19.0\" }\n\nrelative-path = \"1.2.0\"\nsmallvec = \"1.4.0\"\n\n[dev-dependencies]\nanyhow = \"1.0.31\"\nrand = \"0.7.3\"\n\n[workspace]\nmembers = [\"genco-macros\"]\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "Copyright (c) 2017 John-John Tedro\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# genco\n\n[<img alt=\"github\" src=\"https://img.shields.io/badge/github-udoprog/genco-8da0cb?style=for-the-badge&logo=github\" height=\"20\">](https://github.com/udoprog/genco)\n[<img alt=\"crates.io\" src=\"https://img.shields.io/crates/v/genco.svg?style=for-the-badge&color=fc8d62&logo=rust\" height=\"20\">](https://crates.io/crates/genco)\n[<img alt=\"docs.rs\" src=\"https://img.shields.io/badge/docs.rs-genco-66c2a5?style=for-the-badge&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K\" height=\"20\">](https://docs.rs/genco)\n[<img alt=\"build status\" src=\"https://img.shields.io/github/actions/workflow/status/udoprog/genco/ci.yml?branch=main&style=for-the-badge\" height=\"20\">](https://github.com/udoprog/genco/actions?query=branch%3Amain)\n\nA whitespace-aware quasiquoter for beautiful code generation.\n\nCentral to genco are the [`quote!`] and [`quote_in!`] procedural macros which\nease the construction of [token streams].\n\nThis project solves the following language-specific concerns:\n\n* **Imports** — Generates and groups [import statements] as they are used.\n  So you only import what you use, with no redundancy. We also do our best\n  to [solve namespace conflicts].\n\n* **String Quoting** — genco knows how to [quote strings]. And can even\n  [interpolate] values *into* the quoted string if it's supported by the\n  language.\n\n* **Structural Indentation** — The quoter relies on intuitive\n  [whitespace detection] to structurally sort out spacings and indentation.\n  Allowing genco to generate beautiful readable code with minimal effort.\n  This is also a requirement for generating correctly behaving code in\n  languages like Python where [indentation is meaningful].\n\n* **Language Customization** — Building support for new languages is a\n  piece of cake with the help of the [impl_lang!] macro.\n\n<br>\n\nTo support line changes during [whitespace detection], we depend on span\ninformation which was made available in Rust `1.88`. Before that, we rely on\na nightly [`proc_macro_span` feature] to work.\n\n*Prior to this version of Rust* if you want fully functional whitespace\ndetection you must build and run projects using genco with a `nightly`\ncompiler. This is important for whitespace-sensitive languages like python.\n\nYou can try the difference between:\n\n```bash\ncargo run --example rust\n```\n\nAnd:\n\n```bash\ncargo +nightly run --example rust\n```\n\n[`proc_macro_span` feature]: https://github.com/rust-lang/rust/issues/54725\n\n<br>\n\n## Supported Languages\n\nThe following are languages which have built-in support in genco.\n\n* [🦀 <b>Rust</b>][rust]<br>\n  <small>[Example][rust-example]</small>\n\n* [☕ <b>Java</b>][java]<br>\n  <small>[Example][java-example]</small>\n\n* [🎼 <b>C#</b>][c#]<br>\n  <small>[Example][c#-example]</small>\n\n* [🐿️ <b>Go</b>][go]<br>\n  <small>[Example][go-example]</small>\n\n* [🎯 <b>Dart</b>][dart]<br>\n  <small>[Example][dart-example]</small>\n\n* [🌐 <b>JavaScript</b>][js]<br>\n  <small>[Example][js-example]</small>\n\n* [🇨 <b>C</b>][c]<br>\n  <small>[Example][c-example]</small>\n\n* [🐍 <b>Python</b>][python]<br>\n  <small>[Example][python-example]</small>\n\n<small>Is your favorite language missing? <b>[Open an issue!]</b></small>\n\nYou can run one of the examples by:\n\n```bash\ncargo +nightly run --example rust\n```\n\n<br>\n\n## Rust Example\n\nThe following is a simple program producing Rust code to stdout with custom\nconfiguration:\n\n```rust\nuse genco::prelude::*;\n\nlet hash_map = rust::import(\"std::collections\", \"HashMap\");\n\nlet tokens: rust::Tokens = quote! {\n    fn main() {\n        let mut m = $hash_map::new();\n        m.insert(1u32, 2u32);\n    }\n};\n\nprintln!(\"{}\", tokens.to_file_string()?);\n```\n\nThis would produce:\n\n```rust,no_test\nuse std::collections::HashMap;\n\nfn main() {\n    let mut m = HashMap::new();\n    m.insert(1u32, 2u32);\n}\n```\n\n<br>\n\n[`quote_in!`]: <https://docs.rs/genco/latest/genco/macro.quote_in.html>\n[`quote!`]: <https://docs.rs/genco/latest/genco/macro.quote.html>\n[`quoted()`]: <https://docs.rs/genco/latest/genco/tokens/fn.quoted.html>\n[c-example]: <https://github.com/udoprog/genco/blob/master/examples/c.rs>\n[c]: <https://docs.rs/genco/latest/genco/lang/c/index.html>\n[c#-example]: <https://github.com/udoprog/genco/blob/master/examples/csharp.rs>\n[c#]: <https://docs.rs/genco/latest/genco/lang/csharp/index.html>\n[dart-example]: <https://github.com/udoprog/genco/blob/master/examples/dart.rs>\n[dart]: <https://docs.rs/genco/latest/genco/lang/dart/index.html>\n[go-example]: <https://github.com/udoprog/genco/blob/master/examples/go.rs>\n[go]: <https://docs.rs/genco/latest/genco/lang/go/index.html>\n[impl_lang!]: <https://docs.rs/genco/latest/genco/macro.impl_lang.html>\n[import statements]: <https://docs.rs/genco/latest/genco/macro.quote.html#imports>\n[indentation is meaningful]: <https://docs.python.org/3/faq/design.html#why-does-python-use-indentation-for-grouping-of-statements>\n[interpolate]: <https://docs.rs/genco/latest/genco/macro.quote.html#quoted-string-interpolation>\n[java-example]: <https://github.com/udoprog/genco/blob/master/examples/java.rs>\n[java]: <https://docs.rs/genco/latest/genco/lang/java/index.html>\n[js-example]: <https://github.com/udoprog/genco/blob/master/examples/js.rs>\n[js]: <https://docs.rs/genco/latest/genco/lang/js/index.html>\n[Open an issue!]: <https://github.com/udoprog/genco/issues/new>\n[python-example]: <https://github.com/udoprog/genco/blob/master/examples/python.rs>\n[python]: <https://docs.rs/genco/latest/genco/lang/python/index.html>\n[quote strings]: <https://docs.rs/genco/latest/genco/macro.quote.html#string-quoting>\n[rust-example]: <https://github.com/udoprog/genco/blob/master/examples/rust.rs>\n[rust]: <https://docs.rs/genco/latest/genco/lang/rust/index.html>\n[solve namespace conflicts]: <https://docs.rs/genco/latest/genco/lang/csharp/fn.import.html>\n[token streams]: <https://docs.rs/genco/latest/genco/tokens/struct.Tokens.html>\n[whitespace detection]: <https://docs.rs/genco/latest/genco/macro.quote.html#whitespace-detection>\n"
  },
  {
    "path": "examples/c.rs",
    "content": "use genco::fmt;\nuse genco::prelude::*;\n\nfn main() -> anyhow::Result<()> {\n    let printf = &c::include_system(\"stdio.h\", \"printf\");\n\n    let day = \"tuesday\";\n    let name = \"George\";\n\n    let tokens = quote! {\n        const char* greet_user() {\n            return $(quoted(format_args!(\"Hello {name}!\")));\n        }\n\n        int main() {\n            const char* current_day = $(quoted(day));\n            $printf(\"%s\\n\", current_day);\n            $printf(\"%s\\n\", greet_user());\n        }\n    };\n\n    let stdout = std::io::stdout();\n    let mut w = fmt::IoWriter::new(stdout.lock());\n\n    let fmt = fmt::Config::from_lang::<C>();\n    let config = c::Config::default();\n\n    tokens.format_file(&mut w.as_formatter(&fmt), &config)?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/csharp.rs",
    "content": "use csharp::comment;\nuse genco::fmt;\nuse genco::prelude::*;\n\nfn main() -> anyhow::Result<()> {\n    let console = &csharp::import(\"System\", \"Console\");\n    let file = &csharp::import(\"System.IO\", \"File\");\n    let stream = &csharp::import(\"System.IO\", \"Stream\");\n    let soap_formatter = &csharp::import(\n        \"System.Runtime.Serialization.Formatters.Soap\",\n        \"SoapFormatter\",\n    );\n    let simple_object = \"TestSimpleObject\";\n\n    // Note: Comments have to be escaped as raw expressions, since they are\n    // filtered out from procedural macros.\n    let tokens = quote! {\n        public class Test {\n            public static void Main()  {\n                $(comment(&[\"Creates a new TestSimpleObject object.\"]))\n                $simple_object obj = new $simple_object();\n\n                $console.WriteLine(\"Before serialization the object contains: \");\n                obj.Print();\n\n                $(comment(&[\"Opens a file and serializes the object into it in binary format.\"]))\n                $stream stream = $file.Open(\"data.xml\", FileMode.Create);\n                $soap_formatter formatter = new $soap_formatter();\n\n                $(comment(&[\"BinaryFormatter formatter = new BinaryFormatter();\"]))\n\n                formatter.Serialize(stream, obj);\n                stream.Close();\n\n                $(comment(&[\"Empties obj.\"]))\n                obj = null;\n\n                $(comment(&[\"Opens file \\\"data.xml\\\" and deserializes the object from it.\"]))\n                stream = $file.Open(\"data.xml\", FileMode.Open);\n                formatter = new $soap_formatter();\n\n                $(comment(&[\"formatter = new BinaryFormatter();\"]))\n\n                obj = ($simple_object)formatter.Deserialize(stream);\n                stream.Close();\n\n                $console.WriteLine(\"\");\n                $console.WriteLine(\"After deserialization the object contains: \");\n                obj.Print();\n            }\n        }\n    };\n\n    let stdout = std::io::stdout();\n    let mut w = fmt::IoWriter::new(stdout.lock());\n\n    let fmt = fmt::Config::from_lang::<Csharp>().with_indentation(fmt::Indentation::Space(4));\n    let config = csharp::Config::default();\n\n    tokens.format_file(&mut w.as_formatter(&fmt), &config)?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/dart.rs",
    "content": "use genco::fmt;\nuse genco::prelude::*;\n\nfn main() -> anyhow::Result<()> {\n    let hash_map = &dart::import(\"dart:collection\", \"HashMap\");\n\n    let tokens = quote! {\n        print_greeting(String name) {\n            print($[str](Hello $(name)));\n        }\n\n        $hash_map<int, String> map() {\n            return new $hash_map<int, String>();\n        }\n    };\n\n    let stdout = std::io::stdout();\n    let mut w = fmt::IoWriter::new(stdout.lock());\n\n    let fmt = fmt::Config::from_lang::<Dart>();\n    let config = dart::Config::default();\n\n    tokens.format_file(&mut w.as_formatter(&fmt), &config)?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/go.rs",
    "content": "use genco::fmt;\nuse genco::prelude::*;\n\nfn main() -> anyhow::Result<()> {\n    let println = &go::import(\"fmt\", \"Println\");\n\n    let day = \"tuesday\";\n    let name = \"George\";\n\n    let tokens = quote! {\n        func main() {\n            var currentDay string\n            currentDay = $(quoted(day))\n            $println(currentDay)\n            $println(greetUser())\n        }\n\n        func greetUser() string {\n            return $(quoted(format_args!(\"Hello {name}!\")))\n        }\n    };\n\n    let stdout = std::io::stdout();\n    let mut w = fmt::IoWriter::new(stdout.lock());\n\n    let fmt = fmt::Config::from_lang::<Go>();\n    let config = go::Config::default().with_package(\"main\");\n\n    tokens.format_file(&mut w.as_formatter(&fmt), &config)?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/java.rs",
    "content": "use genco::fmt;\nuse genco::prelude::*;\n\nfn main() -> anyhow::Result<()> {\n    let car = &java::import(\"se.tedro\", \"Car\");\n    let list = &java::import(\"java.util\", \"List\");\n    let array_list = &java::import(\"java.util\", \"ArrayList\");\n\n    let tokens = quote! {\n        public class HelloWorld {\n            public static void main(String[] args) {\n                $list<$car> cars = new $array_list<$car>();\n\n                cars.add(new $car(\"Volvo\"));\n                cars.add(new $car(\"Audi\"));\n\n                for ($car car : cars) {\n                    System.out.println(car);\n                }\n            }\n        }\n    };\n\n    let stdout = std::io::stdout();\n    let mut w = fmt::IoWriter::new(stdout.lock());\n\n    let fmt = fmt::Config::from_lang::<Java>().with_newline(\"\\n\\r\");\n    let config = java::Config::default().with_package(\"se.tedro\");\n\n    tokens.format_file(&mut w.as_formatter(&fmt), &config)?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/js.rs",
    "content": "use genco::fmt;\nuse genco::prelude::*;\n\nfn main() -> anyhow::Result<()> {\n    let react = &js::import(\"react\", \"React\").into_default();\n    let display = &js::import(\"./Display\", \"Display\").into_default();\n    let button_panel = &js::import(\"./ButtonPanel\", \"ButtonPanel\").into_default();\n    let calculate = &js::import(\"../logic/calculate\", \"calculate\").into_default();\n\n    let tokens = quote! {\n        export default class App extends $react.Component {\n            state = {\n                total: null,\n                next: null,\n                operation: null,\n            };\n\n            handleClick = buttonName => {\n                this.setState($calculate(this.state, buttonName));\n            };\n\n            render() {\n                return (\n                    <div className=\"component-app\">\n                        <$display value={this.state.next || this.state.total || \"0\"} />\n                        <$button_panel clickHandler={this.handleClick} />\n                    </div>\n                );\n            }\n        }\n    };\n\n    let stdout = std::io::stdout();\n    let mut w = fmt::IoWriter::new(stdout.lock());\n\n    let fmt = fmt::Config::from_lang::<JavaScript>();\n    let config = js::Config::default();\n\n    tokens.format_file(&mut w.as_formatter(&fmt), &config)?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/kotlin.rs",
    "content": "use genco::fmt;\nuse genco::lang::kotlin;\nuse genco::prelude::*;\n\nfn main() -> anyhow::Result<()> {\n    let greeter_ty = &kotlin::import(\"com.example.utils\", \"Greeter\");\n\n    let tokens: kotlin::Tokens = quote! {\n        fun main() {\n            val greeter = $greeter_ty(\"Hello Kotlin from Genco!\");\n            println(greeter.greet());\n        }\n    };\n\n    let stdout = std::io::stdout();\n    let mut w = fmt::IoWriter::new(stdout.lock());\n\n    let fmt_config = fmt::Config::from_lang::<kotlin::Kotlin>()\n        .with_indentation(fmt::Indentation::Space(4))\n        .with_newline(\"\\n\");\n\n    let lang_config = kotlin::Config::default().with_package(\"com.example\");\n\n    tokens.format_file(&mut w.as_formatter(&fmt_config), &lang_config)?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "examples/nix.rs",
    "content": "use genco::fmt;\nuse genco::prelude::*;\n\nfn main() -> anyhow::Result<()> {\n    let nixpkgs = &nix::inherit(\"inputs\", \"nixpkgs\");\n    let pkgs = &nix::variable(\n        \"pkgs\",\n        quote! {\n            import $nixpkgs {\n                inherit ($nixpkgs) system;\n                config.allowUnfree = true;\n                overlays = [];\n            }\n        },\n    );\n    let mk_default = &nix::with(\"lib\", \"mkDefault\");\n\n    let tokens = quote! {\n        {\n            imports = [];\n            environment.systemPackages = with $pkgs; [];\n            networking.useDHCP = $mk_default true;\n        }\n    };\n\n    let stdout = std::io::stdout();\n    let mut w = fmt::IoWriter::new(stdout.lock());\n\n    let fmt = fmt::Config::from_lang::<Nix>();\n    let config = nix::Config::default();\n\n    tokens.format_file(&mut w.as_formatter(&fmt), &config)?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/python.rs",
    "content": "use genco::fmt;\nuse genco::prelude::*;\n\nfn main() -> anyhow::Result<()> {\n    let flask = &python::import(\"flask\", \"Flask\");\n\n    let tokens = quote! {\n        app = $flask(__name__)\n\n        @app.route('/')\n        def hello():\n            return \"Hello World!\"\n\n        if __name__ == \"__main__\":\n            app.run()\n    };\n\n    let stdout = std::io::stdout();\n    let mut w = fmt::IoWriter::new(stdout.lock());\n\n    let fmt = fmt::Config::from_lang::<Python>();\n    let config = python::Config::default();\n\n    tokens.format_file(&mut w.as_formatter(&fmt), &config)?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/rust.rs",
    "content": "use genco::fmt;\nuse genco::prelude::*;\n\nfn main() -> anyhow::Result<()> {\n    // Import the LittleEndian item, without referencing it through the last\n    // module component it is part of.\n    let little_endian = rust::import(\"byteorder\", \"LittleEndian\");\n    let big_endian = rust::import(\"byteorder\", \"BigEndian\").qualified();\n\n    // Trait that we need to import to make use of write_u16.\n    let write_bytes_ext = rust::import(\"byteorder\", \"WriteBytesExt\").with_alias(\"_\");\n\n    // Trait that we import since we want to return it.\n    let result = rust::import(\"anyhow\", \"Result\");\n\n    let tokens = quote! {\n        $(register(write_bytes_ext))\n\n        fn test() -> $result {\n            let mut data = vec![];\n            data.write_u16::<$little_endian>(517)?;\n            data.write_u16::<$big_endian>(768)?;\n            println!(\"{:?}\", data);\n        }\n    };\n\n    let stdout = std::io::stdout();\n    let mut w = fmt::IoWriter::new(stdout.lock());\n\n    let fmt = fmt::Config::from_lang::<Rust>().with_indentation(fmt::Indentation::Space(4));\n\n    let config = rust::Config::default()\n        // Prettier imports and use.\n        .with_default_import(rust::ImportMode::Qualified);\n\n    tokens.format_file(&mut w.as_formatter(&fmt), &config)?;\n    Ok(())\n}\n"
  },
  {
    "path": "genco-macros/.gitignore",
    "content": "/target/\n**/*.rs.bk\nCargo.lock\n"
  },
  {
    "path": "genco-macros/Cargo.toml",
    "content": "[package]\nname = \"genco-macros\"\nversion = \"0.19.0\"\nauthors = [\"John-John Tedro <udoprog@tedro.se>\"]\nedition = \"2018\"\nrust-version = \"1.88\"\ndescription = \"\"\"\nA whitespace-aware quasiquoter for beautiful code generation.\n\"\"\"\ndocumentation = \"https://docs.rs/genco\"\nreadme = \"README.md\"\nhomepage = \"https://github.com/udoprog/genco\"\nrepository = \"https://github.com/udoprog/genco\"\nlicense = \"MIT OR Apache-2.0\"\nkeywords = [\"code-generation\", \"template\"]\ncategories = [\"template-engine\"]\n\n[lints.rust]\nunexpected_cfgs = { level = \"warn\", check-cfg = ['cfg(proc_macro_span, has_proc_macro_span)'] }\n\n[dependencies]\nsyn = { version = \"2.0.38\", features = [\"full\"] }\nq = { package = \"quote\", version = \"1.0.3\" }\nproc-macro2 = { version = \"1.0.10\", features = [\"span-locations\"] }\n\n[lib]\nproc-macro = true\n"
  },
  {
    "path": "genco-macros/README.md",
    "content": "# genco-macros\n\n[<img alt=\"github\" src=\"https://img.shields.io/badge/github-udoprog/genco-8da0cb?style=for-the-badge&logo=github\" height=\"20\">](https://github.com/udoprog/genco)\n[<img alt=\"crates.io\" src=\"https://img.shields.io/crates/v/genco-macros.svg?style=for-the-badge&color=fc8d62&logo=rust\" height=\"20\">](https://crates.io/crates/genco-macros)\n[<img alt=\"docs.rs\" src=\"https://img.shields.io/badge/docs.rs-genco--macros-66c2a5?style=for-the-badge&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K\" height=\"20\">](https://docs.rs/genco-macros)\n[<img alt=\"build status\" src=\"https://img.shields.io/github/actions/workflow/status/udoprog/genco/ci.yml?branch=main&style=for-the-badge\" height=\"20\">](https://github.com/udoprog/genco/actions?query=branch%3Amain)\n"
  },
  {
    "path": "genco-macros/build.rs",
    "content": "use std::env;\nuse std::process::Command;\nuse std::str;\n\nfn main() {\n    println!(\"cargo:rerun-if-changed=build.rs\");\n\n    let version = rustc_version().unwrap_or(RustcVersion {\n        minor: u32::MAX,\n        nightly: false,\n    });\n\n    if version.nightly && version.minor < 88 {\n        println!(\"cargo:rustc-cfg=proc_macro_span\");\n        println!(\"cargo:rustc-cfg=has_proc_macro_span\");\n    } else if version.minor >= 88 {\n        // The relevant parts are stable since 1.88\n        println!(\"cargo:rustc-cfg=has_proc_macro_span\");\n    }\n}\n\nstruct RustcVersion {\n    minor: u32,\n    nightly: bool,\n}\n\nfn rustc_version() -> Option<RustcVersion> {\n    let rustc = env::var_os(\"RUSTC\")?;\n    let output = Command::new(rustc).arg(\"--version\").output().ok()?;\n    let version = str::from_utf8(&output.stdout).ok()?;\n    let nightly = version.contains(\"nightly\") || version.contains(\"dev\");\n    let mut pieces = version.split('.');\n\n    if pieces.next()? != \"rustc 1\" {\n        return None;\n    }\n\n    let minor = pieces.next()?.parse().ok()?;\n    Some(RustcVersion { minor, nightly })\n}\n"
  },
  {
    "path": "genco-macros/src/ast.rs",
    "content": "use core::fmt;\n\nuse proc_macro2::{Span, TokenStream, TokenTree};\nuse syn::Token;\n\nuse crate::static_buffer::StaticBuffer;\n\n/// A single match arm in a match statement.\npub(crate) struct MatchArm {\n    pub(crate) attr: Vec<syn::Attribute>,\n    pub(crate) pattern: syn::Pat,\n    pub(crate) condition: Option<syn::Expr>,\n    pub(crate) block: TokenStream,\n}\n\n/// A delimiter that can be encoded.\n#[derive(Debug, Clone, Copy)]\npub(crate) enum Delimiter {\n    Parenthesis,\n    Brace,\n    Bracket,\n}\n\nimpl Delimiter {\n    pub(crate) fn encode_open(self, output: &mut StaticBuffer) {\n        let c = match self {\n            Self::Parenthesis => '(',\n            Self::Brace => '{',\n            Self::Bracket => '[',\n        };\n\n        output.push(c);\n    }\n\n    pub(crate) fn encode_close(self, output: &mut StaticBuffer) {\n        let c = match self {\n            Self::Parenthesis => ')',\n            Self::Brace => '}',\n            Self::Bracket => ']',\n        };\n\n        output.push(c);\n    }\n}\n\npub(crate) enum LiteralName<'a> {\n    /// The literal name as a string.\n    Ident(&'a str),\n    /// The literal name as a character.\n    Char(char),\n}\n\nimpl fmt::Display for LiteralName<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            LiteralName::Ident(ident) => ident.fmt(f),\n            LiteralName::Char(c) => write!(f, \"{c:?}\"),\n        }\n    }\n}\n\n/// The name of an internal fn.\npub(crate) enum Name {\n    /// The name is the `const` token.\n    Const(Token![const]),\n    /// Custom name.\n    Ident(String),\n    /// Character name.\n    Char(char),\n}\n\nimpl Name {\n    /// Get the name as a string.\n    pub(crate) fn as_literal_name(&self) -> LiteralName<'_> {\n        match self {\n            Name::Const(..) => LiteralName::Ident(\"const\"),\n            Name::Ident(name) => LiteralName::Ident(name.as_str()),\n            Name::Char(c) => LiteralName::Char(*c),\n        }\n    }\n}\n\nimpl q::ToTokens for Name {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        match self {\n            Name::Const(t) => t.to_tokens(tokens),\n            Name::Ident(name) => name.to_tokens(tokens),\n            Name::Char(c) => c.to_tokens(tokens),\n        }\n    }\n}\n\n#[derive(Debug)]\npub(crate) enum ControlKind {\n    Space,\n    Push,\n    Line,\n}\n\n#[derive(Debug)]\npub(crate) struct Control {\n    pub(crate) kind: ControlKind,\n    pub(crate) span: Span,\n}\n\nimpl Control {\n    /// Construct a control from a string identifier.\n    pub(crate) fn from_char(span: Span, c: char) -> Option<Self> {\n        match c {\n            ' ' => Some(Self {\n                kind: ControlKind::Space,\n                span,\n            }),\n            '\\n' => Some(Self {\n                kind: ControlKind::Line,\n                span,\n            }),\n            '\\r' => Some(Self {\n                kind: ControlKind::Push,\n                span,\n            }),\n            _ => None,\n        }\n    }\n}\n\n/// Items to process from the queue.\npub(crate) enum Ast {\n    Tree {\n        tt: TokenTree,\n    },\n    String {\n        has_eval: bool,\n        stream: TokenStream,\n    },\n    /// A quoted string.\n    Quoted {\n        s: syn::LitStr,\n    },\n    /// A literal value embedded in the stream.\n    Literal {\n        string: String,\n    },\n    DelimiterOpen {\n        delimiter: Delimiter,\n    },\n    DelimiterClose {\n        delimiter: Delimiter,\n    },\n    Control {\n        control: Control,\n    },\n    EvalIdent {\n        ident: syn::Ident,\n    },\n    /// Something to be evaluated as rust.\n    Eval {\n        expr: syn::Expr,\n    },\n    /// A bound scope.\n    Scope {\n        binding: Option<syn::Ident>,\n        content: TokenStream,\n    },\n    /// A loop repetition.\n    Loop {\n        /// The pattern being bound.\n        pattern: Box<syn::Pat>,\n        /// Expression being bound to an iterator.\n        expr: Box<syn::Expr>,\n        /// If a join is specified, this is the token stream used to join.\n        /// It's evaluated in the loop scope.\n        join: Option<TokenStream>,\n        /// The inner stream processed.\n        stream: TokenStream,\n    },\n    Condition {\n        /// Expression being use as a condition.\n        condition: syn::Expr,\n        /// Then branch of the conditional.\n        then_branch: TokenStream,\n        /// Else branch of the conditional.\n        else_branch: Option<TokenStream>,\n    },\n    Let {\n        /// Variable name (or names for a tuple)\n        name: syn::Pat,\n        /// Expression\n        expr: syn::Expr,\n    },\n    Match {\n        condition: syn::Expr,\n        arms: Vec<MatchArm>,\n    },\n}\n"
  },
  {
    "path": "genco-macros/src/cursor.rs",
    "content": "use proc_macro2::Span;\n\nuse crate::fake::LineColumn;\n\n#[derive(Clone, Copy, Debug)]\npub(crate) struct Cursor {\n    // Span to use for diagnostics associated with the cursor.\n    pub(crate) span: Span,\n    // The start of the cursor.\n    pub(crate) start: LineColumn,\n    // The end of the cursor.\n    pub(crate) end: LineColumn,\n}\n\nimpl Cursor {\n    /// Construt a cursor.\n    pub(crate) fn new(span: Span, start: LineColumn, end: LineColumn) -> Cursor {\n        Self { span, start, end }\n    }\n\n    /// Calculate the start character for the cursor.\n    pub(crate) fn first_character(self) -> Self {\n        Cursor {\n            span: self.span,\n            start: self.start,\n            end: LineColumn {\n                line: self.start.line,\n                column: self.start.column + 1,\n            },\n        }\n    }\n\n    /// Calculate the end character for the cursor.\n    pub(crate) fn last_character(self) -> Self {\n        Cursor {\n            span: self.span,\n            start: LineColumn {\n                line: self.end.line,\n                column: self.end.column.saturating_sub(1),\n            },\n            end: self.end,\n        }\n    }\n}\n"
  },
  {
    "path": "genco-macros/src/encoder.rs",
    "content": "use crate::ast::{Ast, Control, ControlKind, Delimiter, MatchArm};\nuse crate::cursor::Cursor;\nuse crate::fake::LineColumn;\nuse crate::requirements::Requirements;\nuse crate::static_buffer::StaticBuffer;\nuse crate::Ctxt;\n\nuse proc_macro2::{Span, TokenStream};\nuse syn::Result;\n\n/// Struct to deal with emitting the necessary spacing.\npub(crate) struct Encoder<'a> {\n    /// Context for encoding.\n    cx: &'a Ctxt,\n    /// Use to modify the initial line/column in case something was processed\n    /// before the input was handed off to the quote parser.\n    ///\n    /// See [QuoteInParser].\n    span_start: Option<LineColumn>,\n    /// Override the end span of the quote parser.\n    ///\n    /// This causes whitespace to be emitted at the tail of the expression,\n    /// unless it specifically reached the end of the span.\n    span_end: Option<LineColumn>,\n    /// TODO: make private.\n    item_buffer: StaticBuffer<'a>,\n    /// The token stream we are constructing.\n    output: TokenStream,\n    /// Currently stored cursor.\n    last: Option<Cursor>,\n    /// Which column the last line start on.\n    last_start_column: Option<usize>,\n    /// Indentation columns.\n    indents: Vec<(usize, Option<Span>)>,\n    /// Indicates if the encoder has encountered a string which requires eval\n    /// support in the target language.\n    pub(crate) requirements: Requirements,\n}\n\nimpl<'a> Encoder<'a> {\n    pub(crate) fn new(\n        cx: &'a Ctxt,\n        span_start: Option<LineColumn>,\n        span_end: Option<LineColumn>,\n    ) -> Self {\n        Self {\n            cx,\n            span_start,\n            span_end,\n            item_buffer: StaticBuffer::new(cx),\n            output: TokenStream::new(),\n            last: None,\n            last_start_column: None,\n            indents: Vec::new(),\n            requirements: Requirements::default(),\n        }\n    }\n\n    /// Encode a single item into the encoder.\n    pub(crate) fn encode(&mut self, cursor: Cursor, ast: Ast) -> Result<()> {\n        self.step(cursor)?;\n\n        match ast {\n            Ast::Tree { tt, .. } => {\n                self.encode_literal(&tt.to_string());\n            }\n            Ast::String { has_eval, stream } => {\n                self.requirements.lang_supports_eval |= has_eval;\n                self.encode_string(has_eval, stream);\n            }\n            Ast::Quoted { s } => {\n                self.encode_quoted(s);\n            }\n            Ast::Literal { string } => {\n                self.encode_literal(&string);\n            }\n            Ast::Control { control, .. } => {\n                self.encode_control(control);\n            }\n            Ast::Scope {\n                binding, content, ..\n            } => {\n                self.encode_scope(binding, content);\n            }\n            Ast::EvalIdent { ident } => {\n                self.encode_eval_ident(ident);\n            }\n            Ast::Eval { expr, .. } => {\n                self.encode_eval(expr);\n            }\n            Ast::Loop {\n                pattern,\n                expr,\n                join,\n                stream,\n                ..\n            } => {\n                self.encode_repeat(*pattern, *expr, join, stream);\n            }\n            Ast::DelimiterOpen { delimiter, .. } => {\n                self.encode_open_delimiter(delimiter);\n            }\n            Ast::DelimiterClose { delimiter, .. } => {\n                self.encode_close_delimiter(delimiter);\n            }\n            Ast::Condition {\n                condition,\n                then_branch,\n                else_branch,\n                ..\n            } => {\n                self.encode_condition(condition, then_branch, else_branch);\n            }\n            Ast::Match {\n                condition, arms, ..\n            } => {\n                self.encode_match(condition, arms);\n            }\n            Ast::Let { name, expr } => {\n                self.encode_let(name, expr);\n            }\n        }\n\n        Ok(())\n    }\n\n    /// Finalize and translate into a token stream.\n    pub(crate) fn into_output(mut self) -> Result<(Requirements, TokenStream)> {\n        self.finalize()?;\n        Ok((self.requirements, self.output))\n    }\n\n    pub(crate) fn step(&mut self, next: Cursor) -> Result<()> {\n        if let Some(from) = self.from() {\n            // Insert spacing if appropriate.\n            self.tokenize_whitespace(from, next.start, Some(next.span))?;\n        }\n\n        // Assign the current cursor to the next item.\n        // This will then be used to make future indentation decisions.\n        self.last = Some(next);\n        Ok(())\n    }\n\n    pub(crate) fn encode_open_delimiter(&mut self, d: Delimiter) {\n        d.encode_open(&mut self.item_buffer);\n    }\n\n    pub(crate) fn encode_close_delimiter(&mut self, d: Delimiter) {\n        d.encode_close(&mut self.item_buffer);\n    }\n\n    pub(crate) fn encode_literal(&mut self, string: &str) {\n        self.item_buffer.push_str(string);\n    }\n\n    pub(crate) fn encode_string(&mut self, has_eval: bool, stream: TokenStream) {\n        let Ctxt { receiver, module } = self.cx;\n\n        self.item_buffer.flush(&mut self.output);\n\n        self.output.extend(q::quote! {\n            #receiver.append(#module::__priv::open_quote(#has_eval));\n            #stream\n            #receiver.append(#module::__priv::close_quote());\n        });\n    }\n\n    pub(crate) fn encode_quoted(&mut self, s: syn::LitStr) {\n        let Ctxt { receiver, module } = self.cx;\n\n        self.item_buffer.flush(&mut self.output);\n\n        self.output.extend(q::quote! {\n            #receiver.append(#module::__priv::open_quote(false));\n            #receiver.append(#module::__priv::static_(#s));\n            #receiver.append(#module::__priv::close_quote());\n        });\n    }\n\n    pub(crate) fn encode_control(&mut self, control: Control) {\n        let Ctxt { receiver, .. } = self.cx;\n\n        self.item_buffer.flush(&mut self.output);\n\n        match control.kind {\n            ControlKind::Space => {\n                self.output\n                    .extend(q::quote_spanned!(control.span => #receiver.space();));\n            }\n            ControlKind::Push => {\n                self.output\n                    .extend(q::quote_spanned!(control.span => #receiver.push();));\n            }\n            ControlKind::Line => {\n                self.output\n                    .extend(q::quote_spanned!(control.span => #receiver.line();));\n            }\n        }\n    }\n\n    pub(crate) fn encode_scope(&mut self, binding: Option<syn::Ident>, content: TokenStream) {\n        let Ctxt { receiver, .. } = self.cx;\n\n        if binding.is_some() {\n            self.item_buffer.flush(&mut self.output);\n        }\n\n        let binding = binding.map(|b| q::quote_spanned!(b.span() => let #b = &mut *#receiver;));\n\n        self.output.extend(q::quote! {{\n            #binding\n            #content\n        }});\n    }\n\n    /// Encode an evaluation of the given expression.\n    pub(crate) fn encode_eval_ident(&mut self, ident: syn::Ident) {\n        let Ctxt { receiver, .. } = self.cx;\n\n        self.item_buffer.flush(&mut self.output);\n        self.output.extend(q::quote! {\n            #receiver.append(#ident);\n        });\n    }\n\n    /// Encode an evaluation of the given expression.\n    pub(crate) fn encode_eval(&mut self, expr: syn::Expr) {\n        let Ctxt { receiver, .. } = self.cx;\n\n        self.item_buffer.flush(&mut self.output);\n        self.output.extend(q::quote! {\n            #receiver.append(#expr);\n        });\n    }\n\n    pub(crate) fn encode_repeat(\n        &mut self,\n        pattern: syn::Pat,\n        expr: syn::Expr,\n        join: Option<TokenStream>,\n        stream: TokenStream,\n    ) {\n        self.item_buffer.flush(&mut self.output);\n\n        if let Some(join) = join {\n            self.output.extend(q::quote! {\n                {\n                    let mut __it = IntoIterator::into_iter(#expr).peekable();\n\n                    while let Some(#pattern) = __it.next() {\n                        #stream\n\n                        if __it.peek().is_some() {\n                            #join\n                        }\n                    }\n                }\n            });\n        } else {\n            self.output.extend(q::quote! {\n                for #pattern in #expr {\n                    #stream\n                }\n            });\n        }\n    }\n\n    /// Encode an if statement with an inner stream.\n    pub(crate) fn encode_condition(\n        &mut self,\n        condition: syn::Expr,\n        then_branch: TokenStream,\n        else_branch: Option<TokenStream>,\n    ) {\n        self.item_buffer.flush(&mut self.output);\n\n        let else_branch = else_branch.map(|stream| q::quote!(else { #stream }));\n\n        self.output.extend(q::quote! {\n            if #condition { #then_branch } #else_branch\n        });\n    }\n\n    /// Encode an if statement with an inner stream.\n    pub(crate) fn encode_match(&mut self, condition: syn::Expr, arms: Vec<MatchArm>) {\n        self.item_buffer.flush(&mut self.output);\n\n        let mut stream = TokenStream::new();\n\n        for MatchArm {\n            attr,\n            pattern,\n            condition,\n            block,\n        } in arms\n        {\n            let condition = condition.map(|c| q::quote!(if #c));\n            stream.extend(q::quote!(#(#attr)* #pattern #condition => { #block },));\n        }\n\n        let m = q::quote! {\n            match #condition { #stream }\n        };\n\n        self.output.extend(m);\n    }\n\n    /// Encode a let statement\n    pub(crate) fn encode_let(&mut self, name: syn::Pat, expr: syn::Expr) {\n        self.item_buffer.flush(&mut self.output);\n\n        self.output.extend(q::quote! {\n            let #name = #expr;\n        })\n    }\n\n    fn from(&mut self) -> Option<LineColumn> {\n        // So we've (potentially) encountered the first ever token, while we\n        // have a spanned start like `quote_in! { out => foo }`, `foo` is now\n        // `next`.\n        //\n        // What we want to do is treat the beginning out `out` as the\n        // indentation position, so we adjust the token.\n        //\n        // But we also want to avoid situations like this:\n        //\n        // ```\n        // quote_in! { out =>\n        //     foo\n        //     bar\n        // }\n        // ```\n        //\n        // If we would treat `out` as the start, `foo` would be seen as\n        // unindented. So check if the first encountered token is on the\n        // same line as the binding `out` or not before adjusting them!\n        if let Some(span_start) = self.span_start.take() {\n            self.last_start_column = Some(span_start.column);\n            return Some(span_start);\n        }\n\n        if let Some(last) = self.last {\n            if self.last_start_column.is_none() {\n                self.last_start_column = Some(last.start.column);\n            }\n\n            return Some(last.end);\n        }\n\n        None\n    }\n\n    /// Finalize the encoder.\n    fn finalize(&mut self) -> Result<()> {\n        let Ctxt { receiver, .. } = self.cx;\n\n        // evaluate whitespace in case we have an explicit end span.\n        while let Some(to) = self.span_end.take() {\n            if let Some(from) = self.from() {\n                // Insert spacing if appropriate, up until the \"fake\" end.\n                self.tokenize_whitespace(from, to, None)?;\n            }\n        }\n\n        self.item_buffer.flush(&mut self.output);\n\n        while self.indents.pop().is_some() {\n            self.output.extend(q::quote!(#receiver.unindent();));\n        }\n\n        Ok(())\n    }\n\n    /// If we are in a nightly genco, insert indentation and spacing if\n    /// appropriate in the output token stream.\n    fn tokenize_whitespace(\n        &mut self,\n        from: LineColumn,\n        to: LineColumn,\n        to_span: Option<Span>,\n    ) -> Result<()> {\n        let Ctxt { receiver: r, .. } = self.cx;\n\n        // Do nothing if empty span.\n        if from == to {\n            return Ok(());\n        }\n\n        // Insert spacing if we are on the same line, but column has changed.\n        if from.line == to.line {\n            // Same line, but next item doesn't match.\n            if from.column < to.column {\n                self.item_buffer.flush(&mut self.output);\n                self.output.extend(q::quote!(#r.space();));\n            }\n\n            return Ok(());\n        }\n\n        // Line changed. Determine whether to indent, unindent, or hard break the\n        // line.\n        self.item_buffer.flush(&mut self.output);\n\n        debug_assert!(from.line < to.line);\n\n        let line = to.line - from.line > 1;\n\n        if let Some(last_start_column) = self.last_start_column.take() {\n            if last_start_column < to.column {\n                self.indents.push((last_start_column, to_span));\n                self.output.extend(q::quote!(#r.indent();));\n\n                if line {\n                    self.output.extend(q::quote!(#r.line();));\n                }\n            } else if last_start_column > to.column {\n                while let Some((column, _)) = self.indents.pop() {\n                    if column > to.column && !self.indents.is_empty() {\n                        self.output.extend(q::quote!(#r.unindent();));\n\n                        if line {\n                            self.output.extend(q::quote!(#r.line();));\n                        }\n\n                        continue;\n                    } else if column == to.column {\n                        self.output.extend(q::quote!(#r.unindent();));\n\n                        if line {\n                            self.output.extend(q::quote!(#r.line();));\n                        }\n\n                        break;\n                    }\n\n                    return Err(indentation_error(to.column, column, to_span));\n                }\n            } else if line {\n                self.output.extend(q::quote!(#r.line();));\n            } else {\n                self.output.extend(q::quote!(#r.push();));\n            }\n        }\n\n        return Ok(());\n\n        fn indentation_error(\n            to_column: usize,\n            from_column: usize,\n            to_span: Option<Span>,\n        ) -> syn::Error {\n            let error = if to_column > from_column {\n                let len = to_column.saturating_sub(from_column);\n\n                format!(\n                    \"expected {} less {} of indentation\",\n                    len,\n                    if len == 1 { \"space\" } else { \"spaces\" }\n                )\n            } else {\n                let len = from_column.saturating_sub(to_column);\n\n                format!(\n                    \"expected {} more {} of indentation\",\n                    len,\n                    if len == 1 { \"space\" } else { \"spaces\" }\n                )\n            };\n\n            if let Some(span) = to_span {\n                syn::Error::new(span, error)\n            } else {\n                syn::Error::new(Span::call_site(), error)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "genco-macros/src/fake.rs",
    "content": "use core::cell::{RefCell, RefMut};\nuse core::fmt::Arguments;\n\nuse proc_macro2::Span;\n\nuse crate::cursor::Cursor;\n\n/// Error message raised.\nconst ERROR: &str = \"Your compiler does not support spans which are required by genco and compat doesn't work, see: https://github.com/rust-lang/rust/issues/54725\";\n\n/// Internal line-column abstraction.\n#[derive(Debug, Clone, Copy, PartialEq, Eq)]\npub(crate) struct LineColumn {\n    /// The line.\n    pub(crate) line: usize,\n    /// The column.\n    pub(crate) column: usize,\n}\n\nimpl LineColumn {\n    #[cfg(has_proc_macro_span)]\n    pub(crate) fn start(span: Span) -> Option<Self> {\n        let span = span.unwrap().start();\n\n        Some(Self {\n            line: span.line(),\n            column: span.column(),\n        })\n    }\n\n    #[cfg(has_proc_macro_span)]\n    pub(crate) fn end(span: Span) -> Option<Self> {\n        let span = span.unwrap().end();\n\n        Some(Self {\n            line: span.line(),\n            column: span.column(),\n        })\n    }\n\n    #[cfg(not(has_proc_macro_span))]\n    pub(crate) fn start(_: Span) -> Option<Self> {\n        None\n    }\n\n    #[cfg(not(has_proc_macro_span))]\n    pub(crate) fn end(_: Span) -> Option<Self> {\n        None\n    }\n}\n\n#[derive(Default)]\npub(crate) struct Buf {\n    buf: RefCell<String>,\n}\n\nimpl Buf {\n    /// Format the given arguments and return the associated string.\n    fn format(&self, args: Arguments<'_>) -> RefMut<'_, str> {\n        use std::fmt::Write;\n        let mut buf = self.buf.borrow_mut();\n        buf.clear();\n        buf.write_fmt(args).unwrap();\n        RefMut::map(buf, |buf| buf.as_mut_str())\n    }\n\n    /// Construct a cursor from a span.\n    pub(crate) fn cursor(&self, span: Span) -> syn::Result<Cursor> {\n        let start = LineColumn::start(span);\n        let end = LineColumn::end(span);\n\n        if let (Some(start), Some(end)) = (start, end) {\n            return Ok(Cursor::new(span, start, end));\n        }\n\n        // Try compat.\n        let (start, end) = self.find_line_column(span)?;\n\n        Ok(Cursor::new(\n            span,\n            LineColumn {\n                line: 1,\n                column: start,\n            },\n            LineColumn {\n                line: 1,\n                column: end,\n            },\n        ))\n    }\n\n    /// The start of the given span.\n    pub(crate) fn start(&mut self, span: Span) -> syn::Result<LineColumn> {\n        if let Some(start) = LineColumn::start(span) {\n            return Ok(start);\n        }\n\n        // Try compat.\n        let (column, _) = self.find_line_column(span)?;\n        Ok(LineColumn { line: 1, column })\n    }\n\n    /// The start of the given span.\n    pub(crate) fn end(&mut self, span: Span) -> syn::Result<LineColumn> {\n        if let Some(end) = LineColumn::end(span) {\n            return Ok(end);\n        }\n\n        // Try compat.\n        let (_, column) = self.find_line_column(span)?;\n        Ok(LineColumn { line: 1, column })\n    }\n\n    /// Join two spans.\n    pub(crate) fn join(&mut self, a: Span, b: Span) -> syn::Result<Cursor> {\n        Ok(Cursor::new(\n            a.join(b).unwrap_or(a),\n            self.start(a)?,\n            self.end(b)?,\n        ))\n    }\n\n    /// Try to decode line and column information using the debug implementation of\n    /// a `span` which leaks the byte offset of a thing.\n    fn find_line_column(&self, span: Span) -> syn::Result<(usize, usize)> {\n        match self.find_line_column_inner(span) {\n            Some((start, end)) => Ok((start, end)),\n            None => Err(syn::Error::new(span, ERROR)),\n        }\n    }\n\n    fn find_line_column_inner(&self, span: Span) -> Option<(usize, usize)> {\n        let text = self.format(format_args!(\"{span:?}\"));\n        let start = text.find('(')?;\n        let (start, end) = text\n            .get(start.checked_add(1)?..text.len().checked_sub(1)?)?\n            .split_once(\"..\")?;\n        Some((str::parse(start).ok()?, str::parse(end).ok()?))\n    }\n}\n"
  },
  {
    "path": "genco-macros/src/lib.rs",
    "content": "//! [<img alt=\"github\" src=\"https://img.shields.io/badge/github-udoprog/genco-8da0cb?style=for-the-badge&logo=github\" height=\"20\">](https://github.com/udoprog/genco)\n//! [<img alt=\"crates.io\" src=\"https://img.shields.io/crates/v/genco-macros.svg?style=for-the-badge&color=fc8d62&logo=rust\" height=\"20\">](https://crates.io/crates/genco-macros)\n//! [<img alt=\"docs.rs\" src=\"https://img.shields.io/badge/docs.rs-genco--macros-66c2a5?style=for-the-badge&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K\" height=\"20\">](https://docs.rs/genco-macros)\n\n#![recursion_limit = \"256\"]\n#![allow(clippy::type_complexity)]\n#![cfg_attr(proc_macro_span, feature(proc_macro_span))]\n\nextern crate proc_macro;\n\nuse proc_macro2::Span;\nuse syn::parse::{ParseStream, Parser as _};\n\nstruct Ctxt {\n    receiver: syn::Ident,\n    module: syn::Path,\n}\n\nimpl Default for Ctxt {\n    fn default() -> Self {\n        let mut module = syn::Path {\n            leading_colon: None,\n            segments: syn::punctuated::Punctuated::default(),\n        };\n\n        module\n            .segments\n            .push(syn::Ident::new(\"genco\", Span::call_site()).into());\n\n        Self {\n            receiver: syn::Ident::new(\"__genco_macros_toks\", Span::call_site()),\n            module,\n        }\n    }\n}\n\nmod ast;\nmod cursor;\nmod encoder;\nmod fake;\nmod quote;\nmod quote_fn;\nmod quote_in;\nmod requirements;\nmod static_buffer;\nmod string_parser;\n\n#[proc_macro]\npub fn quote(input: proc_macro::TokenStream) -> proc_macro::TokenStream {\n    let cx = Ctxt::default();\n    let parser = crate::quote::Quote::new(&cx);\n\n    let parser = move |stream: ParseStream| parser.parse(stream);\n\n    let (req, output) = match parser.parse(input) {\n        Ok(data) => data,\n        Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),\n    };\n\n    let check = req.into_check(&cx.receiver);\n\n    let Ctxt { receiver, module } = &cx;\n\n    let gen = q::quote! {{\n        let mut #receiver = #module::tokens::Tokens::new();\n\n        {\n            let mut #receiver = &mut #receiver;\n            #output\n        }\n\n        #check\n        #receiver\n    }};\n\n    gen.into()\n}\n\n#[proc_macro]\npub fn quote_in(input: proc_macro::TokenStream) -> proc_macro::TokenStream {\n    let quote_in = syn::parse_macro_input!(input as quote_in::QuoteIn);\n    quote_in.stream.into()\n}\n\n#[proc_macro]\npub fn quote_fn(input: proc_macro::TokenStream) -> proc_macro::TokenStream {\n    let quote_fn = syn::parse_macro_input!(input as quote_fn::QuoteFn);\n    quote_fn.stream.into()\n}\n"
  },
  {
    "path": "genco-macros/src/quote.rs",
    "content": "use proc_macro2::{Punct, Spacing, Span, TokenStream, TokenTree};\nuse syn::parse::{ParseBuffer, ParseStream};\nuse syn::spanned::Spanned;\nuse syn::{token, Result, Token};\n\nuse crate::ast::{Ast, Control, Delimiter, LiteralName, MatchArm, Name};\nuse crate::encoder::Encoder;\nuse crate::fake::Buf;\nuse crate::fake::LineColumn;\nuse crate::requirements::Requirements;\nuse crate::string_parser::StringParser;\nuse crate::Ctxt;\n\npub(crate) struct Quote<'a> {\n    /// Context variables.\n    cx: &'a Ctxt,\n    /// Use to modify the initial line/column in case something was processed\n    /// before the input was handed off to the quote parser.\n    ///\n    /// See [QuoteInParser].\n    span_start: Option<LineColumn>,\n    /// Override the end span of the quote parser.\n    ///\n    /// This causes encoder to be emitted at the tail of the expression,\n    /// unless it specifically reached the end of the span.\n    span_end: Option<LineColumn>,\n    /// If true, only parse until a comma (`,`) is encountered.\n    until_comma: bool,\n    /// Buffer,\n    buf: Buf,\n}\n\nimpl<'a> Quote<'a> {\n    /// Construct a new quote parser.\n    pub(crate) fn new(cx: &'a Ctxt) -> Self {\n        Self {\n            cx,\n            span_start: None,\n            span_end: None,\n            until_comma: false,\n            buf: Buf::default(),\n        }\n    }\n\n    /// Construct a new quote parser that will only parse until the given token.\n    pub(crate) fn new_until_comma(cx: &'a Ctxt) -> Self {\n        Self {\n            cx,\n            span_start: None,\n            span_end: None,\n            until_comma: true,\n            buf: Buf::default(),\n        }\n    }\n\n    /// Override the default starting span.\n    pub(crate) fn with_span(mut self, span: Span) -> syn::Result<Self> {\n        return Ok(Self {\n            span_start: Some(adjust_start(self.buf.start(span)?)),\n            span_end: Some(adjust_end(self.buf.end(span)?)),\n            ..self\n        });\n\n        fn adjust_start(start: LineColumn) -> LineColumn {\n            LineColumn {\n                line: start.line,\n                column: start.column.saturating_add(1),\n            }\n        }\n\n        fn adjust_end(end: LineColumn) -> LineColumn {\n            LineColumn {\n                line: end.line,\n                column: end.column.saturating_sub(1),\n            }\n        }\n    }\n\n    /// Parse until end of stream.\n    pub(crate) fn parse(mut self, input: ParseStream) -> Result<(Requirements, TokenStream)> {\n        let mut encoder = Encoder::new(self.cx, self.span_start, self.span_end);\n        self.parse_inner(&mut encoder, input, 0)?;\n        encoder.into_output()\n    }\n\n    /// Parse `if <condition> { <quoted> } [else { <quoted> }]`.\n    fn parse_condition(&self, input: ParseStream) -> Result<(Requirements, Ast)> {\n        input.parse::<Token![if]>()?;\n        let condition = syn::Expr::parse_without_eager_brace(input)?;\n\n        if input.peek(Token![=>]) {\n            input.parse::<Token![=>]>()?;\n            let (req, then_branch) = Quote::new(self.cx).parse(input)?;\n\n            return Ok((\n                req,\n                Ast::Condition {\n                    condition,\n                    then_branch,\n                    else_branch: None,\n                },\n            ));\n        }\n\n        let mut req = Requirements::default();\n\n        let content;\n        syn::braced!(content in input);\n\n        let (r, then_branch) = Quote::new(self.cx).parse(&content)?;\n        req.merge_with(r);\n\n        let else_branch = if input.peek(Token![else]) {\n            input.parse::<Token![else]>()?;\n\n            let content;\n            syn::braced!(content in input);\n\n            let (r, else_branch) = Quote::new(self.cx).parse(&content)?;\n            req.merge_with(r);\n\n            Some(else_branch)\n        } else {\n            None\n        };\n\n        Ok((\n            req,\n            Ast::Condition {\n                condition,\n                then_branch,\n                else_branch,\n            },\n        ))\n    }\n\n    /// Parse `for <expr> in <iter> [join (<quoted>)] => <quoted>`.\n    fn parse_loop(&self, input: ParseStream) -> Result<(Requirements, Ast)> {\n        syn::custom_keyword!(join);\n\n        let mut req = Requirements::default();\n\n        input.parse::<Token![for]>()?;\n        let pattern = syn::Pat::parse_single(input)?;\n        input.parse::<Token![in]>()?;\n        let expr = syn::Expr::parse_without_eager_brace(input)?;\n\n        let join = if input.peek(join) {\n            input.parse::<join>()?;\n\n            let content;\n            let paren = syn::parenthesized!(content in input);\n\n            let (r, join) = Quote::new(self.cx)\n                .with_span(paren.span.span())?\n                .parse(&content)?;\n            req.merge_with(r);\n\n            Some(join)\n        } else {\n            None\n        };\n\n        let content;\n\n        let input = if input.peek(Token![=>]) {\n            input.parse::<Token![=>]>()?;\n            input\n        } else {\n            syn::braced!(content in input);\n            &content\n        };\n\n        let parser = Quote::new(self.cx);\n        let (r, stream) = parser.parse(input)?;\n        req.merge_with(r);\n\n        let ast = Ast::Loop {\n            pattern: Box::new(pattern),\n            join,\n            expr: Box::new(expr),\n            stream,\n        };\n\n        Ok((req, ast))\n    }\n\n    fn parse_match(&self, input: ParseStream) -> Result<(Requirements, Ast)> {\n        input.parse::<Token![match]>()?;\n        let condition = syn::Expr::parse_without_eager_brace(input)?;\n\n        let body;\n        syn::braced!(body in input);\n\n        let mut req = Requirements::default();\n        let mut arms = Vec::new();\n\n        while !body.is_empty() {\n            let attr = input.call(syn::Attribute::parse_outer)?;\n            let pattern = syn::Pat::parse_multi_with_leading_vert(&body)?;\n\n            let condition = if body.peek(Token![if]) {\n                body.parse::<Token![if]>()?;\n                let condition = body.parse::<syn::Expr>()?;\n                Some(condition)\n            } else {\n                None\n            };\n\n            body.parse::<Token![=>]>()?;\n\n            let (r, block) = if body.peek(token::Brace) {\n                let block;\n                syn::braced!(block in body);\n\n                let parser = Quote::new(self.cx);\n                parser.parse(&block)?\n            } else if body.peek(token::Paren) {\n                let block;\n                let paren = syn::parenthesized!(block in body);\n\n                Quote::new(self.cx)\n                    .with_span(paren.span.span())?\n                    .parse(&block)?\n            } else {\n                let parser = Quote::new_until_comma(self.cx);\n                parser.parse(&body)?\n            };\n\n            req.merge_with(r);\n\n            arms.push(MatchArm {\n                attr,\n                pattern,\n                condition,\n                block,\n            });\n\n            if body.peek(Token![,]) {\n                body.parse::<Token![,]>()?;\n            }\n        }\n\n        Ok((req, Ast::Match { condition, arms }))\n    }\n\n    fn parse_let(&self, input: ParseStream) -> Result<(Requirements, Ast)> {\n        input.parse::<Token![let]>()?;\n\n        let req = Requirements::default();\n\n        let name = syn::Pat::parse_single(input)?;\n        input.parse::<Token![=]>()?;\n        let expr = syn::Expr::parse_without_eager_brace(input)?;\n\n        let ast = Ast::Let { name, expr };\n\n        Ok((req, ast))\n    }\n\n    /// Parse evaluation: `[*]<binding> => <expr>`.\n    fn parse_scope(&self, input: ParseStream) -> Result<Ast> {\n        input.parse::<Token![ref]>()?;\n\n        let binding = if input.peek(Token![_]) {\n            input.parse::<Token![_]>()?;\n            None\n        } else {\n            Some(input.parse()?)\n        };\n\n        let content;\n\n        let content = if input.peek(token::Brace) {\n            syn::braced!(content in input);\n            &content\n        } else {\n            input.parse::<Token![=>]>()?;\n            input\n        };\n\n        Ok(Ast::Scope {\n            binding,\n            content: content.parse()?,\n        })\n    }\n\n    fn parse_expression(&mut self, encoder: &mut Encoder, input: ParseStream) -> Result<()> {\n        let start = input.parse::<Token![$]>()?.span();\n\n        // Single identifier without quoting.\n        if !input.peek(token::Paren) {\n            let ident = input.parse::<syn::Ident>()?;\n            let cursor = self.buf.join(start, ident.span())?;\n\n            encoder.encode(cursor, Ast::EvalIdent { ident })?;\n            return Ok(());\n        }\n\n        let scope;\n        let outer = syn::parenthesized!(scope in input);\n\n        let cursor = self.buf.join(start, outer.span.span())?;\n\n        let ast = if scope.peek(Token![if]) {\n            let (req, ast) = self.parse_condition(&scope)?;\n            encoder.requirements.merge_with(req);\n            ast\n        } else if scope.peek(Token![for]) {\n            let (req, ast) = self.parse_loop(&scope)?;\n            encoder.requirements.merge_with(req);\n            ast\n        } else if scope.peek(Token![match]) {\n            let (req, ast) = self.parse_match(&scope)?;\n            encoder.requirements.merge_with(req);\n            ast\n        } else if scope.peek(Token![let]) {\n            let (req, ast) = self.parse_let(&scope)?;\n            encoder.requirements.merge_with(req);\n            ast\n        } else if scope.peek(Token![ref]) {\n            self.parse_scope(&scope)?\n        } else if crate::string_parser::is_lit_str_opt(scope.fork())? {\n            let string = scope.parse::<syn::LitStr>()?.value();\n            Ast::Literal { string }\n        } else {\n            Ast::Eval {\n                expr: scope.parse()?,\n            }\n        };\n\n        encoder.encode(cursor, ast)?;\n        Ok(())\n    }\n\n    fn parse_inner(\n        &mut self,\n        encoder: &mut Encoder,\n        input: ParseStream,\n        group_depth: usize,\n    ) -> Result<()> {\n        while !input.is_empty() {\n            if group_depth == 0 && self.until_comma && input.peek(Token![,]) {\n                break;\n            }\n\n            // Escape sequence.\n            if input.peek(Token![$]) && input.peek2(Token![$]) {\n                let [a] = input.parse::<Token![$]>()?.spans;\n                let [b] = input.parse::<Token![$]>()?.spans;\n\n                let cursor = self.buf.join(a, b)?;\n                let mut punct = Punct::new('$', Spacing::Joint);\n                punct.set_span(cursor.span);\n                encoder.encode(cursor, Ast::Tree { tt: punct.into() })?;\n                continue;\n            }\n\n            if let Some((name, content, [start, end])) = parse_internal_function(input)? {\n                match (name.as_literal_name(), content) {\n                    (literal_name @ LiteralName::Ident(\"str\"), None) => {\n                        return Err(syn::Error::new(\n                            name.span(),\n                            format!(\"Function `{literal_name}` expects content, like: $[{literal_name}](<content>)\"),\n                        ));\n                    }\n                    (LiteralName::Ident(\"str\"), Some(content)) => {\n                        let parser = StringParser::new(self.cx, &self.buf, end)?;\n\n                        let (options, r, stream) = parser.parse(&content)?;\n                        encoder.requirements.merge_with(r);\n\n                        let cursor = self.buf.join(start, end)?;\n\n                        encoder.encode(\n                            cursor,\n                            Ast::String {\n                                has_eval: options.has_eval.get(),\n                                stream,\n                            },\n                        )?;\n                    }\n                    (LiteralName::Char(c), content) => {\n                        let control = match Control::from_char(name.span(), c) {\n                            Some(control) => control,\n                            None => {\n                                return Err(syn::Error::new(name.span(), format!(\"Unsupported control {c:?}, expected one of: '\\\\n', '\\r', ' '\")));\n                            }\n                        };\n\n                        if let Some(content) = content {\n                            return Err(syn::Error::new(\n                                content.span(),\n                                format!(\"Control {c:?} does not expect an argument\"),\n                            ));\n                        }\n\n                        let cursor = self.buf.join(start.span(), end.span())?;\n                        encoder.encode(cursor, Ast::Control { control })?;\n                    }\n                    (LiteralName::Ident(string), _) => {\n                        return Err(syn::Error::new(\n                            name.span(),\n                            format!(\"Unsupported function `{string}`, expected one of: str\"),\n                        ));\n                    }\n                }\n\n                continue;\n            }\n\n            let start_expression = input.peek2(token::Paren) || input.peek2(syn::Ident);\n\n            if input.peek(Token![$]) && start_expression {\n                self.parse_expression(encoder, input)?;\n                continue;\n            }\n\n            if input.peek(syn::LitStr) {\n                let s = input.parse::<syn::LitStr>()?;\n                let cursor = self.buf.cursor(s.span())?;\n                encoder.encode(cursor, Ast::Quoted { s })?;\n                continue;\n            }\n\n            // Test for different forms of groups and recurse if necessary.\n            if input.peek(token::Brace) {\n                let content;\n                let braces = syn::braced!(content in input);\n                self.parse_group(\n                    encoder,\n                    Delimiter::Brace,\n                    braces.span.span(),\n                    &content,\n                    group_depth,\n                )?;\n                continue;\n            }\n\n            if input.peek(token::Paren) {\n                let content;\n                let braces = syn::parenthesized!(content in input);\n                self.parse_group(\n                    encoder,\n                    Delimiter::Parenthesis,\n                    braces.span.span(),\n                    &content,\n                    group_depth,\n                )?;\n                continue;\n            }\n\n            if input.peek(token::Bracket) {\n                let content;\n                let braces = syn::bracketed!(content in input);\n                self.parse_group(\n                    encoder,\n                    Delimiter::Bracket,\n                    braces.span.span(),\n                    &content,\n                    group_depth,\n                )?;\n                continue;\n            }\n\n            let tt: TokenTree = input.parse()?;\n            let cursor = self.buf.cursor(tt.span())?;\n            encoder.encode(cursor, Ast::Tree { tt })?;\n        }\n\n        Ok(())\n    }\n\n    fn parse_group(\n        &mut self,\n        encoder: &mut Encoder,\n        delimiter: Delimiter,\n        span: Span,\n        input: ParseStream,\n        group_depth: usize,\n    ) -> Result<()> {\n        let cursor = self.buf.cursor(span)?;\n\n        encoder.encode(cursor.first_character(), Ast::DelimiterOpen { delimiter })?;\n\n        self.parse_inner(encoder, input, group_depth + 1)?;\n\n        encoder.encode(cursor.last_character(), Ast::DelimiterClose { delimiter })?;\n\n        Ok(())\n    }\n}\n\n/// Parse an internal function of the form:\n///\n/// ```text\n/// $[<name>](<content>)\n/// ```\n///\n/// The `(<content>)` part is optional, and if absent the internal function is\n/// known as a \"control function\", like `$[' ']`.\npub(crate) fn parse_internal_function<'a>(\n    input: &'a ParseBuffer,\n) -> Result<Option<(Name, Option<ParseBuffer<'a>>, [Span; 2])>> {\n    // Custom function call.\n    if !(input.peek(Token![$]) && input.peek2(token::Bracket)) {\n        return Ok(None);\n    }\n\n    let start = input.parse::<Token![$]>()?;\n\n    let function;\n    let brackets = syn::bracketed!(function in input);\n\n    let name = if function.peek(Token![const]) {\n        Name::Const(function.parse()?)\n    } else if function.peek(syn::LitChar) {\n        let c = function.parse::<syn::LitChar>()?;\n        Name::Char(c.value())\n    } else {\n        let ident = function.parse::<syn::Ident>()?;\n        Name::Ident(ident.to_string())\n    };\n\n    if !function.is_empty() {\n        return Err(function.error(\"expected nothing after function identifier\"));\n    }\n\n    let (content, end) = if input.peek(token::Paren) {\n        let content;\n        let paren = syn::parenthesized!(content in input);\n        (Some(content), paren.span)\n    } else {\n        (None, brackets.span)\n    };\n\n    Ok(Some((name, content, [start.span(), end.span()])))\n}\n"
  },
  {
    "path": "genco-macros/src/quote_fn.rs",
    "content": "use proc_macro2::TokenStream;\nuse syn::parse::{Parse, ParseStream};\nuse syn::Result;\n\nuse crate::Ctxt;\n\npub(crate) struct QuoteFn {\n    pub(crate) stream: TokenStream,\n}\n\nimpl Parse for QuoteFn {\n    fn parse(input: ParseStream) -> Result<Self> {\n        let cx = Ctxt::default();\n\n        let parser = crate::quote::Quote::new(&cx);\n        let (req, output) = parser.parse(input)?;\n\n        let check = req.into_check(&cx.receiver);\n\n        let Ctxt { receiver, module } = &cx;\n\n        let stream = q::quote! {\n            #module::tokens::from_fn(move |#receiver| {\n                #output\n                #check\n            })\n        };\n\n        Ok(Self { stream })\n    }\n}\n"
  },
  {
    "path": "genco-macros/src/quote_in.rs",
    "content": "use proc_macro2::TokenStream;\nuse syn::parse::{Parse, ParseStream};\nuse syn::spanned::Spanned as _;\nuse syn::{Result, Token};\n\nuse crate::Ctxt;\n\npub(crate) struct QuoteIn {\n    pub(crate) stream: TokenStream,\n}\n\nimpl Parse for QuoteIn {\n    fn parse(input: ParseStream) -> Result<Self> {\n        // Input expression, assign to a variable.\n        let expr = input.parse::<syn::Expr>()?;\n        input.parse::<Token![=>]>()?;\n\n        let cx = Ctxt::default();\n\n        let parser = crate::quote::Quote::new(&cx);\n        let (req, output) = parser.parse(input)?;\n\n        let check = req.into_check(&cx.receiver);\n\n        let Ctxt { receiver, module } = &cx;\n\n        // Give the assignment its own span to improve diagnostics.\n        let assign_mut = q::quote_spanned! { expr.span() =>\n            let #receiver: &mut #module::tokens::Tokens<_> = &mut #expr;\n        };\n\n        let stream = q::quote! {{\n            #assign_mut\n            #output\n            #check\n        }};\n\n        Ok(Self { stream })\n    }\n}\n"
  },
  {
    "path": "genco-macros/src/requirements.rs",
    "content": "use proc_macro2::TokenStream;\n/// Language requirements for token stream.\n#[derive(Debug, Default, Clone, Copy)]\npub(crate) struct Requirements {\n    pub(crate) lang_supports_eval: bool,\n}\n\nimpl Requirements {\n    /// Merge this requirements with another.\n    pub fn merge_with(&mut self, other: Self) {\n        self.lang_supports_eval |= other.lang_supports_eval;\n    }\n\n    /// Generate checks for requirements.\n    pub fn into_check(self, receiver: &syn::Ident) -> TokenStream {\n        let lang_supports_eval = if self.lang_supports_eval {\n            Some(q::quote!(#receiver.lang_supports_eval();))\n        } else {\n            None\n        };\n\n        q::quote! {\n            #lang_supports_eval\n        }\n    }\n}\n"
  },
  {
    "path": "genco-macros/src/static_buffer.rs",
    "content": "use proc_macro2::{Span, TokenStream};\n\nuse crate::Ctxt;\n\n/// Buffer used to resolve static items.\npub(crate) struct StaticBuffer<'a> {\n    cx: &'a Ctxt,\n    buffer: String,\n}\n\nimpl<'a> StaticBuffer<'a> {\n    /// Construct a new line buffer.\n    pub(crate) fn new(cx: &'a Ctxt) -> Self {\n        Self {\n            cx,\n            buffer: String::new(),\n        }\n    }\n\n    /// Push the given character to the line buffer.\n    pub(crate) fn push(&mut self, c: char) {\n        self.buffer.push(c);\n    }\n\n    /// Push the given string to the line buffer.\n    pub(crate) fn push_str(&mut self, s: &str) {\n        self.buffer.push_str(s);\n    }\n\n    /// Flush the line buffer if necessary.\n    pub(crate) fn flush(&mut self, tokens: &mut TokenStream) {\n        if !self.buffer.is_empty() {\n            let Ctxt { receiver, module } = self.cx;\n\n            let s = syn::LitStr::new(&self.buffer, Span::call_site());\n            tokens.extend(q::quote!(#receiver.append(#module::__priv::static_(#s));));\n            self.buffer.clear();\n        }\n    }\n}\n"
  },
  {
    "path": "genco-macros/src/string_parser.rs",
    "content": "//! Helper to parse quoted strings.\n\nuse core::cell::{Cell, RefCell};\nuse core::fmt::Write;\n\nuse proc_macro2::{Span, TokenStream, TokenTree};\nuse syn::parse::{ParseBuffer, ParseStream};\nuse syn::spanned::Spanned;\nuse syn::token;\nuse syn::Result;\n\nuse crate::ast::LiteralName;\nuse crate::fake::{Buf, LineColumn};\nuse crate::quote::parse_internal_function;\nuse crate::requirements::Requirements;\nuse crate::Ctxt;\n\n/// Options for the parsed string.\n#[derive(Default)]\npub(crate) struct Options {\n    /// If the parsed string has any evaluation statements in it.\n    pub(crate) has_eval: Cell<bool>,\n}\n\nfn adjust_start(start: LineColumn) -> LineColumn {\n    LineColumn {\n        line: start.line,\n        column: start.column + 1,\n    }\n}\n\nfn adjust_end(end: LineColumn) -> LineColumn {\n    LineColumn {\n        line: end.line,\n        column: end.column.saturating_sub(1),\n    }\n}\n\nstruct Encoder<'a> {\n    cx: &'a Ctxt,\n    span: Span,\n    cursor: Cell<Option<LineColumn>>,\n    count: Cell<usize>,\n    buf: RefCell<String>,\n    stream: RefCell<TokenStream>,\n    pub(crate) options: Options,\n}\n\nimpl<'a> Encoder<'a> {\n    pub fn new(cx: &'a Ctxt, cursor: LineColumn, span: Span) -> Self {\n        Self {\n            cx,\n            span,\n            cursor: Cell::new(Some(cursor)),\n            count: Cell::new(0),\n            buf: RefCell::new(String::new()),\n            stream: RefCell::new(TokenStream::new()),\n            options: Options::default(),\n        }\n    }\n\n    pub(crate) fn finalize(self, end: LineColumn) -> Result<(Options, TokenStream)> {\n        self.flush(Some(end), None)?;\n        Ok((self.options, self.stream.into_inner()))\n    }\n\n    /// Encode a single character and replace the cursor with the given\n    /// location.\n    pub(crate) fn encode_char(&self, c: char, from: LineColumn, to: LineColumn) -> Result<()> {\n        self.flush_whitespace(Some(from), Some(to))?;\n        self.buf.borrow_mut().push(c);\n        self.cursor.set(Some(to));\n        Ok(())\n    }\n\n    /// Encode a string directly to the static buffer as an optimization.\n    pub(crate) fn encode_str(\n        &self,\n        s: &str,\n        from: LineColumn,\n        to: Option<LineColumn>,\n    ) -> Result<()> {\n        self.flush_whitespace(Some(from), to)?;\n        self.buf.borrow_mut().push_str(s);\n        Ok(())\n    }\n\n    /// Eval the given identifier.\n    pub(crate) fn eval_ident(\n        &self,\n        ident: &syn::Ident,\n        from: LineColumn,\n        to: Option<LineColumn>,\n    ) -> Result<()> {\n        let Ctxt { receiver, module } = self.cx;\n\n        self.flush(Some(from), to)?;\n\n        let ident = syn::LitStr::new(&ident.to_string(), ident.span());\n\n        self.stream.borrow_mut().extend(q::quote! {\n            #receiver.append(#module::__priv::open_eval());\n            #receiver.append(#module::__priv::static_(#ident));\n            #receiver.append(#module::__priv::close_eval());\n        });\n\n        self.options.has_eval.set(true);\n        Ok(())\n    }\n\n    /// Eval the given expression.\n    pub(crate) fn eval_stream(\n        &self,\n        expr: TokenStream,\n        from: LineColumn,\n        to: Option<LineColumn>,\n    ) -> Result<()> {\n        self.flush(Some(from), to)?;\n\n        let Ctxt { receiver, module } = self.cx;\n\n        self.stream.borrow_mut().extend(q::quote! {\n            #receiver.append(#module::__priv::open_eval());\n            #expr\n            #receiver.append(#module::__priv::close_eval());\n        });\n\n        self.options.has_eval.set(true);\n        Ok(())\n    }\n\n    /// Extend the content of the string with the given raw stream.\n    pub(crate) fn raw_expr(\n        &self,\n        expr: &syn::Expr,\n        from: LineColumn,\n        to: Option<LineColumn>,\n    ) -> Result<()> {\n        self.flush(Some(from), to)?;\n\n        let Ctxt { receiver, .. } = self.cx;\n\n        self.stream.borrow_mut().extend(q::quote! {\n            #receiver.append(#expr);\n        });\n        Ok(())\n    }\n\n    pub(crate) fn extend_tt(\n        &self,\n        tt: &TokenTree,\n        from: LineColumn,\n        to: Option<LineColumn>,\n    ) -> Result<()> {\n        self.flush_whitespace(Some(from), to)?;\n        write!(self.buf.borrow_mut(), \"{tt}\").unwrap();\n        Ok(())\n    }\n\n    /// Flush the outgoing buffer.\n    pub fn flush(&self, from: Option<LineColumn>, to: Option<LineColumn>) -> Result<()> {\n        let Ctxt { receiver, module } = self.cx;\n\n        self.flush_whitespace(from, to)?;\n\n        let lit = {\n            let buf = self.buf.borrow();\n\n            if buf.is_empty() {\n                return Ok(());\n            }\n\n            syn::LitStr::new(buf.as_str(), self.span)\n        };\n\n        self.count.set(self.count.get().wrapping_add(1));\n\n        self.stream.borrow_mut().extend(q::quote! {\n            #receiver.append(#module::__priv::static_(#lit));\n        });\n\n        self.buf.borrow_mut().clear();\n        Ok(())\n    }\n\n    /// Flush the outgoing buffer.\n    pub(crate) fn flush_whitespace(\n        &self,\n        from: Option<LineColumn>,\n        to: Option<LineColumn>,\n    ) -> Result<()> {\n        if let (Some(from), Some(cursor)) = (from, self.cursor.get()) {\n            if cursor.line != from.line {\n                return Err(syn::Error::new(\n                    self.span,\n                    \"string interpolations may not contain line breaks\",\n                ));\n            }\n\n            for _ in 0..from.column.saturating_sub(cursor.column) {\n                self.buf.borrow_mut().push(' ');\n            }\n        }\n\n        self.cursor.set(to);\n        Ok(())\n    }\n}\n\npub struct StringParser<'a> {\n    cx: &'a Ctxt,\n    buf: &'a Buf,\n    start: LineColumn,\n    end: LineColumn,\n    span: Span,\n}\n\nimpl<'a> StringParser<'a> {\n    pub(crate) fn new(cx: &'a Ctxt, buf: &'a Buf, span: Span) -> syn::Result<Self> {\n        let cursor = buf.cursor(span)?;\n\n        Ok(Self {\n            cx,\n            buf,\n            // Note: adjusting span since we expect the quoted string to be\n            // withing a block, where the interior span is one character pulled\n            // in in each direction.\n            start: adjust_start(cursor.start),\n            end: adjust_end(cursor.end),\n            span,\n        })\n    }\n\n    pub(crate) fn parse(self, input: ParseStream) -> Result<(Options, Requirements, TokenStream)> {\n        let mut requirements = Requirements::default();\n        let encoder = Encoder::new(self.cx, self.start, self.span);\n\n        while !input.is_empty() {\n            if input.peek(syn::Token![$]) && input.peek2(syn::Token![$]) {\n                let start = input.parse::<syn::Token![$]>()?;\n                let escape = input.parse::<syn::Token![$]>()?;\n                let start = self.buf.cursor(start.span())?;\n                let escape = self.buf.cursor(escape.span())?;\n                encoder.encode_char('$', start.start, escape.end)?;\n                continue;\n            }\n\n            if input.peek(syn::Token![$]) {\n                if let Some((name, content, [start, end])) = parse_internal_function(input)? {\n                    match (name.as_literal_name(), content) {\n                        (LiteralName::Ident(\"const\"), Some(content)) => {\n                            let start = self.buf.cursor(start)?;\n                            let end = self.buf.cursor(end)?;\n\n                            // Compile-time string optimization. A single,\n                            // enclosed literal string can be added to the\n                            // existing static buffer.\n                            if is_lit_str_opt(content.fork())? {\n                                let s = content.parse::<syn::LitStr>()?;\n                                encoder.encode_str(&s.value(), start.start, Some(end.end))?;\n                            } else {\n                                let expr = content.parse::<syn::Expr>()?;\n                                encoder.raw_expr(&expr, start.start, Some(end.end))?;\n                            }\n                        }\n                        (literal_name, _) => {\n                            return Err(syn::Error::new(\n                                name.span(),\n                                format!(\n                                    \"Unsupported [str] function {literal_name}, expected one of: const\"\n                                ),\n                            ));\n                        }\n                    }\n                } else {\n                    let dollar = input.parse::<syn::Token![$]>()?;\n                    let [start] = dollar.spans;\n\n                    if !input.peek(token::Paren) {\n                        let ident = input.parse::<syn::Ident>()?;\n                        let start = self.buf.cursor(start.span())?;\n                        let end = self.buf.cursor(ident.span())?.end;\n                        encoder.eval_ident(&ident, start.start, Some(end))?;\n                        continue;\n                    }\n\n                    let content;\n                    let end = syn::parenthesized!(content in input).span;\n\n                    let (req, stream) = crate::quote::Quote::new(self.cx)\n                        .with_span(content.span())?\n                        .parse(&content)?;\n                    requirements.merge_with(req);\n                    let start = self.buf.cursor(start.span())?;\n                    let end = self.buf.cursor(end.span())?;\n                    encoder.eval_stream(stream, start.start, Some(end.end))?;\n                }\n\n                continue;\n            }\n\n            let tt = input.parse::<TokenTree>()?;\n            let cursor = self.buf.cursor(tt.span())?;\n            encoder.extend_tt(&tt, cursor.start, Some(cursor.end))?;\n        }\n\n        let (options, stream) = encoder.finalize(self.end)?;\n        Ok((options, requirements, stream))\n    }\n}\n\npub(crate) fn is_lit_str_opt(content: ParseBuffer<'_>) -> syn::Result<bool> {\n    if content.parse::<Option<syn::LitStr>>()?.is_none() {\n        return Ok(false);\n    }\n\n    Ok(content.is_empty())\n}\n"
  },
  {
    "path": "src/fmt/config.rs",
    "content": "use crate::lang::Lang;\n\n/// Indentation configuration.\n///\n/// ```\n/// use genco::prelude::*;\n/// use genco::fmt;\n///\n/// let tokens: rust::Tokens = quote! {\n///     fn foo() -> u32 {\n///         42u32\n///     }\n/// };\n///\n/// let mut w = fmt::VecWriter::new();\n///\n/// let fmt = fmt::Config::from_lang::<Rust>()\n///     .with_indentation(fmt::Indentation::Tab);\n/// let config = rust::Config::default();\n///\n/// tokens.format_file(&mut w.as_formatter(&fmt), &config)?;\n///\n/// assert_eq! {\n///     vec![\n///         \"fn foo() -> u32 {\",\n///         \"\\t42u32\",\n///         \"}\",\n///     ],\n///     w.into_vec(),\n/// };\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n#[derive(Debug, Clone, Copy)]\npub enum Indentation {\n    /// Each indentation is the given number of spaces.\n    Space(usize),\n    /// Each indentation is a tab.\n    Tab,\n}\n\n/// Configuration to use for formatting output.\n#[derive(Debug, Clone)]\npub struct Config {\n    /// Indentation level to use.\n    pub(super) indentation: Indentation,\n    /// What to use as a newline.\n    pub(super) newline: &'static str,\n}\n\nimpl Config {\n    /// Construct a new default formatter configuration for the specified\n    /// language.\n    pub fn from_lang<L>() -> Self\n    where\n        L: Lang,\n    {\n        Self {\n            indentation: L::default_indentation(),\n            newline: \"\\n\",\n        }\n    }\n\n    /// Modify indentation to use.\n    pub fn with_indentation(self, indentation: Indentation) -> Self {\n        Self {\n            indentation,\n            ..self\n        }\n    }\n\n    /// Set what to use as newline.\n    pub fn with_newline(self, newline: &'static str) -> Self {\n        Self { newline, ..self }\n    }\n}\n"
  },
  {
    "path": "src/fmt/cursor.rs",
    "content": "use crate::fmt;\nuse crate::tokens::{Item, Kind};\n\n/// Trait for peeking items.\npub(super) trait Parse {\n    type Output: ?Sized;\n\n    /// Parse the given item into its output.\n    fn parse(item: &Item) -> fmt::Result<&Self::Output>;\n\n    /// Test if the peek matches the given item.\n    fn peek(item: &Item) -> bool;\n}\n\n/// Peek for a literal.\npub(super) struct Literal(());\n\nimpl Parse for Literal {\n    type Output = str;\n\n    #[inline]\n    fn peek(item: &Item) -> bool {\n        matches!(item.kind, Kind::Literal(..))\n    }\n\n    #[inline]\n    fn parse(item: &Item) -> fmt::Result<&Self::Output> {\n        match &item.kind {\n            Kind::Literal(s) => Ok(s),\n            _ => Err(core::fmt::Error),\n        }\n    }\n}\n\n/// Peek for an eval marker.\npub(super) struct CloseEval(());\n\nimpl Parse for CloseEval {\n    type Output = ();\n\n    #[inline]\n    fn peek(item: &Item) -> bool {\n        matches!(item.kind, Kind::CloseEval)\n    }\n\n    #[inline]\n    fn parse(item: &Item) -> fmt::Result<&Self::Output> {\n        match &item.kind {\n            Kind::CloseEval => Ok(&()),\n            _ => Err(core::fmt::Error),\n        }\n    }\n}\n\n/// Parser helper.\npub(super) struct Cursor<'a, T> {\n    lang: &'a [T],\n    items: &'a [Item],\n}\n\nimpl<'a, T> Cursor<'a, T> {\n    /// Construct a new cursor.\n    pub(super) fn new(lang: &'a [T], items: &'a [Item]) -> Self {\n        Self { lang, items }\n    }\n\n    /// Get a language item by index.\n    pub(super) fn lang(&self, index: usize) -> fmt::Result<&'a T> {\n        self.lang.get(index).ok_or(core::fmt::Error)\n    }\n\n    /// Get the next item.\n    pub(super) fn next(&mut self) -> Option<&Item> {\n        let (first, rest) = self.items.split_first()?;\n        self.items = rest;\n        Some(first)\n    }\n\n    #[inline]\n    pub(super) fn peek<P>(&self) -> bool\n    where\n        P: Parse,\n    {\n        if let Some(item) = self.items.first() {\n            P::peek(item)\n        } else {\n            false\n        }\n    }\n\n    #[inline]\n    pub(super) fn peek1<P>(&self) -> bool\n    where\n        P: Parse,\n    {\n        if let Some(item) = self.items.get(1) {\n            P::peek(item)\n        } else {\n            false\n        }\n    }\n\n    #[inline]\n    pub(super) fn parse<P>(&mut self) -> fmt::Result<&P::Output>\n    where\n        P: Parse,\n    {\n        let item = self.next().ok_or(core::fmt::Error)?;\n        P::parse(item)\n    }\n}\n"
  },
  {
    "path": "src/fmt/fmt_writer.rs",
    "content": "use crate::fmt;\n\n/// Helper struct to format a token stream to an underlying writer implementing\n/// [fmt::Write][std::fmt::Write].\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n/// use genco::fmt;\n///\n/// let map = rust::import(\"std::collections\", \"HashMap\");\n///\n/// let tokens: rust::Tokens = quote! {\n///     let mut m = $map::new();\n///     m.insert(1u32, 2u32);\n/// };\n///\n/// // Note: String implements std::fmt::Write\n/// let mut w = fmt::FmtWriter::new(String::new());\n///\n/// let fmt = fmt::Config::from_lang::<Rust>();\n///\n/// let config = rust::Config::default();\n/// // Default format state for Rust.\n/// let format = rust::Format::default();\n///\n/// tokens.format(&mut w.as_formatter(&fmt), &config, &format)?;\n///\n/// let string = w.into_inner();\n///\n/// assert_eq!(\"let mut m = HashMap::new();\\nm.insert(1u32, 2u32);\", string);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub struct FmtWriter<W>\nwhere\n    W: core::fmt::Write,\n{\n    writer: W,\n}\n\nimpl<W> FmtWriter<W>\nwhere\n    W: core::fmt::Write,\n{\n    /// Construct a new line writer from the underlying writer.\n    pub fn new(writer: W) -> Self {\n        Self { writer }\n    }\n\n    /// Convert into a formatter.\n    pub fn as_formatter<'a>(&'a mut self, config: &'a fmt::Config) -> fmt::Formatter<'a> {\n        fmt::Formatter::new(self, config)\n    }\n\n    /// Convert into underlying writer.\n    pub fn into_inner(self) -> W {\n        self.writer\n    }\n}\n\nimpl<W> core::fmt::Write for FmtWriter<W>\nwhere\n    W: core::fmt::Write,\n{\n    #[inline(always)]\n    fn write_char(&mut self, c: char) -> core::fmt::Result {\n        self.writer.write_char(c)\n    }\n\n    #[inline(always)]\n    fn write_str(&mut self, s: &str) -> core::fmt::Result {\n        self.writer.write_str(s)\n    }\n}\n\nimpl<W> fmt::Write for FmtWriter<W>\nwhere\n    W: core::fmt::Write,\n{\n    #[inline(always)]\n    fn write_line(&mut self, config: &fmt::Config) -> fmt::Result {\n        self.writer.write_str(config.newline)\n    }\n}\n"
  },
  {
    "path": "src/fmt/formatter.rs",
    "content": "use core::mem;\n\nuse alloc::string::String;\n\nuse crate::fmt;\nuse crate::fmt::config::{Config, Indentation};\nuse crate::fmt::cursor::{self, Cursor};\nuse crate::lang::Lang;\nuse crate::tokens::{Item, Kind};\n\n/// Buffer used as indentation source.\nstatic SPACES: &str = \"                                                                                                    \";\n\nstatic TABS: &str =\n    \"\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\";\n\n#[derive(Default, Debug, Clone, Copy)]\nenum Whitespace {\n    #[default]\n    None,\n    Initial,\n    Push,\n    Line,\n}\n\nimpl Whitespace {\n    /// Convert into an indentation level.\n    ///\n    /// If we return `None`, no indentation nor lines should be written since we\n    /// are at the initial stage of the file.\n    fn into_indent(self) -> Option<usize> {\n        match self {\n            Self::Initial => Some(0),\n            Self::Push => Some(1),\n            Self::Line => Some(2),\n            Self::None => None,\n        }\n    }\n}\n\n/// Token stream formatter. Keeps track of everything we need to know in order\n/// to enforce genco's indentation and whitespace rules.\npub struct Formatter<'a> {\n    write: &'a mut (dyn fmt::Write + 'a),\n    /// Formatter configuration.\n    config: &'a Config,\n    /// How many lines we want to add to the output stream.\n    ///\n    /// This will only be realized if we push non-whitespace.\n    line: Whitespace,\n    /// How many spaces we want to add to the output stream.\n    ///\n    /// This will only be realized if we push non-whitespace, and will be reset\n    /// if a new line is pushed or indentation changes.\n    spaces: usize,\n    /// Current indentation level.\n    indent: i16,\n}\n\nimpl<'a> Formatter<'a> {\n    /// Construct a new formatter.\n    pub(crate) fn new(write: &'a mut (dyn fmt::Write + 'a), config: &'a Config) -> Formatter<'a> {\n        Formatter {\n            write,\n            line: Whitespace::Initial,\n            spaces: 0usize,\n            indent: 0i16,\n            config,\n        }\n    }\n\n    /// Format the given stream of tokens.\n    pub(crate) fn format_items<L>(\n        &mut self,\n        lang: &[L::Item],\n        items: &[Item],\n        config: &L::Config,\n        format: &L::Format,\n    ) -> fmt::Result<()>\n    where\n        L: Lang,\n    {\n        let mut cursor = Cursor::new(lang, items);\n        self.format_cursor::<L>(&mut cursor, config, format, false)\n    }\n\n    /// Forcibly write a line ending, at the end of a file.\n    ///\n    /// This will also reset any whitespace we have pending.\n    pub(crate) fn write_trailing_line(&mut self) -> fmt::Result {\n        self.line = Whitespace::default();\n        self.spaces = 0;\n        self.write.write_trailing_line(self.config)?;\n        Ok(())\n    }\n\n    /// Write the given string.\n    fn write_str(&mut self, s: &str) -> fmt::Result {\n        if !s.is_empty() {\n            self.flush_whitespace()?;\n            self.write.write_str(s)?;\n        }\n\n        Ok(())\n    }\n\n    fn push(&mut self) {\n        self.line = match self.line {\n            Whitespace::Initial => return,\n            Whitespace::Line => return,\n            _ => Whitespace::Push,\n        };\n\n        self.spaces = 0;\n    }\n\n    /// Push a new line.\n    fn line(&mut self) {\n        self.line = match self.line {\n            Whitespace::Initial => return,\n            _ => Whitespace::Line,\n        };\n\n        self.spaces = 0;\n    }\n\n    /// Push a space.\n    fn space(&mut self) {\n        self.spaces += 1;\n    }\n\n    /// Increase indentation level.\n    fn indentation(&mut self, n: i16) {\n        self.push();\n        self.indent += n;\n    }\n\n    /// Internal function for formatting.\n    fn format_cursor<L>(\n        &mut self,\n        cursor: &mut Cursor<'_, L::Item>,\n        config: &L::Config,\n        format: &L::Format,\n        end_on_close_quote: bool,\n    ) -> fmt::Result\n    where\n        L: Lang,\n    {\n        use crate::lang::LangItem as _;\n\n        let mut buf = String::new();\n        let mut stack = smallvec::SmallVec::<[Frame; 4]>::new();\n\n        stack.push(Frame::default());\n\n        while let (Some(item), Some(head)) = (cursor.next(), stack.last_mut()) {\n            let Frame {\n                in_quote,\n                has_eval,\n                end_on_eval,\n            } = head;\n\n            match item.kind {\n                Kind::Indentation(0) => (),\n                Kind::Literal(ref literal) => {\n                    if *in_quote {\n                        L::write_quoted(self, literal)?;\n                    } else {\n                        self.write_str(literal)?;\n                    }\n                }\n                Kind::OpenQuote(e) if !*in_quote => {\n                    *has_eval = e;\n                    *in_quote = true;\n                    L::open_quote(self, config, format, *has_eval)?;\n                }\n                // Warning: slow path which will buffer a string internally.\n                // This is used for expressions like: `$[str](Hello $(quoted(world)))`.\n                //\n                // Evaluating quotes are not supported.\n                Kind::OpenQuote(false) if *in_quote => {\n                    self.quoted_quote::<L>(cursor, &mut buf, config, format)?;\n                    L::write_quoted(self, &buf)?;\n                    buf.clear();\n                }\n                Kind::CloseQuote if end_on_close_quote => {\n                    return Ok(());\n                }\n                Kind::CloseQuote if *in_quote => {\n                    *in_quote = false;\n                    L::close_quote(self, config, format, mem::take(has_eval))?;\n                }\n                Kind::Lang(lang) => {\n                    cursor.lang(lang)?.format(self, config, format)?;\n                }\n                // whitespace below\n                Kind::Push => {\n                    self.push();\n                }\n                Kind::Line => {\n                    self.line();\n                }\n                Kind::Space => {\n                    self.space();\n                }\n                Kind::Indentation(n) => {\n                    self.indentation(n);\n                }\n                Kind::OpenEval if *in_quote => {\n                    if cursor.peek::<cursor::Literal>() && cursor.peek1::<cursor::CloseEval>() {\n                        let literal = cursor.parse::<cursor::Literal>()?;\n                        L::string_eval_literal(self, config, format, literal)?;\n                        cursor.parse::<cursor::CloseEval>()?;\n                    } else {\n                        L::start_string_eval(self, config, format)?;\n\n                        stack.push(Frame {\n                            in_quote: false,\n                            has_eval: false,\n                            end_on_eval: true,\n                        });\n                    }\n                }\n                // Eval are only allowed within quotes.\n                Kind::CloseEval if *end_on_eval => {\n                    L::end_string_eval(self, config, format)?;\n                    stack.pop();\n                }\n                _ => {\n                    // Anything else is an illegal state for formatting.\n                    return Err(core::fmt::Error);\n                }\n            }\n        }\n\n        return Ok(());\n\n        #[derive(Default, Clone)]\n        struct Frame {\n            in_quote: bool,\n            has_eval: bool,\n            end_on_eval: bool,\n        }\n    }\n\n    /// Support for evaluating an interior quote and returning it as a string.\n    fn quoted_quote<L>(\n        &mut self,\n        cursor: &mut Cursor<'_, L::Item>,\n        buf: &mut String,\n        config: &L::Config,\n        format: &L::Format,\n    ) -> fmt::Result<()>\n    where\n        L: Lang,\n    {\n        use crate::fmt::FmtWriter;\n\n        let mut w = FmtWriter::new(buf);\n        let out = &mut Formatter::new(&mut w, self.config);\n        L::open_quote(out, config, format, false)?;\n        out.format_cursor::<L>(cursor, config, format, true)?;\n        L::close_quote(out, config, format, false)?;\n        Ok(())\n    }\n\n    // Realize any pending whitespace just prior to writing a non-whitespace\n    // item.\n    fn flush_whitespace(&mut self) -> fmt::Result {\n        let mut spaces = mem::take(&mut self.spaces);\n\n        if let Some(lines) = mem::take(&mut self.line).into_indent() {\n            for _ in 0..lines {\n                self.write.write_line(self.config)?;\n            }\n\n            let level = i16::max(self.indent, 0) as usize;\n\n            match self.config.indentation {\n                Indentation::Space(n) => {\n                    spaces += level * n;\n                }\n                Indentation::Tab => {\n                    let mut tabs = level;\n\n                    while tabs > 0 {\n                        let len = usize::min(tabs, TABS.len());\n                        self.write.write_str(&TABS[0..len])?;\n                        tabs -= len;\n                    }\n                }\n            }\n        }\n\n        while spaces > 0 {\n            let len = usize::min(spaces, SPACES.len());\n            self.write.write_str(&SPACES[0..len])?;\n            spaces -= len;\n        }\n\n        Ok(())\n    }\n}\n\nimpl core::fmt::Write for Formatter<'_> {\n    fn write_str(&mut self, s: &str) -> fmt::Result {\n        if !s.is_empty() {\n            Formatter::write_str(self, s)?;\n        }\n\n        Ok(())\n    }\n}\n\nimpl core::fmt::Debug for Formatter<'_> {\n    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n        fmt.debug_struct(\"Formatter\")\n            .field(\"line\", &self.line)\n            .field(\"spaces\", &self.spaces)\n            .field(\"indent\", &self.indent)\n            .field(\"config\", self.config)\n            .finish()\n    }\n}\n"
  },
  {
    "path": "src/fmt/io_writer.rs",
    "content": "use std::io;\n\nuse crate::fmt;\n\n/// Helper struct to format a token stream to an underlying writer implementing\n/// [`io::Write`].\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n/// use genco::fmt;\n///\n/// let map = rust::import(\"std::collections\", \"HashMap\");\n///\n/// let tokens: rust::Tokens = quote! {\n///     let mut m = $map::new();\n///     m.insert(1u32, 2u32);\n/// };\n///\n/// // Vec<u8> implements std::io::Write\n/// let mut w = fmt::IoWriter::new(Vec::<u8>::new());\n///\n/// let fmt = fmt::Config::from_lang::<Rust>();\n/// let config = rust::Config::default();\n/// // Default format state for Rust.\n/// let format = rust::Format::default();\n///\n/// tokens.format(&mut w.as_formatter(&fmt), &config, &format)?;\n///\n/// let vector = w.into_inner();\n/// let string = std::str::from_utf8(&vector)?;\n///\n/// assert_eq!(\"let mut m = HashMap::new();\\nm.insert(1u32, 2u32);\", string);\n/// # Ok::<_, anyhow::Error>(())\n/// ```\npub struct IoWriter<W>\nwhere\n    W: io::Write,\n{\n    writer: W,\n}\n\nimpl<W> IoWriter<W>\nwhere\n    W: io::Write,\n{\n    /// Construct a new line writer from the underlying writer.\n    pub fn new(writer: W) -> Self {\n        Self { writer }\n    }\n\n    /// Convert into a formatter.\n    pub fn as_formatter<'a>(&'a mut self, config: &'a fmt::Config) -> fmt::Formatter<'a> {\n        fmt::Formatter::new(self, config)\n    }\n\n    /// Convert into the inner writer.\n    pub fn into_inner(self) -> W {\n        self.writer\n    }\n}\n\nimpl<W> core::fmt::Write for IoWriter<W>\nwhere\n    W: io::Write,\n{\n    #[inline(always)]\n    fn write_char(&mut self, c: char) -> core::fmt::Result {\n        self.writer\n            .write_all(c.encode_utf8(&mut [0; 4]).as_bytes())\n            .map_err(|_| core::fmt::Error)\n    }\n\n    #[inline(always)]\n    fn write_str(&mut self, s: &str) -> core::fmt::Result {\n        self.writer\n            .write_all(s.as_bytes())\n            .map_err(|_| core::fmt::Error)\n    }\n}\n\nimpl<W> fmt::Write for IoWriter<W>\nwhere\n    W: io::Write,\n{\n    #[inline(always)]\n    fn write_line(&mut self, config: &fmt::Config) -> fmt::Result {\n        self.writer\n            .write_all(config.newline.as_bytes())\n            .map_err(|_| core::fmt::Error)\n    }\n}\n"
  },
  {
    "path": "src/fmt/mod.rs",
    "content": "//! Code formatting utilities.\n//!\n//! So you have a token stream and it's time to format it into a\n//! file/string/whatever? You've come to the right place!\n//!\n//! Formatting is done through the following utilities:\n//!\n//! * [fmt::VecWriter][VecWriter] - To write result into a vector.\n//! * [fmt::FmtWriter][FmtWriter] - To write the result into something\n//!   implementing [fmt::Write][std::fmt::Write].\n//! * [fmt::IoWriter][IoWriter]- To write the result into something implementing\n//!   [io::Write][std::io::Write].\n//!\n//! # Examples\n//!\n//! The following is an example, showcasing how you can format directly to\n//! [stdout].\n//!\n//! [stdout]: std::io::stdout\n//!\n//! # Examples\n//!\n//! ```rust,no_run\n//! use genco::prelude::*;\n//! use genco::fmt;\n//!\n//! let map = rust::import(\"std::collections\", \"HashMap\");\n//!\n//! let tokens: rust::Tokens = quote! {\n//!     let mut m = #map::new();\n//!     m.insert(1u32, 2u32);\n//! };\n//!\n//! let stdout = std::io::stdout();\n//! let mut w = fmt::IoWriter::new(stdout.lock());\n//!\n//! let fmt = fmt::Config::from_lang::<Rust>()\n//!     .with_indentation(fmt::Indentation::Space(2));\n//! let config = rust::Config::default();\n//!\n//! // Default format state for Rust.\n//! let format = rust::Format::default();\n//!\n//! tokens.format(&mut w.as_formatter(&fmt), &config, &format)?;\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\nmod config;\nmod cursor;\nmod fmt_writer;\nmod formatter;\n#[cfg(feature = \"std\")]\nmod io_writer;\nmod vec_writer;\n\npub use self::config::{Config, Indentation};\npub use self::fmt_writer::FmtWriter;\npub use self::formatter::Formatter;\n#[cfg(feature = \"std\")]\npub use self::io_writer::IoWriter;\npub use self::vec_writer::VecWriter;\n\n/// Result type for the `fmt` module.\npub type Result<T = ()> = core::result::Result<T, core::fmt::Error>;\n/// Error for the `fmt` module.\npub type Error = core::fmt::Error;\n\n/// Trait that defines a line writer.\npub(crate) trait Write: core::fmt::Write {\n    /// Implement for writing a line.\n    fn write_line(&mut self, config: &Config) -> Result;\n\n    /// Implement for writing the trailing line ending of the file.\n    #[inline]\n    fn write_trailing_line(&mut self, config: &Config) -> Result {\n        self.write_line(config)\n    }\n}\n"
  },
  {
    "path": "src/fmt/vec_writer.rs",
    "content": "use alloc::string::String;\nuse alloc::vec::Vec;\n\nuse crate::fmt;\n\n/// Helper struct to format a token stream as a vector of strings.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n/// use genco::fmt;\n///\n/// let map = rust::import(\"std::collections\", \"HashMap\");\n///\n/// let tokens: rust::Tokens = quote! {\n///     let mut m = $map::new();\n///     m.insert(1u32, 2u32);\n/// };\n///\n/// // Note: String implements std::fmt::Write\n/// let mut w = fmt::VecWriter::new();\n///\n/// let fmt = fmt::Config::from_lang::<Rust>();\n///\n/// let config = rust::Config::default();\n/// // Default format state for Rust.\n/// let format = rust::Format::default();\n///\n/// tokens.format(&mut w.as_formatter(&fmt), &config, &format)?;\n///\n/// let vec = w.into_vec();\n///\n/// assert_eq!(\n///     vec![\n///         \"let mut m = HashMap::new();\",\n///         \"m.insert(1u32, 2u32);\",\n///     ],\n///     vec\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n#[derive(Default)]\npub struct VecWriter {\n    line_buffer: String,\n    target: Vec<String>,\n}\n\nimpl VecWriter {\n    /// Construct a new writer to a vector.\n    pub fn new() -> Self {\n        Self::default()\n    }\n\n    /// Convert into a formatter.\n    pub fn as_formatter<'a>(&'a mut self, config: &'a fmt::Config) -> fmt::Formatter<'a> {\n        fmt::Formatter::new(self, config)\n    }\n\n    /// Convert into a vector.\n    pub fn into_vec(mut self) -> Vec<String> {\n        self.target.push(self.line_buffer);\n        self.target\n    }\n}\n\nimpl core::fmt::Write for VecWriter {\n    #[inline(always)]\n    fn write_char(&mut self, c: char) -> core::fmt::Result {\n        self.line_buffer.write_char(c)\n    }\n\n    #[inline(always)]\n    fn write_str(&mut self, s: &str) -> core::fmt::Result {\n        self.line_buffer.write_str(s)\n    }\n}\n\nimpl fmt::Write for VecWriter {\n    #[inline(always)]\n    fn write_line(&mut self, _: &fmt::Config) -> fmt::Result {\n        self.target.push(self.line_buffer.clone());\n        self.line_buffer.clear();\n        Ok(())\n    }\n\n    // NB: trailing line is ignored for vector writer.\n    fn write_trailing_line(&mut self, _: &fmt::Config) -> fmt::Result {\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "src/lang/c.rs",
    "content": "//! Specialization for C code generation.\n\nuse core::fmt::Write as _;\n\nuse alloc::collections::BTreeSet;\n\nuse crate as genco;\nuse crate::fmt;\nuse crate::quote_in;\nuse crate::tokens::{quoted, ItemStr};\n\n/// Tokens container specialization for C.\npub type Tokens = crate::Tokens<C>;\n\nimpl_lang! {\n    /// Language specialization for C.\n    pub C {\n        type Config = Config;\n        type Format = Format;\n        type Item = Import;\n\n        fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n            super::c_family_write_quoted(out, input)\n        }\n\n        fn format_file(\n            tokens: &Tokens,\n            out: &mut fmt::Formatter<'_>,\n            config: &Self::Config,\n        ) -> fmt::Result {\n            let mut header = Tokens::new();\n\n            Self::imports(&mut header, tokens);\n            let format = Format::default();\n            header.format(out, config, &format)?;\n            tokens.format(out, config, &format)?;\n            Ok(())\n        }\n    }\n\n    Import(Import) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, _: &Config, _: &Format) -> fmt::Result {\n            out.write_str(&self.item)?;\n            Ok(())\n        }\n    }\n}\n\n/// The include statement for a C header file such as `#include \"foo/bar.h\"` or\n/// `#include <stdio.h>`.\n///\n/// Created using the [include()] function.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct Import {\n    /// Path to included file.\n    path: ItemStr,\n    /// Item declared in the included file.\n    item: ItemStr,\n    /// True if the include is specified as a system header using `<>`, false if a local header using `\"\"`.\n    system: bool,\n}\n\n/// Format for C.\n#[derive(Debug, Default)]\npub struct Format {}\n\n/// Config data for C.\n#[derive(Debug, Default)]\npub struct Config {}\n\nimpl C {\n    fn imports(out: &mut Tokens, tokens: &Tokens) {\n        let mut includes = BTreeSet::new();\n\n        for include in tokens.iter_lang() {\n            includes.insert((&include.path, include.system));\n        }\n\n        if includes.is_empty() {\n            return;\n        }\n\n        for (file, system_header) in includes {\n            if system_header {\n                quote_in!(*out => #include <$(file)>);\n            } else {\n                quote_in!(*out => #include $(quoted(file)));\n            }\n            out.push();\n        }\n\n        out.line();\n    }\n}\n\n/// Include an item declared in a local C header file such as `#include \"foo/bar.h\"`\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let fizzbuzz = c::include(\"foo/bar.h\", \"fizzbuzz\");\n///\n/// let fizzbuzz_toks = quote! {\n///     $fizzbuzz\n/// };\n///\n/// assert_eq!(\n///     vec![\n///        \"#include \\\"foo/bar.h\\\"\",\n///        \"\",\n///        \"fizzbuzz\",\n///     ],\n///     fizzbuzz_toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn include(path: impl Into<ItemStr>, item: impl Into<ItemStr>) -> Import {\n    Import {\n        path: path.into(),\n        item: item.into(),\n        system: false,\n    }\n}\n\n/// Include an item declared in a C system header such as `#include <stdio.h>`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let printf = c::include_system(\"stdio.h\", \"printf\");\n///\n/// let printf_toks = quote! {\n///     $printf\n/// };\n///\n/// assert_eq!(\n///     vec![\n///        \"#include <stdio.h>\",\n///        \"\",\n///        \"printf\",\n///     ],\n///     printf_toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn include_system<M, N>(path: M, item: N) -> Import\nwhere\n    M: Into<ItemStr>,\n    N: Into<ItemStr>,\n{\n    Import {\n        path: path.into(),\n        item: item.into(),\n        system: true,\n    }\n}\n"
  },
  {
    "path": "src/lang/csharp/block_comment.rs",
    "content": "use crate::lang::Csharp;\nuse crate::tokens::{FormatInto, ItemStr};\nuse crate::Tokens;\n\n/// Format a doc comment where each line is preceeded by `///`.\n///\n/// This struct is created by the [block_comment][super::block_comment()] function.\npub struct BlockComment<T>(pub(super) T);\n\nimpl<T> FormatInto<Csharp> for BlockComment<T>\nwhere\n    T: IntoIterator,\n    T::Item: Into<ItemStr>,\n{\n    fn format_into(self, tokens: &mut Tokens<Csharp>) {\n        for line in self.0 {\n            tokens.push();\n            tokens.append(ItemStr::static_(\"///\"));\n            tokens.space();\n            tokens.append(line.into());\n        }\n    }\n}\n"
  },
  {
    "path": "src/lang/csharp/comment.rs",
    "content": "use crate::lang::Csharp;\nuse crate::tokens;\nuse crate::Tokens;\n\n/// Format a doc comment where each line is preceeded by `//`.\n///\n/// This struct is created by the [comment][super::comment()] function.\npub struct Comment<T>(pub(super) T);\n\nimpl<T> tokens::FormatInto<Csharp> for Comment<T>\nwhere\n    T: IntoIterator,\n    T::Item: Into<tokens::ItemStr>,\n{\n    fn format_into(self, tokens: &mut Tokens<Csharp>) {\n        for line in self.0 {\n            tokens.push();\n            tokens.append(tokens::static_literal(\"//\"));\n            tokens.space();\n            tokens.append(line.into());\n        }\n    }\n}\n"
  },
  {
    "path": "src/lang/csharp/mod.rs",
    "content": "//! Specialization for Csharp code generation.\n//!\n//! # String Quoting in C#\n//!\n//! Since C# uses UTF-16 internally, but literal strings support C-style family\n//! of escapes.\n//!\n//! See [c_family_write_quoted][super::c_family_write_quoted].\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: csharp::Tokens = quote!(\"start π 😊 \\n \\x7f end\");\n//! assert_eq!(\"\\\"start \\\\u03c0 \\\\U0001f60a \\\\n \\\\x7f end\\\"\", toks.to_string()?);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\nmod block_comment;\nmod comment;\n\nuse core::fmt::Write as _;\n\nuse alloc::collections::{BTreeMap, BTreeSet};\nuse alloc::string::{String, ToString};\n\nuse crate as genco;\nuse crate::fmt;\nuse crate::quote_in;\nuse crate::tokens::ItemStr;\n\npub use self::block_comment::BlockComment;\npub use self::comment::Comment;\n\n/// Tokens container specialization for C#.\npub type Tokens = crate::Tokens<Csharp>;\n\nimpl_lang! {\n    /// Language specialization for C#.\n    pub Csharp {\n        type Config = Config;\n        type Format = Format;\n        type Item = Import;\n\n        fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n            // From: https://csharpindepth.com/articles/Strings\n            super::c_family_write_quoted(out, input)\n        }\n\n        fn format_file(\n            tokens: &Tokens,\n            out: &mut fmt::Formatter<'_>,\n            config: &Self::Config,\n        ) -> fmt::Result {\n            let mut file: Tokens = Tokens::new();\n\n            let mut format = Format::default();\n\n            Self::imports(&mut file, tokens, config, &mut format.imported_names);\n\n            if let Some(namespace) = &config.namespace {\n                quote_in! { file =>\n                    namespace $namespace {\n                        $tokens\n                    }\n                }\n\n                file.format(out, config, &format)?;\n            } else {\n                file.format(out, config, &format)?;\n                tokens.format(out, config, &format)?;\n            }\n\n            Ok(())\n        }\n    }\n\n    Import(Import) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, config: &Config, format: &Format) -> fmt::Result {\n            {\n                let qualified = self.qualified || is_qualified(config, format, &self.namespace, &self.name);\n\n                if qualified {\n                    out.write_str(&self.namespace)?;\n                    out.write_str(SEP)?;\n                }\n            }\n\n            out.write_str(&self.name)?;\n\n            return Ok(());\n\n            fn is_qualified(config: &Config, format: &Format, namespace: &str, name: &str) -> bool {\n                // Name is in current namespace. No need to qualify.\n                if let Some(config) = &config.namespace {\n                    if &**config == namespace {\n                        return false;\n                    }\n                }\n\n                if let Some(imported) = format.imported_names.get(name) {\n                    // a conflicting name is in the namespace.\n                    if imported != namespace {\n                        return true;\n                    }\n                }\n\n                false\n            }\n        }\n    }\n}\n\n/// Separator between types and modules in C#.\nconst SEP: &str = \".\";\n\n/// State using during formatting of C# language items.\n#[derive(Debug, Default)]\npub struct Format {\n    /// Keeping track of names which have been imported, do determine whether\n    /// their use has to be qualified or not.\n    ///\n    /// A missing name means that it has to be used in a qualified manner.\n    imported_names: BTreeMap<String, String>,\n}\n\n/// Config data for Csharp formatting.\n#[derive(Debug, Default)]\npub struct Config {\n    /// namespace to use.\n    namespace: Option<ItemStr>,\n}\n\nimpl Config {\n    /// Set the namespace name to build.\n    pub fn with_namespace<N>(self, namespace: N) -> Self\n    where\n        N: Into<ItemStr>,\n    {\n        Self {\n            namespace: Some(namespace.into()),\n        }\n    }\n}\n\n/// The import of a C# type `using System.IO;`.\n///\n/// Created through the [import()] function.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct Import {\n    /// namespace of the class.\n    namespace: ItemStr,\n    /// Name  of class.\n    name: ItemStr,\n    /// Use as qualified type.\n    qualified: bool,\n}\n\nimpl Import {\n    /// Make this type into a qualified type that is always used with a\n    /// namespace.\n    pub fn qualified(self) -> Self {\n        Self {\n            qualified: true,\n            ..self\n        }\n    }\n}\n\nimpl Csharp {\n    fn imports(\n        out: &mut Tokens,\n        tokens: &Tokens,\n        config: &Config,\n        imported_names: &mut BTreeMap<String, String>,\n    ) {\n        let mut modules = BTreeSet::new();\n\n        for import in tokens.iter_lang() {\n            modules.insert((&*import.namespace, &*import.name));\n        }\n\n        if modules.is_empty() {\n            return;\n        }\n\n        let mut imported = BTreeSet::new();\n\n        for (namespace, name) in modules {\n            if Some(namespace) == config.namespace.as_deref() {\n                continue;\n            }\n\n            match imported_names.get(name) {\n                // already imported...\n                Some(existing) if existing == namespace => continue,\n                // already imported, as something else...\n                Some(_) => continue,\n                _ => {}\n            }\n\n            if !imported.contains(namespace) {\n                quote_in!(*out => using $namespace;);\n                out.push();\n                imported.insert(namespace);\n            }\n\n            imported_names.insert(name.to_string(), namespace.to_string());\n        }\n\n        out.line();\n    }\n}\n\n/// The import of a C# type `using System.IO;`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let a = csharp::import(\"Foo.Bar\", \"A\");\n/// let b = csharp::import(\"Foo.Bar\", \"B\");\n/// let ob = csharp::import(\"Foo.Baz\", \"B\");\n///\n/// let toks: Tokens<Csharp> = quote! {\n///     $a\n///     $b\n///     $ob\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"using Foo.Bar;\",\n///         \"\",\n///         \"A\",\n///         \"B\",\n///         \"Foo.Baz.B\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn import<P, N>(namespace: P, name: N) -> Import\nwhere\n    P: Into<ItemStr>,\n    N: Into<ItemStr>,\n{\n    Import {\n        namespace: namespace.into(),\n        name: name.into(),\n        qualified: false,\n    }\n}\n\n/// Format a doc comment where each line is preceeded by `///`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n/// use std::iter;\n///\n/// let toks = quote! {\n///     $(csharp::block_comment(vec![\"Foo\"]))\n///     $(csharp::block_comment(iter::empty::<&str>()))\n///     $(csharp::block_comment(vec![\"Bar\"]))\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"/// Foo\",\n///         \"/// Bar\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn block_comment<T>(comment: T) -> BlockComment<T>\nwhere\n    T: IntoIterator,\n    T::Item: Into<ItemStr>,\n{\n    BlockComment(comment)\n}\n\n/// Format a doc comment where each line is preceeded by `//`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let toks = quote! {\n///     $(csharp::comment(&[\"Foo\"]))\n///     $(csharp::comment(&[\"Bar\"]))\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"// Foo\",\n///         \"// Bar\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn comment<T>(comment: T) -> Comment<T>\nwhere\n    T: IntoIterator,\n    T::Item: Into<ItemStr>,\n{\n    Comment(comment)\n}\n"
  },
  {
    "path": "src/lang/dart/doc_comment.rs",
    "content": "use crate::lang::Dart;\nuse crate::tokens;\nuse crate::Tokens;\n\n/// Format a doc comment where each line is preceeded by `///`.\n///\n/// This struct is created by the [doc_comment][super::doc_comment()] function.\npub struct DocComment<T>(pub(super) T);\n\nimpl<T> tokens::FormatInto<Dart> for DocComment<T>\nwhere\n    T: IntoIterator,\n    T::Item: Into<tokens::ItemStr>,\n{\n    fn format_into(self, tokens: &mut Tokens<Dart>) {\n        for line in self.0 {\n            tokens.push();\n            tokens.append(tokens::static_literal(\"///\"));\n            tokens.space();\n            tokens.append(line.into());\n        }\n    }\n}\n"
  },
  {
    "path": "src/lang/dart/mod.rs",
    "content": "//! Specialization for Dart code generation.\n//!\n//! # String Quoting in Dart\n//!\n//! Since Java uses UTF-16 internally, string quoting for high unicode\n//! characters is done through surrogate pairs, as seen with the 😊 below.\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: dart::Tokens = quote!(\"start π 😊 \\n \\x7f ÿ $ \\\\ end\");\n//! assert_eq!(\"\\\"start π 😊 \\\\n \\\\x7f ÿ \\\\$ \\\\\\\\ end\\\"\", toks.to_string()?);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n//!\n//! # String Interpolation in Dart\n//!\n//! Strings can be interpolated in Dart, by using the special `$_(<string>)`\n//! escape sequence.\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: dart::Tokens = quote!($[str](  Hello: $var  ));\n//! assert_eq!(\"\\\"  Hello: $var  \\\"\", toks.to_string()?);\n//!\n//! let toks: dart::Tokens = quote!($[str](  Hello: $(a + b)  ));\n//! assert_eq!(\"\\\"  Hello: ${a + b}  \\\"\", toks.to_string()?);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\nmod doc_comment;\npub use self::doc_comment::DocComment;\n\nuse core::fmt::Write as _;\n\nuse alloc::collections::BTreeSet;\n\nuse crate as genco;\nuse crate::fmt;\nuse crate::quote_in;\nuse crate::tokens::{quoted, ItemStr};\n\nconst SEP: &str = \".\";\n/// dart:core package.\nconst DART_CORE: &str = \"dart:core\";\n\n/// Tokens container specialization for Dart.\npub type Tokens = crate::Tokens<Dart>;\n\nimpl genco::lang::LangSupportsEval for Dart {}\n\nimpl_lang! {\n    /// Language specialization for Dart.\n    pub Dart {\n        type Config = Config;\n        type Format = Format;\n        type Item = Import;\n\n        fn string_eval_literal(\n            out: &mut fmt::Formatter<'_>,\n            _config: &Self::Config,\n            _format: &Self::Format,\n            literal: &str,\n        ) -> fmt::Result {\n            write!(out, \"${literal}\")?;\n            Ok(())\n        }\n\n        /// Start a string-interpolated eval.\n        fn start_string_eval(\n            out: &mut fmt::Formatter<'_>,\n            _config: &Self::Config,\n            _format: &Self::Format,\n        ) -> fmt::Result {\n            out.write_str(\"${\")?;\n            Ok(())\n        }\n\n        /// End a string interpolated eval.\n        fn end_string_eval(\n            out: &mut fmt::Formatter<'_>,\n            _config: &Self::Config,\n            _format: &Self::Format,\n        ) -> fmt::Result {\n            out.write_char('}')?;\n            Ok(())\n        }\n\n        fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n            // Note: Dart is like C escape, but since it supports string\n            // interpolation, `$` also needs to be escaped!\n\n            for c in input.chars() {\n                match c {\n                    // backspace\n                    '\\u{0008}' => out.write_str(\"\\\\b\")?,\n                    // form feed\n                    '\\u{0012}' => out.write_str(\"\\\\f\")?,\n                    // new line\n                    '\\n' => out.write_str(\"\\\\n\")?,\n                    // carriage return\n                    '\\r' => out.write_str(\"\\\\r\")?,\n                    // horizontal tab\n                    '\\t' => out.write_str(\"\\\\t\")?,\n                    // vertical tab\n                    '\\u{0011}' => out.write_str(\"\\\\v\")?,\n                    // Note: only relevant if we were to use single-quoted strings.\n                    // '\\'' => out.write_str(\"\\\\'\")?,\n                    '\"' => out.write_str(\"\\\\\\\"\")?,\n                    '\\\\' => out.write_str(\"\\\\\\\\\")?,\n                    '$' => out.write_str(\"\\\\$\")?,\n                    c if !c.is_control() => out.write_char(c)?,\n                    c if (c as u32) < 0x100 => {\n                        write!(out, \"\\\\x{:02x}\", c as u32)?;\n                    }\n                    c => {\n                        for c in c.encode_utf16(&mut [0u16; 2]) {\n                            write!(out, \"\\\\u{c:04x}\")?;\n                        }\n                    }\n                };\n            }\n\n            Ok(())\n        }\n\n        fn format_file(\n            tokens: &Tokens,\n            out: &mut fmt::Formatter<'_>,\n            config: &Self::Config,\n        ) -> fmt::Result {\n            let mut imports: Tokens = Tokens::new();\n            Self::imports(&mut imports, tokens, config);\n            let format = Format::default();\n            imports.format(out, config, &format)?;\n            tokens.format(out, config, &format)?;\n            Ok(())\n        }\n    }\n\n    Import(Import) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, _: &Config, _: &Format) -> fmt::Result {\n            if let Some(alias) = &self.alias {\n                out.write_str(alias.as_ref())?;\n                out.write_str(SEP)?;\n            }\n\n            out.write_str(&self.name)?;\n            Ok(())\n        }\n    }\n}\n\n/// Format state for Dart.\n#[derive(Debug, Default)]\npub struct Format {}\n\n/// Config data for Dart formatting.\n#[derive(Debug, Default)]\npub struct Config {}\n\n/// The import of a Dart type `import \"dart:math\";`.\n///\n/// Created through the [import()] function.\n#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]\npub struct Import {\n    /// Path to import.\n    path: ItemStr,\n    /// Name imported.\n    name: ItemStr,\n    /// Alias of module.\n    alias: Option<ItemStr>,\n}\n\nimpl Import {\n    /// Add an `as` keyword to the import.\n    pub fn with_alias(self, alias: impl Into<ItemStr>) -> Import {\n        Self {\n            alias: Some(alias.into()),\n            ..self\n        }\n    }\n}\n\nimpl Dart {\n    /// Resolve all imports.\n    fn imports(out: &mut Tokens, input: &Tokens, _: &Config) {\n        let mut modules = BTreeSet::new();\n\n        for import in input.iter_lang() {\n            if &*import.path == DART_CORE {\n                continue;\n            }\n\n            modules.insert((import.path.clone(), import.alias.clone()));\n        }\n\n        if modules.is_empty() {\n            return;\n        }\n\n        for (name, alias) in modules {\n            if let Some(alias) = alias {\n                quote_in!(*out => import $(quoted(name)) as $alias;);\n            } else {\n                quote_in!(*out => import $(quoted(name)););\n            }\n\n            out.push();\n        }\n\n        out.line();\n    }\n}\n\n/// The import of a Dart type `import \"dart:math\";`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let a = dart::import(\"package:http/http.dart\", \"A\");\n/// let b = dart::import(\"package:http/http.dart\", \"B\");\n/// let c = dart::import(\"package:http/http.dart\", \"C\").with_alias(\"h2\");\n/// let d = dart::import(\"../http.dart\", \"D\");\n///\n/// let toks = quote! {\n///     $a\n///     $b\n///     $c\n///     $d\n/// };\n///\n/// let expected = vec![\n///     \"import \\\"../http.dart\\\";\",\n///     \"import \\\"package:http/http.dart\\\";\",\n///     \"import \\\"package:http/http.dart\\\" as h2;\",\n///     \"\",\n///     \"A\",\n///     \"B\",\n///     \"h2.C\",\n///     \"D\",\n/// ];\n///\n/// assert_eq!(expected, toks.to_file_vec()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn import<P, N>(path: P, name: N) -> Import\nwhere\n    P: Into<ItemStr>,\n    N: Into<ItemStr>,\n{\n    Import {\n        path: path.into(),\n        alias: None,\n        name: name.into(),\n    }\n}\n\n/// Format a doc comment where each line is preceeded by `///`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n/// use std::iter;\n///\n/// let toks = quote! {\n///     $(dart::doc_comment(vec![\"Foo\"]))\n///     $(dart::doc_comment(iter::empty::<&str>()))\n///     $(dart::doc_comment(vec![\"Bar\"]))\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"/// Foo\",\n///         \"/// Bar\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn doc_comment<T>(comment: T) -> DocComment<T>\nwhere\n    T: IntoIterator,\n    T::Item: Into<ItemStr>,\n{\n    DocComment(comment)\n}\n"
  },
  {
    "path": "src/lang/go.rs",
    "content": "//! Specialization for Go code generation.\n//!\n//! # Examples\n//!\n//! Basic example:\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: js::Tokens = quote! {\n//!     function foo(v) {\n//!         return v + \", World\";\n//!     }\n//!\n//!     foo(\"Hello\");\n//! };\n//!\n//! assert_eq!(\n//!     vec![\n//!         \"function foo(v) {\",\n//!         \"    return v + \\\", World\\\";\",\n//!         \"}\",\n//!         \"\",\n//!         \"foo(\\\"Hello\\\");\",\n//!     ],\n//!     toks.to_file_vec()?\n//! );\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n//!\n//! String quoting in JavaScript:\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: go::Tokens = quote!(\"start π 😊 \\n \\x7f end\");\n//! assert_eq!(\"\\\"start \\\\u03c0 \\\\U0001f60a \\\\n \\\\x7f end\\\"\", toks.to_string()?);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\nuse core::fmt::Write as _;\n\nuse alloc::collections::BTreeSet;\n\nuse crate as genco;\nuse crate::fmt;\nuse crate::quote_in;\nuse crate::tokens::{quoted, ItemStr};\n\nconst MODULE_SEP: &str = \"/\";\nconst SEP: &str = \".\";\n\n/// Tokens container specialization for Go.\npub type Tokens = crate::Tokens<Go>;\n\nimpl_lang! {\n    /// Language specialization for Go.\n    pub Go {\n        type Config = Config;\n        type Format = Format;\n        type Item = Import;\n\n        fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n            // From: https://golang.org/src/strconv/quote.go\n            super::c_family_write_quoted(out, input)\n        }\n\n        fn format_file(\n            tokens: &Tokens,\n            out: &mut fmt::Formatter<'_>,\n            config: &Self::Config,\n        ) -> fmt::Result {\n            let mut header = Tokens::new();\n\n            if let Some(package) = &config.package {\n                quote_in!(header => package $package);\n                header.line();\n            }\n\n            Self::imports(&mut header, tokens);\n            let format = Format::default();\n            header.format(out, config, &format)?;\n            tokens.format(out, config, &format)?;\n            Ok(())\n        }\n    }\n\n    Import(Import) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, _: &Config, _: &Format) -> fmt::Result {\n            if let Some(module) = self.module.rsplit(MODULE_SEP).next() {\n                out.write_str(module)?;\n                out.write_str(SEP)?;\n            }\n\n            out.write_str(&self.name)?;\n            Ok(())\n        }\n    }\n}\n\n/// The import of a Go type `import \"foo/bar\"`.\n///\n/// Created using the [import()] function.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct Import {\n    /// Module of the imported name.\n    module: ItemStr,\n    /// Name imported.\n    name: ItemStr,\n}\n\n/// Format for Go.\n#[derive(Debug, Default)]\npub struct Format {}\n\n/// Config data for Go.\n#[derive(Debug, Default)]\npub struct Config {\n    package: Option<ItemStr>,\n}\n\nimpl Config {\n    /// Configure the specified package.\n    pub fn with_package<P: Into<ItemStr>>(self, package: P) -> Self {\n        Self {\n            package: Some(package.into()),\n        }\n    }\n}\n\nimpl Go {\n    fn imports(out: &mut Tokens, tokens: &Tokens) {\n        let mut modules = BTreeSet::new();\n\n        for import in tokens.iter_lang() {\n            modules.insert(&import.module);\n        }\n\n        if modules.is_empty() {\n            return;\n        }\n\n        for module in modules {\n            quote_in!(*out => import $(quoted(module)));\n            out.push();\n        }\n\n        out.line();\n    }\n}\n\n/// The import of a Go type `import \"foo/bar\"`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let ty = go::import(\"foo/bar\", \"Debug\");\n///\n/// let toks = quote! {\n///     $ty\n/// };\n///\n/// assert_eq!(\n///     vec![\n///        \"import \\\"foo/bar\\\"\",\n///        \"\",\n///        \"bar.Debug\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn import<M, N>(module: M, name: N) -> Import\nwhere\n    M: Into<ItemStr>,\n    N: Into<ItemStr>,\n{\n    Import {\n        module: module.into(),\n        name: name.into(),\n    }\n}\n"
  },
  {
    "path": "src/lang/java/block_comment.rs",
    "content": "use crate::lang::Java;\nuse crate::tokens;\nuse crate::Tokens;\n\n/// Format a block comment, starting with `/**`, and ending in `*/`.\n///\n/// This struct is created by the [block_comment][super::block_comment()] function.\npub struct BlockComment<T>(pub(super) T);\n\nimpl<T> tokens::FormatInto<Java> for BlockComment<T>\nwhere\n    T: IntoIterator,\n    T::Item: Into<tokens::ItemStr>,\n{\n    fn format_into(self, tokens: &mut Tokens<Java>) {\n        let mut it = self.0.into_iter().peekable();\n\n        if it.peek().is_none() {\n            return;\n        }\n\n        tokens.push();\n        tokens.append(tokens::static_literal(\"/**\"));\n        tokens.push();\n\n        for line in it {\n            tokens.space();\n            tokens.append(tokens::static_literal(\"*\"));\n            tokens.space();\n            tokens.append(line.into());\n            tokens.push();\n        }\n\n        tokens.space();\n        tokens.append(\"*/\");\n    }\n}\n"
  },
  {
    "path": "src/lang/java/mod.rs",
    "content": "//! Specialization for Java code generation.\n//!\n//! # String Quoting in Java\n//!\n//! Since Java uses UTF-16 internally, string quoting for high unicode\n//! characters is done through surrogate pairs, as seen with the 😊 below.\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: java::Tokens = quote!(\"start π 😊 \\n \\x7f end\");\n//! assert_eq!(\"\\\"start \\\\u03c0 \\\\ud83d\\\\ude0a \\\\n \\\\u007f end\\\"\", toks.to_string()?);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\nmod block_comment;\npub use self::block_comment::BlockComment;\n\nuse core::fmt::Write as _;\n\nuse alloc::collections::{BTreeMap, BTreeSet};\nuse alloc::string::{String, ToString};\n\nuse crate as genco;\nuse crate::fmt;\nuse crate::tokens::ItemStr;\nuse crate::{quote, quote_in};\n\n/// Tokens container specialized for Java.\npub type Tokens = crate::Tokens<Java>;\n\nimpl_lang! {\n    /// Language specialization for Java.\n    pub Java {\n        type Config = Config;\n        type Format = Format;\n        type Item = Import;\n\n        fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n            // From: https://docs.oracle.com/javase/tutorial/java/data/characters.html\n\n            for c in input.chars() {\n                match c {\n                    '\\t' => out.write_str(\"\\\\t\")?,\n                    '\\u{0008}' => out.write_str(\"\\\\b\")?,\n                    '\\n' => out.write_str(\"\\\\n\")?,\n                    '\\r' => out.write_str(\"\\\\r\")?,\n                    '\\u{0014}' => out.write_str(\"\\\\f\")?,\n                    '\\'' => out.write_str(\"\\\\'\")?,\n                    '\"' => out.write_str(\"\\\\\\\"\")?,\n                    '\\\\' => out.write_str(\"\\\\\\\\\")?,\n                    ' ' => out.write_char(' ')?,\n                    c if c.is_ascii() && !c.is_control() => out.write_char(c)?,\n                    c => {\n                        for c in c.encode_utf16(&mut [0u16; 2]) {\n                            write!(out, \"\\\\u{c:04x}\")?;\n                        }\n                    }\n                }\n            }\n\n            Ok(())\n        }\n\n        fn format_file(\n            tokens: &Tokens,\n            out: &mut fmt::Formatter<'_>,\n            config: &Self::Config,\n        ) -> fmt::Result {\n            let mut header = Tokens::new();\n\n            if let Some(ref package) = config.package {\n                quote_in!(header => package $package;);\n                header.line();\n            }\n\n            let mut format = Format::default();\n            Self::imports(&mut header, tokens, config, &mut format.imported);\n            header.format(out, config, &format)?;\n            tokens.format(out, config, &format)?;\n            Ok(())\n        }\n    }\n\n    Import(Import) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, config: &Config, format: &Format) -> fmt::Result {\n            let file_package = config.package.as_ref().map(|p| p.as_ref());\n            let imported = format.imported.get(self.name.as_ref()).map(String::as_str);\n            let pkg = Some(self.package.as_ref());\n\n            if &*self.package != JAVA_LANG && imported != pkg && file_package != pkg {\n                out.write_str(self.package.as_ref())?;\n                out.write_str(SEP)?;\n            }\n\n            out.write_str(&self.name)?;\n            Ok(())\n        }\n    }\n}\n\nconst JAVA_LANG: &str = \"java.lang\";\nconst SEP: &str = \".\";\n\n/// Formtat state for Java.\n#[derive(Debug, Default)]\npub struct Format {\n    /// Types which has been imported into the local namespace.\n    imported: BTreeMap<String, String>,\n}\n\n/// Configuration for Java.\n#[derive(Debug, Default)]\npub struct Config {\n    /// Package to use.\n    package: Option<ItemStr>,\n}\n\nimpl Config {\n    /// Configure package to use for the file generated.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    /// use genco::fmt;\n    ///\n    /// let optional = java::import(\"java.util\", \"Optional\");\n    ///\n    /// let toks = quote!($optional);\n    ///\n    /// let config = java::Config::default().with_package(\"java.util\");\n    /// let fmt = fmt::Config::from_lang::<Java>();\n    ///\n    /// let mut w = fmt::VecWriter::new();\n    ///\n    /// toks.format_file(&mut w.as_formatter(&fmt), &config)?;\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"package java.util;\",\n    ///         \"\",\n    ///         \"Optional\",\n    ///     ],\n    ///     w.into_vec(),\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn with_package<P>(self, package: P) -> Self\n    where\n        P: Into<ItemStr>,\n    {\n        Self {\n            package: Some(package.into()),\n        }\n    }\n}\n\n/// The import of a Java type `import java.util.Optional;`.\n///\n/// Created through the [import()] function.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct Import {\n    /// Package of the class.\n    package: ItemStr,\n    /// Name  of class.\n    name: ItemStr,\n}\n\nimpl Java {\n    fn imports(\n        out: &mut Tokens,\n        tokens: &Tokens,\n        config: &Config,\n        imported: &mut BTreeMap<String, String>,\n    ) {\n        let mut modules = BTreeSet::new();\n\n        let file_package = config.package.as_ref().map(|p| p.as_ref());\n\n        for import in tokens.iter_lang() {\n            modules.insert((import.package.clone(), import.name.clone()));\n        }\n\n        if modules.is_empty() {\n            return;\n        }\n\n        for (package, name) in modules {\n            if imported.contains_key(&*name) {\n                continue;\n            }\n\n            if &*package == JAVA_LANG {\n                continue;\n            }\n\n            if Some(&*package) == file_package {\n                continue;\n            }\n\n            out.append(quote!(import $(package.clone())$(SEP)$(name.clone());));\n            out.push();\n\n            imported.insert(name.to_string(), package.to_string());\n        }\n\n        out.line();\n    }\n}\n\n/// The import of a Java type `import java.util.Optional;`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let integer = java::import(\"java.lang\", \"Integer\");\n/// let a = java::import(\"java.io\", \"A\");\n///\n/// let toks = quote! {\n///     $integer\n///     $a\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"import java.io.A;\",\n///         \"\",\n///         \"Integer\",\n///         \"A\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn import<P, N>(package: P, name: N) -> Import\nwhere\n    P: Into<ItemStr>,\n    N: Into<ItemStr>,\n{\n    Import {\n        package: package.into(),\n        name: name.into(),\n    }\n}\n\n/// Format a block comment, starting with `/**`, and ending in `*/`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n/// use std::iter;\n///\n/// let toks = quote! {\n///     $(java::block_comment(vec![\"first line\", \"second line\"]))\n///     $(java::block_comment(iter::empty::<&str>()))\n///     $(java::block_comment(vec![\"third line\"]))\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"/**\",\n///         \" * first line\",\n///         \" * second line\",\n///         \" */\",\n///         \"/**\",\n///         \" * third line\",\n///         \" */\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn block_comment<T>(comment: T) -> BlockComment<T>\nwhere\n    T: IntoIterator,\n    T::Item: Into<ItemStr>,\n{\n    BlockComment(comment)\n}\n"
  },
  {
    "path": "src/lang/js.rs",
    "content": "//! Specialization for JavaScript code generation.\n//!\n//! # Examples\n//!\n//! Basic example:\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: js::Tokens = quote! {\n//!     function foo(v) {\n//!         return v + \", World\";\n//!     }\n//!\n//!     foo(\"Hello\");\n//! };\n//!\n//! assert_eq!(\n//!     vec![\n//!         \"function foo(v) {\",\n//!         \"    return v + \\\", World\\\";\",\n//!         \"}\",\n//!         \"\",\n//!         \"foo(\\\"Hello\\\");\",\n//!     ],\n//!     toks.to_file_vec()?\n//! );\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n//!\n//! # String Quoting in JavaScript\n//!\n//! JavaScript uses c-style string quoting, with indefinitely long unicode\n//! escape sequences. But any non-control character can be embedded directly\n//! into the string literal (like `\"😊\"`).\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: js::Tokens = quote!(\"start π 😊 \\n \\x7f ÿ $ \\\\ end\");\n//! assert_eq!(\"\\\"start π 😊 \\\\n \\\\x7f ÿ $ \\\\\\\\ end\\\"\", toks.to_string()?);\n//!\n//! let toks: js::Tokens = quote!($(quoted(\"start π 😊 \\n \\x7f ÿ $ \\\\ end\")));\n//! assert_eq!(\"\\\"start π 😊 \\\\n \\\\x7f ÿ $ \\\\\\\\ end\\\"\", toks.to_string()?);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\nuse core::fmt::Write as _;\n\nuse alloc::collections::{BTreeMap, BTreeSet};\nuse alloc::string::String;\n\nuse crate::fmt;\nuse crate::tokens::ItemStr;\n\nuse relative_path::{RelativePath, RelativePathBuf};\n\n/// Tokens container specialization for Rust.\npub type Tokens = crate::Tokens<JavaScript>;\n\nimpl crate::lang::LangSupportsEval for JavaScript {}\n\nimpl_lang! {\n    /// JavaScript language specialization.\n    pub JavaScript {\n        type Config = Config;\n        type Format = Format;\n        type Item = Import;\n\n        /// Start a string quote.\n        fn open_quote(\n            out: &mut fmt::Formatter<'_>,\n            _config: &Self::Config,\n            _format: &Self::Format,\n            has_eval: bool,\n        ) -> fmt::Result {\n            if has_eval {\n                out.write_char('`')?;\n            } else {\n                out.write_char('\"')?;\n            }\n\n            Ok(())\n        }\n\n        /// End a string quote.\n        fn close_quote(\n            out: &mut fmt::Formatter<'_>,\n            _config: &Self::Config,\n            _format: &Self::Format,\n            has_eval: bool,\n        ) -> fmt::Result {\n            if has_eval {\n                out.write_char('`')?;\n            } else {\n                out.write_char('\"')?;\n            }\n\n            Ok(())\n        }\n\n        fn start_string_eval(\n            out: &mut fmt::Formatter<'_>,\n            _config: &Self::Config,\n            _format: &Self::Format,\n        ) -> fmt::Result {\n            out.write_str(\"${\")?;\n            Ok(())\n        }\n\n        fn end_string_eval(\n            out: &mut fmt::Formatter<'_>,\n            _config: &Self::Config,\n            _format: &Self::Format,\n        ) -> fmt::Result {\n            out.write_char('}')?;\n            Ok(())\n        }\n\n        fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n            // Reference: https://mathiasbynens.be/notes/javascript-escapes\n\n            for c in input.chars() {\n                match c {\n                    // backspace\n                    '\\u{0008}' => out.write_str(\"\\\\b\")?,\n                    // form feed\n                    '\\u{0012}' => out.write_str(\"\\\\f\")?,\n                    // new line\n                    '\\n' => out.write_str(\"\\\\n\")?,\n                    // carriage return\n                    '\\r' => out.write_str(\"\\\\r\")?,\n                    // horizontal tab\n                    '\\t' => out.write_str(\"\\\\t\")?,\n                    // vertical tab\n                    '\\u{0011}' => out.write_str(\"\\\\v\")?,\n                    // null character.\n                    '\\0' => out.write_str(\"\\\\0\")?,\n                    // Note: only relevant if we were to use single-quoted strings.\n                    // '\\'' => out.write_str(\"\\\\'\")?,\n                    '\"' => out.write_str(\"\\\\\\\"\")?,\n                    '\\\\' => out.write_str(\"\\\\\\\\\")?,\n                    c if !c.is_control() => out.write_char(c)?,\n                    c if (c as u32) < 0x100 => {\n                        write!(out, \"\\\\x{:02x}\", c as u32)?;\n                    }\n                    c => {\n                        write!(out, \"\\\\u{{{:x}}}\", c as u32)?;\n                    }\n                };\n            }\n\n            Ok(())\n        }\n\n        fn format_file(\n            tokens: &Tokens,\n            out: &mut fmt::Formatter<'_>,\n            config: &Self::Config,\n        ) -> fmt::Result {\n            let mut imports = Tokens::new();\n            Self::imports(&mut imports, tokens, config);\n            let format = Format::default();\n            imports.format(out, config, &format)?;\n            tokens.format(out, config, &format)?;\n            Ok(())\n        }\n    }\n\n    Import(Import) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, _: &Config, _: &Format) -> fmt::Result {\n            let name = match self.kind {\n                ImportKind::Named => self.alias.as_ref().unwrap_or(&self.name),\n                _ => &self.name,\n            };\n\n            out.write_str(name)\n        }\n    }\n}\n\n/// Format state for JavaScript.\n#[derive(Debug, Default)]\npub struct Format {}\n\n/// Configuration for JavaScript.\n#[derive(Debug, Default)]\npub struct Config {\n    module_path: Option<RelativePathBuf>,\n}\n\nimpl Config {\n    /// Configure the path to the current module being renderer.\n    ///\n    /// This setting will determine what path imports are renderer relative\n    /// towards. So importing a module from `\"foo/bar.js\"`, and setting this to\n    /// `\"foo/baz.js\"` will cause the import to be rendered relatively as\n    /// `\"../bar.js\"`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    /// use genco::fmt;\n    ///\n    /// let foo1 = js::import(js::Module::Path(\"foo/bar.js\".into()), \"Foo1\");\n    /// let foo2 = js::import(js::Module::Path(\"foo/bar.js\".into()), \"Foo2\");\n    /// let react = js::import(\"react\", \"React\").into_default();\n    ///\n    /// let toks: js::Tokens = quote! {\n    ///     $foo1\n    ///     $foo2\n    ///     $react\n    /// };\n    ///\n    /// let mut w = fmt::VecWriter::new();\n    ///\n    /// let config = js::Config::default().with_module_path(\"foo/baz.js\");\n    /// let fmt = fmt::Config::from_lang::<JavaScript>();\n    ///\n    /// toks.format_file(&mut w.as_formatter(&fmt), &config)?;\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"import {Foo1, Foo2} from \\\"../bar.js\\\";\",\n    ///         \"import React from \\\"react\\\";\",\n    ///         \"\",\n    ///         \"Foo1\",\n    ///         \"Foo2\",\n    ///         \"React\"\n    ///     ],\n    ///     w.into_vec()\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn with_module_path<M>(self, module_path: M) -> Self\n    where\n        M: Into<RelativePathBuf>,\n    {\n        Self {\n            module_path: Some(module_path.into()),\n        }\n    }\n}\n\n/// Internal type to determine the kind of import used.\n#[derive(Debug, Clone, Copy, Hash, PartialOrd, Ord, PartialEq, Eq)]\nenum ImportKind {\n    Named,\n    Default,\n    Wildcard,\n}\n\n/// The import of a JavaScript type `import {foo} from \"module.js\"`.\n///\n/// Created through the [import()] function.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct Import {\n    /// The kind of the import.\n    kind: ImportKind,\n    /// Module of the imported name.\n    module: Module,\n    /// Name imported.\n    name: ItemStr,\n    /// Alias of an imported item.\n    ///\n    /// If this is set, you'll get an import like:\n    ///\n    /// ```text\n    /// import {<name> as <alias>} from <module>\n    /// ```\n    alias: Option<ItemStr>,\n}\n\nimpl Import {\n    /// Change alias of imported item.\n    ///\n    /// This implies that the import is a named import.\n    ///\n    /// If this is set, you'll get an import like:\n    ///\n    /// ```text\n    /// import {<name> as <alias>} from <module>\n    /// ```\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let a = js::import(\"collections\", \"vec\");\n    /// let b = js::import(\"collections\", \"vec\").with_alias(\"list\");\n    ///\n    /// let toks = quote! {\n    ///     $a\n    ///     $b\n    /// };\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"import {vec, vec as list} from \\\"collections\\\";\",\n    ///         \"\",\n    ///         \"vec\",\n    ///         \"list\",\n    ///     ],\n    ///     toks.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn with_alias<N>(self, alias: N) -> Self\n    where\n        N: Into<ItemStr>,\n    {\n        Self {\n            kind: ImportKind::Named,\n            alias: Some(alias.into()),\n            ..self\n        }\n    }\n\n    /// Convert into a default import.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let default_vec = js::import(\"collections\", \"defaultVec\").into_default();\n    ///\n    /// let toks = quote!($default_vec);\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"import defaultVec from \\\"collections\\\";\",\n    ///         \"\",\n    ///         \"defaultVec\",\n    ///     ],\n    ///     toks.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn into_default(self) -> Self {\n        Self {\n            kind: ImportKind::Default,\n            alias: None,\n            ..self\n        }\n    }\n\n    /// Convert into a wildcard import.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let all = js::import(\"collections\", \"all\").into_wildcard();\n    ///\n    /// let toks = quote!($all);\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"import * as all from \\\"collections\\\";\",\n    ///         \"\",\n    ///         \"all\",\n    ///     ],\n    ///     toks.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn into_wildcard(self) -> Self {\n        Self {\n            kind: ImportKind::Wildcard,\n            alias: None,\n            ..self\n        }\n    }\n}\n\n/// A module being imported.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub enum Module {\n    /// A module imported from a specific path.\n    ///\n    /// The path will be relativized according to the module specified in the\n    /// [Config::with_module_path].\n    Path(RelativePathBuf),\n    /// A globally imported module.\n    Global(ItemStr),\n}\n\nimpl<'a> From<&'a str> for Module {\n    fn from(value: &'a str) -> Self {\n        Self::Global(value.into())\n    }\n}\n\nimpl From<String> for Module {\n    fn from(value: String) -> Self {\n        Self::Global(value.into())\n    }\n}\n\nimpl From<ItemStr> for Module {\n    fn from(value: ItemStr) -> Self {\n        Self::Global(value)\n    }\n}\n\nimpl JavaScript {\n    /// Translate imports into the necessary tokens.\n    fn imports(out: &mut Tokens, tokens: &Tokens, config: &Config) {\n        use crate as genco;\n        use crate::prelude::*;\n\n        let mut modules = BTreeMap::<&Module, ResolvedModule<'_>>::new();\n        let mut wildcards = BTreeSet::new();\n\n        for import in tokens.iter_lang() {\n            match import.kind {\n                ImportKind::Named => {\n                    let module = modules.entry(&import.module).or_default();\n\n                    module.set.insert(match &import.alias {\n                        None => ImportedElement::Plain(&import.name),\n                        Some(alias) => ImportedElement::Aliased(&import.name, alias),\n                    });\n                }\n                ImportKind::Default => {\n                    let module = modules.entry(&import.module).or_default();\n                    module.default_import = Some(&import.name);\n                }\n                ImportKind::Wildcard => {\n                    wildcards.insert((&import.module, &import.name));\n                }\n            }\n        }\n\n        if modules.is_empty() && wildcards.is_empty() {\n            return;\n        }\n\n        for (module, name) in wildcards {\n            out.push();\n            quote_in! { *out =>\n                import * as $name from $(ref t => render_from(t, config.module_path.as_deref(), module));\n            }\n        }\n\n        for (name, module) in modules {\n            out.push();\n            quote_in! { *out =>\n                import $(ref tokens => {\n                    if let Some(default) = module.default_import {\n                        tokens.append(ItemStr::from(default));\n\n                        if !module.set.is_empty() {\n                            tokens.append(\",\");\n                            tokens.space();\n                        }\n                    }\n\n                    if !module.set.is_empty() {\n                        tokens.append(\"{\");\n\n                        let mut it = module.set.iter().peekable();\n\n                        while let Some(el) = it.next() {\n                            match *el {\n                                ImportedElement::Plain(name) => {\n                                    tokens.append(name);\n                                },\n                                ImportedElement::Aliased(name, alias) => {\n                                    quote_in!(*tokens => $name as $alias);\n                                }\n                            }\n\n                            if it.peek().is_some() {\n                                tokens.append(\",\");\n                                tokens.space();\n                            }\n                        }\n\n                        tokens.append(\"}\");\n                    }\n                }) from $(ref t => render_from(t, config.module_path.as_deref(), name));\n            };\n        }\n\n        out.line();\n\n        #[derive(Default)]\n        struct ResolvedModule<'a> {\n            default_import: Option<&'a ItemStr>,\n            set: BTreeSet<ImportedElement<'a>>,\n        }\n\n        #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]\n        enum ImportedElement<'a> {\n            Plain(&'a ItemStr),\n            Aliased(&'a ItemStr, &'a ItemStr),\n        }\n\n        fn render_from(t: &mut js::Tokens, module_path: Option<&RelativePath>, module: &Module) {\n            quote_in! { *t =>\n                $(match (module_path, module) {\n                    (_, Module::Global(from)) => $(quoted(from)),\n                    (None, Module::Path(path)) => $(quoted(path.as_str())),\n                    (Some(module_path), Module::Path(path)) => $(quoted(module_path.relative(path).as_str())),\n                })\n            }\n        }\n    }\n}\n\n/// The import of a JavaScript type `import {foo} from \"module.js\"`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let default_vec = js::import(\"collections\", \"defaultVec\").into_default();\n/// let all = js::import(\"collections\", \"all\").into_wildcard();\n/// let vec = js::import(\"collections\", \"vec\");\n/// let vec_as_list = js::import(\"collections\", \"vec\").with_alias(\"list\");\n///\n/// let toks = quote! {\n///     $default_vec\n///     $all\n///     $vec\n///     $vec_as_list\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"import * as all from \\\"collections\\\";\",\n///         \"import defaultVec, {vec, vec as list} from \\\"collections\\\";\",\n///         \"\",\n///         \"defaultVec\",\n///         \"all\",\n///         \"vec\",\n///         \"list\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn import<M, N>(module: M, name: N) -> Import\nwhere\n    M: Into<Module>,\n    N: Into<ItemStr>,\n{\n    Import {\n        kind: ImportKind::Named,\n        module: module.into(),\n        name: name.into(),\n        alias: None,\n    }\n}\n"
  },
  {
    "path": "src/lang/kotlin/mod.rs",
    "content": "//! Specialization for Kotlin code generation.\n//!\n//! # String Quoting in Kotlin\n//!\n//! Since Kotlin runs on the JVM, it also uses UTF-16 internally. String\n//! quoting for high unicode characters is done through surrogate pairs, as\n//! seen with the 😊 emoji below. Kotlin also requires escaping `$` characters\n//! in standard string literals.\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: kotlin::Tokens = quote!(\"start π 😊 $var \\n end\");\n//! assert_eq!(\"\\\"start \\\\u03c0 \\\\ud83d\\\\ude0a \\\\$var \\\\n end\\\"\", toks.to_string()?);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\nuse core::fmt::Write as _;\n\nuse crate as genco;\nuse crate::fmt;\nuse crate::quote_in;\nuse crate::tokens::ItemStr;\nuse alloc::collections::{BTreeMap, BTreeSet};\nuse alloc::string::{String, ToString};\n\n/// Tokens container specialized for Kotlin.\npub type Tokens = crate::Tokens<Kotlin>;\n\n// This trait implementation signals to genco that the Kotlin language\n// supports evaluation constructs like `$(if ...)` in `quote!`.\nimpl genco::lang::LangSupportsEval for Kotlin {}\n\nimpl_lang! {\n    /// Language specialization for Kotlin.\n    pub Kotlin {\n        type Config = Config;\n        type Format = Format;\n        type Item = Import;\n\n        fn start_string_eval(\n            out: &mut fmt::Formatter<'_>,\n            _config: &Self::Config,\n            _format: &Self::Format,\n        ) -> fmt::Result {\n            out.write_str(\"${\")?;\n            Ok(())\n        }\n\n        fn end_string_eval(\n            out: &mut fmt::Formatter<'_>,\n            _config: &Self::Config,\n            _format: &Self::Format,\n        ) -> fmt::Result {\n            out.write_char('}')?;\n            Ok(())\n        }\n\n        fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n            // See: https://kotlinlang.org/docs/basic-types.html#escaped-strings\n            for c in input.chars() {\n                match c {\n                    '\\t' => out.write_str(\"\\\\t\")?,\n                    '\\u{0008}' => out.write_str(\"\\\\b\")?, // Backspace\n                    '\\n' => out.write_str(\"\\\\n\")?,\n                    '\\r' => out.write_str(\"\\\\r\")?,\n                    '\\'' => out.write_str(\"\\\\'\")?,\n                    '\"' => out.write_str(\"\\\\\\\"\")?,\n                    '\\\\' => out.write_str(\"\\\\\\\\\")?,\n                    '$' => out.write_str(\"\\\\$\")?,\n                    c if c.is_ascii() && !c.is_control() => out.write_char(c)?,\n                    c => {\n                        // Encode non-ascii characters as UTF-16 surrogate pairs\n                        for unit in c.encode_utf16(&mut [0u16; 2]) {\n                            write!(out, \"\\\\u{unit:04x}\")?;\n                        }\n                    }\n                }\n            }\n\n            Ok(())\n        }\n\n        fn format_file(\n            tokens: &Tokens,\n            out: &mut fmt::Formatter<'_>,\n            config: &Self::Config,\n        ) -> fmt::Result {\n            let mut header = Tokens::new();\n            let mut format = Format::default();\n\n            if let Some(ref package) = config.package {\n                // package declarations in Kotlin do not have semicolons\n                quote_in!(header => package $package);\n                header.line();\n            }\n\n            Self::imports(&mut header, tokens, config, &mut format.imported);\n            header.format(out, config, &format)?;\n            tokens.format(out, config, &format)?;\n            Ok(())\n        }\n    }\n\n    Import(Import) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, config: &Config, format: &Format) -> fmt::Result {\n            let file_package = config.package.as_ref().map(|p| p.as_ref());\n            let imported = format.imported.get(self.name.as_ref()).map(String::as_str);\n            let current_package = Some(self.package.as_ref());\n\n            // Determine if we need to use the fully qualified name (FQN).\n            // Use FQN if the class is not in the current package and has not been imported.\n            // Or if a class with the same name has been imported from a different package.\n            if file_package != current_package && imported != current_package {\n                out.write_str(self.package.as_ref())?;\n                out.write_str(\".\")?;\n            }\n\n            out.write_str(&self.name)?;\n            Ok(())\n        }\n    }\n}\n\n/// Formatting state for Kotlin.\n#[derive(Debug, Default)]\npub struct Format {\n    /// Types which have been imported into the local namespace.\n    /// Maps a simple name to its full package.\n    imported: BTreeMap<String, String>,\n}\n\n/// Configuration for Kotlin.\n#[derive(Debug, Default)]\npub struct Config {\n    /// Package to use.\n    package: Option<ItemStr>,\n}\n\nimpl Config {\n    /// Configure package to use for the file generated.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    /// use genco::fmt;\n    ///\n    /// let list = kotlin::import(\"kotlin.collections\", \"List\");\n    ///\n    /// let toks = quote!($list);\n    ///\n    /// let config = kotlin::Config::default().with_package(\"com.example\");\n    /// let fmt = fmt::Config::from_lang::<Kotlin>();\n    ///\n    /// let mut w = fmt::VecWriter::new();\n    ///\n    /// toks.format_file(&mut w.as_formatter(&fmt), &config)?;\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"package com.example\",\n    ///         \"\",\n    ///         \"import kotlin.collections.List\",\n    ///         \"\",\n    ///         \"List\",\n    ///     ],\n    ///     w.into_vec(),\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn with_package<P>(self, package: P) -> Self\n    where\n        P: Into<ItemStr>,\n    {\n        Self {\n            package: Some(package.into()),\n        }\n    }\n}\n\n/// An import of a Kotlin type, like `import kotlin.collections.List`.\n///\n/// Created through the [import()] function.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct Import {\n    /// Package of the class.\n    package: ItemStr,\n    /// Name of the class.\n    name: ItemStr,\n}\n\nimpl Kotlin {\n    /// Gathers and writes import statements to the header.\n    fn imports(\n        out: &mut Tokens,\n        tokens: &Tokens,\n        config: &Config,\n        imported: &mut BTreeMap<String, String>,\n    ) {\n        let mut to_import = BTreeSet::new();\n        let file_package = config.package.as_ref().map(|p| p.as_ref());\n\n        for import in tokens.iter_lang() {\n            // Don't import if the type is in the current package\n            if Some(import.package.as_ref()) == file_package {\n                continue;\n            }\n\n            // Don't import if a class with the same name is already imported from another package.\n            if let Some(existing_package) = imported.get(import.name.as_ref()) {\n                if existing_package != import.package.as_ref() {\n                    continue;\n                }\n            }\n\n            to_import.insert(import.clone());\n        }\n\n        if to_import.is_empty() {\n            return;\n        }\n\n        for import in to_import {\n            // import statements in Kotlin do not have semicolons\n            quote_in!(*out => import $(&import.package).$(&import.name));\n            out.push();\n            imported.insert(import.name.to_string(), import.package.to_string());\n        }\n\n        out.line();\n    }\n}\n\n/// Create a new Kotlin import.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let list = kotlin::import(\"kotlin.collections\", \"List\");\n/// let map = kotlin::import(\"kotlin.collections\", \"Map\");\n///\n/// let toks = quote! {\n///     val a: $list<String>\n///     val b: $map<String, Int>\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"import kotlin.collections.List\",\n///         \"import kotlin.collections.Map\",\n///         \"\",\n///         \"val a: List<String>\",\n///         \"val b: Map<String, Int>\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn import<P, N>(package: P, name: N) -> Import\nwhere\n    P: Into<ItemStr>,\n    N: Into<ItemStr>,\n{\n    Import {\n        package: package.into(),\n        name: name.into(),\n    }\n}\n"
  },
  {
    "path": "src/lang/mod.rs",
    "content": "//! Language specialization for genco\n//!\n//! This module contains sub-modules which provide implementations of the [Lang]\n//! trait to configure genco for various programming languages.\n//!\n//! This module also provides a dummy [Lang] implementation for `()`.\n//!\n//! This allows `()` to be used as a quick and dirty way to do formatting,\n//! usually for examples.\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let tokens: Tokens = quote!(hello world);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\npub mod c;\npub mod csharp;\npub mod dart;\npub mod go;\npub mod java;\n\npub mod js;\npub mod kotlin;\npub mod nix;\npub mod python;\npub mod rust;\npub mod swift;\n\npub use self::c::C;\npub use self::csharp::Csharp;\npub use self::dart::Dart;\npub use self::go::Go;\npub use self::java::Java;\npub use self::js::JavaScript;\npub use self::kotlin::Kotlin;\npub use self::nix::Nix;\npub use self::python::Python;\npub use self::rust::Rust;\npub use self::swift::Swift;\n\nuse core::fmt::Write as _;\n\nuse crate::fmt;\nuse crate::Tokens;\n\n/// Trait to implement for language specialization.\n///\n/// The various language implementations can be found in the [lang][self]\n/// module.\npub trait Lang: Sized {\n    /// Configuration associated with building a formatting element.\n    type Config;\n    /// State being used during formatting.\n    type Format: Default;\n    /// The type used when resolving imports.\n    type Item: LangItem<Self>;\n\n    /// Provide the default indentation.\n    fn default_indentation() -> fmt::Indentation {\n        fmt::Indentation::Space(4)\n    }\n\n    /// Start a string quote.\n    fn open_quote(\n        out: &mut fmt::Formatter<'_>,\n        _config: &Self::Config,\n        _format: &Self::Format,\n        _has_eval: bool,\n    ) -> fmt::Result {\n        out.write_char('\"')?;\n        Ok(())\n    }\n\n    /// End a string quote.\n    fn close_quote(\n        out: &mut fmt::Formatter<'_>,\n        _config: &Self::Config,\n        _format: &Self::Format,\n        _has_eval: bool,\n    ) -> fmt::Result {\n        out.write_char('\"')?;\n        Ok(())\n    }\n\n    /// A simple, single-literal string evaluation.\n    fn string_eval_literal(\n        out: &mut fmt::Formatter<'_>,\n        config: &Self::Config,\n        format: &Self::Format,\n        literal: &str,\n    ) -> fmt::Result {\n        Self::start_string_eval(out, config, format)?;\n        out.write_str(literal)?;\n        Self::end_string_eval(out, config, format)?;\n        Ok(())\n    }\n\n    /// Start a string-interpolated eval.\n    fn start_string_eval(\n        _out: &mut fmt::Formatter<'_>,\n        _config: &Self::Config,\n        _format: &Self::Format,\n    ) -> fmt::Result {\n        Ok(())\n    }\n\n    /// End a string interpolated eval.\n    fn end_string_eval(\n        _out: &mut fmt::Formatter<'_>,\n        _config: &Self::Config,\n        _format: &Self::Format,\n    ) -> fmt::Result {\n        Ok(())\n    }\n\n    /// Performing string quoting according to language convention.\n    fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n        out.write_str(input)\n    }\n\n    /// Write a file according to the specified language convention.\n    fn format_file(\n        tokens: &Tokens<Self>,\n        out: &mut fmt::Formatter<'_>,\n        config: &Self::Config,\n    ) -> fmt::Result {\n        let format = Self::Format::default();\n        tokens.format(out, config, &format)\n    }\n}\n\n/// Marker trait indicating that a language supports\n/// [quoted string interpolation].\n///\n/// [quoted string interpolation]: https://docs.rs/genco/0/genco/macro.quote.html#quoted-string-interpolation\npub trait LangSupportsEval: Lang {}\n\n/// Dummy implementation for a language.\nimpl Lang for () {\n    type Config = ();\n    type Format = ();\n    type Item = ();\n}\n\nimpl<L> LangItem<L> for ()\nwhere\n    L: Lang,\n{\n    fn format(&self, _: &mut fmt::Formatter<'_>, _: &L::Config, _: &L::Format) -> fmt::Result {\n        Ok(())\n    }\n}\n\n/// A type-erased holder for language-specific items.\n///\n/// Carries formatting and coercion functions like [LangItem][LangItem::format]\n/// to allow language specific processing to work.\npub trait LangItem<L>\nwhere\n    L: Lang,\n{\n    /// Format the language item appropriately.\n    fn format(\n        &self,\n        fmt: &mut fmt::Formatter<'_>,\n        config: &L::Config,\n        format: &L::Format,\n    ) -> fmt::Result;\n}\n\n/// Escape the given string according to a C-family escape sequence.\n///\n/// See <https://en.wikipedia.org/wiki/Escape_sequences_in_C>.\n///\n/// This is one of the more common escape sequences and is provided here so you\n/// can use it if a language you've implemented requires it.\npub fn c_family_write_quoted(out: &mut fmt::Formatter, input: &str) -> fmt::Result {\n    for c in input.chars() {\n        match c {\n            // alert (bell)\n            '\\u{0007}' => out.write_str(\"\\\\a\")?,\n            // backspace\n            '\\u{0008}' => out.write_str(\"\\\\b\")?,\n            // form feed\n            '\\u{0012}' => out.write_str(\"\\\\f\")?,\n            // new line\n            '\\n' => out.write_str(\"\\\\n\")?,\n            // carriage return\n            '\\r' => out.write_str(\"\\\\r\")?,\n            // horizontal tab\n            '\\t' => out.write_str(\"\\\\t\")?,\n            // vertical tab\n            '\\u{0011}' => out.write_str(\"\\\\v\")?,\n            '\\'' => out.write_str(\"\\\\'\")?,\n            '\"' => out.write_str(\"\\\\\\\"\")?,\n            '\\\\' => out.write_str(\"\\\\\\\\\")?,\n            ' ' => out.write_char(' ')?,\n            c if c.is_ascii() => {\n                if !c.is_control() {\n                    out.write_char(c)?\n                } else {\n                    write!(out, \"\\\\x{:02x}\", c as u32)?;\n                }\n            }\n            c if (c as u32) < 0x10000 => {\n                write!(out, \"\\\\u{:04x}\", c as u32)?;\n            }\n            c => {\n                write!(out, \"\\\\U{:08x}\", c as u32)?;\n            }\n        };\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/lang/nix.rs",
    "content": "//! Nix\n\nuse core::fmt::Write as _;\n\nuse alloc::collections::BTreeSet;\nuse alloc::string::ToString;\n\nuse crate as genco;\nuse crate::fmt;\nuse crate::quote_in;\nuse crate::tokens::ItemStr;\n\n/// Tokens\npub type Tokens = crate::Tokens<Nix>;\n\nimpl_lang! {\n    /// Nix\n    pub Nix {\n        type Config = Config;\n        type Format = Format;\n        type Item = Import;\n\n        fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n            super::c_family_write_quoted(out, input)\n        }\n\n        fn format_file(\n            tokens: &Tokens,\n            out: &mut fmt::Formatter<'_>,\n            config: &Self::Config,\n        ) -> fmt::Result {\n            let mut header = Tokens::new();\n\n            if !config.scoped {\n                Self::arguments(&mut header, tokens);\n            }\n            Self::withs(&mut header, tokens);\n            Self::imports(&mut header, tokens);\n            let format = Format::default();\n            header.format(out, config, &format)?;\n            tokens.format(out, config, &format)?;\n            Ok(())\n        }\n    }\n\n    Import(Import) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, _: &Config, _: &Format) -> fmt::Result {\n            match self {\n                Import::Argument(import) => out.write_str(&import.0)?,\n                Import::Inherit(import) => out.write_str(&import.name)?,\n                Import::Variable(import) => out.write_str(&import.name)?,\n                Import::With(import) => out.write_str(&import.name)?,\n            }\n            Ok(())\n        }\n    }\n}\n\n/// Import\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub enum Import {\n    /// Argument\n    Argument(ImportArgument),\n    /// Inherit\n    Inherit(ImportInherit),\n    /// Variable\n    Variable(ImportVariable),\n    /// With\n    With(ImportWith),\n}\n\n/// ImportArgument\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct ImportArgument(ItemStr);\n\n/// ImportInherit\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct ImportInherit {\n    /// Path\n    path: ItemStr,\n    /// Name\n    name: ItemStr,\n}\n\n/// ImportVariable\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct ImportVariable {\n    /// Name\n    name: ItemStr,\n    /// Value\n    value: Tokens,\n}\n\n/// ImportWith\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct ImportWith {\n    /// Argument\n    argument: ItemStr,\n    /// Name\n    name: ItemStr,\n}\n\n/// Format\n#[derive(Debug, Default)]\npub struct Format {}\n\n/// Nix formatting configuration.\n#[derive(Debug, Default)]\npub struct Config {\n    scoped: bool,\n}\n\nimpl Config {\n    /// With scoped\n    pub fn with_scoped(self, scoped: bool) -> Self {\n        Self { scoped }\n    }\n}\n\nimpl Nix {\n    fn arguments(out: &mut Tokens, tokens: &Tokens) {\n        let mut arguments = BTreeSet::new();\n\n        for imports in tokens.iter_lang() {\n            match imports {\n                Import::Argument(argument) => {\n                    arguments.insert(argument.0.to_string());\n                }\n                Import::Inherit(inherit) => {\n                    let argument = inherit.path.split('.').next();\n                    if let Some(a) = argument {\n                        arguments.insert(a.to_string());\n                    }\n                }\n                Import::Variable(variable) => {\n                    let value = &variable.value;\n                    for import in value.iter_lang() {\n                        match import {\n                            Import::Inherit(inherit) => {\n                                let argument = inherit.path.split('.').next();\n                                if let Some(a) = argument {\n                                    arguments.insert(a.to_string());\n                                }\n                            }\n                            Import::Argument(argument) => {\n                                arguments.insert(argument.0.to_string());\n                            }\n                            _ => (),\n                        }\n                    }\n                }\n                Import::With(with) => {\n                    let argument = with.argument.split('.').next();\n                    if let Some(a) = argument {\n                        arguments.insert(a.to_string());\n                    }\n                }\n            }\n        }\n\n        out.append(\"{\");\n        out.push();\n        out.indent();\n\n        for argument in arguments {\n            quote_in!(*out => $argument,);\n            out.push();\n        }\n\n        out.append(\"...\");\n        out.push();\n\n        out.unindent();\n        out.append(\"}:\");\n        out.push();\n\n        out.line();\n    }\n\n    fn withs(out: &mut Tokens, tokens: &Tokens) {\n        let mut withs = BTreeSet::new();\n\n        for imports in tokens.iter_lang() {\n            if let Import::With(with) = imports {\n                withs.insert(&with.argument);\n            }\n        }\n\n        if withs.is_empty() {\n            return;\n        }\n\n        for name in withs {\n            quote_in!(*out => with $name;);\n            out.push();\n        }\n\n        out.line();\n    }\n\n    fn imports(out: &mut Tokens, tokens: &Tokens) {\n        let mut inherits = BTreeSet::new();\n        let mut variables = BTreeSet::new();\n\n        for imports in tokens.iter_lang() {\n            match imports {\n                Import::Inherit(inherit) => {\n                    inherits.insert((&inherit.path, &inherit.name));\n                }\n                Import::Variable(variable) => {\n                    let value = &variable.value;\n                    for import in value.iter_lang() {\n                        if let Import::Inherit(inherit) = import {\n                            inherits.insert((&inherit.path, &inherit.name));\n                        }\n                    }\n                    variables.insert((&variable.name, &variable.value));\n                }\n                _ => (),\n            }\n        }\n\n        if inherits.is_empty() && variables.is_empty() {\n            return;\n        }\n\n        out.append(\"let\");\n        out.push();\n        out.indent();\n\n        for (path, name) in inherits {\n            quote_in!(*out => inherit ($path) $name;);\n            out.push();\n        }\n\n        for (name, value) in variables {\n            quote_in!(*out => $name = $value;);\n            out.push();\n        }\n\n        out.unindent();\n        out.append(\"in\");\n        out.push();\n\n        out.line();\n    }\n}\n\n/// ```\n/// use genco::prelude::*;\n///\n/// let cell = nix::argument(\"cell\");\n///\n/// let toks = quote! {\n///     $cell\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"{\",\n///         \"    cell,\",\n///         \"    ...\",\n///         \"}:\",\n///         \"\",\n///         \"cell\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn argument<M>(name: M) -> Import\nwhere\n    M: Into<ItemStr>,\n{\n    Import::Argument(ImportArgument(name.into()))\n}\n\n/// ```\n/// use genco::prelude::*;\n///\n/// let nixpkgs = nix::inherit(\"inputs\", \"nixpkgs\");\n///\n/// let toks = quote! {\n///     $nixpkgs\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"{\",\n///         \"    inputs,\",\n///         \"    ...\",\n///         \"}:\",\n///         \"\",\n///         \"let\",\n///         \"    inherit (inputs) nixpkgs;\",\n///         \"in\",\n///         \"\",\n///         \"nixpkgs\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn inherit<M, N>(path: M, name: N) -> Import\nwhere\n    M: Into<ItemStr>,\n    N: Into<ItemStr>,\n{\n    Import::Inherit(ImportInherit {\n        path: path.into(),\n        name: name.into(),\n    })\n}\n\n/// ```\n/// use genco::prelude::*;\n///\n/// let nixpkgs = &nix::inherit(\"inputs\", \"nixpkgs\");\n///\n/// let pkgs = nix::variable(\"pkgs\", quote! {\n///     import $nixpkgs {\n///         inherit ($nixpkgs) system;\n///         config.allowUnfree = true;\n///     }\n/// });\n///\n/// let toks = quote! {\n///     $pkgs\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"{\",\n///         \"    inputs,\",\n///         \"    ...\",\n///         \"}:\",\n///         \"\",\n///         \"let\",\n///         \"    inherit (inputs) nixpkgs;\",\n///         \"    pkgs = import nixpkgs {\",\n///         \"        inherit (nixpkgs) system;\",\n///         \"        config.allowUnfree = true;\",\n///         \"    };\",\n///         \"in\",\n///         \"\",\n///         \"pkgs\"\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn variable<M, N>(name: M, value: N) -> Import\nwhere\n    M: Into<ItemStr>,\n    N: Into<Tokens>,\n{\n    Import::Variable(ImportVariable {\n        name: name.into(),\n        value: value.into(),\n    })\n}\n\n/// ```\n/// use genco::prelude::*;\n///\n/// let concat_map = nix::with(\"inputs.nixpkgs.lib\", \"concatMap\");\n/// let list_to_attrs = nix::with(\"inputs.nixpkgs.lib\", \"listToAttrs\");\n///\n/// let toks = quote! {\n///     $list_to_attrs $concat_map\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"{\",\n///         \"    inputs,\",\n///         \"    ...\",\n///         \"}:\",\n///         \"\",\n///         \"with inputs.nixpkgs.lib;\",\n///         \"\",\n///         \"listToAttrs concatMap\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn with<M, N>(argument: M, name: N) -> Import\nwhere\n    M: Into<ItemStr>,\n    N: Into<ItemStr>,\n{\n    Import::With(ImportWith {\n        argument: argument.into(),\n        name: name.into(),\n    })\n}\n"
  },
  {
    "path": "src/lang/python.rs",
    "content": "//! Specialization for Python code generation.\n//!\n//! # Examples\n//!\n//! String quoting in Python:\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: python::Tokens = quote!(\"hello \\n world\");\n//! assert_eq!(\"\\\"hello \\\\n world\\\"\", toks.to_string()?);\n//!\n//! let toks: python::Tokens = quote!($(quoted(\"hello \\n world\")));\n//! assert_eq!(\"\\\"hello \\\\n world\\\"\", toks.to_string()?);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\nuse core::fmt::Write as _;\n\nuse alloc::collections::{BTreeMap, BTreeSet};\nuse alloc::vec::Vec;\n\nuse crate as genco;\nuse crate::fmt;\nuse crate::tokens::ItemStr;\nuse crate::{quote, quote_in};\n\n/// Tokens container specialization for Python.\npub type Tokens = crate::Tokens<Python>;\n\nimpl_lang! {\n    /// Language specialization for Python.\n    pub Python {\n        type Config = Config;\n        type Format = Format;\n        type Item = Any;\n\n        fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n            // From: https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals\n            super::c_family_write_quoted(out, input)\n        }\n\n        fn format_file(\n            tokens: &Tokens,\n            out: &mut fmt::Formatter<'_>,\n            config: &Self::Config,\n        ) -> fmt::Result {\n            let mut imports = Tokens::new();\n            Self::imports(&mut imports, tokens);\n            let format = Format::default();\n            imports.format(out, config, &format)?;\n            tokens.format(out, config, &format)?;\n            Ok(())\n        }\n    }\n\n    Import(Import) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, _: &Config, _: &Format) -> fmt::Result {\n            if let TypeModule::Qualified { module, alias }  = &self.module {\n                out.write_str(alias.as_ref().unwrap_or(module))?;\n                out.write_str(SEP)?;\n            }\n\n            let name = match &self.alias {\n                Some(alias) => alias,\n                None => &self.name,\n            };\n\n            out.write_str(name)?;\n            Ok(())\n        }\n    }\n\n    ImportModule(ImportModule) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, _: &Config, _: &Format) -> fmt::Result {\n            let module = match &self.alias {\n                Some(alias) => alias,\n                None => &self.module,\n            };\n\n            out.write_str(module)?;\n            Ok(())\n        }\n    }\n}\n\n/// Formatting state for python.\n#[derive(Debug, Default)]\npub struct Format {}\n/// Configuration for python.\n#[derive(Debug, Default)]\npub struct Config {}\n\nstatic SEP: &str = \".\";\n\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\nenum TypeModule {\n    Unqualified {\n        /// Name of imported module.\n        module: ItemStr,\n    },\n    Qualified {\n        /// Name of imported module.\n        module: ItemStr,\n        /// Alias of imported module.\n        alias: Option<ItemStr>,\n    },\n}\n\nimpl TypeModule {\n    fn qualified(self) -> Self {\n        match self {\n            Self::Unqualified { module } => Self::Qualified {\n                module,\n                alias: None,\n            },\n            other => other,\n        }\n    }\n\n    fn with_alias<T>(self, alias: T) -> Self\n    where\n        T: Into<ItemStr>,\n    {\n        match self {\n            Self::Qualified { module, .. } | Self::Unqualified { module } => Self::Qualified {\n                module,\n                alias: Some(alias.into()),\n            },\n        }\n    }\n}\n\n/// The import of a Python name `from module import foo`.\n///\n/// Created through the [import()] function.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct Import {\n    /// Module of the imported name.\n    module: TypeModule,\n    /// The name that was imported.\n    name: ItemStr,\n    /// Alias of the name imported.\n    alias: Option<ItemStr>,\n}\n\nimpl Import {\n    /// Configure the importe name with the specified alias.\n    ///\n    /// This implised that the import is not qualified.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let toks = quote! {\n    ///     $(python::import(\"collections\", \"namedtuple\").with_alias(\"nt\"))\n    /// };\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"from collections import namedtuple as nt\",\n    ///         \"\",\n    ///         \"nt\",\n    ///     ],\n    ///     toks.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn with_alias<T>(self, alias: T) -> Self\n    where\n        T: Into<ItemStr>,\n    {\n        Self {\n            alias: Some(alias.into()),\n            ..self\n        }\n    }\n\n    /// Indicate that the import is qualified (module prefixed).\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let toks = quote! {\n    ///     $(python::import(\"collections\", \"namedtuple\").qualified())\n    /// };\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"import collections\",\n    ///         \"\",\n    ///         \"collections.namedtuple\",\n    ///     ],\n    ///     toks.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn qualified(self) -> Self {\n        Self {\n            module: self.module.qualified(),\n            ..self\n        }\n    }\n\n    /// Configure the imported name with the specified alias.\n    ///\n    /// This implies that the import is qualified.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let toks = quote! {\n    ///     $(python::import(\"collections\", \"namedtuple\").with_module_alias(\"c\"))\n    /// };\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"import collections as c\",\n    ///         \"\",\n    ///         \"c.namedtuple\",\n    ///     ],\n    ///     toks.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn with_module_alias<T>(self, module_alias: T) -> Self\n    where\n        T: Into<ItemStr>,\n    {\n        Self {\n            module: self.module.with_alias(module_alias),\n            ..self\n        }\n    }\n}\n\n/// The import of a Python module `import module`.\n///\n/// Created through the [import_module()] function.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct ImportModule {\n    /// Module of the imported name.\n    module: ItemStr,\n\n    /// Alias of module imported.\n    alias: Option<ItemStr>,\n}\n\nimpl ImportModule {\n    /// Set alias for imported module.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let toks = quote! {\n    ///     $(python::import_module(\"collections\").with_alias(\"c\"))\n    /// };\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"import collections as c\",\n    ///         \"\",\n    ///         \"c\",\n    ///     ],\n    ///     toks.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn with_alias<N>(self, new_alias: N) -> Self\n    where\n        N: Into<ItemStr>,\n    {\n        Self {\n            alias: Some(new_alias.into()),\n            ..self\n        }\n    }\n}\n\nimpl Python {\n    fn imports(out: &mut Tokens, tokens: &Tokens) {\n        let mut imported_from = BTreeMap::new();\n        let mut imports = BTreeSet::new();\n\n        for import in tokens.iter_lang() {\n            match import.kind() {\n                AnyKind::Import(Import {\n                    module,\n                    alias,\n                    name,\n                }) => match module {\n                    TypeModule::Qualified { module, alias } => {\n                        imports.insert((module, alias));\n                    }\n                    TypeModule::Unqualified { module } => {\n                        imported_from\n                            .entry(module)\n                            .or_insert_with(BTreeSet::new)\n                            .insert((name, alias));\n                    }\n                },\n                AnyKind::ImportModule(ImportModule { module, alias }) => {\n                    imports.insert((module, alias));\n                }\n            }\n        }\n\n        if imported_from.is_empty() && imports.is_empty() {\n            return;\n        }\n\n        for (module, imports) in imported_from {\n            out.push();\n\n            let imports = imports\n                .into_iter()\n                .map(|(name, alias)| quote!($name$(if let Some(a) = alias => $[' ']as $a)))\n                .collect::<Vec<_>>();\n\n            if imports.len() == 1 {\n                quote_in! {*out =>\n                    from $module import $(imports.into_iter().next())\n                }\n            } else {\n                quote_in! {*out =>\n                    from $module import $(for i in imports join (, ) => $i)\n                }\n            }\n        }\n\n        for (module, alias) in imports {\n            out.push();\n\n            quote_in! {*out =>\n                import $module$(if let Some(a) = alias => $[' ']as $a)\n            }\n        }\n\n        out.line();\n    }\n}\n\n/// The import of a Python name `from module import foo`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let toks = quote! {\n///     $(python::import(\"collections\", \"namedtuple\").with_alias(\"nt\"))\n///     $(python::import(\"collections\", \"namedtuple\"))\n///     $(python::import(\"collections\", \"namedtuple\").qualified())\n///     $(python::import(\"collections\", \"namedtuple\").with_module_alias(\"c\"))\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"from collections import namedtuple, namedtuple as nt\",\n///         \"import collections\",\n///         \"import collections as c\",\n///         \"\",\n///         \"nt\",\n///         \"namedtuple\",\n///         \"collections.namedtuple\",\n///         \"c.namedtuple\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn import<M, N>(module: M, name: N) -> Import\nwhere\n    M: Into<ItemStr>,\n    N: Into<ItemStr>,\n{\n    Import {\n        module: TypeModule::Unqualified {\n            module: module.into(),\n        },\n        name: name.into(),\n        alias: None,\n    }\n}\n\n/// The import of a Python module `import module`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let toks = quote! {\n///     $(python::import_module(\"collections\"))\n///     $(python::import_module(\"collections\").with_alias(\"c\"))\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"import collections\",\n///         \"import collections as c\",\n///         \"\",\n///         \"collections\",\n///         \"c\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn import_module<M>(module: M) -> ImportModule\nwhere\n    M: Into<ItemStr>,\n{\n    ImportModule {\n        module: module.into(),\n        alias: None,\n    }\n}\n"
  },
  {
    "path": "src/lang/rust.rs",
    "content": "//! Specialization for Rust code generation.\n//!\n//! # Examples\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: rust::Tokens = quote! {\n//!     fn foo() -> u32 {\n//!         42\n//!     }\n//! };\n//!\n//! assert_eq!(\n//!     vec![\n//!         \"fn foo() -> u32 {\",\n//!         \"    42\",\n//!         \"}\",\n//!     ],\n//!     toks.to_file_vec()?\n//! );\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n//!\n//! # String Quoting in Rust\n//!\n//! Rust uses UTF-8 internally, string quoting is with the exception of escape\n//! sequences a one-to-one translation.\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: rust::Tokens = quote!(\"start π 😊 \\n \\x7f ÿ $ end\");\n//! assert_eq!(\"\\\"start π 😊 \\\\n \\\\x7f ÿ $ end\\\"\", toks.to_string()?);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\nuse core::fmt::Write as _;\n\nuse alloc::collections::{BTreeMap, BTreeSet, VecDeque};\n\nuse crate::fmt;\nuse crate::tokens::ItemStr;\n\nconst SEP: &str = \"::\";\n\n/// Tokens container specialization for Rust.\npub type Tokens = crate::Tokens<Rust>;\n\nimpl_lang! {\n    /// Language specialization for Rust.\n    pub Rust {\n        type Config = Config;\n        type Format = Format;\n        type Item = Import;\n\n        fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n            // From: https://doc.rust-lang.org/reference/tokens.html#literals\n\n            for c in input.chars() {\n                match c {\n                    // new line\n                    '\\n' => out.write_str(\"\\\\n\")?,\n                    // carriage return\n                    '\\r' => out.write_str(\"\\\\r\")?,\n                    // horizontal tab\n                    '\\t' => out.write_str(\"\\\\t\")?,\n                    // backslash\n                    '\\\\' => out.write_str(\"\\\\\\\\\")?,\n                    // null\n                    '\\0' => out.write_str(\"\\\\0\")?,\n                    // Note: only relevant if we were to use single-quoted strings.\n                    // '\\'' => out.write_str(\"\\\\'\")?,\n                    '\"' => out.write_str(\"\\\\\\\"\")?,\n                    c if !c.is_control() => out.write_char(c)?,\n                    c if (c as u32) < 0x80 => {\n                        write!(out, \"\\\\x{:02x}\", c as u32)?;\n                    }\n                    c => {\n                        write!(out, \"\\\\u{{{:04x}}}\", c as u32)?;\n                    }\n                };\n            }\n\n            Ok(())\n        }\n\n        fn format_file(\n            tokens: &Tokens,\n            out: &mut fmt::Formatter<'_>,\n            config: &Self::Config,\n        ) -> fmt::Result {\n            let mut imports: Tokens = Tokens::new();\n            Self::imports(&mut imports, config, tokens);\n\n            let format = Format::default();\n            imports.format(out, config, &format)?;\n            tokens.format(out, config, &format)?;\n            Ok(())\n        }\n    }\n\n    Import(Import) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, config: &Config, _: &Format) -> fmt::Result {\n            match &self.module {\n                Module::Module {\n                    import: Some(ImportMode::Direct),\n                    ..\n                } => {\n                    self.write_direct(out)?;\n                }\n                Module::Module {\n                    import: Some(ImportMode::Qualified),\n                    module,\n                } => {\n                    self.write_prefixed(out, module)?;\n                }\n                Module::Module {\n                    import: None,\n                    module,\n                } => match &config.default_import {\n                    ImportMode::Direct => self.write_direct(out)?,\n                    ImportMode::Qualified => self.write_prefixed(out, module)?,\n                },\n                Module::Aliased {\n                    alias: ref module, ..\n                } => {\n                    out.write_str(module)?;\n                    out.write_str(SEP)?;\n                    out.write_str(&self.name)?;\n                }\n            }\n\n            Ok(())\n        }\n    }\n}\n\n/// Format state for Rust.\n#[derive(Debug, Default)]\npub struct Format {}\n\n/// Language configuration for Rust.\n#[derive(Debug)]\npub struct Config {\n    default_import: ImportMode,\n}\n\nimpl Config {\n    /// Configure the default import mode to use.\n    ///\n    /// See [Import] for more details.\n    pub fn with_default_import(self, default_import: ImportMode) -> Self {\n        Self { default_import }\n    }\n}\n\nimpl Default for Config {\n    fn default() -> Self {\n        Config {\n            default_import: ImportMode::Direct,\n        }\n    }\n}\n\n/// The import mode to use when generating import statements.\n#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]\npub enum ImportMode {\n    /// Import names without a module prefix.\n    ///\n    /// so for `std::fmt::Debug` it would import `std::fmt::Debug`, and use\n    /// `Debug`.\n    Direct,\n    /// Import qualified names with a module prefix.\n    ///\n    /// so for `std::fmt::Debug` it would import `std::fmt`, and use\n    /// `fmt::Debug`.\n    Qualified,\n}\n\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\nenum Module {\n    /// Type imported directly from module with the specified mode.\n    Module {\n        import: Option<ImportMode>,\n        module: ItemStr,\n    },\n    /// Prefixed with an alias.\n    Aliased { module: ItemStr, alias: ItemStr },\n}\n\nimpl Module {\n    /// Convert into an aliased import, or keep as same in case that's not\n    /// feasible.\n    fn into_module_aliased<A>(self, alias: A) -> Self\n    where\n        A: Into<ItemStr>,\n    {\n        match self {\n            Self::Module { module, .. } => Self::Aliased {\n                module,\n                alias: alias.into(),\n            },\n            other => other,\n        }\n    }\n\n    /// Aliasing a type explicitly means you no longer want to import it by\n    /// module. Set the correct import here.\n    fn into_aliased(self) -> Self {\n        match self {\n            Self::Module { module, .. } => Self::Module {\n                import: Some(ImportMode::Direct),\n                module,\n            },\n            other => other,\n        }\n    }\n\n    /// Switch to a direct import mode.\n    ///\n    /// See [ImportMode::Direct].\n    fn direct(self) -> Self {\n        match self {\n            Self::Module { module, .. } => Self::Module {\n                module,\n                import: Some(ImportMode::Direct),\n            },\n            other => other,\n        }\n    }\n\n    /// Switch into a qualified import mode.\n    ///\n    /// See [ImportMode::Qualified].\n    fn qualified(self) -> Self {\n        match self {\n            Self::Module { module, .. } => Self::Module {\n                module,\n                import: Some(ImportMode::Qualified),\n            },\n            other => other,\n        }\n    }\n}\n\n/// The import of a Rust type `use std::collections::HashMap`.\n///\n/// Created through the [import()] function.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct Import {\n    /// How the type is imported.\n    module: Module,\n    /// Name of type.\n    name: ItemStr,\n    /// Alias to use for the type.\n    alias: Option<ItemStr>,\n}\n\nimpl Import {\n    /// Alias the given type as it's imported.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let ty = rust::import(\"std::fmt\", \"Debug\").with_alias(\"FmtDebug\");\n    ///\n    /// let toks = quote!($ty);\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"use std::fmt::Debug as FmtDebug;\",\n    ///         \"\",\n    ///         \"FmtDebug\",\n    ///     ],\n    ///     toks.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn with_alias<A: Into<ItemStr>>(self, alias: A) -> Self {\n        Self {\n            module: self.module.into_aliased(),\n            alias: Some(alias.into()),\n            ..self\n        }\n    }\n\n    /// Alias the module being imported.\n    ///\n    /// This also implies that the import is [qualified()].\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let ty = rust::import(\"std::fmt\", \"Debug\").with_module_alias(\"other\");\n    ///\n    /// let toks = quote!($ty);\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"use std::fmt as other;\",\n    ///         \"\",\n    ///         \"other::Debug\",\n    ///     ],\n    ///     toks.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    ///\n    /// [qualified()]: Self::qualified()\n    pub fn with_module_alias<A: Into<ItemStr>>(self, alias: A) -> Self {\n        Self {\n            module: self.module.into_module_aliased(alias),\n            ..self\n        }\n    }\n\n    /// Switch to a qualified import mode.\n    ///\n    /// See [ImportMode::Qualified].\n    ///\n    /// So importing `std::fmt::Debug` will cause the module to be referenced as\n    /// `fmt::Debug` instead of `Debug`.\n    ///\n    /// This is implied if [with_module_alias()][Self::with_module_alias()] is used.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let ty = rust::import(\"std::fmt\", \"Debug\").qualified();\n    ///\n    /// let toks = quote!($ty);\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"use std::fmt;\",\n    ///         \"\",\n    ///         \"fmt::Debug\",\n    ///     ],\n    ///     toks.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn qualified(self) -> Self {\n        Self {\n            module: self.module.qualified(),\n            ..self\n        }\n    }\n\n    /// Switch into a direct import mode.\n    ///\n    /// See [ImportMode::Direct].\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let ty = rust::import(\"std::fmt\", \"Debug\").direct();\n    ///\n    /// let toks = quote!($ty);\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"use std::fmt::Debug;\",\n    ///         \"\",\n    ///         \"Debug\",\n    ///     ],\n    ///     toks.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn direct(self) -> Self {\n        Self {\n            module: self.module.direct(),\n            ..self\n        }\n    }\n\n    /// Write the direct name of the type.\n    fn write_direct(&self, out: &mut fmt::Formatter<'_>) -> fmt::Result {\n        if let Some(alias) = &self.alias {\n            out.write_str(alias)\n        } else {\n            out.write_str(&self.name)\n        }\n    }\n\n    /// Write the prefixed name of the type.\n    fn write_prefixed(&self, out: &mut fmt::Formatter<'_>, module: &ItemStr) -> fmt::Result {\n        if let Some(module) = module.rsplit(SEP).next() {\n            out.write_str(module)?;\n            out.write_str(SEP)?;\n        }\n\n        out.write_str(&self.name)?;\n        Ok(())\n    }\n}\n\nimpl Rust {\n    fn imports(out: &mut Tokens, config: &Config, tokens: &Tokens) {\n        use alloc::collections::btree_set;\n\n        use crate as genco;\n        use crate::quote_in;\n\n        let mut modules = BTreeMap::<&ItemStr, Import>::new();\n\n        let mut queue = VecDeque::new();\n\n        for import in tokens.iter_lang() {\n            queue.push_back(import);\n        }\n\n        while let Some(import) = queue.pop_front() {\n            match &import.module {\n                Module::Module {\n                    module,\n                    import: Some(ImportMode::Direct),\n                } => {\n                    let module = modules.entry(module).or_default();\n                    module.names.insert((&import.name, import.alias.as_ref()));\n                }\n                Module::Module {\n                    module,\n                    import: Some(ImportMode::Qualified),\n                } => {\n                    let module = modules.entry(module).or_default();\n                    module.self_import = true;\n                }\n                Module::Module {\n                    module,\n                    import: None,\n                } => match config.default_import {\n                    ImportMode::Direct => {\n                        let module = modules.entry(module).or_default();\n                        module.names.insert((&import.name, import.alias.as_ref()));\n                    }\n                    ImportMode::Qualified => {\n                        let module = modules.entry(module).or_default();\n                        module.self_import = true;\n                    }\n                },\n                Module::Aliased { module, alias } => {\n                    let module = modules.entry(module).or_default();\n                    module.self_aliases.insert(alias);\n                }\n            }\n        }\n\n        let mut has_any = false;\n\n        for (m, module) in modules {\n            let mut render = module.iter(m);\n\n            if let Some(first) = render.next() {\n                has_any = true;\n                out.push();\n\n                // render as a group if there's more than one thing being\n                // imported.\n                if let Some(second) = render.next() {\n                    quote_in! { *out =>\n                        use $m::{$(ref o =>\n                            first.render(o);\n                            quote_in!(*o => , $(ref o => second.render(o)));\n\n                            for item in render {\n                                quote_in!(*o => , $(ref o => item.render(o)));\n                            }\n                        )};\n                    };\n                } else {\n                    match first {\n                        RenderItem::SelfImport => {\n                            quote_in!(*out => use $m;);\n                        }\n                        RenderItem::SelfAlias { alias } => {\n                            quote_in!(*out => use $m as $alias;);\n                        }\n                        RenderItem::Name {\n                            name,\n                            alias: Some(alias),\n                        } => {\n                            quote_in!(*out => use $m::$name as $alias;);\n                        }\n                        RenderItem::Name { name, alias: None } => {\n                            quote_in!(*out => use $m::$name;);\n                        }\n                    }\n                }\n            }\n        }\n\n        if has_any {\n            out.line();\n        }\n\n        return;\n\n        /// An imported module.\n        #[derive(Debug, Default)]\n        struct Import<'a> {\n            /// If we need the module (e.g. through an alias).\n            self_import: bool,\n            /// Aliases for the own module.\n            self_aliases: BTreeSet<&'a ItemStr>,\n            /// Set of imported names.\n            names: BTreeSet<(&'a ItemStr, Option<&'a ItemStr>)>,\n        }\n\n        impl<'a> Import<'a> {\n            fn iter(self, module: &'a str) -> ImportedIter<'a> {\n                ImportedIter {\n                    module,\n                    self_import: self.self_import,\n                    self_aliases: self.self_aliases.into_iter(),\n                    names: self.names.into_iter(),\n                }\n            }\n        }\n\n        struct ImportedIter<'a> {\n            module: &'a str,\n            self_import: bool,\n            self_aliases: btree_set::IntoIter<&'a ItemStr>,\n            names: btree_set::IntoIter<(&'a ItemStr, Option<&'a ItemStr>)>,\n        }\n\n        impl<'a> Iterator for ImportedIter<'a> {\n            type Item = RenderItem<'a>;\n\n            fn next(&mut self) -> Option<Self::Item> {\n                if core::mem::take(&mut self.self_import) {\n                    // Only render self-import if it's not a top level module.\n                    if self.module.split(SEP).count() > 1 {\n                        return Some(RenderItem::SelfImport);\n                    }\n                }\n\n                if let Some(alias) = self.self_aliases.next() {\n                    return Some(RenderItem::SelfAlias { alias });\n                }\n\n                if let Some((name, alias)) = self.names.next() {\n                    return Some(RenderItem::Name { name, alias });\n                }\n\n                None\n            }\n        }\n\n        #[derive(Clone, Copy)]\n        enum RenderItem<'a> {\n            SelfImport,\n            SelfAlias {\n                alias: &'a ItemStr,\n            },\n            Name {\n                name: &'a ItemStr,\n                alias: Option<&'a ItemStr>,\n            },\n        }\n\n        impl RenderItem<'_> {\n            fn render(self, out: &mut Tokens) {\n                match self {\n                    Self::SelfImport => {\n                        quote_in!(*out => self);\n                    }\n                    Self::SelfAlias { alias } => {\n                        quote_in!(*out => self as $alias);\n                    }\n                    Self::Name {\n                        name,\n                        alias: Some(alias),\n                    } => {\n                        quote_in!(*out => $name as $alias);\n                    }\n                    Self::Name { name, alias: None } => {\n                        quote_in!(*out => $name);\n                    }\n                }\n            }\n        }\n    }\n}\n\n/// The import of a Rust type `use std::collections::HashMap`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let a = rust::import(\"std::fmt\", \"Debug\").qualified();\n/// let b = rust::import(\"std::fmt\", \"Debug\").with_module_alias(\"fmt2\");\n/// let c = rust::import(\"std::fmt\", \"Debug\");\n/// let d = rust::import(\"std::fmt\", \"Debug\").with_alias(\"FmtDebug\");\n///\n/// let toks = quote!{\n///     $a\n///     $b\n///     $c\n///     $d\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"use std::fmt::{self, self as fmt2, Debug, Debug as FmtDebug};\",\n///         \"\",\n///         \"fmt::Debug\",\n///         \"fmt2::Debug\",\n///         \"Debug\",\n///         \"FmtDebug\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// # Example with an alias\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let ty = rust::import(\"std::fmt\", \"Debug\").with_alias(\"FmtDebug\");\n///\n/// let toks = quote!{\n///     $ty\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"use std::fmt::Debug as FmtDebug;\",\n///         \"\",\n///         \"FmtDebug\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// # Example with a module alias\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let ty = rust::import(\"std::fmt\", \"Debug\").with_module_alias(\"fmt2\");\n///\n/// let toks = quote!{\n///     $ty\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"use std::fmt as fmt2;\",\n///         \"\",\n///         \"fmt2::Debug\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// # Example with multiple aliases\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let a = rust::import(\"std::fmt\", \"Debug\").with_alias(\"FmtDebug\");\n/// let b = rust::import(\"std::fmt\", \"Debug\").with_alias(\"FmtDebug2\");\n///\n/// let toks = quote!{\n///     $a\n///     $b\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"use std::fmt::{Debug as FmtDebug, Debug as FmtDebug2};\",\n///         \"\",\n///         \"FmtDebug\",\n///         \"FmtDebug2\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn import<M, N>(module: M, name: N) -> Import\nwhere\n    M: Into<ItemStr>,\n    N: Into<ItemStr>,\n{\n    Import {\n        module: Module::Module {\n            import: None,\n            module: module.into(),\n        },\n        name: name.into(),\n        alias: None,\n    }\n}\n"
  },
  {
    "path": "src/lang/swift.rs",
    "content": "//! Specialization for Swift code generation.\n//!\n//! # String Quoting in Swift\n//!\n//! Swift uses UTF-8 internally, string quoting is with the exception of escape\n//! sequences a one-to-one translation.\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let toks: swift::Tokens = quote!(\"start π 😊 \\n \\x7f ÿ $ end\");\n//! assert_eq!(\"\\\"start π 😊 \\\\n \\\\u{7f} ÿ $ end\\\"\", toks.to_string()?);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\nuse core::fmt::Write as _;\n\nuse alloc::collections::BTreeSet;\n\nuse crate::fmt;\nuse crate::tokens::ItemStr;\n\n/// Tokens container specialization for Rust.\npub type Tokens = crate::Tokens<Swift>;\n\nimpl_lang! {\n    /// Swift token specialization.\n    pub Swift {\n        type Config = Config;\n        type Format = Format;\n        type Item = Any;\n\n        fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n            // From: https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html\n\n            for c in input.chars() {\n                match c {\n                    '\\0' => out.write_str(\"\\\\0\")?,\n                    '\\\\' => out.write_str(\"\\\\\\\\\")?,\n                    '\\t' => out.write_str(\"\\\\t\")?,\n                    '\\n' => out.write_str(\"\\\\n\")?,\n                    '\\r' => out.write_str(\"\\\\r\")?,\n                    '\\'' => out.write_str(\"\\\\'\")?,\n                    '\"' => out.write_str(\"\\\\\\\"\")?,\n                    c if !c.is_control() => out.write_char(c)?,\n                    c => {\n                        write!(out, \"\\\\u{{{:x}}}\", c as u32)?;\n                    }\n                };\n            }\n\n            Ok(())\n        }\n\n        fn format_file(\n            tokens: &Tokens,\n            out: &mut fmt::Formatter<'_>,\n            config: &Self::Config,\n        ) -> fmt::Result {\n            let mut imports = Tokens::new();\n            Self::imports(&mut imports, tokens);\n            let format = Format::default();\n            imports.format(out, config, &format)?;\n            tokens.format(out, config, &format)?;\n            Ok(())\n        }\n    }\n\n    Import(Import) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, _: &Config, _: &Format) -> fmt::Result {\n            out.write_str(&self.name)\n        }\n    }\n\n    ImportImplementationOnly(ImportImplementationOnly) {\n        fn format(&self, out: &mut fmt::Formatter<'_>, _: &Config, _: &Format) -> fmt::Result {\n            out.write_str(&self.name)\n        }\n    }\n}\n\n/// Format state for Swift code.\n#[derive(Debug, Default)]\npub struct Format {}\n\n/// Configuration for formatting Swift code.\n#[derive(Debug, Default)]\npub struct Config {}\n\n/// The import of a Swift type `import UIKit`.\n///\n/// Created through the [import()] function.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct Import {\n    /// Module of the imported name.\n    module: ItemStr,\n    /// Name imported.\n    name: ItemStr,\n}\n\n/// The implementation-only import of a Swift type `@_implementationOnly import UIKit`.\n///\n/// Created through the [import_implementation_only()] function.\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\npub struct ImportImplementationOnly {\n    /// Module of the imported name.\n    module: ItemStr,\n    /// Name imported.\n    name: ItemStr,\n}\n\n/// The type of import statement to use when importing a Swift module.\n/// - Standard imports that make the module's public API available\n/// - Implementation-only imports that hide the imported module from clients\n#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]\nenum ImportType {\n    /// A standard Swift import statement: `import ModuleName`\n    Import,\n    /// An implementation-only import statement: `@_implementationOnly import ModuleName`\n    ///\n    /// This type of import hides the imported module from the public API,\n    /// preventing clients from depending on it transitively.\n    ImportImplementationOnly,\n}\n\nimpl Swift {\n    fn imports(out: &mut Tokens, tokens: &Tokens) {\n        use crate as genco;\n        use crate::quote_in;\n\n        let mut modules = BTreeSet::new();\n\n        for import in tokens.iter_lang() {\n            match import.kind() {\n                AnyKind::Import(ref i) => {\n                    modules.insert((&i.module, ImportType::Import));\n                }\n                AnyKind::ImportImplementationOnly(ref i) => {\n                    modules.insert((&i.module, ImportType::ImportImplementationOnly));\n                }\n            }\n        }\n\n        if !modules.is_empty() {\n            for (module, import_type) in modules {\n                match import_type {\n                    ImportType::Import => {\n                        quote_in! { *out => $['\\r']import $module}\n                    }\n                    ImportType::ImportImplementationOnly => {\n                        quote_in! { *out => $['\\r']@_implementationOnly import $module}\n                    }\n                }\n            }\n        }\n\n        out.line();\n    }\n}\n\n/// The import of a Swift type `import UIKit`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let toks = quote!($(swift::import(\"Foo\", \"Debug\")));\n///\n/// assert_eq!(\n///     vec![\n///         \"import Foo\",\n///         \"\",\n///         \"Debug\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn import<M, N>(module: M, name: N) -> Import\nwhere\n    M: Into<ItemStr>,\n    N: Into<ItemStr>,\n{\n    Import {\n        module: module.into(),\n        name: name.into(),\n    }\n}\n\n/// The implementation-only import of a Swift type `@_implementationOnly import UIKit`.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let toks = quote!($(swift::import_implementation_only(\"Foo\", \"Debug\")));\n///\n/// assert_eq!(\n///     vec![\n///         \"@_implementationOnly import Foo\",\n///         \"\",\n///         \"Debug\",\n///     ],\n///     toks.to_file_vec()?\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn import_implementation_only(\n    module: impl Into<ItemStr>,\n    name: impl Into<ItemStr>,\n) -> ImportImplementationOnly {\n    ImportImplementationOnly {\n        module: module.into(),\n        name: name.into(),\n    }\n}\n"
  },
  {
    "path": "src/lib.rs",
    "content": "//! [<img alt=\"github\" src=\"https://img.shields.io/badge/github-udoprog/genco-8da0cb?style=for-the-badge&logo=github\" height=\"20\">](https://github.com/udoprog/genco)\n//! [<img alt=\"crates.io\" src=\"https://img.shields.io/crates/v/genco.svg?style=for-the-badge&color=fc8d62&logo=rust\" height=\"20\">](https://crates.io/crates/genco)\n//! [<img alt=\"docs.rs\" src=\"https://img.shields.io/badge/docs.rs-genco-66c2a5?style=for-the-badge&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K\" height=\"20\">](https://docs.rs/genco)\n//!\n//! A whitespace-aware quasiquoter for beautiful code generation.\n//!\n//! Central to genco are the [`quote!`] and [`quote_in!`] procedural macros which\n//! ease the construction of [token streams].\n//!\n//! This project solves the following language-specific concerns:\n//!\n//! * **Imports** — Generates and groups [import statements] as they are used.\n//!   So you only import what you use, with no redundancy. We also do our best\n//!   to [solve namespace conflicts].\n//!\n//! * **String Quoting** — genco knows how to [quote strings]. And can even\n//!   [interpolate] values *into* the quoted string if it's supported by the\n//!   language.\n//!\n//! * **Structural Indentation** — The quoter relies on intuitive\n//!   [whitespace detection] to structurally sort out spacings and indentation.\n//!   Allowing genco to generate beautiful readable code with minimal effort.\n//!   This is also a requirement for generating correctly behaving code in\n//!   languages like Python where [indentation is meaningful].\n//!\n//! * **Language Customization** — Building support for new languages is a\n//!   piece of cake with the help of the [impl_lang!] macro.\n//!\n//! <br>\n//!\n//! To support line changes during [whitespace detection], we depend on span\n//! information which was made available in Rust `1.88`. Before that, we rely on\n//! a nightly [`proc_macro_span` feature] to work.\n//!\n//! *Prior to this version of Rust* if you want fully functional whitespace\n//! detection you must build and run projects using genco with a `nightly`\n//! compiler. This is important for whitespace-sensitive languages like python.\n//!\n//! You can try the difference between:\n//!\n//! ```bash\n//! cargo run --example rust\n//! ```\n//!\n//! And:\n//!\n//! ```bash\n//! cargo +nightly run --example rust\n//! ```\n//!\n//! [`proc_macro_span` feature]: https://github.com/rust-lang/rust/issues/54725\n//!\n//! <br>\n//!\n//! ## Supported Languages\n//!\n//! The following are languages which have built-in support in genco.\n//!\n//! * [🦀 <b>Rust</b>][rust]<br>\n//!   <small>[Example][rust-example]</small>\n//!\n//! * [☕ <b>Java</b>][java]<br>\n//!   <small>[Example][java-example]</small>\n//!\n//! * [🎼 <b>C#</b>][c#]<br>\n//!   <small>[Example][c#-example]</small>\n//!\n//! * [🐿️ <b>Go</b>][go]<br>\n//!   <small>[Example][go-example]</small>\n//!\n//! * [🎯 <b>Dart</b>][dart]<br>\n//!   <small>[Example][dart-example]</small>\n//!\n//! * [🌐 <b>JavaScript</b>][js]<br>\n//!   <small>[Example][js-example]</small>\n//!\n//! * [🇨 <b>C</b>][c]<br>\n//!   <small>[Example][c-example]</small>\n//!\n//! * [🐍 <b>Python</b>][python]<br>\n//!   <small>[Example][python-example]</small>\n//!\n//! <small>Is your favorite language missing? <b>[Open an issue!]</b></small>\n//!\n//! You can run one of the examples by:\n//!\n//! ```bash\n//! cargo +nightly run --example rust\n//! ```\n//!\n//! <br>\n//!\n//! ## Rust Example\n//!\n//! The following is a simple program producing Rust code to stdout with custom\n//! configuration:\n//!\n//! ```rust,no_run\n//! use genco::prelude::*;\n//!\n//! let hash_map = rust::import(\"std::collections\", \"HashMap\");\n//!\n//! let tokens: rust::Tokens = quote! {\n//!     fn main() {\n//!         let mut m = $hash_map::new();\n//!         m.insert(1u32, 2u32);\n//!     }\n//! };\n//!\n//! println!(\"{}\", tokens.to_file_string()?);\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n//!\n//! This would produce:\n//!\n//! ```rust,no_test\n//! use std::collections::HashMap;\n//!\n//! fn main() {\n//!     let mut m = HashMap::new();\n//!     m.insert(1u32, 2u32);\n//! }\n//! ```\n//!\n//! <br>\n//!\n//! [`quote_in!`]: <https://docs.rs/genco/latest/genco/macro.quote_in.html>\n//! [`quote!`]: <https://docs.rs/genco/latest/genco/macro.quote.html>\n//! [`quoted()`]: <https://docs.rs/genco/latest/genco/tokens/fn.quoted.html>\n//! [c-example]: <https://github.com/udoprog/genco/blob/master/examples/c.rs>\n//! [c]: <https://docs.rs/genco/latest/genco/lang/c/index.html>\n//! [c#-example]: <https://github.com/udoprog/genco/blob/master/examples/csharp.rs>\n//! [c#]: <https://docs.rs/genco/latest/genco/lang/csharp/index.html>\n//! [dart-example]: <https://github.com/udoprog/genco/blob/master/examples/dart.rs>\n//! [dart]: <https://docs.rs/genco/latest/genco/lang/dart/index.html>\n//! [go-example]: <https://github.com/udoprog/genco/blob/master/examples/go.rs>\n//! [go]: <https://docs.rs/genco/latest/genco/lang/go/index.html>\n//! [impl_lang!]: <https://docs.rs/genco/latest/genco/macro.impl_lang.html>\n//! [import statements]: <https://docs.rs/genco/latest/genco/macro.quote.html#imports>\n//! [indentation is meaningful]: <https://docs.python.org/3/faq/design.html#why-does-python-use-indentation-for-grouping-of-statements>\n//! [interpolate]: <https://docs.rs/genco/latest/genco/macro.quote.html#quoted-string-interpolation>\n//! [java-example]: <https://github.com/udoprog/genco/blob/master/examples/java.rs>\n//! [java]: <https://docs.rs/genco/latest/genco/lang/java/index.html>\n//! [js-example]: <https://github.com/udoprog/genco/blob/master/examples/js.rs>\n//! [js]: <https://docs.rs/genco/latest/genco/lang/js/index.html>\n//! [Open an issue!]: <https://github.com/udoprog/genco/issues/new>\n//! [python-example]: <https://github.com/udoprog/genco/blob/master/examples/python.rs>\n//! [python]: <https://docs.rs/genco/latest/genco/lang/python/index.html>\n//! [quote strings]: <https://docs.rs/genco/latest/genco/macro.quote.html#string-quoting>\n//! [rust-example]: <https://github.com/udoprog/genco/blob/master/examples/rust.rs>\n//! [rust]: <https://docs.rs/genco/latest/genco/lang/rust/index.html>\n//! [solve namespace conflicts]: <https://docs.rs/genco/latest/genco/lang/csharp/fn.import.html>\n//! [token streams]: <https://docs.rs/genco/latest/genco/tokens/struct.Tokens.html>\n//! [whitespace detection]: <https://docs.rs/genco/latest/genco/macro.quote.html#whitespace-detection>\n\n#![deny(missing_docs)]\n#![deny(rustdoc::broken_intra_doc_links)]\n#![allow(clippy::needless_doctest_main)]\n#![no_std]\n\n#[cfg(feature = \"std\")]\nextern crate std;\n\n#[cfg(feature = \"alloc\")]\nextern crate alloc;\n\n#[cfg(not(feature = \"alloc\"))]\ncompile_error!(\"genco: The `alloc` feature must be enabled\");\n\n/// Whitespace sensitive quasi-quoting.\n///\n/// This and the [`quote_in!`] macro is the thing that this library revolves\n/// around.\n///\n/// It provides a flexible and intuitive mechanism for efficiently generating\n/// beautiful code directly inside of Rust.\n///\n/// > Note that this macro **can only detect line changes** if it's built with\n/// > Rust 1.88 or by using a `nightly` compiler. See the [main genco\n/// > documentation] for more information.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let hash_map = &dart::import(\"dart:collection\", \"HashMap\");\n///\n/// let tokens: dart::Tokens = quote! {\n///     print_greeting(String name) {\n///         print($[str](Hello $(name)));\n///     }\n///\n///     $hash_map<int, String> map() {\n///         return new $hash_map<int, String>();\n///     }\n/// };\n///\n/// println!(\"{}\", tokens.to_file_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// # Interpolation\n///\n/// Variables are interpolated using `$`, so to include the variable `test`, you\n/// would write `$test`. Interpolated variables must implement [`FormatInto`].\n/// Expressions can be interpolated with `$(<expr>)`.\n///\n/// > *Note:* The `$` punctuation itself can be escaped by repeating it twice.\n/// > So `$$` would produce a single `$` token.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let hash_map = rust::import(\"std::collections\", \"HashMap\");\n///\n/// let tokens: rust::Tokens = quote! {\n///     struct Quoted {\n///         field: $hash_map<u32, u32>,\n///     }\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"use std::collections::HashMap;\",\n///         \"\",\n///         \"struct Quoted {\",\n///         \"    field: HashMap<u32, u32>,\",\n///         \"}\",\n///     ],\n///     tokens.to_file_vec()?,\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// The following is an expression interpolated with `$(<expr>)`.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let tokens: genco::Tokens = quote! {\n///     hello $(\"world\".to_uppercase())\n/// };\n///\n/// assert_eq!(\"hello WORLD\", tokens.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// Interpolations are evaluated in the same scope as the macro, so you can\n/// freely make use of Rust operations like the try keyword (`?`) if\n/// appropriate:\n///\n/// ```\n/// use std::error::Error;\n///\n/// use genco::prelude::*;\n///\n/// fn age_fn(age: &str) -> Result<rust::Tokens, Box<dyn Error>> {\n///     Ok(quote! {\n///         fn age() {\n///             println!(\"You are {} years old!\", $(str::parse::<u32>(age)?));\n///         }\n///     })\n/// }\n/// ```\n///\n/// [`FormatInto`]: crate::tokens::FormatInto\n/// [main genco documentation]: https://docs.rs/genco\n///\n/// <br>\n///\n/// # Escape Sequences\n///\n/// Because this macro is *whitespace sensitive*, it might sometimes be\n/// necessary to provide hints of where whitespace should be inserted.\n///\n/// `quote!` trims any trailing and leading whitespace that it sees. So\n/// `quote!(Hello )` is the same as `quote!(Hello)`. To include a space at the\n/// end, we can use the special `$[' ']` escape sequence:\n/// `quote!(Hello$[' '])`.\n///\n/// The available escape sequences are:\n///\n/// * `$[' ']` — Inserts spacing between tokens. This corresponds to the\n///   [Tokens::space] function.\n///\n/// * `$['\\r']` — Inserts a push operation. Push operations makes sure that\n///   any following tokens are on their own dedicated line. This corresponds to\n///   the [Tokens::push] function.\n///\n/// * `$['\\n']` — Inserts a forced line. Line operations makes sure that any\n///   following tokens have an empty line separating them. This corresponds to\n///   the [Tokens::line] function.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let numbers = 3..=5;\n///\n/// let tokens: Tokens<()> = quote!(foo$['\\r']bar$['\\n']baz$[' ']biz);\n///\n/// assert_eq!(\"foo\\nbar\\n\\nbaz biz\", tokens.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// # String Quoting\n///\n/// Literal strings like `\"hello\"` are automatically quoted for the target\n/// language according to its [Lang::write_quoted] implementation.\n///\n/// [Lang::write_quoted]: crate::lang::Lang::write_quoted\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let tokens: java::Tokens = quote! {\n///     \"hello world 😊\"\n///     $(quoted(\"hello world 😊\"))\n///     $(\"\\\"hello world 😊\\\"\")\n///     $[str](hello world $[const](\"😊\"))\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"\\\"hello world \\\\ud83d\\\\ude0a\\\"\",\n///         \"\\\"hello world \\\\ud83d\\\\ude0a\\\"\",\n///         \"\\\"hello world 😊\\\"\",\n///         \"\\\"hello world \\\\ud83d\\\\ude0a\\\"\",\n///     ],\n///     tokens.to_file_vec()?,\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// # Efficient String Quoting\n///\n/// It's worth investigating the different forms of tokens produced by the\n/// above example.\n///\n/// * The first one is a static *quoted string*.\n/// * The second one is a boxed *quoted string*, who's content will be copied\n///   and is stored on the heap.\n/// * The third one is a static *literal* which bypasses language quoting\n///   entirely.\n/// * Finally the fourth one is an interpolated string. They are really neat,\n///   and will be covered more in the next section. It's worth noting that\n///   `$(\"😊\")` is used, because 😊 is not a valid identifier in Rust. So this\n///   example showcases how strings can be directly embedded in an\n///   interpolation.\n///\n/// Here you can see the items produced by the macro.\n///\n/// ```\n/// # use genco::prelude::*;\n/// # let tokens: rust::Tokens = quote! {\n/// #     \"hello world 😊\"\n/// #     $(quoted(\"hello world 😊\"))\n/// #     $(\"\\\"hello world 😊\\\"\")\n/// #     $[str](hello world $[const](\"😊\"))\n/// # };\n/// use genco::tokens::{Item, ItemStr};\n///\n/// assert_eq!(\n///     vec![\n///         Item::open_quote(false),\n///         Item::literal(ItemStr::static_(\"hello world 😊\")),\n///         Item::close_quote(),\n///         Item::push(),\n///         Item::open_quote(false),\n///         Item::literal(\"hello world 😊\".into()),\n///         Item::close_quote(),\n///         Item::push(),\n///         Item::literal(ItemStr::static_(\"\\\"hello world 😊\\\"\")),\n///         Item::push(),\n///         Item::open_quote(false),\n///         Item::literal(ItemStr::static_(\"hello world 😊\")),\n///         Item::close_quote()\n///     ],\n///     tokens,\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// # Quoted String Interpolation\n///\n/// Some languages support interpolating values into strings.\n///\n/// Examples of these are:\n///\n/// * JavaScript - With [template literals] `` `Hello ${a}` `` (note the\n///   backticks).\n/// * Dart - With [interpolated strings] like `\"Hello $a\"` or `\"Hello ${a +\n///   b}\"`.\n///\n/// The [`quote!`] macro supports this through `$[str](<content>)`. This will\n/// produce literal strings with the appropriate language-specific quoting and\n/// string interpolation formats used.\n///\n/// Components of the string are runtime evaluated with the typical variable\n/// escape sequences `$ident`, `$(<expr>)`. In order to interpolate the string\n/// at compile time we can instead make use of `$[const](<content>)` like you can see with the smile below:\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let smile = \"😊\";\n///\n/// let t: js::Tokens = quote!($[str](Hello $[const](smile) $world));\n/// assert_eq!(\"`Hello 😊 ${world}`\", t.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// Interpolated values are specified with `$(<quoted>)`. And `$` itself is\n/// escaped by repeating it twice through `$$`. The `<quoted>` section is\n/// interpreted the same as in the [`quote!`] macro, but is whitespace sensitive.\n/// This means that `$(foo)` is not the same as `$(foo )` since the latter will\n/// have a space preserved at the end.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let smile = \"😊\";\n///\n/// let t: dart::Tokens = quote!($[str](Hello $[const](smile) $(world)));\n/// assert_eq!(\"\\\"Hello 😊 $world\\\"\", t.to_string()?);\n///\n/// let t: dart::Tokens = quote!($[str](Hello $[const](smile) $(a + b)));\n/// assert_eq!(\"\\\"Hello 😊 ${a + b}\\\"\", t.to_string()?);\n///\n/// let t: js::Tokens = quote!($[str](Hello $[const](smile) $(world)));\n/// assert_eq!(\"`Hello 😊 ${world}`\", t.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// [template literals]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals\n/// [interpolated strings]: https://medium.com/run-dart/dart-dartlang-introduction-string-interpolation-8ed99174119a\n///\n/// # Control Flow\n///\n/// [`quote!`] provides some limited mechanisms for control flow inside of the\n/// macro for convenience. The supported mechanisms are:\n///\n/// * [Loops](#loops) - `$(for <bindings> in <expr> [join (<quoted>)] => <quoted>)`.\n/// * [Conditionals](#conditionals) - `$(if <pattern> => <quoted>)`.\n/// * [Match Statements](#match-statements) - `$(match <expr> { [<pattern> => <quoted>,]* })`.\n///\n/// <br>\n///\n/// # Loops\n///\n/// To repeat a pattern you can use `$(for <bindings> in <expr> { <quoted> })`,\n/// where `<expr>` is an iterator.\n///\n/// It is also possible to use the more compact `$(for <bindings> in <expr> =>\n/// <quoted>)` (note the arrow).\n///\n/// `<quoted>` will be treated as a quoted expression, so anything which works\n/// during regular quoting will work here as well, with the addition that\n/// anything defined in `<bindings>` will be made available to the statement.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let numbers = 3..=5;\n///\n/// let tokens: Tokens<()> = quote! {\n///     Your numbers are: $(for n in numbers => $n$[' '])\n/// };\n///\n/// assert_eq!(\"Your numbers are: 3 4 5\", tokens.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// # Joining Loops\n///\n/// You can add `join (<quoted>)` to the end of a repetition.\n///\n/// The expression specified in `join (<quoted>)` is added _between_ each\n/// element produced by the loop.\n///\n/// > *Note:* The argument to `join` is *whitespace sensitive*, so leading and\n/// > trailing is preserved. `join (,)` and `join (, )` would therefore produce\n/// > different results.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let numbers = 3..=5;\n///\n/// let tokens: Tokens<()> = quote! {\n///     Your numbers are: $(for n in numbers join (, ) => $n).\n/// };\n///\n/// assert_eq!(\"Your numbers are: 3, 4, 5.\", tokens.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// # Conditionals\n///\n/// You can specify a conditional with `$(if <pattern> => <then>)` where\n/// `<pattern>` is an pattern or expression evaluating to a `bool`, and `<then>`\n/// is a quoted expressions.\n///\n/// It's also possible to specify a condition with an else branch, by using\n/// `$(if <pattern> { <then> } else { <else> })`. `<else>` is also a quoted\n/// expression.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// fn greeting(hello: bool, name: &str) -> Tokens<()> {\n///     quote!(Custom Greeting: $(if hello {\n///         Hello $name\n///     } else {\n///         Goodbye $name\n///     }))\n/// }\n///\n/// let tokens = greeting(true, \"John\");\n/// assert_eq!(\"Custom Greeting: Hello John\", tokens.to_string()?);\n///\n/// let tokens = greeting(false, \"John\");\n/// assert_eq!(\"Custom Greeting: Goodbye John\", tokens.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// The `<else>` branch is optional, conditionals which do not have an else\n/// branch and evaluated to `false` won't produce any tokens:\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// fn greeting(hello: bool, name: &str) -> Tokens<()> {\n///     quote!(Custom Greeting:$(if hello {\n///         $[' ']Hello $name\n///     }))\n/// }\n///\n/// let tokens = greeting(true, \"John\");\n/// assert_eq!(\"Custom Greeting: Hello John\", tokens.to_string()?);\n///\n/// let tokens = greeting(false, \"John\");\n/// assert_eq!(\"Custom Greeting:\", tokens.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// # Match Statements\n///\n/// You can specify a match expression using `$(match <expr> { [<pattern> =>\n/// <quoted>,]* }`, where `<expr>` is an evaluated expression that is match\n/// against each subsequent `<pattern>`. If a pattern matches, the arm with the\n/// matching `<quoted>` block is evaluated.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// fn greeting(name: &str) -> Tokens<()> {\n///     quote!(Hello $(match name {\n///         \"John\" | \"Jane\" => $(\"Random Stranger\"),\n///         other => $other,\n///     }))\n/// }\n///\n/// let tokens = greeting(\"John\");\n/// assert_eq!(\"Hello Random Stranger\", tokens.to_string()?);\n///\n/// let tokens = greeting(\"Mio\");\n/// assert_eq!(\"Hello Mio\", tokens.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// If a match arm contains parenthesis (`=> (<quoted>)`), the expansion will be\n/// *whitespace sensitive*. Allowing leading and trailing whitespace to be\n/// preserved:\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// fn greeting(name: &str) -> Tokens<()> {\n///     quote!(Hello$(match name {\n///         \"John\" | \"Jane\" => ( $(\"Random Stranger\")),\n///         other => ( $other),\n///     }))\n/// }\n///\n/// let tokens = greeting(\"John\");\n/// assert_eq!(\"Hello Random Stranger\", tokens.to_string()?);\n///\n/// let tokens = greeting(\"Mio\");\n/// assert_eq!(\"Hello Mio\", tokens.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// The following is an example with more complex matching:\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// enum Greeting {\n///     Named(&'static str),\n///     Unknown,\n/// }\n///\n/// fn greeting(name: Greeting) -> Tokens<()> {\n///     quote!(Hello $(match name {\n///         Greeting::Named(\"John\") | Greeting::Named(\"Jane\") => $(\"Random Stranger\"),\n///         Greeting::Named(other) => $other,\n///         Greeting::Unknown => $(\"Unknown Person\"),\n///     }))\n/// }\n///\n/// let tokens = greeting(Greeting::Named(\"John\"));\n/// assert_eq!(\"Hello Random Stranger\", tokens.to_string()?);\n///\n/// let tokens = greeting(Greeting::Unknown);\n/// assert_eq!(\"Hello Unknown Person\", tokens.to_string()?);\n///\n/// let tokens = greeting(Greeting::Named(\"Mio\"));\n/// assert_eq!(\"Hello Mio\", tokens.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// # Variable assignment\n///\n/// You can use `$(let <binding> = <expr>)` to define variables with their value.\n/// This is useful within loops to compute values from iterator items.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let names = [\"A.B\", \"C.D\"];\n///\n/// let tokens: Tokens<()> = quote! {\n///     $(for name in names =>\n///         $(let (first, second) = name.split_once('.').unwrap())\n///         $first and $second.\n///     )\n/// };\n/// assert_eq!(\"A and B.\\nC and D.\", tokens.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// Variables can also be mutable:\n///\n/// ```\n/// use genco::prelude::*;\n/// let path = \"A.B.C.D\";\n///\n/// let tokens: Tokens<()> = quote! {\n///     $(let mut items = path.split('.'))\n///     $(if let Some(first) = items.next() =>\n///         First is $first\n///     )\n///     $(if let Some(second) = items.next() =>\n///         Second is $second\n///     )\n/// };\n///\n/// assert_eq!(\"First is A\\nSecond is B\", tokens.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// # Scopes\n///\n/// You can use `$(ref <binding> { <expr> })` to gain access to the current\n/// token stream. This is an alternative to existing control flow operators if\n/// you want to run some custom code during evaluation which is otherwise not\n/// supported. This is called a *scope*.\n///\n/// For a more compact variant you can omit the braces with `$(ref <binding> =>\n/// <expr>)`.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// fn quote_greeting(surname: &str, lastname: Option<&str>) -> rust::Tokens {\n///     quote! {\n///         Hello $surname$(ref toks {\n///             if let Some(lastname) = lastname {\n///                 toks.space();\n///                 toks.append(lastname);\n///             }\n///         })\n///     }\n/// }\n///\n/// assert_eq!(\"Hello John\", quote_greeting(\"John\", None).to_string()?);\n/// assert_eq!(\"Hello John Doe\", quote_greeting(\"John\", Some(\"Doe\")).to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// ## Whitespace Detection\n///\n/// The [`quote!`] macro has the following rules for dealing with indentation and\n/// spacing.\n///\n/// **Spaces** — Two tokens that are separated are spaced. Regardless of how\n/// many spaces there are between them. This can be controlled manually by\n/// inserting the [`$[' ']`][escape] escape sequence in the token stream.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let tokens: rust::Tokens = quote! {\n///     fn     test()     {\n///         println!(\"Hello... \");\n///\n///         println!(\"World!\");\n///     }\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"fn test() {\",\n///         \"    println!(\\\"Hello... \\\");\",\n///         \"\",\n///         \"    println!(\\\"World!\\\");\",\n///         \"}\",\n///     ],\n///     tokens.to_file_vec()?,\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// **Line breaking** — Line breaks are detected by leaving two empty lines\n/// between two tokens. This can be controlled manually by inserting the\n/// [`$['\\n']`][escape] escape in the token stream.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let tokens: rust::Tokens = quote! {\n///     fn test() {\n///         println!(\"Hello... \");\n///\n///\n///\n///         println!(\"World!\");\n///     }\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"fn test() {\",\n///         \"    println!(\\\"Hello... \\\");\",\n///         \"\",\n///         \"    println!(\\\"World!\\\");\",\n///         \"}\",\n///     ],\n///     tokens.to_file_vec()?,\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// <br>\n///\n/// **Indentation** — Indentation is determined on a row-by-row basis. If a\n/// column is further in than the one on the preceeding row, it is indented *one\n/// level* deeper.\n///\n/// If a column starts shallower than a preceeding, non-whitespace only row, it\n/// will be matched against previously known indentation levels. Failure to\n/// match a previously known level is an error.\n///\n/// All indentations inserted during the macro will be unrolled at the end of\n/// it. So any trailing indentations will be matched by unindentations.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let tokens: rust::Tokens = quote! {\n///     fn test() {\n///             println!(\"Hello... \");\n///\n///             println!(\"World!\");\n///     }\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"fn test() {\",\n///         \"    println!(\\\"Hello... \\\");\",\n///         \"\",\n///         \"    println!(\\\"World!\\\");\",\n///         \"}\",\n///     ],\n///     tokens.to_file_vec()?,\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// Example showcasing an indentation mismatch:\n///\n/// ```,compile_fail\n/// use genco::prelude::*;\n///\n/// let tokens: rust::Tokens = quote! {\n///     fn test() {\n///             println!(\"Hello... \");\n///\n///         println!(\"World!\");\n///     }\n/// };\n/// ```\n///\n/// ```text\n/// ---- src\\lib.rs -  (line 150) stdout ----\n/// error: expected 4 less spaces of indentation\n/// --> src\\lib.rs:157:9\n///    |\n/// 10 |         println!(\"World!\");\n///    |         ^^^^^^^\n/// ```\n///\n/// [escape]: #escape-sequences\npub use genco_macros::quote;\n\n/// Convenience macro for constructing a [`FormatInto`] implementation in-place.\n///\n/// Constructing [`FormatInto`] implementation instead of short lived [token\n/// streams] can be more beneficial for memory use and performance.\n///\n/// [`FormatInto`]: crate::tokens::FormatInto\n/// [token streams]: Tokens\n///\n/// # Comparison\n///\n/// In the below example, `f1` and `f2` are equivalent. In here [quote_fn!]\n/// simply makes it easier to build.\n///\n/// ```\n/// use genco::prelude::*;\n/// use genco::tokens::from_fn;\n///\n/// let f1 = from_fn(move |t| {\n///     quote_in!{ *t =>\n///         println!(\"Hello World\");\n///     }\n/// });\n///\n/// let f2 = quote_fn!{\n///     println!(\"Hello World\");\n/// };\n///\n/// let tokens: rust::Tokens = quote!{\n///     $f1\n///     $f2\n/// };\n///\n/// assert_eq!{\n///     vec![\n///         \"println!(\\\"Hello World\\\");\",\n///         \"println!(\\\"Hello World\\\");\",\n///     ],\n///     tokens.to_file_vec()?,\n/// };\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// # Examples which borrow\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// fn greeting(name: &str) -> impl FormatInto<Rust> + '_ {\n///     quote_fn! {\n///         println!($[str](Hello $[const](name)))\n///     }\n/// }\n///\n/// fn advanced_greeting<'a>(first: &'a str, last: &'a str) -> impl FormatInto<Rust> + 'a {\n///     quote_fn! {\n///         println!($[str](Hello $[const](first) $[const](last)))\n///     }\n/// }\n///\n/// let tokens = quote! {\n///     $(greeting(\"Mio\"));\n///     $(advanced_greeting(\"Jane\", \"Doe\"));\n/// };\n///\n/// assert_eq!{\n///     vec![\n///         \"println!(\\\"Hello Mio\\\");\",\n///         \"println!(\\\"Hello Jane Doe\\\");\",\n///     ],\n///     tokens.to_file_vec()?\n/// };\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub use genco_macros::quote_fn;\n\n/// Behaves the same as [`quote!`] while quoting into an existing token stream\n/// with `<target> => <quoted>`.\n///\n/// This macro takes a destination stream followed by an `=>` and the tokens to\n/// extend that stream with.\n///\n/// Note that it must be possible to borrow `<target>` mutably, so a reference\n/// like `&mut rust::Tokens` will have to be dereferenced when used with this\n/// macro.\n///\n/// ```\n/// # use genco::prelude::*;\n///\n/// # fn generate() -> rust::Tokens {\n/// let mut tokens = rust::Tokens::new();\n/// quote_in!(tokens => hello world);\n/// # tokens\n/// # }\n///\n/// fn generate_into(tokens: &mut rust::Tokens) {\n///     quote_in! { *tokens =>\n///         hello...\n///         world!\n///     };\n/// }\n/// ```\n///\n/// # Example\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let mut tokens = rust::Tokens::new();\n///\n/// quote_in! { tokens =>\n///     fn foo() -> u32 {\n///         42\n///     }\n/// }\n/// ```\n///\n/// # Use with scopes\n///\n/// [`quote_in!`] can be used inside of a [`quote!`] through [a scope].\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let tokens: rust::Tokens = quote! {\n///     fn foo(v: bool) -> u32 {\n///         $(ref out {\n///             quote_in! { *out =>\n///                 if v {\n///                     1\n///                 } else {\n///                     0\n///                 }\n///             }\n///         })\n///     }\n/// };\n/// ```\n///\n/// [a scope]: quote#scopes\npub use genco_macros::quote_in;\n\n#[macro_use]\nmod macros;\npub mod fmt;\npub mod lang;\npub mod prelude;\npub mod tokens;\n#[doc(inline)]\npub use self::tokens::Tokens;\n\n/// Private module used for macros.\n#[doc(hidden)]\npub mod __priv {\n    use crate::lang::Lang;\n    use crate::tokens::{from_fn, FormatInto};\n    use crate::tokens::{Item, ItemStr};\n\n    #[inline]\n    pub const fn static_(string: &'static str) -> Item {\n        Item::static_(string)\n    }\n\n    #[inline]\n    pub const fn literal(string: ItemStr) -> Item {\n        Item::literal(string)\n    }\n\n    #[inline]\n    pub const fn indentation(level: i16) -> Item {\n        Item::indentation(level)\n    }\n\n    #[inline]\n    pub const fn push() -> Item {\n        Item::push()\n    }\n\n    #[inline]\n    pub const fn line() -> Item {\n        Item::line()\n    }\n\n    #[inline]\n    pub const fn space() -> Item {\n        Item::space()\n    }\n\n    #[inline]\n    pub const fn open_quote(is_interpolation: bool) -> Item {\n        Item::open_quote(is_interpolation)\n    }\n\n    #[inline]\n    pub const fn close_quote() -> Item {\n        Item::close_quote()\n    }\n\n    #[inline]\n    pub const fn open_eval() -> Item {\n        Item::open_eval()\n    }\n\n    #[inline]\n    pub const fn close_eval() -> Item {\n        Item::close_eval()\n    }\n\n    /// Add a language item directly.\n    ///\n    /// This must only be used by the [`impl_lang!`] macro.\n    ///\n    /// [`impl_lang!`]: crate::impl_lang!\n    #[doc(hidden)]\n    #[inline]\n    pub fn item<L>(item: L::Item) -> impl FormatInto<L>\n    where\n        L: Lang,\n    {\n        from_fn(|t| {\n            t.lang_item(item);\n        })\n    }\n\n    /// Register a language item directly.\n    ///\n    /// This must only be used by the [`impl_lang!`] macro.\n    ///\n    /// [`impl_lang!`]: crate::impl_lang!\n    #[doc(hidden)]\n    #[inline]\n    pub fn register<L>(item: L::Item) -> impl FormatInto<L>\n    where\n        L: Lang,\n    {\n        from_fn(|t| {\n            t.lang_item_register(item);\n        })\n    }\n}\n"
  },
  {
    "path": "src/macros.rs",
    "content": "//! Macros helpers in genco.\n\n/// Macro to implement support for a custom language.\n///\n/// # Examples\n///\n/// ```\n/// use genco::fmt;\n/// use std::fmt::Write as _;\n///\n/// #[derive(Default)]\n/// struct Config {\n/// }\n///\n/// #[derive(Default)]\n/// struct Format {\n/// }\n///\n/// genco::impl_lang! {\n///     MyLang {\n///         type Config = Config;\n///         type Item = Any;\n///         type Format = Format;\n///\n///         fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {\n///             genco::lang::c_family_write_quoted(out, input)\n///         }\n///\n///         fn format_file(\n///             tokens: &Tokens<MyLang>,\n///             out: &mut fmt::Formatter<'_>,\n///             config: &Self::Config,\n///         ) -> fmt::Result {\n///             use genco::quote_in;\n///\n///             let mut header: Tokens<MyLang> = Tokens::new();\n///             let mut any_imports = false;\n///\n///             for import in tokens.iter_lang() {\n///                 any_imports = true;\n///\n///                 match import.kind() {\n///                     AnyKind::Import(import) => {\n///                         header.push();\n///                         quote_in!(header => import $(import.0));\n///                     }\n///                     AnyKind::ImportDefault(import) => {\n///                         header.push();\n///                         quote_in!(header => import default $(import.0));\n///                     }\n///                 }\n///             }\n///\n///             if any_imports {\n///                 // Add a line as padding in case we have any imports.\n///                 header.line();\n///             }\n///\n///             let format = Format::default();\n///             header.format(out, config, &format)?;\n///             tokens.format(out, config, &format)?;\n///             Ok(())\n///         }\n///     }\n///\n///     Import(Import) {\n///         fn format(&self, out: &mut fmt::Formatter<'_>, config: &Config, _: &Format) -> fmt::Result {\n///             out.write_str(self.0)?;\n///             Ok(())\n///         }\n///     }\n///\n///     ImportDefault(ImportDefault) {\n///         fn format(&self, out: &mut fmt::Formatter<'_>, config: &Config, _: &Format) -> fmt::Result {\n///             write!(out, \"default:{}\", self.0)?;\n///             Ok(())\n///         }\n///     }\n/// }\n///\n/// #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]\n/// struct Import(&'static str);\n///\n/// #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]\n/// struct ImportDefault(&'static str);\n///\n/// use genco::{quote, Tokens};\n///\n/// let a = Import(\"first\");\n/// let b = ImportDefault(\"second\");\n///\n/// let t: Tokens<MyLang> = quote! {\n///     $a\n///     $b\n/// };\n///\n/// assert_eq! {\n///     vec![\n///         \"import first\",\n///         \"import default second\",\n///         \"\",\n///         \"first\",\n///         \"default:second\"\n///     ],\n///     t.to_file_vec()?\n/// };\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n#[macro_export]\nmacro_rules! impl_lang {\n    (\n        $(#[$($meta:meta)*])*\n        $vis:vis $lang:ident {\n            $($lang_item:tt)*\n        }\n\n        $(\n            $name:ident($ty:ty) {\n                $($ty_lang_item_item:tt)*\n            }\n        )*\n    ) => {\n        $(#[$($meta)*])*\n        #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]\n        $vis struct $lang(());\n\n        impl $crate::lang::Lang for $lang {\n            $($lang_item)*\n        }\n\n        #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]\n        enum AnyKind {\n            $($name($ty),)*\n        }\n\n        /// A type-erased language item capable of holding any kind.\n        #[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]\n        $vis struct Any {\n            kind: AnyKind,\n        }\n\n        impl core::fmt::Debug for Any {\n            #[inline]\n            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n                self.kind.fmt(f)\n            }\n        }\n\n        impl Any {\n            /// Access the kind of the any type.\n            #[allow(unused)]\n            fn kind(&self) -> &AnyKind {\n                &self.kind\n            }\n        }\n\n        $(\n            impl From<$ty> for Any {\n                #[inline]\n                fn from(lang: $ty) -> Self {\n                    Any { kind: AnyKind::$name(lang) }\n                }\n            }\n        )*\n\n        impl $crate::lang::LangItem<$lang> for Any {\n            #[inline]\n            fn format(\n                &self,\n                out: &mut $crate::fmt::Formatter<'_>,\n                config: &<$lang as $crate::lang::Lang>::Config,\n                format: &<$lang as $crate::lang::Lang>::Format,\n            ) -> $crate::fmt::Result {\n                match self.kind {\n                    $(AnyKind::$name(ref lang) => lang.format(out, config, format),)*\n                }\n            }\n        }\n\n        $(\n            impl $crate::tokens::FormatInto<$lang> for $ty {\n                #[inline]\n                fn format_into(self, tokens: &mut $crate::Tokens<$lang>) {\n                    tokens.append($crate::__priv::item::<$lang>(\n                        <<$lang as $crate::lang::Lang>::Item as ::core::convert::From<$ty>>::from(self)\n                    ));\n                }\n            }\n\n            impl<'a> $crate::tokens::FormatInto<$lang> for &'a $ty {\n                #[inline]\n                fn format_into(self, tokens: &mut $crate::Tokens<$lang>) {\n                    $crate::tokens::FormatInto::<$lang>::format_into(::core::clone::Clone::clone(self), tokens)\n                }\n            }\n\n            impl $crate::tokens::Register<$lang> for $ty {\n                #[inline]\n                fn register(self, tokens: &mut $crate::Tokens<$lang>) {\n                    tokens.append($crate::__priv::register::<$lang>(\n                        <<$lang as $crate::lang::Lang>::Item as ::core::convert::From<$ty>>::from(self)\n                    ));\n                }\n            }\n\n            impl<'a> $crate::tokens::Register<$lang> for &'a $ty {\n                #[inline]\n                fn register(self, tokens: &mut $crate::Tokens<$lang>) {\n                    $crate::tokens::Register::<$lang>::register(::core::clone::Clone::clone(self), tokens)\n                }\n            }\n\n            impl $crate::lang::LangItem<$lang> for $ty {\n                $($ty_lang_item_item)*\n            }\n        )*\n    }\n}\n"
  },
  {
    "path": "src/prelude.rs",
    "content": "//! Prelude containing typical things to import when using the library.\n\npub use crate::lang::*;\npub use crate::tokens::{display, quoted, register, FormatInto};\npub use crate::{quote, quote_fn, quote_in, Tokens};\n"
  },
  {
    "path": "src/tokens/display.rs",
    "content": "use core::fmt;\n\nuse alloc::string::ToString;\n\nuse crate::lang::Lang;\nuse crate::tokens::FormatInto;\nuse crate::Tokens;\n\n/// Function to build a string literal.\n///\n/// This is an alternative to manually implementing [tokens::FormatInto], since\n/// it can tokenize anything that implements [Display][fmt::Display]\n/// directly.\n///\n/// On the other hand, things implementing [tokens::FormatInto] have access to the\n/// full range of the [Tokens] api, allowing it to work more efficiently.\n///\n/// [tokens::FormatInto]: crate::tokens::FormatInto\n/// [Tokens]: crate::Tokens\n///\n/// # Examples\n///\n/// Example showcasing quoted strings when generating Rust.\n///\n/// ```\n/// use genco::prelude::*;\n/// use std::fmt;\n///\n/// struct Foo(());\n///\n/// impl fmt::Display for Foo {\n///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\n///         write!(fmt, \"Foo\")\n///     }\n/// }\n///\n/// let map = rust::import(\"std::collections\", \"HashMap\");\n///\n/// let foo = Foo(());\n///\n/// let tokens = quote! {\n///     let mut m = $map::<u32, &str>::new();\n///     m.insert(0, $(display(&foo)));\n/// };\n///\n/// assert_eq!(\n///     vec![\n///        \"use std::collections::HashMap;\",\n///        \"\",\n///        \"let mut m = HashMap::<u32, &str>::new();\",\n///        \"m.insert(0, Foo);\",\n///     ],\n///     tokens.to_file_vec()?,\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn display<T>(inner: T) -> Display<T>\nwhere\n    T: fmt::Display,\n{\n    Display { inner }\n}\n\n/// Struct containing a type that implements [Display][fmt::Display] and can be\n/// tokenized into a stream.\n///\n/// This is constructed with the [display()] function.\n#[derive(Clone, Copy)]\npub struct Display<T> {\n    inner: T,\n}\n\nimpl<T, L> FormatInto<L> for Display<T>\nwhere\n    L: Lang,\n    T: fmt::Display,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        tokens.literal(self.inner.to_string());\n    }\n}\n"
  },
  {
    "path": "src/tokens/format_into.rs",
    "content": "use core::fmt::Arguments;\n\nuse alloc::borrow::Cow;\nuse alloc::rc::Rc;\nuse alloc::string::{String, ToString};\nuse alloc::vec::Vec;\n\nuse crate::lang::Lang;\nuse crate::tokens::{ItemStr, Tokens};\n\n/// Trait for types that can be formatted in-place into a token stream.\n///\n/// Things implementing [`FormatInto`] can be used as arguments for\n/// [interpolation] in the [`quote!`] macro.\n///\n/// [`from_fn()`] is a helper function which simplifies the task of creating a\n/// [`FormatInto`] implementation on the fly. The [`quote_fn!`] macro is also a\n/// specialization of this.\n///\n/// [`from_fn()`]: crate::tokens::from_fn()\n/// [`quote!`]: crate::quote\n/// [`quote_fn!`]: crate::quote_fn\n/// [interpolation]: crate::quote#interpolation\n///\n/// # Examples\n///\n/// ```\n/// use genco::quote_in;\n/// use genco::tokens::{ItemStr, FormatInto, from_fn, static_literal};\n/// use genco::lang::Lang;\n///\n/// fn comment<L>(s: impl Into<ItemStr>) -> impl FormatInto<L>\n/// where\n///     L: Lang\n/// {\n///     from_fn(move |tokens| {\n///         let s = s.into();\n///         quote_in!(*tokens => $(static_literal(\"//\")) $s);\n///     })\n/// }\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub trait FormatInto<L>\nwhere\n    L: Lang,\n{\n    /// Convert the type into tokens in-place.\n    fn format_into(self, tokens: &mut Tokens<L>);\n}\n\n/// Formatting a reference to a token stream is exactly the same as extending\n/// the token stream with a copy of the stream being formatted.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let a: Tokens = quote!(foo bar);\n///\n/// let result = quote!($a baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L> FormatInto<L> for Tokens<L>\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Self) {\n        tokens.extend_by_owned(self);\n    }\n}\n\n/// Formatting a reference to a token stream is exactly the same as extending\n/// the token stream with a copy of the stream being formatted.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let a: &Tokens = &quote!(foo bar);\n///\n/// let result = quote!($a baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L> FormatInto<L> for &Tokens<L>\nwhere\n    L: Lang,\n    L::Item: Clone,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        tokens.extend_by_ref(self);\n    }\n}\n\n/// Formatting a vector of token streams is like formatting each, one after\n/// another.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let mut vec = Vec::<Tokens>::new();\n/// vec.push(quote!(foo));\n/// vec.push(quote!($[' ']bar));\n///\n/// let result = quote!($vec baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L, T> FormatInto<L> for Vec<T>\nwhere\n    L: Lang,\n    T: FormatInto<L>,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        for t in self {\n            tokens.append(t);\n        }\n    }\n}\n\n/// Formatting a reference to a vector of token streams is like formatting each,\n/// one after another.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let mut vec = Vec::<Tokens>::new();\n/// vec.push(quote!(foo));\n/// vec.push(quote!($[' ']bar));\n///\n/// let result = quote!($(&vec) baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L, T> FormatInto<L> for &Vec<T>\nwhere\n    L: Lang,\n    T: FormatInto<L> + Clone,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        for t in self {\n            tokens.append(t.clone());\n        }\n    }\n}\n\n/// Formatting a slice of token streams is like formatting each, one after\n/// another.\n///\n/// This will cause each token stream to be cloned into the destination stream.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let vec = vec![\"foo\", \" \", \"bar\"];\n/// let slice = &vec[..];\n///\n/// let result: Tokens = quote!($slice baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L, T> FormatInto<L> for &[T]\nwhere\n    L: Lang,\n    T: Clone + FormatInto<L>,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        for t in self {\n            tokens.append(t.clone());\n        }\n    }\n}\n\n/// Formatting borrowed string boxed them on the heap.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let foo = \"foo\";\n/// let bar = \"bar\";\n///\n/// let result: Tokens = quote!($foo $bar baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L> FormatInto<L> for &str\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        tokens.literal(self);\n    }\n}\n\n/// Formatting borrowed string boxed them on the heap.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let foo = String::from(\"foo\");\n/// let bar = String::from(\"bar\");\n///\n/// let result: Tokens = quote!($(&foo) $(&bar) baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L> FormatInto<L> for &String\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        tokens.literal(self);\n    }\n}\n\n/// Formatting owned strings takes ownership of the string directly from the\n/// heap.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let foo = String::from(\"foo\");\n/// let bar = String::from(\"bar\");\n///\n/// let result: Tokens = quote!($foo $bar baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L> FormatInto<L> for String\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        tokens.literal(self);\n    }\n}\n\n/// Refcounted strings are moved into the token stream without copying.\n///\n/// # Examples\n///\n/// ```\n/// use std::rc::Rc;\n/// use genco::prelude::*;\n///\n/// let foo = Rc::new(String::from(\"foo\"));\n/// let bar = Rc::new(String::from(\"bar\"));\n///\n/// let result: Tokens = quote!($foo $bar baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L> FormatInto<L> for Rc<String>\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        tokens.literal(self);\n    }\n}\n\n/// Refcounted strings are cloned and moved into the token stream without\n/// copying.\n///\n/// # Examples\n///\n/// ```\n/// use std::rc::Rc;\n/// use genco::prelude::*;\n///\n/// let foo = Rc::new(String::from(\"foo\"));\n/// let bar = Rc::new(String::from(\"bar\"));\n///\n/// let result: Tokens = quote!($(&foo) $(&bar) baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L> FormatInto<L> for &Rc<String>\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        tokens.literal(self.as_ref());\n    }\n}\n\n/// Implementation for [`Arguments`] which allows for arbitrary and efficient\n/// literal formatting.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let name = \"John\";\n/// let result: Tokens = quote!($(format_args!(\"Hello {name}\")));\n///\n/// assert_eq!(\"Hello John\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L> FormatInto<L> for Arguments<'_>\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        if let Some(s) = self.as_str() {\n            tokens.literal(ItemStr::static_(s));\n        } else {\n            tokens.literal(self.to_string());\n        }\n    }\n}\n\n/// Optional items are formatted if they are present.\n///\n/// # Examples\n///\n/// ```\n/// use std::rc::Rc;\n/// use genco::prelude::*;\n///\n/// let foo = Some(\"foo\");\n/// let bar = Some(\"bar\");\n/// let biz = None::<&str>;\n///\n/// let result: Tokens = quote!($foo $bar baz $biz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L, T> FormatInto<L> for Option<T>\nwhere\n    L: Lang,\n    T: FormatInto<L>,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        if let Some(inner) = self {\n            inner.format_into(tokens);\n        }\n    }\n}\n\n/// Cow strings are formatted by either borrowing or cloning the string.\n///\n/// # Examples\n///\n/// ```\n/// use std::borrow::Cow;\n/// use genco::prelude::*;\n///\n/// let foo = Cow::<str>::Borrowed(\"foo\");\n/// let bar = Cow::<str>::Owned(String::from(\"bar\"));\n///\n/// let result: Tokens = quote!($foo $bar baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L> FormatInto<L> for Cow<'_, str>\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        match self {\n            Cow::Borrowed(b) => tokens.literal(b),\n            Cow::Owned(o) => o.format_into(tokens),\n        }\n    }\n}\n\n/// Cow strings are formatted by either borrowing or cloning the string.\n///\n/// # Examples\n///\n/// ```\n/// use std::borrow::Cow;\n/// use genco::prelude::*;\n///\n/// let foo = &Cow::<str>::Borrowed(\"foo\");\n/// let bar = &Cow::<str>::Owned(String::from(\"bar\"));\n///\n/// let result: Tokens = quote!($foo $bar baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L> FormatInto<L> for &Cow<'_, str>\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        match self {\n            Cow::Borrowed(b) => tokens.literal(b),\n            Cow::Owned(o) => o.format_into(tokens),\n        }\n    }\n}\n\n/// Cow slices are formatted by either borrowing or cloning the slice.\n///\n/// # Examples\n///\n/// ```\n/// use std::borrow::Cow;\n/// use genco::prelude::*;\n///\n/// let foo = Cow::<[&str]>::Borrowed(&[\"foo\", \"bar\"]);\n/// let bar = Cow::<[&str]>::Owned(vec![\"baz\"]);\n///\n/// let result: Tokens = quote!($foo $bar biz);\n///\n/// assert_eq!(\"foobar baz biz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L, T> FormatInto<L> for Cow<'_, [T]>\nwhere\n    L: Lang,\n    T: FormatInto<L> + Clone,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        match self {\n            Cow::Borrowed(b) => {\n                for t in b.iter() {\n                    tokens.append(t.clone());\n                }\n            }\n            Cow::Owned(o) => o.format_into(tokens),\n        }\n    }\n}\n\n/// Cow slices are formatted by either borrowing or cloning the slice.\n///\n/// # Examples\n///\n/// ```\n/// use std::borrow::Cow;\n/// use genco::prelude::*;\n///\n/// let foo = &Cow::<[&str]>::Borrowed(&[\"foo\", \"bar\"]);\n/// let bar = &Cow::<[&str]>::Owned(vec![\"baz\"]);\n///\n/// let result: Tokens = quote!($foo $bar biz);\n///\n/// assert_eq!(\"foobar baz biz\", result.to_string()?);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L, T> FormatInto<L> for &Cow<'_, [T]>\nwhere\n    L: Lang,\n    T: FormatInto<L> + Clone,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        match self {\n            Cow::Borrowed(b) => {\n                for t in b.iter() {\n                    tokens.append(t.clone());\n                }\n            }\n            Cow::Owned(o) => o.format_into(tokens),\n        }\n    }\n}\n\nmacro_rules! impl_display {\n    ($($ty:ty),*) => {\n        $(\n            /// Implementation for primitive type. Uses the corresponding\n            /// [Display][std::fmt::Display] implementation for the\n            /// primitive type.\n            impl<L> FormatInto<L> for $ty\n            where\n                L: Lang,\n            {\n                fn format_into(self, tokens: &mut Tokens<L>) {\n                    tokens.append(self.to_string());\n                }\n            }\n        )*\n    };\n}\n\nimpl_display!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, isize, usize);\n"
  },
  {
    "path": "src/tokens/from_fn.rs",
    "content": "use crate::lang::Lang;\nuse crate::tokens;\nuse crate::Tokens;\n\n/// Construct a [`FormatInto`][crate::tokens::FormatInto] implementation from a\n/// function.\n///\n/// # Examples\n///\n/// ```\n/// use genco::{quote, quote_in};\n/// use genco::lang::{Lang, Rust};\n/// use genco::tokens::{ItemStr, FormatInto, Tokens, from_fn, static_literal};\n///\n/// fn comment(s: impl Into<ItemStr> + Copy) -> impl FormatInto<Rust> + Copy {\n///     from_fn(move |tokens| {\n///         let s = s.into();\n///         quote_in!(*tokens => $(static_literal(\"//\")) #s);\n///     })\n/// }\n///\n/// let c = comment(\"hello world\");\n/// let _: Tokens<Rust> = quote!($c $['\\n'] $c);\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n#[inline]\npub fn from_fn<F, L>(f: F) -> FromFn<F>\nwhere\n    F: FnOnce(&mut Tokens<L>),\n    L: Lang,\n{\n    FromFn { f }\n}\n\n/// A captured function used for formatting tokens.\n///\n/// Constructed using [from_fn()] or the [quote_fn!][crate::quote_fn] macro.\n#[derive(Clone, Copy)]\npub struct FromFn<F> {\n    f: F,\n}\n\nimpl<L, F> tokens::FormatInto<L> for FromFn<F>\nwhere\n    L: Lang,\n    F: FnOnce(&mut Tokens<L>),\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        (self.f)(tokens);\n    }\n}\n"
  },
  {
    "path": "src/tokens/internal.rs",
    "content": "\n"
  },
  {
    "path": "src/tokens/item.rs",
    "content": "//! A single element\n\nuse core::fmt;\n\nuse crate::lang::Lang;\nuse crate::tokens::{FormatInto, ItemStr, Tokens};\n\n#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]\npub(crate) enum Kind {\n    /// A literal item.\n    /// Is added as a raw string to the stream of tokens.\n    Literal(ItemStr),\n    /// A language-specific item.\n    Lang(usize),\n    /// Push a new line unless the current line is empty. Will be flushed on\n    /// indentation changes.\n    Push,\n    /// Push a line. Will be flushed on indentation changes.\n    Line,\n    /// Space between language items. Typically a single space.\n    ///\n    /// Multiple spacings in sequence are collapsed into one.\n    /// A spacing does nothing if at the beginning of a line.\n    Space,\n    /// Manage indentation.\n    ///\n    /// An indentation of 0 has no effect.\n    Indentation(i16),\n    /// Switch to handling input as a quote.\n    OpenQuote(bool),\n    /// Close the last quote.\n    CloseQuote,\n    /// Switch on evaluation. Only valid during string handling.\n    OpenEval,\n    /// Close evaluation.\n    CloseEval,\n}\n\n/// A single item in a stream of tokens.\n#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]\n#[non_exhaustive]\npub struct Item {\n    pub(crate) kind: Kind,\n}\n\nimpl Item {\n    /// Construct a new item based on a kind.\n    #[inline]\n    pub(crate) const fn new(kind: Kind) -> Self {\n        Self { kind }\n    }\n\n    /// Shorthand for constructing a new static literal item.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::tokens::{Item, ItemStr};\n    /// use genco::lang::Rust;\n    ///\n    /// let a = Item::static_(\"hello\");\n    /// let b = Item::literal(\"hello\".into());\n    ///\n    /// assert_eq!(a, b);\n    /// ```\n    #[inline]\n    pub const fn static_(literal: &'static str) -> Self {\n        Self::new(Kind::Literal(ItemStr::static_(literal)))\n    }\n\n    /// Construct a new push item.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::tokens::Item;\n    /// use genco::lang::Rust;\n    ///\n    /// let a = Item::push();\n    /// let b = Item::push();\n    ///\n    /// assert_eq!(a, b);\n    /// ```\n    #[inline]\n    pub const fn push() -> Self {\n        Self::new(Kind::Push)\n    }\n\n    /// Construct a new line item.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::tokens::Item;\n    /// use genco::lang::Rust;\n    ///\n    /// let a = Item::line();\n    /// let b = Item::line();\n    ///\n    /// assert_eq!(a, b);\n    /// ```\n    #[inline]\n    pub const fn line() -> Self {\n        Self::new(Kind::Line)\n    }\n\n    /// Construct a new space item.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::tokens::Item;\n    /// use genco::lang::Rust;\n    ///\n    /// let a = Item::space();\n    /// let b = Item::space();\n    ///\n    /// assert_eq!(a, b);\n    /// ```\n    #[inline]\n    pub const fn space() -> Self {\n        Self::new(Kind::Space)\n    }\n\n    /// Construct a new indentation item.\n    #[inline]\n    pub(crate) const fn indentation(n: i16) -> Self {\n        Self::new(Kind::Indentation(n))\n    }\n\n    /// Construct a quote open.\n    ///\n    /// Switches to handling input as a quote. The argument indicates whether\n    /// the string contains any interpolated values. The string content is\n    /// quoted with the language-specific [quoting method].\n    ///\n    /// [quoting method]: Lang::open_quote\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::tokens::Item;\n    /// use genco::lang::Rust;\n    ///\n    /// let a = Item::open_quote(true);\n    /// let b = Item::open_quote(false);\n    ///\n    /// assert_eq!(a, a);\n    /// assert_ne!(a, b);\n    /// ```\n    #[inline]\n    pub const fn open_quote(is_interpolated: bool) -> Self {\n        Self::new(Kind::OpenQuote(is_interpolated))\n    }\n\n    /// Construct a quote close.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::tokens::Item;\n    /// use genco::lang::Rust;\n    ///\n    /// let a = Item::close_quote();\n    /// let b = Item::close_quote();\n    ///\n    /// assert_eq!(a, b);\n    /// ```\n    #[inline]\n    pub const fn close_quote() -> Self {\n        Self::new(Kind::CloseQuote)\n    }\n\n    /// Construct a new eval open.\n    #[inline]\n    pub(crate) const fn open_eval() -> Self {\n        Self::new(Kind::OpenEval)\n    }\n\n    /// Construct a new eval close.\n    #[inline]\n    pub(crate) const fn close_eval() -> Self {\n        Self::new(Kind::CloseEval)\n    }\n\n    /// Construct a new literal item.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::tokens::{Item, ItemStr};\n    /// use genco::lang::Rust;\n    ///\n    /// let a = Item::static_(\"hello\");\n    /// let b = Item::literal(\"hello\".into());\n    ///\n    /// assert_eq!(a, b);\n    /// ```\n    #[inline]\n    pub const fn literal(lit: ItemStr) -> Self {\n        Self::new(Kind::Literal(lit))\n    }\n\n    /// Construct a lang item with the given index.\n    #[inline]\n    pub(crate) const fn lang(index: usize) -> Item {\n        Item::new(Kind::Lang(index))\n    }\n}\n\nimpl fmt::Debug for Item {\n    #[inline]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.kind.fmt(f)\n    }\n}\n\n/// Formatting an item is the same as simply adding that item to the token\n/// stream.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n/// use genco::tokens::{Item, ItemStr};\n///\n/// let foo = Item::literal(ItemStr::static_(\"foo\"));\n/// let bar = Item::literal(\"bar\".into());\n///\n/// let result: Tokens = quote!($foo $bar baz);\n///\n/// assert_eq!(\"foo bar baz\", result.to_string()?);\n///\n/// assert_eq!{\n///     vec![\n///         Item::literal(ItemStr::static_(\"foo\")),\n///         Item::space(),\n///         Item::literal(\"bar\".into()),\n///         Item::space(),\n///         Item::literal(ItemStr::static_(\"baz\")),\n///     ],\n///     result,\n/// };\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\nimpl<L> FormatInto<L> for Item\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        tokens.item(self);\n    }\n}\n"
  },
  {
    "path": "src/tokens/item_str.rs",
    "content": "//! Helper trait to take ownership of strings.\n\nuse core::fmt;\nuse core::hash::{Hash, Hasher};\nuse core::ops::Deref;\n\n#[cfg(feature = \"alloc\")]\nuse alloc::borrow::{Cow, ToOwned};\n#[cfg(feature = \"alloc\")]\nuse alloc::boxed::Box;\n#[cfg(feature = \"alloc\")]\nuse alloc::rc::Rc;\n#[cfg(feature = \"alloc\")]\nuse alloc::string::String;\n\nuse crate::lang::Lang;\nuse crate::tokens::{FormatInto, Item, Tokens};\n\n/// Internal representation.\n#[derive(Clone)]\nenum ItemStrKind {\n    /// A boxed string.\n    #[cfg(feature = \"alloc\")]\n    Box(Box<str>),\n    /// A static string.\n    Static(&'static str),\n}\n\n/// A managed string that permits immutable borrowing.\n#[derive(Clone)]\npub struct ItemStr {\n    kind: ItemStrKind,\n}\n\nimpl ItemStr {\n    /// Create a new ItemStr from the given kind.\n    #[inline]\n    const fn new(kind: ItemStrKind) -> Self {\n        Self { kind }\n    }\n\n    /// Construct a new string item based on a static string.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::tokens::ItemStr;\n    ///\n    /// let string = ItemStr::static_(\"hello world\");\n    /// assert_eq!(&string[..], \"hello world\");\n    /// ```\n    pub const fn static_(s: &'static str) -> Self {\n        Self::new(ItemStrKind::Static(s))\n    }\n}\n\n/// Convert stringy things.\nimpl<L> FormatInto<L> for ItemStr\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        tokens.append(Item::literal(self));\n    }\n}\n\nimpl<L> FormatInto<L> for &ItemStr\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut Tokens<L>) {\n        tokens.append(Item::literal(self.clone()));\n    }\n}\n\nimpl AsRef<str> for ItemStr {\n    #[inline]\n    fn as_ref(&self) -> &str {\n        match &self.kind {\n            #[cfg(feature = \"alloc\")]\n            ItemStrKind::Box(b) => b,\n            ItemStrKind::Static(s) => s,\n        }\n    }\n}\n\nimpl Deref for ItemStr {\n    type Target = str;\n\n    fn deref(&self) -> &str {\n        match &self.kind {\n            #[cfg(feature = \"alloc\")]\n            ItemStrKind::Box(b) => b,\n            ItemStrKind::Static(s) => s,\n        }\n    }\n}\n\n#[cfg(feature = \"alloc\")]\nimpl From<Box<str>> for ItemStr {\n    #[inline]\n    fn from(value: Box<str>) -> Self {\n        Self::new(ItemStrKind::Box(value))\n    }\n}\n\nimpl<'a> From<&'a ItemStr> for ItemStr {\n    #[inline]\n    fn from(value: &'a ItemStr) -> Self {\n        value.clone()\n    }\n}\n\n#[cfg(feature = \"alloc\")]\nimpl<'a> From<&'a String> for ItemStr {\n    #[inline]\n    fn from(value: &'a String) -> Self {\n        value.clone().into()\n    }\n}\n\n#[cfg(feature = \"alloc\")]\nimpl From<String> for ItemStr {\n    #[inline]\n    fn from(value: String) -> Self {\n        Self::new(ItemStrKind::Box(value.into_boxed_str()))\n    }\n}\n\n#[cfg(feature = \"alloc\")]\nimpl<'a> From<&'a str> for ItemStr {\n    #[inline]\n    fn from(value: &'a str) -> Self {\n        Self::new(ItemStrKind::Box(value.to_owned().into_boxed_str()))\n    }\n}\n\n#[cfg(feature = \"alloc\")]\nimpl<'a, 'b> From<&'b &'a str> for ItemStr {\n    #[inline]\n    fn from(value: &'b &'a str) -> Self {\n        Self::new(ItemStrKind::Box((*value).to_owned().into_boxed_str()))\n    }\n}\n\n#[cfg(feature = \"alloc\")]\nimpl<'a> From<Cow<'a, str>> for ItemStr {\n    #[inline]\n    fn from(value: Cow<'a, str>) -> Self {\n        Self::new(ItemStrKind::Box(match value {\n            Cow::Owned(string) => string.into_boxed_str(),\n            Cow::Borrowed(string) => string.to_owned().into_boxed_str(),\n        }))\n    }\n}\n\n#[cfg(feature = \"alloc\")]\nimpl<'a, 'b> From<&'b Cow<'a, str>> for ItemStr {\n    #[inline]\n    fn from(value: &'b Cow<'a, str>) -> Self {\n        Self::new(ItemStrKind::Box(match value {\n            Cow::Owned(string) => string.clone().into_boxed_str(),\n            Cow::Borrowed(string) => (*string).to_owned().into_boxed_str(),\n        }))\n    }\n}\n\n#[cfg(feature = \"alloc\")]\nimpl From<Rc<String>> for ItemStr {\n    #[inline]\n    fn from(value: Rc<String>) -> Self {\n        Self::new(ItemStrKind::Box((*value).clone().into()))\n    }\n}\n\nimpl fmt::Debug for ItemStr {\n    #[inline]\n    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\n        self.as_ref().fmt(fmt)\n    }\n}\n\nimpl fmt::Display for ItemStr {\n    #[inline]\n    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\n        self.as_ref().fmt(fmt)\n    }\n}\n\nimpl PartialEq for ItemStr {\n    #[inline]\n    fn eq(&self, other: &Self) -> bool {\n        self.as_ref() == other.as_ref()\n    }\n}\n\nimpl Eq for ItemStr {}\n\nimpl PartialOrd for ItemStr {\n    #[inline]\n    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {\n        Some(self.cmp(other))\n    }\n}\n\nimpl Ord for ItemStr {\n    #[inline]\n    fn cmp(&self, other: &Self) -> core::cmp::Ordering {\n        self.as_ref().cmp(other.as_ref())\n    }\n}\n\nimpl Hash for ItemStr {\n    #[inline]\n    fn hash<H>(&self, state: &mut H)\n    where\n        H: Hasher,\n    {\n        self.as_ref().hash(state);\n    }\n}\n"
  },
  {
    "path": "src/tokens/mod.rs",
    "content": "//! Utilities for working with token streams.\n//!\n//! This is typically a module you will use if you intend to provide a manual\n//! implementation of [`FormatInto`].\n//!\n//! # Examples\n//!\n//! ```rust\n//! use genco::quote_in;\n//! use genco::tokens::{from_fn, ItemStr, FormatInto, static_literal};\n//! use genco::lang::Lang;\n//!\n//! /// Format a block comment, starting with `/**`, and ending in `*/`.\n//! pub fn block_comment<I, L>(text: I) -> impl FormatInto<L>\n//! where\n//!     I: IntoIterator,\n//!     I::Item: Into<ItemStr>,\n//!     L: Lang,\n//! {\n//!     from_fn(move |t| {\n//!         let mut it = text.into_iter().peekable();\n//!\n//!         if it.peek().is_some() {\n//!             quote_in! { *t =>\n//!                 $(static_literal(\"/**\"))\n//!                 $(for line in it join ($['\\r']) {\n//!                     $[' ']* $(line.into())\n//!                 })\n//!                 $[' ']$(static_literal(\"*/\"))\n//!             }\n//!         }\n//!     })\n//! }\n//!\n//! use genco::prelude::*;\n//!\n//! let tokens: java::Tokens = quote! {\n//!     $(block_comment(&[\"This class is used for awesome stuff\", \"ok?\"]))\n//!     public static class Foo {\n//!     }\n//! };\n//!\n//! assert_eq!(\n//!     vec![\n//!         \"/**\",\n//!         \" * This class is used for awesome stuff\",\n//!         \" * ok?\",\n//!         \" */\",\n//!         \"public static class Foo {\",\n//!         \"}\"\n//!     ],\n//!     tokens.to_vec()?\n//! );\n//! # Ok::<_, genco::fmt::Error>(())\n//! ```\n\nmod display;\nmod format_into;\nmod from_fn;\nmod internal;\nmod item;\nmod item_str;\nmod quoted;\nmod register;\nmod static_literal;\nmod tokens;\n\npub use self::display::{display, Display};\npub use self::format_into::FormatInto;\npub use self::from_fn::{from_fn, FromFn};\npub use self::item::Item;\npub(crate) use self::item::Kind;\npub use self::item_str::ItemStr;\npub use self::quoted::{quoted, QuotedFn};\npub use self::register::{register, Register, RegisterFn};\npub use self::static_literal::static_literal;\npub use self::tokens::Tokens;\n"
  },
  {
    "path": "src/tokens/quoted.rs",
    "content": "use crate::lang::Lang;\nuse crate::tokens::{FormatInto, Tokens};\n\n/// Function to provide string quoting.\n///\n/// Note that quoting is applied automatically for literal strings inside of\n/// the [`quote!`] macro, like: `quote!(\"hello\")`.\n///\n/// This is used to generated quoted strings, in the language of choice.\n///\n/// # Examples\n///\n/// Example showcasing quoted strings when generating Rust.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let map = rust::import(\"std::collections\", \"HashMap\");\n///\n/// let tokens = quote! {\n///     let mut m = $map::<u32, &str>::new();\n///     m.insert(0, $(quoted(\"hello\\\" world\")));\n/// };\n///\n/// assert_eq!(\n///     vec![\n///        \"use std::collections::HashMap;\",\n///        \"\",\n///        \"let mut m = HashMap::<u32, &str>::new();\",\n///        \"m.insert(0, \\\"hello\\\\\\\" world\\\");\",\n///     ],\n///     tokens.to_file_vec()?,\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// # Example: A quote inside a quote\n///\n/// Note that this requires extra buffering to occur when formatting the token stream.\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let tokens: python::Tokens = quote!($[str](Hello $[const](quoted(\"World 😊\"))));\n///\n/// assert_eq!(\n///     \"\\\"Hello \\\\\\\"World \\\\U0001f60a\\\\\\\"\\\"\",\n///     tokens.to_string()?,\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// [`quote!`]: crate::quote\npub fn quoted<T>(inner: T) -> QuotedFn<T> {\n    QuotedFn { inner }\n}\n\n/// Struct containing a type that is quoted.\n///\n/// This is constructed with the [quoted()] function.\n#[derive(Clone, Copy, Debug)]\npub struct QuotedFn<T> {\n    inner: T,\n}\n\nimpl<T, L> FormatInto<L> for QuotedFn<T>\nwhere\n    L: Lang,\n    T: FormatInto<L>,\n{\n    #[inline]\n    fn format_into(self, t: &mut Tokens<L>) {\n        t.open_quote(false);\n        self.inner.format_into(t);\n        t.close_quote();\n    }\n}\n"
  },
  {
    "path": "src/tokens/register.rs",
    "content": "use crate::lang::Lang;\nuse crate::tokens::FormatInto;\nuse crate::Tokens;\n\n/// Function to provide item registration.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let write_bytes_ext = rust::import(\"byteorder\", \"WriteBytesExt\").with_alias(\"_\");\n/// let read_bytes_ext = rust::import(\"byteorder\", \"ReadBytesExt\").with_alias(\"_\");\n/// let cursor = &rust::import(\"std::io\", \"Cursor\");\n/// let big_endian = &rust::import(\"byteorder\", \"BigEndian\");\n///\n/// let tokens = quote! {\n///     $(register((write_bytes_ext, read_bytes_ext)))\n///\n///     let mut wtr = vec![];\n///     wtr.write_u16::<$big_endian>(517).unwrap();\n///     wtr.write_u16::<$big_endian>(768).unwrap();\n///     assert_eq!(wtr, vec![2, 5, 3, 0]);\n///\n///     let mut rdr = $cursor::new(vec![2, 5, 3, 0]);\n///     assert_eq!(517, rdr.read_u16::<$big_endian>().unwrap());\n///     assert_eq!(768, rdr.read_u16::<$big_endian>().unwrap());\n/// };\n///\n/// assert_eq!(\n///     vec![\n///         \"use byteorder::{BigEndian, ReadBytesExt as _, WriteBytesExt as _};\",\n///         \"use std::io::Cursor;\",\n///         \"\",\n///         \"let mut wtr = vec![];\",\n///         \"wtr.write_u16::<BigEndian>(517).unwrap();\",\n///         \"wtr.write_u16::<BigEndian>(768).unwrap();\",\n///         \"assert_eq!(wtr, vec![2, 5, 3, 0]);\",\n///         \"\",\n///         \"let mut rdr = Cursor::new(vec![2, 5, 3, 0]);\",\n///         \"assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap());\",\n///         \"assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap());\"\n///     ],\n///     tokens.to_file_vec()?,\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub fn register<T, L>(inner: T) -> RegisterFn<T>\nwhere\n    T: Register<L>,\n    L: Lang,\n{\n    RegisterFn { inner }\n}\n\n/// Struct containing a type only intended to be registered.\n///\n/// This is constructed with the [register()] function.\n#[derive(Debug, Clone, Copy)]\npub struct RegisterFn<T> {\n    inner: T,\n}\n\nimpl<T, L> FormatInto<L> for RegisterFn<T>\nwhere\n    T: Register<L>,\n    L: Lang,\n{\n    fn format_into(self, t: &mut Tokens<L>) {\n        t.register(self.inner);\n    }\n}\n\n/// Helper trait to convert something into a stream of registrations.\n///\n/// Thanks to this, we can provide a flexible number of arguments to\n/// [register()], like a tuple.\n///\n/// This is trait is very similar to [`FormatInto`], except that it constrains\n/// the types that can be \"registered\" to only language items. An implementation\n/// of register must not be used as a substitute for [`FormatInto`].\n///\n/// [register()]: crate::Tokens::register()\n/// [`FormatInto`]: crate::tokens::FormatInto\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n///\n/// let mut tokens = rust::Tokens::new();\n///\n/// let hash_map = rust::import(\"std::collections\", \"HashMap\");\n/// let btree_map = rust::import(\"std::collections\", \"BTreeMap\");\n///\n/// tokens.register((hash_map, btree_map));\n///\n/// assert_eq!(\n///     vec![\n///         \"use std::collections::{BTreeMap, HashMap};\",\n///     ],\n///     tokens.to_file_vec()?,\n/// );\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\npub trait Register<L>\nwhere\n    L: Lang,\n{\n    /// Convert the type into tokens.\n    fn register(self, tokens: &mut Tokens<L>);\n}\n\n/// Macro to build implementations of `Register<T>` for a tuple.\nmacro_rules! impl_register_tuple {\n    ($($ty:ident, $var:ident),*) => {\n        impl<L, $($ty,)*> Register<L> for ($($ty,)*)\n        where\n            $($ty: Register<L>,)*\n            L: Lang,\n        {\n            fn register(self, tokens: &mut Tokens<L>) {\n                let ($($var,)*) = self;\n                $(tokens.register($var);)*\n            }\n        }\n    }\n}\n\nimpl_register_tuple!(T1, t1);\nimpl_register_tuple!(T1, t1, T2, t2);\nimpl_register_tuple!(T1, t1, T2, t2, T3, t3);\nimpl_register_tuple!(T1, t1, T2, t2, T3, t3, T4, t4);\nimpl_register_tuple!(T1, t1, T2, t2, T3, t3, T4, t4, T5, t5);\nimpl_register_tuple!(T1, t1, T2, t2, T3, t3, T4, t4, T5, t5, T6, t6);\nimpl_register_tuple!(T1, t1, T2, t2, T3, t3, T4, t4, T5, t5, T6, t6, T7, t7);\nimpl_register_tuple!(T1, t1, T2, t2, T3, t3, T4, t4, T5, t5, T6, t6, T7, t7, T8, t8);\n"
  },
  {
    "path": "src/tokens/static_literal.rs",
    "content": "use crate::lang::Lang;\nuse crate::tokens::{FormatInto, ItemStr};\n\n/// A formatter from a static literal.\n///\n/// Created from the [static_literal()] function.\n#[derive(Debug, Clone, Copy)]\npub struct StaticLiteral {\n    literal: &'static str,\n}\n\nimpl<L> FormatInto<L> for StaticLiteral\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn format_into(self, tokens: &mut crate::Tokens<L>) {\n        tokens.literal(ItemStr::static_(self.literal));\n    }\n}\n\n/// A formatter from a static literal.\n///\n/// This is typically more efficient than using [append()] with a string\n/// directly, since it can avoid copying the string.\n///\n/// # Examples\n///\n/// ```\n/// use genco::prelude::*;\n/// use genco::tokens;\n///\n/// let mut tokens = Tokens::<()>::new();\n/// tokens.append(tokens::static_literal(\"hello\"));\n/// # Ok::<_, genco::fmt::Error>(())\n/// ```\n///\n/// [append()]: crate::Tokens::append()\npub fn static_literal(literal: &'static str) -> StaticLiteral {\n    StaticLiteral { literal }\n}\n"
  },
  {
    "path": "src/tokens/tokens.rs",
    "content": "//! A set of tokens that make up a single source-file.\n//!\n//! ## Example\n//!\n//! ```rust\n//! use genco::prelude::*;\n//!\n//! let mut toks = java::Tokens::new();\n//! toks.append(\"foo\");\n//! ```\n#![allow(clippy::module_inception)]\n\nuse core::cmp::Ordering;\nuse core::hash;\nuse core::slice;\n\nuse alloc::string::String;\nuse alloc::vec::Vec;\n\nuse crate::fmt;\nuse crate::lang::{Lang, LangSupportsEval};\nuse crate::tokens::{FormatInto, Item, ItemStr, Kind, Register};\n\n/// A stream of tokens.\n///\n/// # Structural Guarantees\n///\n/// This stream of tokens provides the following structural guarantees.\n///\n/// * Only one [`space`] occurs in sequence and indicates spacing between\n///   tokens.\n/// * Only one [`push`] occurs in sequence and indicates that the next token\n///   should be spaced onto a new line.\n/// * A [`line`] is never by a [`push`] since it would have no effect. A line\n///   ensures an empty line between two tokens.\n///\n/// ```\n/// use genco::Tokens;\n/// use genco::tokens::Item;\n///\n/// let mut tokens = Tokens::<()>::new();\n///\n/// // The first push token is \"overriden\" by a line.\n/// tokens.space();\n/// tokens.space();\n///\n/// assert_eq!(tokens, [Item::space()]);\n///\n/// let mut tokens = Tokens::<()>::new();\n///\n/// tokens.space();\n/// tokens.push();\n/// tokens.push();\n///\n/// assert_eq!(tokens, [Item::push()]);\n///\n/// let mut tokens = Tokens::<()>::new();\n///\n/// // The first space and push tokens are \"overriden\" by a line.\n/// tokens.space();\n/// tokens.push();\n/// tokens.line();\n///\n/// assert_eq!(tokens, [Item::line()]);\n/// ```\n///\n/// [`space`]: Self::space\n/// [`push`]: Self::push\n/// [`line`]: Self::line\npub struct Tokens<L = ()>\nwhere\n    L: Lang,\n{\n    items: Vec<Item>,\n    lang: Vec<L::Item>,\n}\n\nimpl<L> Tokens<L>\nwhere\n    L: Lang,\n{\n    /// Create a new empty stream of tokens.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let tokens = Tokens::<()>::new();\n    ///\n    /// assert!(tokens.is_empty());\n    /// ```\n    pub fn new() -> Self {\n        Tokens {\n            items: Vec::new(),\n            lang: Vec::new(),\n        }\n    }\n\n    /// Create a new empty stream of tokens with the specified capacity.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let tokens = Tokens::<()>::with_capacity(10);\n    ///\n    /// assert!(tokens.is_empty());\n    /// ```\n    pub fn with_capacity(cap: usize) -> Self {\n        Tokens {\n            items: Vec::with_capacity(cap),\n            lang: Vec::new(),\n        }\n    }\n\n    /// Construct an iterator over the token stream.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    /// use genco::tokens::{ItemStr, Item};\n    ///\n    /// let tokens: Tokens<()> = quote!(foo bar baz);\n    /// let mut it = tokens.iter();\n    ///\n    /// assert_eq!(Item::literal(ItemStr::static_(\"foo\")), it.next().unwrap());\n    /// assert_eq!(Item::space(), it.next().unwrap());\n    /// assert_eq!(Item::literal(ItemStr::static_(\"bar\")), it.next().unwrap());\n    /// assert_eq!(Item::space(), it.next().unwrap());\n    /// assert_eq!(Item::literal(ItemStr::static_(\"baz\")), it.next().unwrap());\n    /// assert_eq!(None, it.next());\n    /// ```\n    #[inline]\n    pub fn iter(&self) -> Iter<'_, L::Item> {\n        Iter {\n            lang: &self.lang[..],\n            iter: self.items.iter(),\n        }\n    }\n\n    /// Append the given tokens.\n    ///\n    /// This append function takes anything implementing [`FormatInto`] making\n    /// the argument's behavior customizable. Most primitive types have built-in\n    /// implementations of [`FormatInto`] treating them as raw tokens.\n    ///\n    /// Most notabley, things implementing [`FormatInto`] can be used as\n    /// arguments for [interpolation] in the [`quote!`] macro.\n    ///\n    /// [`quote!`]: crate::quote\n    /// [interpolation]: crate::quote#interpolation\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let mut tokens = Tokens::<()>::new();\n    /// tokens.append(4u32);\n    ///\n    /// assert_eq!(quote!($(4u32)), tokens);\n    /// ```\n    pub fn append<T>(&mut self, tokens: T)\n    where\n        T: FormatInto<L>,\n    {\n        tokens.format_into(self)\n    }\n\n    #[inline]\n    pub(crate) fn item(&mut self, item: Item) {\n        match item.kind {\n            Kind::Push => self.push(),\n            Kind::Line => self.line(),\n            Kind::Space => self.space(),\n            Kind::Indentation(n) => self.indentation(n),\n            Kind::Lang(..) => { /* ignored */ }\n            kind => self.items.push(Item::new(kind)),\n        }\n    }\n\n    /// Extend with another stream of tokens.\n    ///\n    /// This respects the structural requirements of adding one element at a\n    /// time, like you would get by calling `space`, `push`, or `line`.\n    #[inline]\n    pub(crate) fn extend_by_ref(&mut self, other: &Tokens<L>)\n    where\n        L::Item: Clone,\n    {\n        self.items.reserve(other.items.len());\n        let base = self.lang.len();\n        self.lang.extend(other.lang.iter().cloned());\n\n        for item in &other.items {\n            match &item.kind {\n                Kind::Push => self.push(),\n                Kind::Line => self.line(),\n                Kind::Space => self.space(),\n                Kind::Indentation(n) => self.indentation(*n),\n                Kind::Lang(lang) => {\n                    self.items.push(Item::lang(base.saturating_add(*lang)));\n                }\n                kind => self.items.push(Item::new(kind.clone())),\n            }\n        }\n    }\n\n    /// Extend with another stream of tokens.\n    ///\n    /// This respects the structural requirements of adding one element at a\n    /// time, like you would get by calling `space`, `push`, or `line`.\n    #[inline]\n    pub(crate) fn extend_by_owned(&mut self, mut other: Tokens<L>) {\n        self.items.reserve(other.items.len());\n        let base = self.lang.len();\n        self.lang.append(&mut other.lang);\n\n        for item in other.items {\n            match item.kind {\n                Kind::Push => self.push(),\n                Kind::Line => self.line(),\n                Kind::Space => self.space(),\n                Kind::Indentation(n) => self.indentation(n),\n                Kind::Lang(lang) => {\n                    self.items.push(Item::lang(base.saturating_add(lang)));\n                }\n                kind => self.items.push(Item::new(kind)),\n            }\n        }\n    }\n\n    /// Iterate over all registered [`Lang`] items.\n    ///\n    /// The order in which the imports are returned is *not* defined. So if you\n    /// need them in some particular order you have to sort them.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let debug = rust::import(\"std::fmt\", \"Debug\");\n    /// let ty = rust::import(\"std::collections\", \"HashMap\");\n    ///\n    /// let tokens = quote!(foo $ty<u32, dyn $debug> baz);\n    ///\n    /// for import in tokens.iter_lang() {\n    ///     println!(\"{:?}\", import);\n    /// }\n    /// ```\n    #[inline]\n    pub fn iter_lang(&self) -> IterLang<'_, L> {\n        IterLang {\n            lang: self.lang.iter(),\n        }\n    }\n\n    /// Add an registered custom element that is _not_ rendered.\n    ///\n    /// Registration can be used to generate imports that do not render a\n    /// visible result.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let write_bytes_ext = rust::import(\"byteorder\", \"WriteBytesExt\").with_alias(\"_\");\n    ///\n    /// let tokens = quote!($(register(write_bytes_ext)));\n    ///\n    /// assert_eq!(\"use byteorder::WriteBytesExt as _;\\n\", tokens.to_file_string()?);\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn register<T>(&mut self, tokens: T)\n    where\n        T: Register<L>,\n    {\n        tokens.register(self);\n    }\n\n    /// Check if tokens contain no items.\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let tokens: Tokens<()> = quote!();\n    ///\n    /// assert!(tokens.is_empty());\n    /// ```\n    pub fn is_empty(&self) -> bool {\n        self.items.is_empty()\n    }\n\n    /// Add a single spacing to the token stream.\n    ///\n    /// Note that due to structural guarantees two consequent spaces may not\n    /// follow each other in the same token stream.\n    ///\n    /// A space operation has no effect unless it's followed by a non-whitespace\n    /// token.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let mut tokens = Tokens::<()>::new();\n    ///\n    /// tokens.space();\n    /// tokens.append(\"hello\");\n    /// tokens.space();\n    /// tokens.space(); // Note: ignored\n    /// tokens.append(\"world\");\n    /// tokens.space();\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \" hello world\",\n    ///     ],\n    ///     tokens.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn space(&mut self) {\n        if let Some(Item { kind: Kind::Space }) = self.items.last() {\n            return;\n        }\n\n        self.items.push(Item::space());\n    }\n\n    /// Add a single push operation.\n    ///\n    /// Push operations ensure that any following tokens are added to their own\n    /// line.\n    ///\n    /// A push has no effect unless it's *preceeded* or *followed* by\n    /// non-whitespace tokens.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let mut tokens = Tokens::<()>::new();\n    ///\n    /// tokens.push();\n    /// tokens.append(\"hello\");\n    /// tokens.push();\n    /// tokens.append(\"world\");\n    /// tokens.push();\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"hello\",\n    ///         \"world\"\n    ///     ],\n    ///     tokens.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn push(&mut self) {\n        let item = loop {\n            let Some(item) = self.items.pop() else {\n                break None;\n            };\n\n            match &item.kind {\n                // NB: never reconfigure a line into a push.\n                Kind::Line => {\n                    self.items.push(item);\n                    return;\n                }\n                Kind::Space | Kind::Push => continue,\n                _ => break Some(item),\n            }\n        };\n\n        self.items.extend(item);\n        self.items.push(Item::push());\n    }\n\n    /// Add a single line operation.\n    ///\n    /// A line ensures that any following tokens have one line of separation\n    /// between them and the preceeding tokens.\n    ///\n    /// A line has no effect unless it's *preceeded* and *followed* by\n    /// non-whitespace tokens.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let mut tokens = Tokens::<()>::new();\n    ///\n    /// tokens.line();\n    /// tokens.append(\"hello\");\n    /// tokens.line();\n    /// tokens.append(\"world\");\n    /// tokens.line();\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"hello\",\n    ///         \"\",\n    ///         \"world\"\n    ///     ],\n    ///     tokens.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn line(&mut self) {\n        let item = loop {\n            let Some(item) = self.items.pop() else {\n                break None;\n            };\n\n            if matches!(item.kind, Kind::Line | Kind::Push) {\n                continue;\n            }\n\n            break Some(item);\n        };\n\n        self.items.extend(item);\n        self.items.push(Item::line());\n    }\n\n    /// Increase the indentation of the token stream.\n    ///\n    /// An indentation is a language-specific operation which adds whitespace to\n    /// the beginning of a line preceeding any non-whitespace tokens.\n    ///\n    /// An indentation has no effect unless it's *followed* by non-whitespace\n    /// tokens. It also acts like a [`push`], in that it will shift any tokens to\n    /// a new line.\n    ///\n    /// [`push`]: Self::push\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let mut tokens = Tokens::<()>::new();\n    ///\n    /// tokens.indent();\n    /// tokens.append(\"hello\");\n    /// tokens.indent();\n    /// tokens.append(\"world\");\n    /// tokens.indent();\n    /// tokens.append(\"😀\");\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"    hello\",\n    ///         \"        world\",\n    ///         \"            😀\",\n    ///     ],\n    ///     tokens.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn indent(&mut self) {\n        self.indentation(1);\n    }\n\n    /// Decrease the indentation of the token stream.\n    ///\n    /// An indentation is a language-specific operation which adds whitespace to\n    /// the beginning of a line preceeding any non-whitespace tokens.\n    ///\n    /// An indentation has no effect unless it's *followed* by non-whitespace\n    /// tokens. It also acts like a [`push`], in that it will shift any tokens to\n    /// a new line.\n    ///\n    /// Indentation can never go below zero, and will just be ignored if that\n    /// were to happen. However, negative indentation is stored in the token\n    /// stream, so any negative indentation in place will have to be countered\n    /// before indentation starts again.\n    ///\n    /// [`push`]: Self::push\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let mut tokens = Tokens::<()>::new();\n    ///\n    /// tokens.indent();\n    /// tokens.append(\"hello\");\n    /// tokens.unindent();\n    /// tokens.append(\"world\");\n    /// tokens.unindent();\n    /// tokens.append(\"😀\");\n    /// tokens.indent();\n    /// tokens.append(\"😁\");\n    /// tokens.indent();\n    /// tokens.append(\"😂\");\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"    hello\",\n    ///         \"world\",\n    ///         \"😀\",\n    ///         \"😁\",\n    ///         \"    😂\",\n    ///     ],\n    ///     tokens.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn unindent(&mut self) {\n        self.indentation(-1);\n    }\n\n    /// Formatting function for token streams that gives full control over the\n    /// formatting environment.\n    ///\n    /// The configurations and `format` arguments will be provided to all\n    /// registered language items as well, and can be used to customize\n    /// formatting through [LangItem::format()].\n    ///\n    /// The `format` argument is primarily used internally by\n    /// [Lang::format_file] to provide intermediate state that can be affect how\n    /// language items are formatter. So formatting something as a file might\n    /// yield different results than using this raw formatting function.\n    ///\n    /// Available formatters:\n    ///\n    /// * [fmt::VecWriter] - To write result into a vector.\n    /// * [fmt::FmtWriter] - To write the result into something implementing\n    ///   [fmt::Write][std::fmt::Write].\n    /// * [fmt::IoWriter]- To write the result into something implementing\n    ///   [io::Write][std::io::Write].\n    ///\n    /// # Examples\n    ///\n    /// ```,no_run\n    /// use genco::prelude::*;\n    /// use genco::fmt;\n    ///\n    /// let map = rust::import(\"std::collections\", \"HashMap\");\n    ///\n    /// let tokens: rust::Tokens = quote! {\n    ///     let mut m = $map::new();\n    ///     m.insert(1u32, 2u32);\n    /// };\n    ///\n    /// let stdout = std::io::stdout();\n    /// let mut w = fmt::IoWriter::new(stdout.lock());\n    ///\n    /// let fmt = fmt::Config::from_lang::<Rust>()\n    ///     .with_indentation(fmt::Indentation::Space(2));\n    /// let mut formatter = w.as_formatter(&fmt);\n    /// let config = rust::Config::default();\n    ///\n    /// // Default format state for Rust.\n    /// let format = rust::Format::default();\n    ///\n    /// tokens.format(&mut formatter, &config, &format)?;\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    ///\n    /// [LangItem::format()]: crate::lang::LangItem::format()\n    pub fn format(\n        &self,\n        out: &mut fmt::Formatter<'_>,\n        config: &L::Config,\n        format: &L::Format,\n    ) -> fmt::Result {\n        out.format_items::<L>(&self.lang, &self.items, config, format)\n    }\n\n    /// Push a literal item to the stream.\n    #[inline]\n    pub(crate) fn literal(&mut self, lit: impl Into<ItemStr>) {\n        self.items.push(Item::literal(lit.into()));\n    }\n\n    /// Push an open quote item to the stream.\n    #[inline]\n    pub(crate) fn open_quote(&mut self, is_interpolated: bool) {\n        self.items.push(Item::open_quote(is_interpolated));\n    }\n\n    /// Push a close quote item to the stream.\n    #[inline]\n    pub(crate) fn close_quote(&mut self) {\n        self.items.push(Item::close_quote());\n    }\n\n    /// Add a language item directly.\n    pub(crate) fn lang_item(&mut self, item: L::Item) {\n        self.items.push(Item::lang(self.lang.len()));\n        self.lang.push(item);\n    }\n\n    /// Register a language item directly.\n    pub(crate) fn lang_item_register(&mut self, item: L::Item) {\n        self.lang.push(item);\n    }\n\n    /// File formatting function for token streams that gives full control over the\n    /// formatting environment.\n    ///\n    /// File formatting will render preambles like namespace declarations and\n    /// imports.\n    ///\n    /// Available formatters:\n    ///\n    /// * [fmt::VecWriter] - To write result into a vector.\n    /// * [fmt::FmtWriter] - To write the result into something implementing\n    ///   [fmt::Write][std::fmt::Write].\n    /// * [fmt::IoWriter]- To write the result into something implementing\n    ///   [io::Write][std::io::Write].\n    ///\n    /// # Examples\n    ///\n    /// ```,no_run\n    /// use genco::prelude::*;\n    /// use genco::fmt;\n    ///\n    /// let map = rust::import(\"std::collections\", \"HashMap\");\n    ///\n    /// let tokens: rust::Tokens = quote! {\n    ///     let mut m = $map::new();\n    ///     m.insert(1u32, 2u32);\n    /// };\n    ///\n    /// let stdout = std::io::stdout();\n    /// let mut w = fmt::IoWriter::new(stdout.lock());\n    ///\n    /// let fmt = fmt::Config::from_lang::<Rust>()\n    ///     .with_indentation(fmt::Indentation::Space(2));\n    /// let mut formatter = w.as_formatter(&fmt);\n    /// let config = rust::Config::default();\n    ///\n    /// tokens.format_file(&mut formatter, &config)?;\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn format_file(&self, out: &mut fmt::Formatter<'_>, config: &L::Config) -> fmt::Result {\n        L::format_file(self, out, config)?;\n        out.write_trailing_line()?;\n        Ok(())\n    }\n\n    /// Internal function to modify the indentation of the token stream.\n    fn indentation(&mut self, mut n: i16) {\n        let item = loop {\n            // flush all whitespace preceeding the indentation change.\n            let Some(item) = self.items.pop() else {\n                break None;\n            };\n\n            match &item.kind {\n                Kind::Push => continue,\n                Kind::Space => continue,\n                Kind::Line => continue,\n                Kind::Indentation(u) => n += u,\n                _ => break Some(item),\n            }\n        };\n\n        self.items.extend(item);\n\n        if n != 0 {\n            self.items.push(Item::new(Kind::Indentation(n)));\n        }\n    }\n}\n\nimpl<L> Default for Tokens<L>\nwhere\n    L: Lang,\n{\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl<L> Tokens<L>\nwhere\n    L: LangSupportsEval,\n{\n    /// Helper function to determine if the token stream supports evaluation at compile time.\n    #[doc(hidden)]\n    #[inline]\n    pub fn lang_supports_eval(&self) {}\n}\n\nimpl<L> Tokens<L>\nwhere\n    L: Lang,\n    L::Config: Default,\n{\n    /// Format the token stream as a file for the given target language to a\n    /// string using the default configuration.\n    ///\n    /// This is a shorthand to using [FmtWriter][fmt::FmtWriter] directly in\n    /// combination with [format][Self::format_file].\n    ///\n    /// This function will render imports.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    /// use genco::fmt;\n    ///\n    /// let map = rust::import(\"std::collections\", \"HashMap\");\n    ///\n    /// let tokens: rust::Tokens = quote! {\n    ///     let mut m = $map::new();\n    ///     m.insert(1u32, 2u32);\n    /// };\n    ///\n    /// assert_eq!(\n    ///     \"use std::collections::HashMap;\\n\\nlet mut m = HashMap::new();\\nm.insert(1u32, 2u32);\\n\",\n    ///     tokens.to_file_string()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn to_file_string(&self) -> fmt::Result<String> {\n        let mut w = fmt::FmtWriter::new(String::new());\n        let fmt = fmt::Config::from_lang::<L>();\n        let mut formatter = w.as_formatter(&fmt);\n        let config = L::Config::default();\n        self.format_file(&mut formatter, &config)?;\n        Ok(w.into_inner())\n    }\n\n    /// Format only the current token stream as a string using the default\n    /// configuration.\n    ///\n    /// This is a shorthand to using [FmtWriter][fmt::FmtWriter] directly in\n    /// combination with [format][Self::format].\n    ///\n    /// This function _will not_ render imports.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let map = rust::import(\"std::collections\", \"HashMap\");\n    ///\n    /// let tokens: rust::Tokens = quote! {\n    ///     let mut m = $map::new();\n    ///     m.insert(1u32, 2u32);\n    /// };\n    ///\n    /// assert_eq!(\n    ///     \"let mut m = HashMap::new();\\nm.insert(1u32, 2u32);\",\n    ///     tokens.to_string()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn to_string(&self) -> fmt::Result<String> {\n        let mut w = fmt::FmtWriter::new(String::new());\n        let fmt = fmt::Config::from_lang::<L>();\n        let mut formatter = w.as_formatter(&fmt);\n        let config = L::Config::default();\n        let format = L::Format::default();\n        self.format(&mut formatter, &config, &format)?;\n        Ok(w.into_inner())\n    }\n\n    /// Format tokens into a vector, where each entry equals a line in the\n    /// resulting file using the default configuration.\n    ///\n    /// This is a shorthand to using [VecWriter][fmt::VecWriter] directly in\n    /// combination with [format][Self::format_file].\n    ///\n    /// This function will render imports.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let map = rust::import(\"std::collections\", \"HashMap\");\n    ///\n    /// let tokens: rust::Tokens = quote! {\n    ///     let mut m = $map::new();\n    ///     m.insert(1u32, 2u32);\n    /// };\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"use std::collections::HashMap;\",\n    ///         \"\",\n    ///         \"let mut m = HashMap::new();\",\n    ///         \"m.insert(1u32, 2u32);\"\n    ///     ],\n    ///     tokens.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    ///\n    /// # Example with Python indentation\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let tokens: python::Tokens = quote! {\n    ///     def foo():\n    ///         pass\n    ///\n    ///     def bar():\n    ///         pass\n    /// };\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"def foo():\",\n    ///         \"    pass\",\n    ///         \"\",\n    ///         \"def bar():\",\n    ///         \"    pass\",\n    ///     ],\n    ///     tokens.to_file_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn to_file_vec(&self) -> fmt::Result<Vec<String>> {\n        let mut w = fmt::VecWriter::new();\n        let fmt = fmt::Config::from_lang::<L>();\n        let mut formatter = w.as_formatter(&fmt);\n        let config = L::Config::default();\n        self.format_file(&mut formatter, &config)?;\n        Ok(w.into_vec())\n    }\n\n    /// Helper function to format tokens into a vector, where each entry equals\n    /// a line using the default configuration.\n    ///\n    /// This is a shorthand to using [VecWriter][fmt::VecWriter] directly in\n    /// combination with [format][Self::format].\n    ///\n    /// This function _will not_ render imports.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use genco::prelude::*;\n    ///\n    /// let map = rust::import(\"std::collections\", \"HashMap\");\n    ///\n    /// let tokens: rust::Tokens = quote! {\n    ///     let mut m = $map::new();\n    ///     m.insert(1u32, 2u32);\n    /// };\n    ///\n    /// assert_eq!(\n    ///     vec![\n    ///         \"let mut m = HashMap::new();\",\n    ///         \"m.insert(1u32, 2u32);\"\n    ///     ],\n    ///     tokens.to_vec()?\n    /// );\n    /// # Ok::<_, genco::fmt::Error>(())\n    /// ```\n    pub fn to_vec(&self) -> fmt::Result<Vec<String>> {\n        let mut w = fmt::VecWriter::new();\n        let fmt = fmt::Config::from_lang::<L>();\n        let mut formatter = w.as_formatter(&fmt);\n        let config = L::Config::default();\n        let format = L::Format::default();\n        self.format(&mut formatter, &config, &format)?;\n        Ok(w.into_vec())\n    }\n}\n\nimpl<L> PartialEq<Tokens<L>> for Tokens<L>\nwhere\n    L: Lang,\n    L::Item: PartialEq,\n{\n    #[inline]\n    fn eq(&self, other: &Tokens<L>) -> bool {\n        self.items == other.items\n    }\n}\n\nimpl<L> PartialEq<Vec<Item>> for Tokens<L>\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn eq(&self, other: &Vec<Item>) -> bool {\n        self.iter().eq(other.iter())\n    }\n}\n\nimpl<L> PartialEq<Tokens<L>> for Vec<Item>\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn eq(&self, other: &Tokens<L>) -> bool {\n        self.iter().eq(other.iter())\n    }\n}\n\nimpl<L> PartialEq<[Item]> for Tokens<L>\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn eq(&self, other: &[Item]) -> bool {\n        self.iter().eq(other)\n    }\n}\n\nimpl<L, const N: usize> PartialEq<[Item; N]> for Tokens<L>\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn eq(&self, other: &[Item; N]) -> bool {\n        self == &other[..]\n    }\n}\n\nimpl<L> PartialEq<Tokens<L>> for [Item]\nwhere\n    L: Lang,\n{\n    #[inline]\n    fn eq(&self, other: &Tokens<L>) -> bool {\n        self.iter().eq(other.iter())\n    }\n}\n\nimpl<L> Eq for Tokens<L>\nwhere\n    L: Lang,\n    L::Item: Eq,\n{\n}\n\nimpl<L> PartialOrd<Tokens<L>> for Tokens<L>\nwhere\n    L: Lang,\n    L::Item: PartialOrd,\n{\n    #[inline]\n    fn partial_cmp(&self, other: &Tokens<L>) -> Option<Ordering> {\n        self.items.iter().partial_cmp(other.items.iter())\n    }\n}\n\nimpl<L> Ord for Tokens<L>\nwhere\n    L: Lang,\n    L::Item: Ord,\n{\n    #[inline]\n    fn cmp(&self, other: &Tokens<L>) -> Ordering {\n        self.items.iter().cmp(other.items.iter())\n    }\n}\n\n/// An item reference, where language items are translated into a reference to\n/// them.\n#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]\npub struct ItemRef<'a, T> {\n    kind: ItemRefKind<'a, T>,\n}\n\nimpl<T> core::fmt::Debug for ItemRef<'_, T>\nwhere\n    T: core::fmt::Debug,\n{\n    #[inline]\n    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n        self.kind.fmt(f)\n    }\n}\n\n#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]\nenum ItemRefKind<'a, T> {\n    Lang(&'a T),\n    Item(&'a Item),\n}\n\nimpl<T> PartialEq<Item> for ItemRef<'_, T> {\n    #[inline]\n    fn eq(&self, other: &Item) -> bool {\n        match self.kind {\n            ItemRefKind::Lang(..) => false,\n            ItemRefKind::Item(item) => *item == *other,\n        }\n    }\n}\n\nimpl<T> PartialEq<&Item> for ItemRef<'_, T> {\n    #[inline]\n    fn eq(&self, other: &&Item) -> bool {\n        match self.kind {\n            ItemRefKind::Lang(..) => false,\n            ItemRefKind::Item(item) => *item == **other,\n        }\n    }\n}\n\nimpl<T> PartialEq<ItemRef<'_, T>> for Item {\n    #[inline]\n    fn eq(&self, other: &ItemRef<'_, T>) -> bool {\n        *other == *self\n    }\n}\n\nimpl<T> PartialEq<ItemRef<'_, T>> for &Item {\n    #[inline]\n    fn eq(&self, other: &ItemRef<'_, T>) -> bool {\n        *other == **self\n    }\n}\n\n/// Iterator over [`Tokens`].\n///\n/// This is created using [`Tokens::iter()`].\npub struct Iter<'a, T> {\n    lang: &'a [T],\n    iter: slice::Iter<'a, Item>,\n}\n\nimpl<'a, T> Iterator for Iter<'a, T> {\n    type Item = ItemRef<'a, T>;\n\n    #[inline]\n    fn next(&mut self) -> Option<Self::Item> {\n        let item = self.iter.next()?;\n\n        let kind = if let Kind::Lang(n) = item.kind {\n            ItemRefKind::Lang(self.lang.get(n)?)\n        } else {\n            ItemRefKind::Item(item)\n        };\n\n        Some(ItemRef { kind })\n    }\n\n    #[inline]\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        self.iter.size_hint()\n    }\n}\n\nimpl<'a, L> IntoIterator for &'a Tokens<L>\nwhere\n    L: Lang,\n{\n    type Item = ItemRef<'a, L::Item>;\n    type IntoIter = Iter<'a, L::Item>;\n\n    #[inline]\n    fn into_iter(self) -> Self::IntoIter {\n        self.iter()\n    }\n}\n\nimpl<L> core::fmt::Debug for Tokens<L>\nwhere\n    L: Lang,\n    L::Item: core::fmt::Debug,\n{\n    #[inline]\n    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n        f.debug_list().entries(&self.items).finish()\n    }\n}\n\nimpl<L> Clone for Tokens<L>\nwhere\n    L: Lang,\n    L::Item: Clone,\n{\n    #[inline]\n    fn clone(&self) -> Self {\n        Self {\n            items: self.items.clone(),\n            lang: self.lang.clone(),\n        }\n    }\n}\n\nimpl<L> hash::Hash for Tokens<L>\nwhere\n    L: Lang,\n    L::Item: hash::Hash,\n{\n    #[inline]\n    fn hash<H>(&self, state: &mut H)\n    where\n        H: hash::Hasher,\n    {\n        self.items.hash(state);\n        self.lang.hash(state);\n    }\n}\n\n/// An iterator over language-specific imported items.\n///\n/// Constructed using the [`Tokens::iter_lang`] method.\npub struct IterLang<'a, L>\nwhere\n    L: Lang,\n{\n    lang: slice::Iter<'a, L::Item>,\n}\n\nimpl<'a, L> Iterator for IterLang<'a, L>\nwhere\n    L: Lang,\n{\n    type Item = &'a L::Item;\n\n    #[inline]\n    fn next(&mut self) -> Option<Self::Item> {\n        self.lang.next()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use core::fmt::Write as _;\n\n    use alloc::string::String;\n    use alloc::vec;\n    use alloc::vec::Vec;\n\n    use crate as genco;\n    use crate::fmt;\n    use crate::{quote, Tokens};\n\n    /// Own little custom language for this test.\n    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]\n    struct Import(u32);\n\n    impl_lang! {\n        Lang {\n            type Config = ();\n            type Format = ();\n            type Item = Any;\n        }\n\n        Import(Import) {\n            fn format(&self, out: &mut fmt::Formatter<'_>, _: &(), _: &()) -> fmt::Result {\n                write!(out, \"{}\", self.0)\n            }\n        }\n    }\n\n    #[test]\n    fn test_walk_custom() {\n        let toks: Tokens<Lang> = quote! {\n            1:1 $(Import(1)) 1:2\n            bar\n            2:1 2:2 $(quote!(3:1 3:2)) $(Import(2))\n            $(String::from(\"nope\"))\n        };\n\n        let mut output: Vec<_> = toks.iter_lang().cloned().collect();\n        output.sort();\n\n        let expected: Vec<Any> = vec![Import(1).into(), Import(2).into()];\n\n        assert_eq!(expected, output);\n    }\n}\n"
  },
  {
    "path": "tests/test_indentation_rules.rs",
    "content": "use genco::prelude::*;\n\n#[test]\nfn test_indentation_rules() -> genco::fmt::Result {\n    let rule1: Tokens<Rust> = quote!(fn     test());\n\n    let rule2: Tokens<Rust> = quote! {\n        fn test() {\n            println!(\"Hello...\");\n\n\n            println!(\"... World!\");\n        }\n    };\n\n    let rule3: Tokens<Rust> = quote! {\n        fn test() {\n            println!(\"Hello...\");\n            println!(\"... World!\");\n        }\n    };\n\n    assert_eq!(\"fn test()\", rule1.to_string()?);\n\n    assert_eq!(\n        \"fn test() {\\n    println!(\\\"Hello...\\\");\\n\\n    println!(\\\"... World!\\\");\\n}\",\n        rule2.to_string()?\n    );\n\n    assert_eq!(\n        \"fn test() {\\n    println!(\\\"Hello...\\\");\\n    println!(\\\"... World!\\\");\\n}\",\n        rule3.to_string()?\n    );\n\n    Ok(())\n}\n"
  },
  {
    "path": "tests/test_option.rs",
    "content": "use genco::prelude::*;\n\n#[test]\nfn test_option() -> genco::fmt::Result {\n    let test1 = Some(quote!(println!(\"{}\", $(quoted(\"one\")))));\n    let test2 = None::<rust::Tokens>;\n\n    let tokens: rust::Tokens = quote! {\n        fn test_option() -> u32 {\n            $test1\n            $test2\n\n            42\n        }\n    };\n\n    assert_eq!(\n        vec![\n            \"fn test_option() -> u32 {\",\n            \"    println!(\\\"{}\\\", \\\"one\\\")\",\n            \"\",\n            \"    42\",\n            \"}\"\n        ],\n        tokens.to_file_vec()?\n    );\n\n    Ok(())\n}\n"
  },
  {
    "path": "tests/test_quote.rs",
    "content": "use genco::prelude::*;\n\n#[test]\nfn test_quote() -> genco::fmt::Result {\n    let test = quoted(\"one\");\n\n    let tokens: rust::Tokens = quote! {\n        fn test() -> u32 {\n            println!(\"{}\", $(test));\n\n            42\n        }\n    };\n\n    assert_eq!(\n        \"fn test() -> u32 {\\n    println!(\\\"{}\\\", \\\"one\\\");\\n\\n    42\\n}\",\n        tokens.to_string()?\n    );\n\n    let tokens: rust::Tokens = quote! {\n        fn test() -> u32 {\n            println!(\"{}\", $(quoted(\"two\")));\n\n            42\n        }\n    };\n\n    assert_eq!(\n        \"fn test() -> u32 {\\n    println!(\\\"{}\\\", \\\"two\\\");\\n\\n    42\\n}\",\n        tokens.to_string()?\n    );\n\n    let tokens: rust::Tokens = quote! {\n        fn test() -> u32 {\n            println!(\"{}\", $$(quoted(\"two\")));\n\n            42\n        }\n    };\n\n    assert_eq!(\n        \"fn test() -> u32 {\\n    println!(\\\"{}\\\", $(quoted(\\\"two\\\")));\\n\\n    42\\n}\",\n        tokens.to_string()?\n    );\n\n    Ok(())\n}\n\n#[test]\nfn test_tight_quote() -> genco::fmt::Result {\n    let a = \"foo\";\n    let b = \"bar\";\n    let c = \"baz\";\n    let tokens: rust::Tokens = quote!($(a)$(b)$(c));\n    assert_eq!(\"foobarbaz\", tokens.to_string()?);\n    Ok(())\n}\n\n#[test]\nfn test_escape() -> genco::fmt::Result {\n    let tokens: rust::Tokens = quote!($$$$ $$ $$$$ $$$$ $$ $$ $$[test]);\n    assert_eq!(\"$$ $ $$ $$ $ $ $[test]\", tokens.to_string()?);\n\n    Ok(())\n}\n\n#[test]\nfn test_scope() -> genco::fmt::Result {\n    let tokens: rust::Tokens = quote! {\n        // Nested factory.\n        $(ref tokens {\n            quote_in!(*tokens => fn test() -> u32 { 42 });\n        })\n    };\n\n    assert_eq!(\"fn test() -> u32 { 42 }\", tokens.to_string()?);\n\n    Ok(())\n}\n"
  },
  {
    "path": "tests/test_quote_in.rs",
    "content": "use genco::prelude::*;\n\n/// basic smoketests.\n#[test]\nfn test_quote_in() -> genco::fmt::Result {\n    let mut tokens = rust::Tokens::new();\n    quote_in!(tokens => fn hello() -> u32 { 42 });\n    assert_eq!(\"fn hello() -> u32 { 42 }\", tokens.to_string()?);\n    Ok(())\n}\n\n/// quote_in! must expand into a unit expression.\n#[test]\nfn test_quote_into_unit() -> genco::fmt::Result {\n    let tokens = &mut go::Tokens::new();\n    quote_in!(*tokens => uint32);\n    assert_eq!(\"uint32\", tokens.to_string()?);\n    Ok(())\n}\n"
  },
  {
    "path": "tests/test_quote_simple_expression.rs",
    "content": "use genco::prelude::*;\n\n#[test]\nfn test_quote_simple_expression() -> genco::fmt::Result {\n    let tokens: Tokens<Rust> = quote!(fn $(\"test\")());\n    assert_eq!(\"fn test()\", tokens.to_string()?);\n\n    let expr = &quote!(test);\n    let tokens: Tokens<Rust> = quote!(fn $expr());\n    assert_eq!(\"fn test()\", tokens.to_string()?);\n\n    let tokens: Tokens<Rust> = quote!(fn $(expr)());\n    assert_eq!(\"fn test()\", tokens.to_string()?);\n\n    // inline macro expansion.\n    let tokens: Tokens<Rust> = quote!(fn $(quote!(test))());\n    assert_eq!(\"fn test()\", tokens.to_string()?);\n\n    Ok(())\n}\n"
  },
  {
    "path": "tests/test_register.rs",
    "content": "use genco::prelude::*;\n\n#[test]\nfn test_register() -> genco::fmt::Result {\n    let import = rust::import(\"std::iter\", \"FromIterator\").with_alias(\"_\");\n\n    let tokens: Tokens<Rust> = quote! {\n        $(register(import))\n        // additional lines are ignored!\n\n        fn test() -> u32 {\n            42\n        }\n    };\n\n    println!(\"{tokens:?}\");\n\n    assert_eq!(\n        vec![\n            \"use std::iter::FromIterator as _;\",\n            \"\",\n            \"fn test() -> u32 {\",\n            \"    42\",\n            \"}\"\n        ],\n        tokens.to_file_vec()?\n    );\n\n    Ok(())\n}\n"
  },
  {
    "path": "tests/test_string.rs",
    "content": "use genco::prelude::*;\n\n#[test]\nfn test_quoted() -> genco::fmt::Result {\n    let t: dart::Tokens = quote!($[str](Hello $($(quoted(\"World\")))));\n    assert_eq!(\"\\\"Hello ${\\\"World\\\"}\\\"\", t.to_string()?);\n\n    let t: dart::Tokens = quote!($[str](Hello \"World\"));\n    assert_eq!(\"\\\"Hello \\\\\\\"World\\\\\\\"\\\"\", t.to_string()?);\n\n    let t: dart::Tokens = quote!($[str](Hello $(World)));\n    assert_eq!(\"\\\"Hello $World\\\"\", t.to_string()?);\n\n    let t: js::Tokens = quote!($[str](Hello $(World)));\n    assert_eq!(\"`Hello ${World}`\", t.to_string()?);\n    Ok(())\n}\n\n#[test]\nfn test_string_in_string_in() -> genco::fmt::Result {\n    let t: dart::Tokens = quote!($[str](Hello $($[str]($($[str](World))))));\n    assert_eq!(\"\\\"Hello ${\\\"${\\\"World\\\"}\\\"}\\\"\", t.to_string()?);\n\n    let t: js::Tokens = quote!($[str](Hello $($[str]($($[str](World))))));\n    assert_eq!(\"`Hello ${`${\\\"World\\\"}`}`\", t.to_string()?);\n    Ok(())\n}\n"
  },
  {
    "path": "tests/test_token_gen.rs",
    "content": "//! Test to assert that the tokens generated are equivalent.\n\nuse genco::fmt;\nuse genco::prelude::*;\nuse genco::tokens::ItemStr;\n\nuse genco::__priv::{indentation, line, literal, push, space, static_};\n\n#[test]\nfn test_token_gen() {\n    let tokens: rust::Tokens = quote! {\n        foo\n        bar\n        baz\n            $(ref tokens => quote_in! { *tokens => hello })\n        out?\n    };\n\n    assert_eq! {\n        vec![\n            static_(\"foo\"),\n            push(),\n            static_(\"bar\"),\n            push(),\n            static_(\"baz\"),\n            indentation(1),\n            static_(\"hello\"),\n            indentation(-1),\n            static_(\"out?\")\n        ],\n        tokens,\n    }\n}\n\n#[test]\nfn test_iterator_gen() {\n    let tokens: rust::Tokens = quote! {\n        $(ref t => for n in 0..3 {\n            t.push();\n            t.append(n);\n        })\n    };\n\n    assert_eq! {\n        vec![\n            push(),\n            literal(\"0\".into()),\n            push(),\n            literal(\"1\".into()),\n            push(),\n            literal(\"2\".into()),\n        ],\n        tokens,\n    };\n\n    let tokens: rust::Tokens = quote! {\n        $(ref t {\n            for n in 0..3 {\n                t.push();\n                t.append(n);\n            }\n        })\n    };\n\n    assert_eq! {\n        vec![\n            push(),\n            literal(\"0\".into()),\n            push(),\n            literal(\"1\".into()),\n            push(),\n            literal(\"2\".into()),\n        ],\n        tokens,\n    };\n}\n\n#[test]\nfn test_tricky_continuation() {\n    let mut output = rust::Tokens::new();\n\n    let bar = ItemStr::static_(\"bar\");\n\n    quote_in! {\n        output =>\n        foo, $(ref output {\n            output.append(&bar);\n            output.append(static_(\",\"));\n            output.space();\n        })baz\n        biz\n    };\n\n    assert_eq! {\n        output,\n        vec![\n            static_(\"foo,\"),\n            space(),\n            static_(\"bar\"),\n            static_(\",\"),\n            space(),\n            static_(\"baz\"),\n            push(),\n            static_(\"biz\"),\n        ]\n    };\n}\n\n#[test]\nfn test_indentation() {\n    // Bug: Since we carry the span of out, the line after counts as unindented.\n    //\n    // These two should be identical:\n\n    let mut a = rust::Tokens::new();\n\n    quote_in! { a =>\n        a\n            b\n        c\n    };\n\n    assert_eq! {\n        a,\n        vec![\n            static_(\"a\"),\n            indentation(1),\n            static_(\"b\"),\n            indentation(-1),\n            static_(\"c\")\n        ]\n    };\n\n    let mut b = rust::Tokens::new();\n\n    quote_in! {\n        b =>\n        a\n            b\n        c\n    };\n\n    assert_eq! {\n        b,\n        vec![\n            static_(\"a\"),\n            indentation(1),\n            static_(\"b\"),\n            indentation(-1),\n            static_(\"c\")\n        ]\n    };\n}\n\n#[test]\nfn test_repeat() {\n    let tokens: rust::Tokens = quote! {\n        foo $(for (a, b) in (0..3).zip(3..6) => $a $b)\n    };\n\n    assert_eq! {\n        vec![\n            static_(\"foo\"),\n            space(),\n            literal(\"0\".into()),\n            space(),\n            literal(\"3\".into()),\n            literal(\"1\".into()),\n            space(),\n            literal(\"4\".into()),\n            literal(\"2\".into()),\n            space(),\n            literal(\"5\".into())\n        ],\n        tokens,\n    };\n\n    let tokens: rust::Tokens = quote! {\n        foo $(for (a, b) in (0..3).zip(3..6) { $a $b })\n    };\n\n    assert_eq! {\n        vec![\n            static_(\"foo\"),\n            space(),\n            literal(\"0\".into()),\n            space(),\n            literal(\"3\".into()),\n            literal(\"1\".into()),\n            space(),\n            literal(\"4\".into()),\n            literal(\"2\".into()),\n            space(),\n            literal(\"5\".into())\n        ],\n        tokens,\n    };\n}\n\n#[test]\nfn test_tight_quote() {\n    let output: rust::Tokens = quote! {\n        You are:$(\"fine\")\n    };\n\n    assert_eq! {\n        output,\n        vec![\n            static_(\"You\"),\n            space(),\n            static_(\"are:fine\"),\n        ]\n    };\n}\n\n#[test]\nfn test_tight_repitition() {\n    let output: rust::Tokens = quote! {\n        You are: $(for v in 0..3 join (, ) => $v)\n    };\n\n    assert_eq! {\n        output,\n        vec![\n            static_(\"You\"),\n            space(),\n            static_(\"are:\"),\n            space(),\n            literal(\"0\".into()),\n            static_(\",\"),\n            space(),\n            literal(\"1\".into()),\n            static_(\",\"),\n            space(),\n            literal(\"2\".into()),\n        ]\n    };\n}\n\n#[test]\nfn test_if() {\n    let a = true;\n    let b = false;\n\n    let output: rust::Tokens = quote! {\n        $(if a => foo)\n        $(if a { foo2 })\n        $(if b { bar })\n        $(if b => bar2)\n        $(if a => baz)\n        $(if a { baz2 })\n        $(if b { not_biz } else { biz })\n    };\n\n    assert_eq! {\n        output,\n        vec![\n            static_(\"foo\"),\n            push(),\n            static_(\"foo2\"),\n            push(),\n            static_(\"baz\"),\n            push(),\n            static_(\"baz2\"),\n            push(),\n            static_(\"biz\"),\n        ]\n    };\n}\n\n#[test]\nfn test_match() {\n    enum Alt {\n        A,\n        B,\n    }\n\n    fn test(alt: Alt) -> rust::Tokens {\n        quote! {\n            $(match alt { Alt::A => a, Alt::B => b })\n        }\n    }\n\n    fn test2(alt: Alt) -> rust::Tokens {\n        quote! {\n            $(match alt { Alt::A => { a }, Alt::B => { b } })\n        }\n    }\n\n    fn test2_cond(alt: Alt, cond: bool) -> rust::Tokens {\n        quote! {\n            $(match alt { Alt::A if cond => { a }, _ => { b } })\n        }\n    }\n\n    assert_eq! {\n        test(Alt::A),\n        vec![static_(\"a\")]\n    };\n\n    assert_eq! {\n        test(Alt::B),\n        vec![static_(\"b\")]\n    };\n\n    assert_eq! {\n        test2(Alt::A),\n        vec![static_(\"a\")]\n    };\n\n    assert_eq! {\n        test2(Alt::B),\n        vec![static_(\"b\")]\n    };\n\n    assert_eq! {\n        test2_cond(Alt::A, true),\n        vec![static_(\"a\")]\n    };\n\n    assert_eq! {\n        test2_cond(Alt::A, false),\n        vec![static_(\"b\")]\n    };\n}\n\n#[test]\nfn test_let() {\n    let tokens: rust::Tokens = quote! {\n        $(let x = 1) $x\n    };\n\n    assert_eq! {\n        tokens,\n        vec![space(), literal(\"1\".into())]\n    };\n\n    // Tuple binding\n    let tokens: rust::Tokens = quote! {\n        $(let (a, b) = (\"c\", \"d\")) $a, $b\n    };\n\n    assert_eq! {\n        tokens,\n        vec![\n            space(), literal(\"c\".into()),\n            static_(\",\"),\n            space(), literal(\"d\".into())\n        ]\n    };\n\n    // Function call in expression\n    let x = \"bar\";\n    fn baz(s: &str) -> String {\n        format!(\"{s}baz\")\n    }\n\n    let tokens: rust::Tokens = quote! {\n        $(let a = baz(x)) $a\n    };\n\n    assert_eq! {\n        tokens,\n        vec![space(), literal(\"barbaz\".into())]\n    };\n\n    // Complex expression\n    let x = 2;\n    let tokens: rust::Tokens = quote! {\n        $(let even = if x % 2 == 0 { \"even\" } else { \"odd\" }) $even\n    };\n\n    assert_eq! {\n        tokens,\n        vec![space(), literal(\"even\".into())]\n    };\n}\n\n#[test]\nfn test_mutable_let() {\n    let path = \"A.B.C.D\";\n\n    let tokens: Tokens<()> = quote! {\n        $(let mut items = path.split('.'))\n        $(if let Some(first) = items.next() =>\n            First is $first\n        )\n        $(if let Some(second) = items.next() =>\n            Second is $second\n        )\n    };\n\n    assert_eq!(\n        tokens,\n        vec![\n            push(),\n            static_(\"First\"),\n            space(),\n            static_(\"is\"),\n            space(),\n            literal(\"A\".into()),\n            push(),\n            static_(\"Second\"),\n            space(),\n            static_(\"is\"),\n            space(),\n            literal(\"B\".into())\n        ]\n    );\n}\n\n#[test]\nfn test_empty_loop_whitespace() {\n    // Bug: This should generate two commas. But did generate a space following\n    // it!\n    let tokens: rust::Tokens = quote! {\n        $(for _ in 0..3 join(,) =>)\n    };\n\n    assert_eq! {\n        tokens,\n        vec![static_(\",\"), static_(\",\")]\n    };\n\n    let tokens: rust::Tokens = quote! {\n        $(for _ in 0..3 join( ,) =>)\n    };\n\n    assert_eq! {\n        tokens,\n        vec![space(), static_(\",\"), space(), static_(\",\")]\n    };\n\n    let tokens: rust::Tokens = quote! {\n          $(for _ in 0..3 join(, ) =>)\n    };\n\n    assert_eq! {\n        tokens,\n        vec![static_(\",\"), space(), static_(\",\"), space()]\n    };\n\n    let tokens: rust::Tokens = quote! {\n          $(for _ in 0..3 join( , ) =>)\n    };\n\n    assert_eq! {\n        tokens,\n        vec![space(), static_(\",\"), space(), static_(\",\"), space()]\n    };\n}\n\n#[test]\nfn test_indentation_empty() {\n    let tokens: rust::Tokens = quote! {\n        a\n            $(for _ in 0..3 =>)\n        b\n    };\n\n    assert_eq! {\n        tokens,\n        vec![\n            static_(\"a\"),\n            static_(\"b\")\n        ]\n    };\n\n    let tokens: rust::Tokens = quote! {\n        a\n            $(if false {})\n        b\n    };\n\n    assert_eq! {\n        tokens,\n        vec![\n            static_(\"a\"),\n            static_(\"b\")\n        ]\n    };\n\n    let tokens: rust::Tokens = quote! {\n        a\n            $(ref _tokens =>)\n        b\n    };\n\n    assert_eq! {\n        tokens,\n        vec![\n            static_(\"a\"),\n            static_(\"b\")\n        ]\n    };\n}\n\n#[test]\nfn test_indentation_management() {\n    let tokens: rust::Tokens = quote! {\n        if a:\n            if b:\n                foo\n        else:\n            c\n    };\n\n    assert_eq! {\n        vec![\n            static_(\"if\"),\n            space(),\n            static_(\"a:\"),\n            indentation(1),\n            static_(\"if\"),\n            space(),\n            static_(\"b:\"),\n            indentation(1),\n            static_(\"foo\"),\n            indentation(-2),\n            static_(\"else:\"),\n            indentation(1),\n            static_(\"c\"),\n            indentation(-1)\n        ],\n        tokens,\n    };\n\n    let tokens: rust::Tokens = quote! {\n        if a:\n            if b:\n                foo\n\n        $(if false => bar)\n\n        $(if true => baz)\n    };\n\n    assert_eq! {\n        vec![\n            static_(\"if\"),\n            space(),\n            static_(\"a:\"),\n            indentation(1),\n            static_(\"if\"),\n            space(),\n            static_(\"b:\"),\n            indentation(1),\n            static_(\"foo\"),\n            indentation(-2),\n            line(),\n            static_(\"baz\"),\n        ],\n        tokens,\n    };\n}\n\n#[test]\nfn test_indentation_management2() -> fmt::Result {\n    let tokens: python::Tokens = quote! {\n        def foo():\n            pass\n\n        def bar():\n            pass\n    };\n\n    assert_eq! {\n        vec![\n            static_(\"def\"),\n            space(),\n            static_(\"foo():\"),\n            indentation(1),\n            static_(\"pass\"),\n            indentation(-1),\n            line(),\n            static_(\"def\"),\n            space(),\n            static_(\"bar():\"),\n            indentation(1),\n            static_(\"pass\"),\n            indentation(-1)\n        ],\n        tokens,\n    };\n\n    assert_eq!(\n        vec![\"def foo():\", \"    pass\", \"\", \"def bar():\", \"    pass\",],\n        tokens.to_file_vec()?\n    );\n\n    Ok(())\n}\n\n#[test]\nfn test_lines() -> fmt::Result {\n    let mut tokens: rust::Tokens = quote! {\n        fn foo() {\n        }\n    };\n\n    tokens.line();\n\n    quote_in! { tokens =>\n        $(if false =>)\n        fn bar() {\n        }\n    };\n\n    assert_eq! {\n        vec![\n            static_(\"fn\"),\n            space(),\n            static_(\"foo()\"),\n            space(),\n            static_(\"{\"),\n            push(),\n            static_(\"}\"),\n            line(),\n            static_(\"fn\"),\n            space(),\n            static_(\"bar()\"),\n            space(),\n            static_(\"{\"),\n            push(),\n            static_(\"}\")\n        ],\n        tokens.clone(),\n    };\n\n    assert_eq!(\n        vec![\"fn foo() {\", \"}\", \"\", \"fn bar() {\", \"}\",],\n        tokens.to_file_vec()?\n    );\n\n    Ok(())\n}\n"
  }
]