├── .deepsource.toml
├── .editorconfig
├── .github
├── CODE-OF-CONDUCT.md
├── CODEOWNERS
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── config.yml
│ └── feature_request.yml
├── SECURITY.md
├── dependabot.yml
├── funding.yml
└── workflows
│ ├── audit.yml
│ ├── check.yml
│ ├── coverage.yml
│ ├── document.yml
│ ├── lint.yml
│ ├── release.yml
│ └── test.yml
├── .gitignore
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── TEMPLATE.md
├── benches
└── criterion.rs
├── build.rs
├── deny.toml
├── examples
├── example.rs
├── generate_from_args.rs
├── generate_from_config.rs
├── generate_from_csv.rs
├── generate_from_json.rs
├── generate_from_toml.rs
├── generate_from_yaml.rs
├── get_csv_field.rs
├── get_json_field.rs
└── get_yaml_field.rs
├── rustfmt.toml
├── src
├── args.rs
├── cli.rs
├── generator.rs
├── generators
│ ├── args.rs
│ ├── ascii.rs
│ ├── csv.rs
│ ├── ini.rs
│ ├── json.rs
│ ├── mod.rs
│ ├── toml.rs
│ └── yaml.rs
├── interface.rs
├── lib.rs
├── macros
│ ├── ascii_macros.rs
│ ├── directory_macros.rs
│ ├── file_macros.rs
│ ├── generator_macros.rs
│ ├── log_macros.rs
│ ├── mod.rs
│ └── utility_macros.rs
├── main.rs
├── models
│ ├── error_ascii_art.rs
│ ├── mod.rs
│ └── model_params.rs
├── utilities
│ ├── directory.rs
│ ├── mod.rs
│ └── uuid.rs
└── utils.rs
├── template
├── AUTHORS.tpl
├── CONTRIBUTING.tpl
├── Cargo.tpl
├── README.tpl
├── TEMPLATE.tpl
├── build.tpl
├── ci.tpl
├── criterion.tpl
├── deepsource.tpl
├── deny.tpl
├── example.tpl
├── github
│ └── workflows
│ │ ├── audit.tpl
│ │ ├── check.tpl
│ │ ├── coverage.tpl
│ │ ├── document.tpl
│ │ ├── lint.tpl
│ │ ├── release.tpl
│ │ └── test.tpl
├── gitignore.tpl
├── lib.tpl
├── macros.tpl
├── main.tpl
├── rustfmt.tpl
├── test.tpl
└── test_test.tpl
└── tests
├── data
├── mylibrary.csv
├── mylibrary.ini
├── mylibrary.json
├── mylibrary.toml
└── mylibrary.yaml
├── generators
├── mod.rs
├── test_args.rs
├── test_ascii.rs
├── test_csv.rs
├── test_ini.rs
├── test_json.rs
├── test_toml.rs
└── test_yaml.rs
├── macros
├── mod.rs
├── test_ascii_macros.rs
├── test_directory_macros.rs
├── test_file_macros.rs
├── test_generator_macros.rs
├── test_log_macros.rs
└── test_utility_macros.rs
├── mod.rs
├── models
├── mod.rs
├── test_error_ascii_art.rs
└── test_model_params.rs
├── test_cli.rs
├── test_generator.rs
├── test_interface.rs
├── test_utils.rs
└── utilities
├── mod.rs
├── test_directory.rs
└── test_uuid.rs
/.deepsource.toml:
--------------------------------------------------------------------------------
1 | version = 1
2 |
3 | [[analyzers]]
4 | name = "rust"
5 | enabled = true
6 |
7 | [analyzers.meta]
8 | msrv = "stable"
9 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Copyright © 2023 LibMake. All rights reserved.
2 | # SPDX-License-Identifier: Apache-2.0 OR MIT
3 |
4 | # EditorConfig helps developers define and maintain consistent
5 | # coding styles between different editors and IDEs
6 | # editorconfig.org
7 |
8 | root = true
9 |
10 | [*]
11 | end_of_line = lf
12 | charset = utf-8
13 | trim_trailing_whitespace = true
14 | insert_final_newline = true
15 | indent_style = space
16 | indent_size = 4
17 |
18 | [*.rs]
19 | max_line_length = 80
20 |
21 | [*.md]
22 | # double whitespace at end of line
23 | # denotes a line break in Markdown
24 | trim_trailing_whitespace = false
25 |
26 | [*.yml]
27 | indent_size = 2
28 |
29 | [Makefile]
30 | indent_style = tab
31 |
--------------------------------------------------------------------------------
/.github/CODE-OF-CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our
7 | project and our community a harassment-free experience for everyone,
8 | regardless of age, body size, disability, ethnicity, gender identity and
9 | expression, level of experience, nationality, personal appearance, race,
10 | religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behaviour that contributes to creating a positive
15 | environment include:
16 |
17 | - Using welcoming and inclusive language
18 | - Being respectful of differing viewpoints and experiences
19 | - Gracefully accepting constructive criticism
20 | - Focusing on what is best for the community
21 | - Showing empathy towards other community members
22 |
23 | Examples of unacceptable behaviour by participants include:
24 |
25 | - The use of sexualized language or imagery and unwelcome sexual
26 | attention or advances
27 | - Trolling, insulting/derogatory comments, and personal or political
28 | attacks
29 | - Public or private harassment
30 | - Publishing others' private information, such as a physical or
31 | electronic address, without explicit permission
32 | - Other conduct which could reasonably be considered inappropriate in a
33 | professional setting
34 |
35 | ## Our Responsibilities
36 |
37 | Project maintainers are responsible for clarifying the standards of
38 | acceptable behaviour and are expected to take appropriate and fair
39 | corrective action in response to any instances of unacceptable
40 | behaviour.
41 |
42 | Project maintainers have the right and responsibility to remove, edit,
43 | or reject comments, commits, code, wiki edits, issues, and other
44 | contributions that are not aligned to this Code of Conduct, or to ban
45 | temporarily or permanently any contributor for other behaviors that they
46 | deem inappropriate, threatening, offensive, or harmful.
47 |
48 | ## Scope
49 |
50 | This Code of Conduct applies both within project spaces and in public
51 | spaces when an individual is representing the project or its community.
52 | Examples of representing a project or community include using an
53 | official project e-mail address, posting via an official social media
54 | account, or acting as an appointed representative at an online or
55 | offline event. Representation of a project may be further defined and
56 | clarified by project maintainers.
57 |
58 | ## Enforcement
59 |
60 | Instances of abusive, harassing, or otherwise unacceptable behaviour may
61 | be reported by contacting the project team. The project team will review
62 | and investigate all complaints, and will respond in a way that it deems
63 | appropriate to the circumstances. The project team is obligated to
64 | maintain confidentiality with regard to the reporter of an incident.
65 | Further details of specific enforcement policies may be posted
66 | separately.
67 |
68 | Project maintainers who do not follow or enforce the Code of Conduct in
69 | good faith may face temporary or permanent repercussions as determined
70 | by other members of the project's leadership.
71 |
72 | ## Attribution
73 |
74 | This Code of Conduct is adapted from the Contributor Covenant homepage,
75 | version 1.4, available at
76 | [version](http://contributor-covenant.org/version/1/4)
77 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | @sebastienrousseau/libmake
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: Create a report to help us improve
3 | labels: ["bug-report"]
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: Thanks for filing a 🐛 bug report 😄!
8 | - type: textarea
9 | id: problem
10 | attributes:
11 | label: Problem
12 | description: >
13 | Please provide a clear and concise description of what the bug is,
14 | including what currently happens and what you expected to happen.
15 | validations:
16 | required: true
17 | - type: textarea
18 | id: steps
19 | attributes:
20 | label: Steps
21 | description: Please list the steps to reproduce the bug.
22 | placeholder: |
23 | 1.
24 | 2.
25 | 3.
26 | - type: textarea
27 | id: possible-solutions
28 | attributes:
29 | label: Possible Solution(s)
30 | description: >
31 | Not obligatory, but suggest a fix/reason for the bug,
32 | or ideas how to implement the addition or change.
33 | - type: textarea
34 | id: notes
35 | attributes:
36 | label: Notes
37 | description: Provide any additional notes that might be helpful.
38 | - type: textarea
39 | id: version
40 | attributes:
41 | label: Version
42 | description: Please paste the output of running `cargo version --verbose`.
43 | render: text
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | contact_links:
2 | - name: Question
3 | url: https://users.rust-lang.org
4 | about: >
5 | Got a question about Cargo? Ask the community on the user forum.
6 | - name: Inspiring Idea
7 | url: https://internals.rust-lang.org/c/tools-and-infrastructure/cargo
8 | about: >
9 | Need more discussions with your next big idea?
10 | Reach out the coummunity on the internals forum.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: Feature Request
2 | description: Suggest an idea for enhancement
3 | labels: ["feature-request"]
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: |
8 | Thanks for filing a feature request!
9 |
10 | If the feature request is relatively small and already with a possible solution, this might be the place for you.
11 |
12 | If you are brewing a big feature that needs feedback from the community, [the internal forum] is the best fit, especially for pre-RFC. You can also talk the idea over with other developers in [#t-cargo Zulip stream].
13 |
14 | [the internal forum]: https://internals.rust-lang.org/c/tools-and-infrastructure/cargo/15
15 | [#t-cargo Zulip stream]: https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo
16 | - type: textarea
17 | id: problem
18 | attributes:
19 | label: Problem
20 | description: >
21 | Please provide a clear description of your use case and the problem
22 | this feature request is trying to solve.
23 | validations:
24 | required: true
25 | - type: textarea
26 | id: solution
27 | attributes:
28 | label: Proposed Solution
29 | description: >
30 | Please provide a clear and concise description of what you want to happen.
31 | - type: textarea
32 | id: notes
33 | attributes:
34 | label: Notes
35 | description: Provide any additional context or information that might be helpful.
--------------------------------------------------------------------------------
/.github/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security
2 |
3 | We take the security of our software products and services seriously,
4 | which includes all source code repositories managed through our GitHub
5 | repositories.
6 |
7 | If you believe you have found a security vulnerability in any of our
8 | repository, please report it to us as described below.
9 |
10 | ## Reporting Security Issues
11 |
12 | Please include the requested information listed below (as much as you
13 | can provide) to help us better understand the nature and scope of the
14 | possible issue:
15 |
16 | - Type of issue (e.g. buffer overflow, SQL injection, cross-site
17 | scripting, etc.)
18 | - Full paths of source file(s) related to the manifestation of the issue
19 | - The location of the affected source code (tag/branch/commit or direct
20 | URL)
21 | - Any special configuration required to reproduce the issue
22 | - Step-by-step instructions to reproduce the issue
23 | - Proof-of-concept or exploit code (if possible)
24 | - Impact of the issue, including how an attacker might exploit the issue
25 |
26 | This information will help us triage your report more quickly.
27 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "cargo"
4 | directory: "/"
5 | schedule:
6 | interval: "daily"
7 |
8 | - package-ecosystem: "github-actions"
9 | directory: "/"
10 | schedule:
11 | interval: "daily"
12 |
--------------------------------------------------------------------------------
/.github/funding.yml:
--------------------------------------------------------------------------------
1 | github: sebastienrousseau
2 | custom: https://paypal.me/wwdseb
3 |
--------------------------------------------------------------------------------
/.github/workflows/audit.yml:
--------------------------------------------------------------------------------
1 | name: 🧪 Audit
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - feat/libmake
8 | pull_request:
9 | branches:
10 | - feat/libmake
11 | release:
12 | types: [created]
13 |
14 | jobs:
15 | dependencies:
16 | name: Audit dependencies
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: hecrj/setup-rust-action@v2
20 | - name: Install cargo-audit
21 | run: cargo install cargo-audit
22 |
23 | - uses: actions/checkout@v4
24 | - name: Resolve dependencies
25 | run: cargo update
26 |
27 | - name: Audit vulnerabilities
28 | run: cargo audit
29 |
--------------------------------------------------------------------------------
/.github/workflows/check.yml:
--------------------------------------------------------------------------------
1 | name: 🧪 Check
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - feat/libmake
8 | pull_request:
9 | branches:
10 | - feat/libmake
11 | release:
12 | types: [created]
13 |
14 | jobs:
15 | all:
16 | name: Check
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: hecrj/setup-rust-action@v2
20 | with:
21 | components: clippy
22 | - uses: actions/checkout@v4
23 | - name: Check lints
24 | run: cargo check --all-targets --workspace --all-features
25 |
--------------------------------------------------------------------------------
/.github/workflows/coverage.yml:
--------------------------------------------------------------------------------
1 | name: 📶 Coverage
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 |
9 | env:
10 | CARGO_TERM_COLOR: always
11 |
12 | jobs:
13 | coverage:
14 | name: Code Coverage
15 | runs-on: ubuntu-latest
16 | env:
17 | CARGO_INCREMENTAL: "0"
18 | RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests"
19 | RUSTDOCFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests"
20 |
21 | steps:
22 | # Checkout the repository
23 | - name: Checkout repository
24 | uses: actions/checkout@v4
25 |
26 | # Setup Rust nightly
27 | - name: Install Rust
28 | uses: actions-rs/toolchain@v1
29 | id: toolchain
30 | with:
31 | toolchain: nightly
32 | override: true
33 |
34 | # Configure cache for Cargo
35 | - name: Cache Cargo registry, index
36 | uses: actions/cache@v4
37 | id: cache-cargo
38 | with:
39 | path: |
40 | ~/.cargo/registry
41 | ~/.cargo/bin
42 | ~/.cargo/git
43 | key: linux-${{ steps.toolchain.outputs.rustc_hash }}-rust-cov-${{ hashFiles('**/Cargo.lock') }}
44 |
45 | # Run tests with all features
46 | - name: Test (cargo test)
47 | uses: actions-rs/cargo@v1
48 | with:
49 | command: test
50 | args: "--workspace"
51 |
52 | # Install grcov
53 | - uses: actions-rs/grcov@v0.1
54 | id: coverage
55 |
56 | # Upload to Codecov.io
57 | - name: Upload to Codecov.io
58 | uses: codecov/codecov-action@v4
59 | with:
60 | token: ${{ secrets.CODECOV_TOKEN }}
61 | file: ${{ steps.coverage.outputs.report }}
62 |
--------------------------------------------------------------------------------
/.github/workflows/document.yml:
--------------------------------------------------------------------------------
1 | name: 🧪 Document
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 | release:
11 | types: [created]
12 |
13 | jobs:
14 | all:
15 | name: Document
16 | if: github.ref == 'refs/heads/main' && github.event_name == 'push'
17 | runs-on: ubuntu-latest
18 | concurrency:
19 | group: ${{ github.workflow }}-${{ github.ref }}
20 | steps:
21 | - uses: hecrj/setup-rust-action@v2
22 | with:
23 | rust-version: nightly
24 |
25 | - uses: actions/checkout@v4
26 |
27 | - name: Update libssl
28 | run: |
29 | sudo apt-get update
30 | sudo apt-get install -y libssl1.1
31 |
32 | - name: Generate documentation for all features and publish it
33 | run: |
34 | RUSTDOCFLAGS="--cfg docsrs" \
35 | cargo doc --no-deps --all-features --workspace
36 | # Write index.html with redirect
37 | echo '
' > ./target/doc/index.html
38 |
39 | - name: Deploy
40 | uses: actions/upload-artifact@v4
41 | with:
42 | name: documentation
43 | path: target/doc
44 | if-no-files-found: error
45 | retention-days: 1
46 |
47 | - name: Write CNAME file
48 | run: echo 'doc.libmake.com' > ./target/doc/CNAME
49 |
50 | - name: Deploy to GitHub Pages
51 | uses: peaceiris/actions-gh-pages@v4
52 | with:
53 | cname: true
54 | commit_message: Deploy documentation at ${{ github.sha }}
55 | github_token: ${{ secrets.GITHUB_TOKEN }}
56 | publish_branch: gh-pages
57 | publish_dir: ./target/doc
58 | user_email: actions@users.noreply.github.com
59 | user_name: github-actions
60 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | name: 🧪 Document
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 | release:
11 | types: [created]
12 |
13 | jobs:
14 | all:
15 | name: Document
16 | if: github.ref == 'refs/heads/main' && github.event_name == 'push'
17 | runs-on: ubuntu-latest
18 | concurrency:
19 | group: ${{ github.workflow }}-${{ github.ref }}
20 | steps:
21 | - uses: hecrj/setup-rust-action@v2
22 | with:
23 | rust-version: nightly
24 |
25 | - uses: actions/checkout@v4
26 |
27 | - name: Update libssl
28 | run: |
29 | sudo apt-get update
30 | sudo apt-get install -y libssl1.1
31 |
32 | - name: Generate documentation for all features and publish it
33 | run: |
34 | RUSTDOCFLAGS="--cfg docsrs" \
35 | cargo doc --no-deps --all-features --workspace
36 | # Write index.html with redirect
37 | echo ' ' > ./target/doc/index.html
38 |
39 | - name: Deploy
40 | uses: actions/upload-artifact@v4
41 | with:
42 | name: documentation
43 | path: target/doc
44 | if-no-files-found: error
45 | retention-days: 1
46 |
47 | - name: Write CNAME file
48 | run: echo 'doc.libmakelib.com' > ./target/doc/CNAME
49 |
50 | - name: Deploy to GitHub Pages
51 | uses: peaceiris/actions-gh-pages@v4
52 | with:
53 | cname: true
54 | commit_message: Deploy documentation at ${{ github.sha }}
55 | github_token: ${{ secrets.GITHUB_TOKEN }}
56 | publish_branch: gh-pages
57 | publish_dir: ./target/doc
58 | user_email: actions@users.noreply.github.com
59 | user_name: github-actions
60 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: 🧪 Lint
2 |
3 | on:
4 | push:
5 | branches:
6 | - feat/libmake
7 | pull_request:
8 | branches:
9 | - feat/libmake
10 | release:
11 | types: [created]
12 |
13 | jobs:
14 | all:
15 | name: Lint
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: hecrj/setup-rust-action@v2
19 | with:
20 | components: clippy
21 | - uses: actions/checkout@v4
22 | - name: Check lints
23 | run: cargo clippy --workspace --all-features --all-targets --no-deps -- -D warnings
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | *.profraw
3 | *.log
4 | /.vscode/
5 | /target/
6 | build
7 | Cargo.lock
8 | Icon?
9 | src/.DS_Store
10 | /my_library/
11 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to `LibMake`
2 |
3 | Welcome! We're thrilled that you're interested in contributing to the `LibMake` library. Whether you're looking to evangelize, submit feedback, or contribute code, we appreciate your involvement in making `LibMake` a better tool for everyone. Here's how you can get started.
4 |
5 | ## Evangelize
6 |
7 | One of the simplest ways to help us out is by spreading the word about LibMake. We believe that a bigger, more involved community makes for a better framework, and that better frameworks make the world a better place. If you know people who might benefit from using LibMake, please let them know!
8 |
9 | ## How to Contribute
10 |
11 | If you're interested in making a more direct contribution, there are several ways you can help us improve LibMake. Here are some guidelines for submitting feedback, bug reports, and code contributions.
12 |
13 | ### Feedback
14 |
15 | Your feedback is incredibly valuable to us, and we're always looking for ways to make LibMake better. If you have ideas, suggestions, or questions about LibMake, we'd love to hear them. Here's how you can provide feedback:
16 |
17 | - Click [here][2] to submit a new feedback.
18 | - Use a descriptive title that clearly summarizes your feedback.
19 | - Provide a detailed description of the issue or suggestion.
20 | - Be patient while we review and respond to your feedback.
21 |
22 | ### Bug Reports
23 |
24 | If you encounter a bug while using LibMake, please let us know so we can fix it. Here's how you can submit a bug report:
25 |
26 | - Click [here][2] to submit a new issue.
27 | - Use a descriptive title that clearly summarizes the bug.
28 | - Provide a detailed description of the issue, including steps to reproduce it.
29 | - Be patient while we review and respond to your bug report.
30 |
31 | ### Code Contributions
32 |
33 | If you're interested in contributing code to LibMake, we're excited to have your help! Here's what you need to know:
34 |
35 | #### Feature Requests
36 |
37 | If you have an idea for a new feature or improvement, we'd love to hear it. Here's how you can contribute code for a new feature to LibMake:
38 |
39 | - Fork the repo.
40 | - Clone the LibMake[1] repo by running:
41 | `git clone {repository}`
42 | - Edit files in the `src/` folder. The `src/` folder contains the source code for LibMake.
43 | - Submit a pull request, and we'll review and merge your changes if they fit with our vision for LibMake.
44 |
45 | #### Submitting Code
46 |
47 | If you've identified a bug or have a specific code improvement in mind, we welcome your pull requests. Here's how to submit your code changes:
48 |
49 | - Fork the repo.
50 | - Clone the LibMake repo by running:
51 | `git clone {repository}`
52 | - Edit files in the `src/` folder. The `src/` folder contains the source code for LibMake.
53 | - Submit a pull request, and we'll review and merge your changes if they fit with our vision for LibMake.
54 |
55 | We hope that this guide has been helpful in explaining how you can contribute to LibMake. Thank you for your interest and involvement in our project!
56 |
57 | [1]: https://github.com/sebastienrousseau/libmake
58 | [2]: https://github.com/sebastienrousseau/libmake/issues/new
59 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | # Metadata about the package.
3 | authors = ["The LibMake (LM) library contributors "]
4 | build = "build.rs"
5 | categories = ["development-tools", "command-line-utilities", "template-engine"]
6 | description = """
7 | A code generator to reduce repetitive tasks and build high-quality Rust
8 | libraries and applications, by providing a simple interface to create
9 | projects, generate code, and manage dependencies.
10 | """
11 | documentation = "https://docs.rs/libmake"
12 | edition = "2021"
13 | exclude = [
14 | "/.git/*",
15 | "/.github/*",
16 | "/.gitignore",
17 | "/.vscode/*"
18 | ]
19 | homepage = "https://libmake.com"
20 | include = [
21 | "/CONTRIBUTING.md",
22 | "/LICENSE-APACHE",
23 | "/LICENSE-MIT",
24 | "/benches/**",
25 | "/build.rs",
26 | "/Cargo.toml",
27 | "/examples/**",
28 | "/README.md",
29 | "/src/**",
30 | "/tests/**",
31 | ]
32 | keywords = [
33 | 'code-generation',
34 | 'generator',
35 | 'library',
36 | 'project-creation',
37 | 'scaffolding',
38 | ]
39 | license = "MIT OR Apache-2.0"
40 | name = "libmake"
41 | readme = "README.md"
42 | repository = "https://github.com/sebastienrousseau/libmake.git"
43 | rust-version = "1.60"
44 | version = "0.2.6"
45 |
46 | [[bench]]
47 | # Benchmarking configuration.
48 | name = "benchmark"
49 | harness = false
50 | path = "benches/criterion.rs"
51 |
52 | [profile.bench]
53 | debug = true
54 |
55 | [[example]]
56 | # Example configuration.
57 | name = "libmake"
58 | path = "examples/example.rs"
59 |
60 | [dependencies]
61 | # The dependencies of the package.
62 | anyhow = "1.0.83"
63 | assert_cmd = "2.0.14"
64 | clap = "4.5.4"
65 | configparser = "3.0.4"
66 | csv = "1.3.0"
67 | dtt = "0.0.6"
68 | env_logger = "0.11.3"
69 | figlet-rs = "0.1.5"
70 | log = {version="0.4.21", features = ["std"] }
71 | regex = "1.10.4"
72 | reqwest = { version = "0.12.4", features = ["blocking"] }
73 | rlg = "0.0.4"
74 | serde = { version = "1.0.202", features = ["derive"] }
75 | serde_ini = "0.2.0"
76 | serde_json = "1.0.117"
77 | serde_yml = "0.0.7"
78 | tempfile = "3.10.1"
79 | toml = "0.8.13"
80 | uuid = { version = "1.8.0", features = ["v4"] }
81 | vrd = "0.0.7"
82 |
83 | [dev-dependencies]
84 | # The dev-dependencies of the package.
85 | criterion = "0.5.1"
86 | predicates = "3.1.0"
87 |
88 | [lib]
89 | # Metadata about the library.
90 | crate-type = ["lib"]
91 | name = "libmake"
92 | path = "src/lib.rs"
93 | required-features = []
94 |
95 | [features]
96 | # The features of the package.
97 | default = []
98 |
99 | [package.metadata.docs.rs]
100 | targets = ["x86_64-unknown-linux-gnu"]
101 | rustdoc-args = ["--generate-link-to-definition"]
102 |
103 | # Linting config
104 | [lints.rust]
105 |
106 | ## Warn
107 | # box_pointers = "warn"
108 | missing_copy_implementations = "warn"
109 | missing_docs = "warn"
110 | unstable_features = "warn"
111 | # unused_crate_dependencies = "warn"
112 | unused_extern_crates = "warn"
113 | unused_results = "warn"
114 |
115 | ## Allow
116 | bare_trait_objects = "allow"
117 | elided_lifetimes_in_paths = "allow"
118 | non_camel_case_types = "allow"
119 | non_upper_case_globals = "allow"
120 | trivial_bounds = "allow"
121 | unsafe_code = "allow"
122 |
123 | ## Forbid
124 | missing_debug_implementations = "forbid"
125 | non_ascii_idents = "forbid"
126 | unreachable_pub = "forbid"
127 |
128 | ## Deny
129 | dead_code = "deny"
130 | deprecated_in_future = "deny"
131 | ellipsis_inclusive_range_patterns = "deny"
132 | explicit_outlives_requirements = "deny"
133 | future_incompatible = { level = "deny", priority = -1 }
134 | keyword_idents = "deny"
135 | macro_use_extern_crate = "deny"
136 | meta_variable_misuse = "deny"
137 | missing_fragment_specifier = "deny"
138 | noop_method_call = "deny"
139 | pointer_structural_match = "deny"
140 | rust_2018_idioms = { level = "deny", priority = -1 }
141 | rust_2021_compatibility = { level = "deny", priority = -1 }
142 | single_use_lifetimes = "deny"
143 | trivial_casts = "deny"
144 | trivial_numeric_casts = "deny"
145 | unused = { level = "deny", priority = -1 }
146 | unused_features = "deny"
147 | unused_import_braces = "deny"
148 | unused_labels = "deny"
149 | unused_lifetimes = "deny"
150 | unused_macro_rules = "deny"
151 | unused_qualifications = "deny"
152 | variant_size_differences = "deny"
153 |
154 | [package.metadata.clippy]
155 | warn-lints = ["clippy::all", "clippy::pedantic", "clippy::cargo", "clippy::nursery"]
156 |
157 | [profile.dev]
158 | codegen-units = 256
159 | debug = true
160 | debug-assertions = true
161 | incremental = true
162 | lto = false
163 | opt-level = 0
164 | overflow-checks = true
165 | panic = 'unwind'
166 | rpath = false
167 | strip = false
168 |
169 | [profile.release]
170 | codegen-units = 1
171 | debug = false
172 | debug-assertions = false
173 | incremental = false
174 | lto = true
175 | opt-level = "s"
176 | overflow-checks = false
177 | panic = "abort"
178 | rpath = false
179 | strip = "symbols"
180 |
181 | [profile.test]
182 | codegen-units = 256
183 | debug = true
184 | debug-assertions = true
185 | incremental = true
186 | lto = false
187 | opt-level = 0
188 | overflow-checks = true
189 | rpath = false
190 | strip = false
191 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022-2023 Sebastien Rousseau
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 | # LibMake v0.2.6 🦀
9 |
10 | A code generator to reduce repetitive tasks and build high-quality Rust libraries.
11 |
12 | *Part of the [Mini Functions][00] family of libraries.*
13 |
14 |
15 |
16 |
17 |
18 | ![Libmake Banner][banner]
19 |
20 | [![Made With Rust][made-with-rust-badge]][09] [![Crates.io][crates-badge]][06] [![Lib.rs][libs-badge]][08] [![Docs.rs][docs-badge]][07]
21 | [![License][license-badge]][02] [![Codecov][codecov-badge]][10]
22 |
23 | • [Website][01] • [Documentation][07] • [Report Bug][03] • [Request Feature][03] • [Contributing Guidelines][04]
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | ## Overview 📖
32 |
33 | `LibMake` is a tool designed to quickly help creating high-quality Rust libraries by generating a set of pre-filled and pre-defined templated files. This opinionated boilerplate scaffolding tool aims to greatly reduces development time and minimizes repetitive tasks, allowing you to focus on your business logic while enforcing standards, best practices, consistency, and providing style guides for your library.
34 |
35 | With `LibMake`, you can easily generate a new Rust library code base structure with all the necessary files, layouts, build configurations, code, tests, benchmarks, documentation, and much more in a matter of seconds.
36 |
37 | The library is designed to be used as a command-line tool. It is available on [Crates.io][05] and [Lib.rs][06].
38 |
39 | ## Features ✨
40 |
41 | `LibMake` offers the following features and benefits:
42 |
43 | - Create your Rust library with ease using the command line interface or by providing a configuration file in CSV, JSON, TOML, or YAML format.
44 | - Rapidly generate new library projects with a pre-defined structure and boilerplate code that you can customize with your own template.
45 | - Generate a library pre-defined GitHub Actions workflow to help you automate your library development and testing.
46 | - Automatically generate basic functions, methods, and macros to get you started with your Rust library.
47 | - Enforce best practices and standards with starter documentation, test suites, and benchmark suites that are designed to help you get up and running quickly.
48 |
49 | ## Changelog 📚
50 |
51 | [00]: https://minifunctions.com/libmake "Mini Functions"
52 | [01]: https://libmake.com "LibMake"
53 | [02]: http://opensource.org/licenses/MIT "MIT license"
54 | [03]: https://github.com/sebastienrousseau/libmake/issues "Issues"
55 | [04]: https://github.com/sebastienrousseau/libmake/blob/main/CONTRIBUTING.md "Contributing"
56 | [05]: http://semver.org/ "Semantic Versioning"
57 | [06]: https://crates.io/crates/libmake "LibMake on Crates.io"
58 | [07]: https://docs.rs/libmake "LibMake on docs.rs"
59 | [08]: https://lib.rs/crates/libmake "LibMake on lib.rs"
60 | [09]: https://www.rust-lang.org "The Rust Programming Language"
61 | [10]: https://codecov.io/gh/sebastienrousseau/libmake "Codecov"
62 |
63 | [banner]: https://kura.pro/libmake/images/titles/title-libmake.svg "LibMake Banner"
64 | [codecov-badge]: https://img.shields.io/codecov/c/github/sebastienrousseau/libmake?style=for-the-badge&token=Q9KJ6XXL67 "Codecov Badge"
65 | [crates-badge]: https://img.shields.io/crates/v/libmake.svg?style=for-the-badge "Crates.io Badge"
66 | [docs-badge]: https://img.shields.io/docsrs/libmake.svg?style=for-the-badge "Docs.rs Badge"
67 | [libs-badge]: https://img.shields.io/badge/lib.rs-v0.2.6-orange.svg?style=for-the-badge "Lib.rs Badge"
68 | [license-badge]: https://img.shields.io/crates/l/libmake.svg?style=for-the-badge "License Badge"
69 | [made-with-rust-badge]: https://img.shields.io/badge/rust-f04041?style=for-the-badge&labelColor=c0282d&logo=rust "Made With Rust Badge"
70 |
--------------------------------------------------------------------------------
/benches/criterion.rs:
--------------------------------------------------------------------------------
1 | //! # Benchmark: libmake
2 | //!
3 | //! This benchmark tests the performance of the `libmake` crate using the Criterion library.
4 | //! It measures the execution time of the `run` function from the `libmake` crate.
5 | //!
6 | //! ## Purpose
7 | //!
8 | //! The purpose of this benchmark is to assess the execution time of the `run` function
9 | //! from the `libmake` crate under controlled conditions. It helps identify any potential
10 | //! performance bottlenecks and allows for optimization if needed.
11 | //!
12 | //! ## Usage
13 | //!
14 | //! To run this benchmark, ensure that you have the `criterion` and `libmake` crates
15 | //! included as dependencies in your project's `Cargo.toml` file.
16 | //!
17 | //! In your project's code, you can use the `criterion_group` and `criterion_main` macros
18 | //! to define and run benchmarks. In this specific benchmark, the `libmake_benchmark` function
19 | //! is defined to measure the execution time of the `run` function.
20 | //!
21 | //! ```rust
22 | //! extern crate criterion;
23 | //! extern crate libmake;
24 | //!
25 | //! use criterion::{criterion_group, criterion_main, Criterion};
26 | //! use libmake::run;
27 | //!
28 | //! fn libmake_benchmark(c: &mut Criterion) {
29 | //! c.bench_function("libmake", |b| b.iter(run));
30 | //! }
31 | //!
32 | //! criterion_group!(benches, libmake_benchmark);
33 | //! criterion_main!(benches);
34 | //! ```
35 | //!
36 | //! Running this benchmark will provide performance metrics for the `run` function
37 | //! from the `libmake` crate, helping you evaluate and optimize its performance.
38 |
39 | #![allow(missing_docs)]
40 |
41 | use criterion::{criterion_group, criterion_main, Criterion};
42 | use libmake::run;
43 |
44 | #[allow(unused_results)]
45 | fn libmake_benchmark(c: &mut Criterion) {
46 | c.bench_function("libmake", |b| b.iter(run));
47 | }
48 |
49 | criterion_group!(benches, libmake_benchmark);
50 | criterion_main!(benches);
51 |
--------------------------------------------------------------------------------
/build.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! This is the main function for the build script.
7 | //!
8 | //! Currently, it only instructs Cargo to re-run this build script if `build.rs` is changed.
9 | fn main() {
10 | // Avoid unnecessary re-building.
11 | println!("cargo:rerun-if-changed=build.rs");
12 | }
13 |
--------------------------------------------------------------------------------
/deny.toml:
--------------------------------------------------------------------------------
1 | [licenses]
2 | # The lint level for crates which do not have a detectable license
3 | unlicensed = "deny"
4 |
5 | # List of explicitly allowed licenses
6 | # See https://spdx.org/licenses/ for list of possible licenses
7 | # [possible values: any SPDX 3.7 short identifier (+ optional exception)].
8 | allow = [
9 | "Apache-2.0",
10 | "MIT",
11 | "CC0-1.0",
12 | "ISC",
13 | "0BSD",
14 | "BSD-2-Clause",
15 | "BSD-3-Clause",
16 | "Unlicense",
17 | "Unicode-DFS-2016",
18 | ]
19 |
20 | # List of banned licenses
21 | [bans]
22 | multiple-versions = "deny"
23 |
24 |
25 | # The lint level for licenses considered copyleft
26 | copyleft = "deny"
27 |
28 | # Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
29 | # * both - The license will only be approved if it is both OSI-approved *AND* FSF/Free
30 | # * either - The license will be approved if it is either OSI-approved *OR* FSF/Free
31 | # * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF/Free
32 | # * fsf-only - The license will be approved if is FSF/Free *AND NOT* OSI-approved
33 | # * neither - The license will be denied if is FSF/Free *OR* OSI-approved
34 | allow-osi-fsf-free = "either"
35 |
36 | # The confidence threshold for detecting a license from license text.
37 | # The higher the value, the more closely the license text must be to the
38 | # canonical license text of a valid SPDX license file.
39 | # [possible values: any between 0.0 and 1.0].
40 | confidence-threshold = 0.8
41 |
42 | # The graph highlighting used when creating dotgraphs for crates
43 | # with multiple versions
44 | # * lowest-version - The path to the lowest versioned duplicate is highlighted
45 | # * simplest-path - The path to the version with the fewest edges is highlighted
46 | # * all - Both lowest-version and simplest-path are used
47 | highlight = "all"
48 |
49 | # List of crates that are allowed. Use with care!
50 | allow = []
51 |
52 | # List of crates to deny
53 | deny = [
54 | # Each entry the name of a crate and a version range. If version is
55 | # not specified, all versions will be matched.
56 | ]
57 |
58 | # Certain crates/versions that will be skipped when doing duplicate detection.
59 | skip = []
60 |
61 | # Similarly to `skip` allows you to skip certain crates during duplicate detection,
62 | # unlike skip, it also includes the entire tree of transitive dependencies starting at
63 | # the specified crate, up to a certain depth, which is by default infinite
64 | skip-tree = []
65 |
66 |
67 | [advisories]
68 | notice = "deny"
69 | unmaintained = "deny"
70 | unsound = "deny"
71 | vulnerability = "deny"
72 |
--------------------------------------------------------------------------------
/examples/example.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! This is an example crate for LibMake.
7 | //!
8 | //! This crate provides various modules and examples for demonstrating the functionality
9 | //! of LibMake. Each module focuses on a specific feature or functionality.
10 | //!
11 | //! Copyright © 2023-2024 LibMake. All rights reserved.
12 | //!
13 | //! Dual-licensed under the terms of the Apache License, Version 2.0, or the MIT License,
14 | //! at your option. See the 'LICENSE' file for details.
15 |
16 | // Module Declarations
17 | // Each `mod` statement declares a module in the current crate.
18 | // Modules help organize code into separate namespaces, each focusing on specific functionalities.
19 |
20 | /// This is a module for the example `generate_from_args`.
21 | mod generate_from_args;
22 |
23 | /// This is a module for the example `generate_from_config`.
24 | mod generate_from_config;
25 |
26 | /// This is a module for the example `generate_from_csv`.
27 | mod generate_from_csv;
28 |
29 | /// This is a module for the example `generate_from_json`.
30 | mod generate_from_json;
31 |
32 | /// This is a module for the example `generate_from_toml`.
33 | mod generate_from_toml;
34 |
35 | /// This is a module for the example `generate_from_yaml`.
36 | mod generate_from_yaml;
37 |
38 | /// This is a module for the example `get_csv_field`.
39 | mod get_csv_field;
40 |
41 | /// This is a module for the example `get_json_field`.
42 | mod get_json_field;
43 |
44 | /// This is a module for the example `get_yaml_field`.
45 | mod get_yaml_field;
46 |
47 | // Main Function
48 | // The `main` function serves as the entry point of the program.
49 | // Here, it calls the `main` function of each module to execute their respective examples.
50 |
51 | /// The main function that runs all the example modules.
52 | fn main() {
53 | // Run the example module `generate_from_args`.
54 | generate_from_args::main();
55 |
56 | // Run the example module `generate_from_config`.
57 | generate_from_config::main();
58 |
59 | // Run the example module `generate_from_csv`.
60 | generate_from_csv::main();
61 |
62 | // Run the example module `generate_from_json`.
63 | generate_from_json::main();
64 |
65 | // Run the example module `generate_from_toml`.
66 | generate_from_toml::main();
67 |
68 | // Run the example module `generate_from_yaml`.
69 | generate_from_yaml::main();
70 |
71 | // Run the example module `get_csv_field`.
72 | get_csv_field::main();
73 |
74 | // Run the example module `get_json_field`.
75 | get_json_field::main();
76 |
77 | // Run the example module `get_yaml_field`.
78 | get_yaml_field::main();
79 | }
80 |
--------------------------------------------------------------------------------
/examples/generate_from_args.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! A simple test program for the `generate_from_args` function.
7 | //!
8 | //! This program simulates command line arguments and calls the `generate_from_args` function
9 | //! to generate files based on the provided arguments.
10 | //!
11 | //! # Arguments
12 | //!
13 | //! * `--author=` - The author name for the generated files.
14 | //! * `--output=` - The output directory for the generated files.
15 | //!
16 | //! # Example
17 | //!
18 | //! To run this test program, use the following command:
19 | //!
20 | //! ```
21 | //! $ cargo run --release
22 | //! ```
23 | //!
24 | //! Make sure to replace `` with the desired values for `--author` and `--output`.
25 | //!
26 | //! If successful, this program will print "Successfully generated files!".
27 | //!
28 | //! If there is an error, it will print an error message.
29 |
30 | // Import the necessary function for generating files from arguments
31 | use libmake::generators::args::generate_from_args;
32 |
33 | /// A simple test program for the `generate_from_args` function.
34 | ///
35 | /// This program simulates command line arguments and calls the `generate_from_args` function
36 | /// to generate files based on the provided arguments.
37 | ///
38 | /// # Arguments
39 | ///
40 | /// * `--author=` - The author name for the generated files.
41 | /// * `--output=` - The output directory for the generated files.
42 | ///
43 | /// # Example
44 | ///
45 | /// To run this test program, use the following command:
46 | ///
47 | /// ```
48 | /// $ cargo run --release
49 | /// ```
50 | ///
51 | /// Make sure to replace `` with the desired values for `--author` and `--output`.
52 | ///
53 | /// If successful, this program will print "Successfully generated files!".
54 | ///
55 | /// If there is an error, it will print an error message.
56 | pub(crate) fn main() {
57 | // Simulate command line arguments
58 | let args = "--author=Me --output=my_library"
59 | .split(' ')
60 | .map(ToString::to_string) // Directly using the method
61 | .collect::>();
62 |
63 | // Check if there are at least two arguments (program name and at least one option)
64 | if args.len() < 2 {
65 | eprintln!("Usage: {} ", args[0]);
66 | return;
67 | }
68 |
69 | // Join the arguments (excluding the program name) into a single string
70 | let args_str = args[1..].join(" ");
71 |
72 | // Call the `generate_from_args` function with the arguments string
73 | let result = generate_from_args(&args_str);
74 | println!("{result:?}");
75 |
76 | // Check the result of the function call and print a message accordingly
77 | match result {
78 | Ok(()) => println!("Successfully generated files!"),
79 | Err(err) => eprintln!("Error: {err}"),
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/examples/generate_from_config.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! # Example: Generating Templates from a Configuration File
7 | //!
8 | //! This is an example that demonstrates how to generate template files
9 | //! based on a configuration file using the `generate_from_config` function.
10 | //!
11 | //! ## Usage
12 | //!
13 | //! To run this example, make sure you have a valid configuration file at the specified path.
14 | //! The example allows you to define the file type (e.g., "yaml") and the file path.
15 | //! It then calls the `generate_from_config` function with the file path and file type as parameters.
16 | //!
17 | //! If generation is successful, it does nothing (the template files are created).
18 | //! If there is an error during generation, it prints an error message.
19 | //!
20 | //! ```rust
21 | //! use libmake::generator::generate_from_config;
22 | //!
23 | //! // Define the file path for the configuration file.
24 | //! let file_path = "./tests/data/mylibrary.yaml";
25 | //!
26 | //! // Define the file type, which is "yaml" in this case.
27 | //! let file_type = "yaml";
28 | //!
29 | //! // Call the generate_from_config function with the file_path and file_type.
30 | //! // This function generates template files based on the configuration.
31 | //! match generate_from_config(file_path, file_type) {
32 | //! // If generation is successful, do nothing (the template files are created).
33 | //! Ok(_) => (),
34 | //! // If there is an error during generation, print an error message.
35 | //! Err(err) => eprintln!("Error: {}", err),
36 | //! }
37 | //! ```
38 |
39 | use libmake::generator::generate_from_config;
40 |
41 | /// Generate template files based on a configuration file.
42 | ///
43 | /// # Arguments
44 | ///
45 | /// * `file_path` - Path to the configuration file.
46 | /// * `file_type` - Type of the configuration file (e.g., "yaml").
47 | ///
48 | /// # Returns
49 | ///
50 | /// * `Ok(())` - If generation is successful.
51 | /// * `Err(String)` - If there is an error during generation.
52 | pub(crate) fn main() {
53 | // Define the file path for the configuration file.
54 | let file_path = "./tests/data/mylibrary.yaml";
55 |
56 | // Define the file type, which is "yaml" in this case.
57 | let file_type = "yaml";
58 |
59 | // Call the generate_from_config function with the file_path and file_type.
60 | // This function generates template files based on the configuration.
61 | match generate_from_config(file_path, file_type) {
62 | // If generation is successful, do nothing (the template files are created).
63 | Ok(()) => (),
64 | // If there is an error during generation, print an error message.
65 | Err(err) => eprintln!("Error: {err}"),
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/examples/generate_from_csv.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! # Example: Generating Templates from a CSV File
7 | //!
8 | //! This is a simple test that demonstrates how to generate files from a CSV file
9 | //! using the `generate_from_csv` function. It attempts to generate template files
10 | //! from a CSV file and expects the operation to be successful.
11 | //!
12 | //! ## Usage
13 | //!
14 | //! To run this example, make sure you have a valid CSV file at the specified path.
15 | //! The example will attempt to generate template files based on the CSV data.
16 | //! If generation fails, it will print an error message.
17 | //!
18 | //! ```rust
19 | //! // Import the necessary function for generating templates from a CSV file.
20 | //! use libmake::generator::generate_from_csv;
21 | //!
22 | //! /// This is a simple test for generating files from a CSV file using the `generate_from_csv` function.
23 | //! /// It attempts to generate template files from a CSV file and expects the operation to be successful.
24 | //! // Define the path to the CSV file to be used for testing.
25 | //! let csv_file_path = "./tests/data/mylibrary.csv";
26 | //!
27 | //! // Attempt to generate template files from the specified CSV file.
28 | //! // If successful, it indicates that the generation process worked as expected.
29 | //! generate_from_csv(csv_file_path)
30 | //! .expect("Failed to generate the template files");
31 | //! ```
32 |
33 | // Import the necessary function for generating templates from a CSV file.
34 | use libmake::generators::csv::generate_from_csv;
35 |
36 | /// Attempts to generate template files from the specified CSV file.
37 | ///
38 | /// # Parameters
39 | ///
40 | /// * `csv_file_path` - The path to the CSV file that contains the template generation information.
41 | ///
42 | /// # Returns
43 | ///
44 | /// * `Result<()>` - Returns `Ok(())` if the template generation process was successful, or returns an error if it failed.
45 | ///
46 | /// # Examples
47 | ///
48 | /// The following example demonstrates how to use the `generate_from_csv` function:
49 | ///
50 | /// ```rust
51 | /// use libmake::generators::csv::generate_from_csv;
52 | ///
53 | /// let csv_file_path = "./tests/data/mylibrary.csv";
54 | ///
55 | /// // Attempt to generate template files from the specified CSV file.
56 | /// // If successful, it indicates that the generation process worked as expected.
57 | /// generate_from_csv(csv_file_path)
58 | /// .expect("Failed to generate the template files");
59 | /// ```
60 | pub(crate) fn main() {
61 | // Define the path to the CSV file to be used for testing.
62 | let csv_file_path = "./tests/data/mylibrary.csv";
63 |
64 | // Attempt to generate template files from the specified CSV file.
65 | // If successful, it indicates that the generation process worked as expected.
66 | generate_from_csv(csv_file_path)
67 | .expect("Failed to generate the template files");
68 | }
69 |
--------------------------------------------------------------------------------
/examples/generate_from_json.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! # Example: Generating Templates from a JSON File
7 | //!
8 | //! This example demonstrates how to use the `generate_from_json` function from the `libmake` crate
9 | //! to generate template files from a JSON file containing configuration data.
10 | //!
11 | //! ## Usage
12 | //!
13 | //! To run this example, ensure that you have a valid JSON file at the specified path.
14 | //! The example defines the path to the JSON file (`json_file_path`) and then calls
15 | //! the `generate_from_json` function with this path as a parameter.
16 | //!
17 | //! If the generation process is successful, it does nothing (the template files are created).
18 | //! If there is an error during generation, it prints an error message.
19 | //!
20 | //! ```rust
21 | //! // Import the necessary function for generating templates from a JSON file.
22 | //! use libmake::generator::generate_from_json;
23 | //!
24 | //! /// This test demonstrates how to use the `generate_from_json` function from the `libmake` crate
25 | //! /// to generate template files from a JSON file.
26 | //!
27 | //! // Define the path to the JSON file that contains configuration data.
28 | //! let json_file_path = "./tests/data/mylibrary.json";
29 | //!
30 | //! // Generate template files based on the data in the JSON file.
31 | //! // If the generation process fails, an error message is printed.
32 | //! generate_from_json(json_file_path)
33 | //! .expect("Failed to generate the template files");
34 | //! ```
35 |
36 | // Import the necessary function for generating templates from a JSON file.
37 | use libmake::generators::json::generate_from_json;
38 |
39 | /// Generate template files based on the data in the JSON file.
40 | ///
41 | /// # Arguments
42 | ///
43 | /// * `json_file_path` - Path to the JSON file that contains the configuration data.
44 | ///
45 | /// # Returns
46 | ///
47 | /// * `Result<(), String>` - Returns `Ok(())` if the template files are generated successfully, or returns an error message if there is an error during generation.
48 | ///
49 | pub(crate) fn main() {
50 | // Define the path to the JSON file that contains configuration data.
51 | let json_file_path = "./tests/data/mylibrary.json";
52 |
53 | // Generate template files based on the data in the JSON file.
54 | // If the generation process fails, an error message is printed.
55 | generate_from_json(json_file_path)
56 | .expect("Failed to generate the template files");
57 | }
58 |
--------------------------------------------------------------------------------
/examples/generate_from_toml.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! # Example: Generating Templates from a TOML File
7 | //!
8 | //! This is a simple example that demonstrates how to generate template files
9 | //! based on configuration stored in a TOML file using the `generate_from_toml`
10 | //! function.
11 | //!
12 | //! ## Usage
13 | //!
14 | //! To run this example, make sure you have a valid TOML configuration file
15 | //! at the specified path. The example will attempt to generate template files
16 | //! based on the configuration. If generation fails, it will print an error
17 | //! message.
18 | //!
19 | //! ```rust
20 | //! // Import the necessary function for generating templates from a TOML file.
21 | //! use libmake::generator::generate_from_toml;
22 | //!
23 | //! // Define the path to the TOML file containing configuration.
24 | //! let toml_file_path = "./tests/data/mylibrary.toml"
25 | //! // Generate template files based on the configuration in the TOML file.
26 | //! // If generation fails, it will print an error message.
27 | //! generate_from_toml(toml_file_path)
28 | //! .expect("Failed to generate the template files");
29 | //! ```
30 | //!
31 | // Import the necessary function for generating templates from a TOML file.
32 | use libmake::generators::toml::generate_from_toml;
33 |
34 | /// Generate template files based on the configuration in the TOML file.
35 | ///
36 | /// # Arguments
37 | ///
38 | /// * `toml_file_path` - Path to the TOML file containing the configuration.
39 | ///
40 | /// # Returns
41 | ///
42 | /// * `Result<(), String>` - Returns `Ok(())` if the template files are generated successfully, or returns an error message if generation fails.
43 | ///
44 | pub(crate) fn main() {
45 | // Define the path to the TOML file containing configuration.
46 | let toml_file_path = "./tests/data/mylibrary.toml";
47 |
48 | // Generate template files based on the configuration in the TOML file.
49 | // If generation fails, it will print an error message.
50 | generate_from_toml(toml_file_path)
51 | .expect("Failed to generate the template files");
52 | }
53 |
--------------------------------------------------------------------------------
/examples/generate_from_yaml.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! # Example: Generating Templates from a YAML File
7 | //!
8 | //! This is a simple example that demonstrates how to use the `generate_from_yaml` function
9 | //! from the `libmake` crate to generate template files from a YAML file.
10 | //!
11 | //! ## Usage
12 | //!
13 | //! To run this example, make sure you have a valid YAML file at the specified path.
14 | //! The example specifies the path to the YAML file (`yaml_file_path`) and then calls
15 | //! the `generate_from_yaml` function with this path as a parameter.
16 | //!
17 | //! If the generation process is successful, it does nothing (the template files are created).
18 | //! If there is an error during generation, it prints an error message.
19 | //!
20 | //! ```rust
21 | //! // Import the necessary function for generating templates from a YAML file.
22 | //! use libmake::generator::generate_from_yaml;
23 | //!
24 | //! // Specify the path to the YAML file to be used for generating templates.
25 | //! let yaml_file_path = "./tests/data/mylibrary.yaml";
26 | //!
27 | //! // Generate template files from the specified YAML file.
28 | //! generate_from_yaml(yaml_file_path)
29 | //! .expect("Failed to generate the template files");
30 | //! ```
31 |
32 | // Import the necessary function for generating templates from a YAML file.
33 | use libmake::generators::yaml::generate_from_yaml;
34 |
35 | /// Generate template files from the specified YAML file.
36 | ///
37 | /// # Arguments
38 | ///
39 | /// * `yaml_file_path` - Path to the YAML file to be used for generating templates.
40 | ///
41 | /// # Returns
42 | ///
43 | /// * `Result<(), String>` - Returns `Ok(())` if the template files are generated successfully, or returns an error message if there is an error during generation.
44 | ///
45 | pub(crate) fn main() {
46 | // Specify the path to the YAML file to be used for generating templates.
47 | let yaml_file_path = "./tests/data/mylibrary.yaml";
48 |
49 | // Generate template files from the specified YAML file.
50 | generate_from_yaml(yaml_file_path)
51 | .expect("Failed to generate the template files");
52 | }
53 |
--------------------------------------------------------------------------------
/examples/get_csv_field.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! # Test: Retrieving a CSV Field
7 | //!
8 | //! This is a test that demonstrates how to retrieve a specific field from a CSV file
9 | //! using the `get_csv_field` function from the `libmake` crate.
10 | //!
11 | //! ## Purpose
12 | //!
13 | //! The purpose of this test is to show how to extract a CSV field at a specified index
14 | //! from a CSV file located at the specified path (`file_path`).
15 | //!
16 | //! ## Usage
17 | //!
18 | //! To run this test, ensure that you have a valid CSV file at the specified path.
19 | //! The test uses the `get_csv_field` function to retrieve the field at the specified index (0).
20 | //! It then prints the result.
21 | //!
22 | //! ```rust
23 | //! // Import the necessary function for retrieving a field from a CSV file.
24 | //! use libmake::utils::get_csv_field;
25 | //!
26 | //! // Specify the path to the CSV file.
27 | //! let file_path = "../tests/data/mylibrary.csv";
28 | //!
29 | //! // Retrieve the CSV field at index 0 and print the result.
30 | //! println!(
31 | //! "🦀 get_csv_field, ✅ {:?}",
32 | //! get_csv_field(Some(file_path), 0)
33 | //! );
34 | //! ```
35 |
36 | // Title: Test: Retrieving a CSV Field
37 | use libmake::utils::get_csv_field;
38 |
39 | /// Retrieve CSV field
40 | ///
41 | /// # Arguments
42 | ///
43 | /// * `file_path` - Path to CSV file
44 | /// * `index` - Index of field to retrieve
45 | ///
46 | /// # Returns
47 | ///
48 | /// String containing the requested field
49 | ///
50 | pub(crate) fn main() {
51 | // Retrieve CSV field
52 | let file_path = "../tests/data/mylibrary.csv";
53 | println!(
54 | "🦀 get_csv_field, ✅ {:?}",
55 | get_csv_field(Some(file_path), 0)
56 | );
57 | }
58 |
--------------------------------------------------------------------------------
/examples/get_json_field.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! # Test: Retrieving a Field from a CSV File
7 | //!
8 | //! This is a test that demonstrates how to retrieve a specific field from a CSV file
9 | //! using the `get_csv_field` function from the `libmake` crate.
10 | //!
11 | //! ## Purpose
12 | //!
13 | //! The purpose of this test is to show how to extract a CSV field (`field_title`)
14 | //! from a CSV file located at the specified path (`file_path`).
15 | //!
16 | //! ## Usage
17 | //!
18 | //! To run this test, ensure that you have a valid CSV file at the specified path.
19 | //! The test checks if the file exists and then uses the `get_csv_field` function
20 | //! to retrieve the specified CSV field. If the file exists and the field is found,
21 | //! it prints the field's value; otherwise, it prints an error message or an empty string.
22 | //!
23 | //! ```rust
24 | //! // Import the necessary function for retrieving a field from a CSV file.
25 | //! use libmake::utils::get_csv_field;
26 | //! use std::path::Path;
27 | //!
28 | //! // Specify the path to the CSV file.
29 | //! let file_path = "../tests/data/mylibrary.csv";
30 | //!
31 | //! // Define the CSV field to retrieve.
32 | //! let field_title = "title";
33 | //!
34 | //! // Check if the CSV file exists before retrieving the field.
35 | //! let value = if Path::new(file_path).exists() {
36 | //! // If the file exists, use the `get_csv_field` function to retrieve the field.
37 | //! match get_csv_field(Some(file_path), 0) {
38 | //! Some(values) => values.join(", "),
39 | //! None => {
40 | //! eprintln!("Error retrieving field: {}", field_title);
41 | //! String::new()
42 | //! }
43 | //! }
44 | //! } else {
45 | //! // If the file doesn't exist, set the value to an empty string.
46 | //! String::new()
47 | //! };
48 | //!
49 | //! // Print the result.
50 | //! println!("🦀 get_csv_field, ✅ {}: {}", field_title, value);
51 | //! ```
52 |
53 | // Title: Test: Retrieving a field from a CSV file
54 | use libmake::utils::get_csv_field;
55 | use std::path::Path;
56 |
57 | /// Retrieve CSV field
58 | ///
59 | /// # Arguments
60 | ///
61 | /// * `file_path` - Path to the CSV file
62 | /// * `field_title` - Name of the CSV field to retrieve
63 | ///
64 | /// # Returns
65 | ///
66 | /// The value of the CSV field, or an empty string if the file does not exist or the field cannot be found
67 | ///
68 | pub(crate) fn main() {
69 | // Retrieve CSV field
70 | let file_path = "../tests/data/mylibrary.csv";
71 | let field_title = "title";
72 |
73 | let value = if Path::new(file_path).exists() {
74 | match get_csv_field(Some(file_path), 0) {
75 | Some(values) => values.join(", "),
76 | None => {
77 | eprintln!("Error retrieving field: {field_title}");
78 | String::new()
79 | }
80 | }
81 | } else {
82 | String::new()
83 | };
84 |
85 | println!("🦀 get_csv_field, ✅ {field_title}: {value}");
86 | }
87 |
--------------------------------------------------------------------------------
/examples/get_yaml_field.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! # Test: Retrieving a Field from a YAML File
7 | //!
8 | //! This is a test that demonstrates how to retrieve a specific field from a YAML file
9 | //! using the `get_yaml_field` function from the `libmake` crate.
10 | //!
11 | //! ## Purpose
12 | //!
13 | //! The purpose of this test is to show how to extract a YAML field (`field_keywords`)
14 | //! from a YAML file located at the specified path (`file_path`). The test specifically
15 | //! handles YAML arrays and converts them into a formatted string.
16 | //!
17 | //! ## Usage
18 | //!
19 | //! To run this test, ensure that you have a valid YAML file at the specified path.
20 | //! The test checks if the file exists and then uses the `get_yaml_field` function
21 | //! to retrieve the specified YAML field (`field_keywords`). If the file exists and
22 | //! the field is found, it processes the field's content (assuming it's an array),
23 | //! formats it into a string, and prints the result. If the file doesn't exist,
24 | //! it prints an empty string.
25 | //!
26 | //! ```rust
27 | //! // Import the necessary function for retrieving a field from a YAML file.
28 | //! use libmake::utils::get_yaml_field;
29 | //! use std::error::Error;
30 | //! use std::path::Path;
31 | //!
32 | //! // Specify the path to the YAML file.
33 | //! let file_path = "../tests/data/mylibrary.yaml";
34 | //!
35 | //! // Define the YAML field to retrieve.
36 | //! let field_keywords = "keywords";
37 | //!
38 | //! // Check if the YAML file exists before retrieving the field.
39 | //! let value = if Path::new(file_path).exists() {
40 | //! // If the file exists, use the `get_yaml_field` function to retrieve the field.
41 | //! let keywords: Result, Box> = get_yaml_field(Some(file_path), field_keywords)
42 | //! .map(|s| s.split('\n')
43 | //! .map(|s| s.trim_start_matches("- "))
44 | //! .filter(|s| !s.is_empty())
45 | //! .map(|s| format!("\"{}\"", s))
46 | //! .collect());
47 | //!
48 | //! match keywords {
49 | //! Ok(keywords) => format!("[{}]", keywords.join(", ")),
50 | //! Err(e) => {
51 | //! eprintln!("Error retrieving keywords: {}", e);
52 | //! String::new()
53 | //! }
54 | //! }
55 | //! } else {
56 | //! // If the file doesn't exist, set the value to an empty string.
57 | //! String::new()
58 | //! };
59 | //!
60 | //! // Print the result.
61 | //! println!("🦀 get_yaml_field, ✅ {}: {}", field_keywords, value);
62 | //! ```
63 |
64 | // Title: Test: Retrieving a field from a YAML file
65 | use libmake::utils::get_yaml_field;
66 | use std::error::Error;
67 | use std::path::Path;
68 |
69 | /// # Test: Retrieving a Field from a YAML File
70 | ///
71 | /// This is a test that demonstrates how to retrieve a specific field from a YAML file
72 | /// using the `get_yaml_field` function from the `libmake` crate.
73 | ///
74 | /// ## Purpose
75 | ///
76 | /// The purpose of this test is to show how to extract a YAML field (`field_keywords`)
77 | /// from a YAML file located at the specified path (`file_path`). The test specifically
78 | /// handles YAML arrays and converts them into a formatted string.
79 | ///
80 | /// ## Usage
81 | ///
82 | /// To run this test, ensure that you have a valid YAML file at the specified path.
83 | /// The test checks if the file exists and then uses the `get_yaml_field` function
84 | /// to retrieve the specified YAML field (`field_keywords`). If the file exists and
85 | /// the field is found, it processes the field's content (assuming it's an array),
86 | /// formats it into a string, and prints the result. If the file doesn't exist,
87 | /// it prints an empty string.
88 | ///
89 | /// ```rust
90 | /// // Import the necessary function for retrieving a field from a YAML file.
91 | /// use libmake::utils::get_yaml_field;
92 | /// use std::error::Error;
93 | /// use std::path::Path;
94 | ///
95 | /// // Specify the path to the YAML file.
96 | /// let file_path = "../tests/data/mylibrary.yaml";
97 | ///
98 | /// // Define the YAML field to retrieve.
99 | /// let field_keywords = "keywords";
100 | ///
101 | /// // Check if the YAML file exists before retrieving the field.
102 | /// let value = if Path::new(file_path).exists() {
103 | /// // If the file exists, use the `get_yaml_field` function to retrieve the field.
104 | /// let keywords: Result, Box> = get_yaml_field(Some(file_path), field_keywords)
105 | /// .map(|s| s.split('\n')
106 | /// .map(|s| s.trim_start_matches("- "))
107 | /// .filter(|s| !s.is_empty())
108 | /// .map(|s| format!("\"{}\"", s))
109 | /// .collect());
110 | ///
111 | /// match keywords {
112 | /// Ok(keywords) => format!("[{}]", keywords.join(", ")),
113 | /// Err(e) => {
114 | /// eprintln!("Error retrieving keywords: {}", e);
115 | /// String::new()
116 | /// }
117 | /// }
118 | /// } else {
119 | /// // If the file doesn't exist, set the value to an empty string.
120 | /// String::new()
121 | /// };
122 | ///
123 | /// // Print the result.
124 | /// println!("🦀 get_yaml_field, ✅ {}: {}", field_keywords, value);
125 | /// ```
126 | ///
127 | pub(crate) fn main() {
128 | let file_path = "../tests/data/mylibrary.yaml";
129 | let field_keywords = "keywords";
130 |
131 | let value = if Path::new(file_path).exists() {
132 | let keywords: Result, Box> =
133 | get_yaml_field(Some(file_path), field_keywords).map(|s| {
134 | s.split('\n')
135 | .map(|s| s.trim_start_matches("- "))
136 | .filter(|s| !s.is_empty())
137 | .map(|s| format!("\"{s}\""))
138 | .collect()
139 | });
140 |
141 | match keywords {
142 | Ok(keywords) => format!("[{}]", keywords.join(", ")),
143 | Err(e) => {
144 | eprintln!("Error retrieving keywords: {e}");
145 | String::new()
146 | }
147 | }
148 | } else {
149 | String::new()
150 | };
151 |
152 | println!("🦀 get_yaml_field, ✅ {field_keywords}: {value}");
153 | }
154 |
--------------------------------------------------------------------------------
/rustfmt.toml:
--------------------------------------------------------------------------------
1 | edition = "2021"
2 | max_width = 72
3 | tab_spaces = 4
4 | use_field_init_shorthand = true
5 |
--------------------------------------------------------------------------------
/src/cli.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | // use std::path::Path;
7 |
8 | use clap::{error::Error, Arg, ArgMatches, Command};
9 |
10 | /// Constructs the command-line interface for the application using Clap,
11 | /// including all necessary arguments.
12 | ///
13 | /// # Examples
14 | ///
15 | /// ```
16 | /// use libmake::cli;
17 | /// let matches = cli::build().expect("CLI parsing failed");
18 | /// ```
19 | ///
20 | /// # Errors
21 | ///
22 | /// This function will return an error if the command-line argument parsing fails.
23 | ///
24 | pub fn build() -> Result {
25 | let manual_args = vec![
26 | create_arg_info("author", Some("Me"), "Sets the author of the library", 'a', "author", "AUTHOR"),
27 | create_arg_info("build", Some("build.rs"), "Sets the build script that is used to perform additional build-time operations.", 'b', "build", "BUILD"),
28 | create_arg_info("categories", Some("['category 1', 'category 2']"), "Sets the categories of the library", 'c', "categories", "CATEGORIES"),
29 | create_arg_info("description", Some("A library for doing things"), "Sets the description of the library", 'd', "description", "DESCRIPTION"),
30 | create_arg_info("documentation", Some("https://lib.rs/crates/my_library"), "Sets the documentation URL of the library", 'u', "documentation", "DOCUMENTATION"),
31 | create_arg_info("edition", Some("2021"), "Sets the edition of the library", 'e', "edition", "EDITION"),
32 | create_arg_info("email", Some("test@test.com"), "Sets the email of the library author", '@', "email", "EMAIL"),
33 | create_arg_info("homepage", Some("https://test.com"), "Sets the homepage of the library", 'p', "homepage", "HOMEPAGE"),
34 | create_arg_info("keywords", Some("['keyword1', 'keyword2']"), "Sets the keywords of the library", 'k', "keywords", "KEYWORDS"),
35 | create_arg_info("license", Some("MIT OR Apache-2.0"), "Sets the license of the library", 'l', "license", "LICENSE"),
36 | create_arg_info("name", Some("my_library"), "Sets the name of the library", 'n', "name", "NAME"),
37 | create_arg_info("output", Some("my_library"), "Sets the output directory for the library", 'o', "output", "OUTPUT"),
38 | create_arg_info("readme", Some("README.md"), "Sets the README file for the library", 'm', "readme", "README"),
39 | create_arg_info("repository", Some("https://github.com/example/my_library"), "Sets the repository URL of the library", 'g', "repository", "REPOSITORY"),
40 | create_arg_info("rustversion", Some("1.60"), "Sets the Rust version of the library", 'r', "rustversion", "RUSTVERSION"),
41 | create_arg_info("version", Some("0.2.6"), "Sets the version of the library", 'v', "version", "VERSION"),
42 | create_arg_info("website", Some("https://test.com"), "Sets the website of the library author", 'w', "website", "WEBSITE"),
43 | ];
44 |
45 | let file_args = vec![
46 | create_arg_info(
47 | "csv",
48 | Some(""),
49 | "Sets the CSV file to use for generating the library",
50 | 'x',
51 | "csv",
52 | "CSV",
53 | ),
54 | create_arg_info(
55 | "ini",
56 | Some(""),
57 | "Sets the INI file to use for generating the library",
58 | 'i',
59 | "ini",
60 | "INI",
61 | ),
62 | create_arg_info(
63 | "json",
64 | Some(""),
65 | "Sets the JSON file to use for generating the library",
66 | 'j',
67 | "json",
68 | "JSON",
69 | ),
70 | create_arg_info(
71 | "yaml",
72 | Some(""),
73 | "Sets the YAML file to use for generating the library",
74 | 'y',
75 | "yaml",
76 | "YAML",
77 | ),
78 | create_arg_info(
79 | "toml",
80 | Some(""),
81 | "Sets the TOML file to use for generating the library",
82 | 't',
83 | "toml",
84 | "TOML",
85 | ),
86 | ];
87 |
88 | let command = Command::new("My Library")
89 | .author("Sebastien Rousseau")
90 | .about("A Rust library generator that helps create high-quality Rust libraries quickly and easily.")
91 | .after_help("By default, if no arguments are passed in, the CLI will throw an error. To see a list of available actions, run `--help`.")
92 | .subcommand(
93 | Command::new("manual")
94 | .about("Set library information manually")
95 | .args(manual_args.into_iter().map(create_arg).collect::>()),
96 | )
97 | .subcommand(
98 | Command::new("file")
99 | .about("Set library information from a file")
100 | .args(file_args.into_iter().map(create_arg).collect::>()),
101 | );
102 |
103 | // Assuming validate_args is a custom function that you have implemented
104 | let matches = command.clone().try_get_matches()?;
105 |
106 | Ok(matches)
107 | }
108 |
109 | /// Helper function to create a command-line argument.
110 | const fn create_arg_info(
111 | name: &'static str,
112 | default: Option<&'static str>,
113 | help: &'static str,
114 | short: char,
115 | long: &'static str,
116 | value_name: &'static str,
117 | ) -> (
118 | &'static str,
119 | Option<&'static str>,
120 | &'static str,
121 | char,
122 | &'static str,
123 | &'static str,
124 | ) {
125 | (name, default, help, short, long, value_name)
126 | }
127 |
128 | /// Creates an argument based on provided information.
129 | pub fn create_arg(
130 | arg_info: (
131 | &'static str,
132 | Option<&'static str>,
133 | &'static str,
134 | char,
135 | &'static str,
136 | &'static str,
137 | ),
138 | ) -> Arg {
139 | let (name, default, help, short, long, value_name) = arg_info;
140 |
141 | let mut arg = Arg::new(name)
142 | .help(help)
143 | .short(short)
144 | .long(long)
145 | .value_name(value_name);
146 |
147 | if let Some(default_value) = default {
148 | arg = arg.default_value(default_value);
149 | }
150 | arg
151 | }
152 |
--------------------------------------------------------------------------------
/src/generators/args.rs:
--------------------------------------------------------------------------------
1 | use crate::{
2 | generator::generate_files,
3 | models::model_params::FileGenerationParams,
4 | };
5 | use std::io;
6 |
7 | /// Generates files for a new Rust project based on command line arguments.
8 | /// The arguments must be in the form `--name=value`.
9 | /// The following arguments are supported:
10 | /// - `author` - the author of the project (optional).
11 | /// - `build` - the build command to be used for building the project (optional).
12 | /// - `categories` - the categories that the project belongs to (optional).
13 | /// - `description` - a short description of the project (optional).
14 | /// - `documentation` - the documentation URL of the project (optional).
15 | /// - `edition` - the edition of the project (optional).
16 | /// - `email` - the email address of the author (optional).
17 | /// - `homepage` - the homepage of the project (optional).
18 | /// - `keywords` - keywords that describe the project (optional).
19 | /// - `license` - the license under which the project is released (optional).
20 | /// - `name` - the name of the project (optional).
21 | /// - `output` - the output directory where the project files will be created (required).
22 | /// - `readme` - the name of the readme file (optional).
23 | /// - `repository` - the url of the project's repository (optional).
24 | /// - `rustversion` - the minimum Rust version required by the project (optional).
25 | /// - `version` - the initial version of the project (optional).
26 | /// - `website` - the website of the project (optional).
27 | ///
28 | /// # Errors
29 | ///
30 | /// This function will return an error in the following situations:
31 | ///
32 | /// - If an invalid argument is provided. Each argument must be in the form `--name=value`.
33 | /// - If there is an error in generating files based on the parameters derived from the arguments.
34 | ///
35 | pub fn generate_from_args(args_str: &str) -> io::Result<()> {
36 | let args = args_str.split_whitespace();
37 | let mut params = FileGenerationParams::default();
38 | for arg in args {
39 | let mut parts = arg.splitn(2, '=');
40 | let name = parts.next().unwrap_or_default();
41 | let value = parts.next().unwrap_or_default();
42 | match name {
43 | "--author" => params.author = Some(value.to_string()),
44 | "--build" => params.build = Some(value.to_string()),
45 | "--categories" => {
46 | params.categories = Some(value.to_string());
47 | }
48 | "--description" => {
49 | params.description = Some(value.to_string());
50 | }
51 | "--documentation" => {
52 | params.documentation = Some(value.to_string());
53 | }
54 | "--edition" => params.edition = Some(value.to_string()),
55 | "--email" => params.email = Some(value.to_string()),
56 | "--homepage" => params.homepage = Some(value.to_string()),
57 | "--keywords" => params.keywords = Some(value.to_string()),
58 | "--license" => params.license = Some(value.to_string()),
59 | "--name" => params.name = Some(value.to_string()),
60 | "--output" => params.output = Some(value.to_string()),
61 | "--readme" => params.readme = Some(value.to_string()),
62 | "--repository" => {
63 | params.repository = Some(value.to_string());
64 | }
65 | "--rustversion" => {
66 | params.rustversion = Some(value.to_string());
67 | }
68 | "--version" => params.version = Some(value.to_string()),
69 | "--website" => params.website = Some(value.to_string()),
70 | _ => {
71 | return Err(io::Error::new(
72 | io::ErrorKind::Other,
73 | format!("Invalid argument: {name}"),
74 | ))
75 | }
76 | }
77 | }
78 | println!("{params:?}");
79 | generate_files(params)?;
80 | Ok(())
81 | }
82 |
--------------------------------------------------------------------------------
/src/generators/ascii.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! This module provides functionality for generating ASCII art from text using the FIGlet library.
7 |
8 | use crate::models::error_ascii_art::AsciiArtError;
9 | use figlet_rs::FIGfont;
10 |
11 | /// Generates ASCII art from the given text using the standard `FIGfont`.
12 | ///
13 | /// # Arguments
14 | ///
15 | /// * `text` - The text to convert to ASCII art.
16 | ///
17 | /// # Errors
18 | ///
19 | /// This function returns an `Err` in the following situations:
20 | ///
21 | /// - If the input `text` is empty (`ConversionError`).
22 | /// - If the standard `FIGfont` fails to load (`FontLoadError`).
23 | /// - If the text cannot be converted to ASCII art (`ConversionError`).
24 | ///
25 | /// # Examples
26 | ///
27 | /// ```
28 | /// use libmake::generators::ascii::generate_ascii_art;
29 | ///
30 | /// let text = "Hello, world!";
31 | /// let result = generate_ascii_art(text);
32 | /// assert!(result.is_ok());
33 | /// ```
34 | pub fn generate_ascii_art(text: &str) -> Result {
35 | if text.is_empty() {
36 | return Err(AsciiArtError::ConversionError);
37 | }
38 |
39 | let standard_font = load_standard_font()?;
40 | let figure = standard_font
41 | .convert(text)
42 | .ok_or(AsciiArtError::ConversionError)?;
43 |
44 | Ok(figure.to_string())
45 | }
46 |
47 | /// Loads the standard FIGfont.
48 | ///
49 | /// # Errors
50 | ///
51 | /// This function returns an `Err` if the standard `FIGfont` fails to load (`FontLoadError`).
52 | ///
53 | /// # Examples
54 | ///
55 | /// ```
56 | /// use libmake::generators::ascii::load_standard_font;
57 | ///
58 | /// let result = load_standard_font();
59 | /// assert!(result.is_ok());
60 | /// ```
61 | pub fn load_standard_font() -> Result {
62 | FIGfont::standard().map_err(|_| AsciiArtError::FontLoadError)
63 | }
64 |
--------------------------------------------------------------------------------
/src/generators/csv.rs:
--------------------------------------------------------------------------------
1 | use crate::macro_generate_files;
2 | use crate::models::model_params::FileGenerationParams;
3 | use csv::Reader;
4 | use std::io;
5 |
6 | /// Generates files for a new Rust project based on a CSV file.
7 | ///
8 | /// # Arguments
9 | ///
10 | /// The CSV file must contain the following columns:
11 | ///
12 | /// - `author` - the author of the project (optional).
13 | /// - `build` - the build command to be used for building the project (optional).
14 | /// - `categories` - the categories that the project belongs to (optional).
15 | /// - `description` - a short description of the project (optional).
16 | /// - `documentation` - the documentation URL of the project (optional).
17 | /// - `edition` - the edition of the project (optional).
18 | /// - `email` - the email address of the author (optional).
19 | /// - `homepage` - the homepage of the project (optional).
20 | /// - `keywords` - keywords that describe the project (optional).
21 | /// - `license` - the license under which the project is released (optional).
22 | /// - `name` - the name of the project (optional).
23 | /// - `output` - the output directory where the project files will be created (required).
24 | /// - `readme` - the name of the readme file (optional).
25 | /// - `repository` - the url of the project's repository (optional).
26 | /// - `rustversion` - the minimum Rust version required by the project (optional).
27 | /// - `version` - the initial version of the project (optional).
28 | /// - `website` - the website of the project (optional).
29 | ///
30 | /// # Errors
31 | ///
32 | /// This function will return an error in the following situations:
33 | ///
34 | /// - If the specified CSV file cannot be found, read, or is not valid CSV.
35 | /// - If an error occurs while parsing the CSV data into the `FileGenerationParams` struct.
36 | /// - If there is an error in generating files based on the parameters from each CSV record.
37 | ///
38 | pub fn generate_from_csv(path: &str) -> io::Result<()> {
39 | let mut reader = Reader::from_path(path)?;
40 | for result in reader.records() {
41 | let record = result?;
42 | let params = FileGenerationParams {
43 | author: record.get(0).map(ToString::to_string),
44 | build: record.get(1).map(ToString::to_string),
45 | categories: record.get(2).map(ToString::to_string),
46 | description: record.get(3).map(ToString::to_string),
47 | documentation: record.get(4).map(ToString::to_string),
48 | edition: record.get(5).map(ToString::to_string),
49 | email: record.get(6).map(ToString::to_string),
50 | homepage: record.get(7).map(ToString::to_string),
51 | keywords: record.get(8).map(ToString::to_string),
52 | license: record.get(9).map(ToString::to_string),
53 | name: record.get(10).map(ToString::to_string),
54 | output: record.get(11).map(ToString::to_string),
55 | readme: record.get(12).map(ToString::to_string),
56 | repository: record.get(13).map(ToString::to_string),
57 | rustversion: record.get(14).map(ToString::to_string),
58 | version: record.get(15).map(ToString::to_string),
59 | website: record.get(16).map(ToString::to_string),
60 | };
61 | macro_generate_files!(params.clone())
62 | .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
63 | }
64 | Ok(())
65 | }
66 |
--------------------------------------------------------------------------------
/src/generators/ini.rs:
--------------------------------------------------------------------------------
1 | use crate::macro_generate_files;
2 | use crate::models::model_params::FileGenerationParams;
3 | use serde_ini::from_str;
4 | use std::fs;
5 | use std::io;
6 |
7 | /// Generates files for a new Rust project based on an INI file.
8 | ///
9 | /// The INI file must contain a single section with the following
10 | /// keys:
11 | /// - `author` - the author of the project (optional).
12 | /// - `build` - the build command to be used for building the project (optional).
13 | /// - `categories` - the categories that the project belongs to (optional).
14 | /// - `description` - a short description of the project (optional).
15 | /// - `documentation` - the documentation URL of the project (optional).
16 | /// - `edition` - the edition of the project (optional).
17 | /// - `email` - the email address of the author (optional).
18 | /// - `homepage` - the homepage of the project (optional).
19 | /// - `keywords` - keywords that describe the project (optional).
20 | /// - `license` - the license under which the project is released (optional).
21 | /// - `name` - the name of the project (optional).
22 | /// - `output` - the output directory where the project files will be created (required).
23 | /// - `readme` - the name of the readme file (optional).
24 | /// - `repository` - the url of the project's repository (optional).
25 | /// - `rustversion` - the minimum Rust version required by the project (optional).
26 | /// - `version` - the initial version of the project (optional).
27 | /// - `website` - the website of the project (optional).
28 | ///
29 | /// # Errors
30 | ///
31 | /// This function will return an error in the following situations:
32 | ///
33 | /// - If the specified INI file cannot be found, read, or is not valid UTF-8.
34 | /// - If the INI data cannot be parsed into the `FileGenerationParams` struct.
35 | /// - If there is an error in generating files based on the parameters.
36 | ///
37 | pub fn generate_from_ini(path: &str) -> io::Result<()> {
38 | let contents = fs::read_to_string(path)?;
39 | let params: FileGenerationParams =
40 | from_str(&contents).map_err(|e| {
41 | io::Error::new(io::ErrorKind::InvalidData, e.to_string())
42 | })?;
43 | macro_generate_files!(params.clone())
44 | .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
45 | Ok(())
46 | }
47 |
--------------------------------------------------------------------------------
/src/generators/json.rs:
--------------------------------------------------------------------------------
1 | use crate::macro_generate_files;
2 | use crate::models::model_params::FileGenerationParams;
3 | use std::fs;
4 | use std::io;
5 |
6 | /// Generates files for a new Rust project based on a JSON file.
7 | ///
8 | /// # Arguments
9 | ///
10 | /// The JSON file must contain a single object with the following
11 | /// properties:
12 | ///
13 | /// - `author` - the author of the project (optional).
14 | /// - `build` - the build command to be used for building the project (optional).
15 | /// - `categories` - the categories that the project belongs to (optional).
16 | /// - `description` - a short description of the project (optional).
17 | /// - `documentation` - the documentation URL of the project (optional).
18 | /// - `edition` - the edition of the project (optional).
19 | /// - `email` - the email address of the author (optional).
20 | /// - `homepage` - the homepage of the project (optional).
21 | /// - `keywords` - keywords that describe the project (optional).
22 | /// - `license` - the license under which the project is released (optional).
23 | /// - `name` - the name of the project (optional).
24 | /// - `output` - the output directory where the project files will be created (required).
25 | /// - `readme` - the name of the readme file (optional).
26 | /// - `repository` - the url of the project's repository (optional).
27 | /// - `rustversion` - the minimum Rust version required by the project (optional).
28 | /// - `version` - the initial version of the project (optional).
29 | /// - `website` - the website of the project (optional).
30 | ///
31 | /// # Errors
32 | ///
33 | /// This function will return an error in the following situations:
34 | ///
35 | /// - If the specified JSON file cannot be found, read, or is not valid UTF-8.
36 | /// - If the JSON data cannot be deserialized into the `FileGenerationParams` struct.
37 | /// - If there is an error in generating files based on the parameters.
38 | ///
39 | pub fn generate_from_json(path: &str) -> io::Result<()> {
40 | let contents = fs::read_to_string(path)?;
41 | let params: FileGenerationParams = serde_json::from_str(&contents)
42 | .map_err(|e| {
43 | io::Error::new(io::ErrorKind::Other, e.to_string())
44 | })?;
45 | macro_generate_files!(params.clone())
46 | .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
47 | Ok(())
48 | }
49 |
--------------------------------------------------------------------------------
/src/generators/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | /// The `ascii` module contains functionality for generating ASCII art from
7 | /// text using the FIGlet library.
8 | pub mod ascii;
9 |
10 | /// The `args` module contains functionality for parsing command-line arguments.
11 | pub mod args;
12 |
13 | /// The `csv` module contains functionality for parsing CSV files.
14 | pub mod csv;
15 |
16 | /// The `ini` module contains functionality for parsing INI files.
17 | pub mod ini;
18 |
19 | /// The `json` module contains functionality for parsing JSON files.
20 | pub mod json;
21 |
22 | /// The `toml` module contains functionality for parsing TOML files.
23 | pub mod toml;
24 |
25 | /// The `yaml` module contains functionality for parsing YAML files.
26 | pub mod yaml;
27 |
--------------------------------------------------------------------------------
/src/generators/toml.rs:
--------------------------------------------------------------------------------
1 | use crate::macro_generate_files;
2 | use crate::models::model_params::FileGenerationParams;
3 | use std::fs;
4 | use std::io;
5 |
6 | /// Generates files for a new Rust project based on a TOML file.
7 | ///
8 | /// The TOML file must contain a single object with the following
9 | /// properties:
10 | ///
11 | /// - `author` - the author of the project (optional).
12 | /// - `build` - the build command to be used for building the project (optional).
13 | /// - `categories` - the categories that the project belongs to (optional).
14 | /// - `description` - a short description of the project (optional).
15 | /// - `documentation` - the documentation URL of the project (optional).
16 | /// - `edition` - the edition of the project (optional).
17 | /// - `email` - the email address of the author (optional).
18 | /// - `homepage` - the homepage of the project (optional).
19 | /// - `keywords` - keywords that describe the project (optional).
20 | /// - `license` - the license under which the project is released (optional).
21 | /// - `name` - the name of the project (optional).
22 | /// - `output` - the output directory where the project files will be created (required).
23 | /// - `readme` - the name of the readme file (optional).
24 | /// - `repository` - the url of the project's repository (optional).
25 | /// - `rustversion` - the minimum Rust version required by the project (optional).
26 | /// - version - the initial version of the project (optional).
27 | /// - website - the website of the project (optional).
28 | ///
29 | /// # Errors
30 | ///
31 | /// This function will return an error in the following situations:
32 | ///
33 | /// - If the specified TOML file cannot be found, read, or is not valid UTF-8.
34 | /// - If the TOML data cannot be deserialized into the FileGenerationParams struct.
35 | /// - If there is an error in generating files based on the parameters.
36 | ///
37 | pub fn generate_from_toml(path: &str) -> io::Result<()> {
38 | let contents = fs::read_to_string(path)?;
39 | let params: FileGenerationParams = toml::from_str(&contents)
40 | .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
41 | macro_generate_files!(params.clone())
42 | .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
43 | Ok(())
44 | }
45 |
--------------------------------------------------------------------------------
/src/generators/yaml.rs:
--------------------------------------------------------------------------------
1 | use crate::macro_generate_files;
2 | use crate::models::model_params::FileGenerationParams;
3 | use std::fs;
4 | use std::io;
5 |
6 | /// Generates files for a new Rust project based on a YAML file.
7 | ///
8 | /// The YAML file must contain a single object with the following
9 | /// properties:
10 | ///
11 | /// - `author` - the author of the project (optional).
12 | /// - `build` - the build command to be used for building the project (optional).
13 | /// - `categories` - the categories that the project belongs to (optional).
14 | /// - `description` - a short description of the project (optional).
15 | /// - `documentation` - the documentation URL of the project (optional).
16 | /// - `edition` - the edition of the project (optional).
17 | /// - `email` - the email address of the author (optional).
18 | /// - `homepage` - the homepage of the project (optional).
19 | /// - `keywords` - keywords that describe the project (optional).
20 | /// - `license` - the license under which the project is released (optional).
21 | /// - `name` - the name of the project (optional).
22 | /// - `output` - the output directory where the project files will be created (required).
23 | /// - `readme` - the name of the readme file (optional).
24 | /// - `repository` - the url of the project's repository (optional).
25 | /// - `rustversion` - the minimum Rust version required by the project (optional).
26 | /// - `version` - the initial version of the project (optional).
27 | /// - `website` - the website of the project (optional).
28 | ///
29 | /// # Errors
30 | ///
31 | /// This function will return an error in the following situations:
32 | ///
33 | /// - If the specified YAML file cannot be found, read, or is not valid UTF-8.
34 | /// - If the YAML data cannot be deserialized into the `FileGenerationParams` struct.
35 | /// - If there is an error in generating files based on the parameters.
36 | ///
37 | pub fn generate_from_yaml(path: &str) -> io::Result<()> {
38 | let contents = fs::read_to_string(path)?;
39 | let params: FileGenerationParams =
40 | serde_yml::from_str(&contents)
41 | .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
42 | macro_generate_files!(params.clone())
43 | .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
44 | Ok(())
45 | }
46 |
--------------------------------------------------------------------------------
/src/interface.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | use crate::macro_replace_placeholder;
7 | use crate::models::model_params::FileGenerationParams;
8 | use std::{
9 | fs::File,
10 | io::{BufRead, BufReader, Write},
11 | path::PathBuf,
12 | };
13 |
14 | /// Replaces placeholders in a template file with values from the provided parameters
15 | /// and writes the result to an output file.
16 | ///
17 | /// # Arguments
18 | ///
19 | /// * `template_file` - Path to the template file.
20 | /// * `output_file` - Path to the output file where the result should be written.
21 | /// * `params` - Parameters containing values to replace placeholders in the template.
22 | ///
23 | /// # Errors
24 | ///
25 | /// Returns an `std::io::Result` error if:
26 | ///
27 | /// - The template file cannot be read.
28 | /// - The output file cannot be created or written to.
29 | /// - There are issues parsing the template or replacing placeholders.
30 | ///
31 | pub fn replace_placeholders(
32 | template_file: &PathBuf,
33 | output_file: &PathBuf,
34 | params: &FileGenerationParams,
35 | ) -> std::io::Result<()> {
36 | let tpl = File::open(template_file)?;
37 | let tpl_reader = BufReader::new(tpl);
38 | let mut output = File::create(output_file)?;
39 | let tpl_lines = tpl_reader.lines();
40 |
41 | for line in tpl_lines {
42 | let line = line?;
43 | let replaced_line = macro_replace_placeholder!(
44 | line,
45 | params,
46 | author,
47 | build,
48 | categories,
49 | description,
50 | documentation,
51 | edition,
52 | email,
53 | homepage,
54 | keywords,
55 | license,
56 | name,
57 | output,
58 | readme,
59 | repository,
60 | rustversion,
61 | version,
62 | website
63 | );
64 | writeln!(output, "{replaced_line}")?;
65 | }
66 |
67 | Ok(())
68 | }
69 |
--------------------------------------------------------------------------------
/src/macros/ascii_macros.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | /// A macro for generating ASCII art from text.
7 | ///
8 | /// This macro takes a string literal as input and generates ASCII art using the `generate_ascii_art` function.
9 | /// If the conversion is successful, the macro returns the ASCII art as a string.
10 | /// If an error occurs during the conversion, the macro panics with an error message.
11 | ///
12 | /// # Examples
13 | ///
14 | /// ```
15 | /// use libmake::macro_ascii;
16 | ///
17 | /// let art = macro_ascii!("Hello, world!");
18 | /// println!("{}", art);
19 | /// ```
20 | #[macro_export]
21 | macro_rules! macro_ascii {
22 | ($text:expr) => {
23 | match $crate::generators::ascii::generate_ascii_art($text) {
24 | Ok(art) => art,
25 | Err(err) => panic!("Failed to generate ASCII art: {}", err),
26 | }
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/src/macros/file_macros.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | /// Macro to simplify the match logic for file generation.
7 | #[macro_export]
8 | macro_rules! generate_file {
9 | ($file_type:expr, $value:expr, $generator:expr) => {
10 | if !$value.trim().is_empty() {
11 | if let Err(err) = $generator($value) {
12 | eprintln!(
13 | "Error generating {} file: {}",
14 | $file_type, err
15 | );
16 | }
17 | }
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/src/macros/log_macros.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! This module contains macros related to logging messages at various log levels and formats.
7 | //!
8 | //! It includes a custom logging macro, `macro_log_info`, which allows logging messages with
9 | //! specified log levels, components, descriptions, and formats.
10 | //!
11 | //! # Custom Logging Macro
12 | //!
13 | //! The `macro_log_info` macro is designed for logging messages with customizable log levels,
14 | //! components, descriptions, and formats. It provides flexibility in defining log messages
15 | //! according to specific requirements.
16 | //!
17 | //! # Parameters
18 | //!
19 | //! - `$level`: The log level of the message.
20 | //! - `$component`: The component where the log is coming from.
21 | //! - `$description`: A description of the log message.
22 | //! - `$format`: The format of the log message.
23 | //!
24 |
25 | /// Custom logging macro for various log levels and formats.
26 | ///
27 | /// # Parameters
28 | ///
29 | /// * `$level`: The log level of the message.
30 | /// * `$component`: The component where the log is coming from.
31 | /// * `$description`: A description of the log message.
32 | /// * `$format`: The format of the log message.
33 | ///
34 | #[macro_export]
35 | macro_rules! macro_log_info {
36 | ($level:expr, $component:expr, $description:expr, $format:expr) => {{
37 | // Get the current date and time in ISO 8601 format.
38 | let date = DateTime::new(); // Create a new DateTime instance
39 | let iso = date.iso_8601; // Get ISO 8601 formatted date and time
40 |
41 | // Create a new random number generator
42 | let mut rng = Random::default(); // Default random number generator
43 | let session_id = rng.rand().to_string(); // Generate session ID
44 |
45 | // Create a new log instance
46 | let log = Log::new(
47 | &session_id, // Session ID
48 | &iso, // ISO 8601 formatted date and time
49 | $level, // Log level
50 | $component, // Component name
51 | $description, // Log description
52 | $format, // Log format
53 | );
54 | log // Return the Log instance
55 | }};
56 | }
57 |
--------------------------------------------------------------------------------
/src/macros/mod.rs:
--------------------------------------------------------------------------------
1 | /// A macro for generating ASCII art from text.
2 | pub mod ascii_macros;
3 |
4 | /// The `directory_macros` module contains macros related to directory
5 | /// operations.
6 | pub mod directory_macros;
7 |
8 | /// The `file_macros` module contains macros related to file operations.
9 | pub mod file_macros;
10 |
11 | /// The `generator_macros` module contains macros related to generating
12 | /// templates from JSON, YAML, and CSV files, and custom logging functionality.
13 | pub mod generator_macros;
14 |
15 | /// The `log_macros` module contains macros related to logging messages at various log levels and formats.
16 | pub mod log_macros;
17 |
18 | /// The `utility_macros` module contains utility macros for common tasks such as
19 | /// replacing placeholders in a line with values from parameters.
20 | pub mod utility_macros;
21 |
--------------------------------------------------------------------------------
/src/macros/utility_macros.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | /// Replaces placeholders in a given line with corresponding values from the provided parameters.
7 | ///
8 | /// # Arguments
9 | ///
10 | /// * `line` - The line containing placeholders to be replaced.
11 | /// * `params` - The parameters containing values to replace the placeholders.
12 | /// * `$($field:ident),+` - Identifiers representing the fields in `params` to be replaced.
13 | ///
14 | /// # Returns
15 | ///
16 | /// The line with placeholders replaced by their corresponding values.
17 | ///
18 | #[macro_export]
19 | macro_rules! macro_replace_placeholder {
20 | ($line:expr, $params:expr, $($field:ident),+) => {
21 | {
22 | let mut line = $line;
23 | $(
24 | line = line.replace(
25 | concat!("{", stringify!($field), "}"),
26 | &$params.$field.as_deref().unwrap_or(""),
27 | );
28 | )+
29 | line
30 | }
31 | };
32 | }
33 |
34 | /// Macro to generate a function that retrieves a field value from a JSON file.
35 | ///
36 | /// # Arguments
37 | ///
38 | /// * `$func_name` - The name of the generated function.
39 | /// * `$deserializer` - The deserializer used to parse the JSON file.
40 | ///
41 | /// # Returns
42 | ///
43 | /// The generated function returns a `Result` containing the field value as a `String`,
44 | /// or a `Box` if an error occurs.
45 | ///
46 | #[macro_export]
47 | macro_rules! macro_get_field {
48 | ($func_name:ident, $deserializer:expr) => {
49 | /// Reads a file and deserializes its content using the specified
50 | /// deserializer function.
51 | pub fn $func_name(
52 | // The path of the JSON file to read.
53 | file_path: Option<&str>,
54 | // The name of the field to retrieve.
55 | field_name: &str,
56 | ) -> Result> {
57 | file_path.map_or_else(
58 | || Ok(String::new()),
59 | |file_path| {
60 | let current_dir = env::current_dir()?;
61 | let file_path =
62 | Path::new(¤t_dir).join(file_path);
63 | read_file(&file_path, |file| {
64 | let value: serde_json::Value =
65 | $deserializer(file)?;
66 | let field_value = value
67 | .get(field_name)
68 | .ok_or_else(|| {
69 | format!(
70 | "Field '{}' not found",
71 | field_name
72 | )
73 | })?
74 | .as_str()
75 | .map(|s| s.to_string())
76 | .unwrap_or_else(|| {
77 | value[field_name].to_string()
78 | });
79 | Ok(field_value)
80 | })
81 | },
82 | )
83 | }
84 | };
85 | }
86 |
--------------------------------------------------------------------------------
/src/main.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | //! # Libmake Application
7 | //!
8 | //! This is the main entry point for the cmn application.
9 | //! Call the `run()` function from the `LibMake (LM)` module.
10 | //!
11 | //! # Purpose
12 | //! The purpose of this function is to serve as the entry point for the `cmn` application.
13 | //! It calls the `run` function from the `LibMake (LM)` crate to execute the desired tasks.
14 | //!
15 | //! # Usage
16 | //! To use the `cmn` application, you can include it as part of your Rust project.
17 | //! The `main` function of the application calls the `run` function from the `LibMake (LM)` module.
18 | //! If an error occurs during execution, it prints an error message and exits with a non-zero status code.
19 | //!
20 | //! ```rust
21 | //! use libmake::run;
22 | //!
23 | //!/ This is the main entry point for the cmn application.
24 | //! Call the `run()` function from the `LibMake (LM)` module.
25 | //! if let Err(ref e) = run() {
26 | //! eprintln!("Error running cmn: {}", e);
27 | //! std::process::exit(1);
28 | //! }
29 | //! ```
30 | //!
31 | //! This application allows you to interact with and use the functionality provided by the `LibMake (LM)` crate.
32 |
33 | use libmake::run;
34 |
35 | /// This is the main entry point for the cmn application.
36 | /// Call the `run()` function from the `LibMake (LM)` module.
37 | ///
38 | /// # Parameters
39 | /// This function does not take any parameters.
40 | ///
41 | /// # Returns
42 | /// This function returns a `Result` type. If the `run` function from the `LibMake (LM)` module succeeds, it returns `Ok(())`. If an error occurs, it returns `Err(err)`, where `err` is an instance of the `Error` type.
43 | ///
44 | /// # Panics
45 | /// This function may panic if the `run` function from the `LibMake (LM)` module returns an error and the error is not handled properly.
46 | ///
47 | /// # Examples
48 | /// ```rust
49 | /// use libmake::run;
50 | ///
51 | /// This is the main entry point for the cmn application.
52 | /// Call the `run()` function from the `LibMake (LM)` module.
53 | /// if let Err(err) = run() {
54 | /// eprintln!("Error running cmn: {}", err);
55 | /// std::process::exit(1);
56 | /// }
57 | /// ```
58 | ///
59 | /// # See Also
60 | /// - [`run` function from the `LibMake (LM)` module](crate::libmake::run)
61 | ///
62 | /// # Author
63 | /// Copyright © 2023-2024 LibMake. All rights reserved.
64 | ///
65 | /// # License
66 | /// This code is dual-licensed under the Apache License 2.0 and the MIT License.
67 |
68 | fn main() {
69 | // Call the `run()` function from the `LibMake (LM)` module.
70 | if let Err(err) = run() {
71 | eprintln!("Error running cmn: {}", err);
72 | std::process::exit(1);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/models/error_ascii_art.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | use std::error::Error;
7 | use std::fmt;
8 |
9 | /// Error type for ASCII art generation failures.
10 | #[derive(Clone, Copy, Debug, PartialEq, Eq)]
11 | pub enum AsciiArtError {
12 | /// Represents a failure to load the FIGfont.
13 | FontLoadError,
14 | /// Represents a failure to convert text to ASCII art.
15 | ConversionError,
16 | }
17 |
18 | impl fmt::Display for AsciiArtError {
19 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 | match *self {
21 | Self::FontLoadError => write!(f, "Failed to load FIGfont"),
22 | Self::ConversionError => {
23 | write!(f, "Failed to convert text to ASCII art")
24 | }
25 | }
26 | }
27 | }
28 |
29 | impl Error for AsciiArtError {
30 | fn source(&self) -> Option<&(dyn Error + 'static)> {
31 | None
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/models/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | /// The `ascii_art_error` module contains the `AsciiArtError` type for ASCII art generation failures.
7 | pub mod error_ascii_art;
8 |
9 | /// The `model_params` module contains the `FileGenerationParams` type for holding the parameters for generating the project files.
10 | pub mod model_params;
11 |
--------------------------------------------------------------------------------
/src/utilities/directory.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | use std::{
7 | error::Error,
8 | fs::{self},
9 | path::{Path, PathBuf},
10 | };
11 | /// Ensures a directory exists, creating it if necessary.
12 | ///
13 | /// This function takes a reference to a `Path` object for a directory and a
14 | /// human-readable name for the directory, and creates the directory if it
15 | /// does not already exist.
16 | ///
17 | /// # Arguments
18 | ///
19 | /// * `dir` - A reference to a `Path` object for the directory.
20 | /// * `name` - A human-readable name for the directory, used in error messages.
21 | ///
22 | /// # Returns
23 | ///
24 | /// * `Result<(), String>` - A result indicating success or failure.
25 | /// - `Ok(())` if the directory exists or was created successfully.
26 | /// - `Err(String)` if the directory does not exist and could not be created.
27 | ///
28 | /// # Example
29 | ///
30 | /// ```
31 | /// use libmake::utilities::directory::directory;
32 | /// use std::path::Path;
33 | /// use std::fs;
34 | ///
35 | /// // Create a "logs" directory if it doesn't exist
36 | /// let dir = Path::new("logs");
37 | /// directory(dir, "logs").expect("Could not create logs directory");
38 | /// fs::remove_dir_all(dir).expect("Could not remove logs directory");
39 | /// ```
40 | ///
41 | pub fn directory(dir: &Path, name: &str) -> Result {
42 | if dir.exists() {
43 | if !dir.is_dir() {
44 | return Err(format!(
45 | "❌ Error: {} is not a directory.",
46 | name
47 | ));
48 | }
49 | } else {
50 | match fs::create_dir_all(dir) {
51 | Ok(_) => {}
52 | Err(e) => {
53 | return Err(format!(
54 | "❌ Error: Cannot create {} directory: {}",
55 | name, e
56 | ))
57 | }
58 | }
59 | }
60 | Ok(String::new())
61 | }
62 |
63 | /// Moves the output directory to the public directory.
64 | ///
65 | /// This function takes a reference to a `Path` object for the output directory
66 | /// and a string for the site name, and moves the output directory to the
67 | /// public directory.
68 | ///
69 | /// # Arguments
70 | ///
71 | /// * `site_name` - A string for the site name.
72 | /// * `out_dir` - A reference to a `Path` object for the output directory.
73 | ///
74 | /// # Returns
75 | ///
76 | /// * `Result<(), std::io::Error>` - A result indicating success or failure.
77 | /// - `Ok(())` if the output directory was moved successfully.
78 | /// - `Err(std::io::Error)` if the output directory could not be moved.
79 | ///
80 | pub fn move_output_directory(
81 | site_name: &str,
82 | out_dir: &Path,
83 | ) -> std::io::Result<()> {
84 | println!("❯ Moving output directory...");
85 |
86 | let public_dir = Path::new("public");
87 |
88 | if public_dir.exists() {
89 | fs::remove_dir_all(public_dir)?;
90 | }
91 |
92 | fs::create_dir(public_dir)?;
93 |
94 | let site_name = site_name.replace(' ', "_");
95 | let new_project_dir = public_dir.join(site_name);
96 | fs::create_dir_all(&new_project_dir)?;
97 |
98 | fs::rename(out_dir, &new_project_dir)?;
99 |
100 | println!(" Done.\n");
101 |
102 | Ok(())
103 | }
104 |
105 | /// Cleans up the directory at the given path.
106 | ///
107 | /// If the directory does not exist, this function does nothing.
108 | ///
109 | /// # Arguments
110 | ///
111 | /// * `directories` - An array of references to `Path` objects representing the
112 | /// directories to be cleaned up.
113 | ///
114 | /// # Returns
115 | ///
116 | /// * `Result<(), Box>` - A result indicating success or failure.
117 | /// - `Ok(())` if the directories were cleaned up successfully.
118 | /// - `Err(Box)` if an error occurred during the cleanup process.
119 | ///
120 | pub fn cleanup_directory(
121 | directories: &[&Path],
122 | ) -> Result<(), Box> {
123 | for directory in directories {
124 | if !directory.exists() {
125 | continue;
126 | }
127 |
128 | println!("\n❯ Cleaning up directories");
129 |
130 | fs::remove_dir_all(directory)?;
131 |
132 | println!(" Done.\n");
133 | }
134 |
135 | Ok(())
136 | }
137 |
138 | /// Creates a new directory at the given path.
139 | ///
140 | /// If the directory already exists, this function does nothing.
141 | ///
142 | /// # Arguments
143 | ///
144 | /// * `directories` - An array of references to `Path` objects representing the
145 | /// directories to be created.
146 | ///
147 | /// # Returns
148 | ///
149 | /// * `Result<(), Box>` - A result indicating success or failure.
150 | /// - `Ok(())` if the directories were created successfully.
151 | /// - `Err(Box)` if an error occurred during the creation process.
152 | ///
153 | pub fn create_directory(
154 | directories: &[&Path],
155 | ) -> Result<(), Box> {
156 | for directory in directories {
157 | if directory.exists() {
158 | continue;
159 | }
160 |
161 | fs::create_dir(directory)?;
162 | }
163 |
164 | Ok(())
165 | }
166 |
167 | /// Truncates a path to only have a set number of path components.
168 | ///
169 | /// Will truncate a path to only show the last `length` components in a path.
170 | /// If a length of `0` is provided, the path will not be truncated.
171 | /// A value will only be returned if the path has been truncated.
172 | ///
173 | /// # Arguments
174 | ///
175 | /// * `path` - The path to truncate.
176 | /// * `length` - The number of path components to keep.
177 | ///
178 | /// # Returns
179 | ///
180 | /// * An `Option` of the truncated path as a string. If the path was not truncated, `None` is returned.
181 | pub fn truncate(path: &Path, length: usize) -> Option {
182 | // Checks if the length is 0. If it is, returns `None`.
183 | if length == 0 {
184 | return None;
185 | }
186 |
187 | // Creates a new PathBuf object to store the truncated path.
188 | let mut truncated = PathBuf::new();
189 |
190 | // Iterates over the components of the path in reverse order.
191 | let mut count = 0;
192 | while let Some(component) = path.components().next_back() {
193 | // Adds the component to the truncated path.
194 | truncated.push(component);
195 | count += 1;
196 |
197 | // If the count reaches the desired length, breaks out of the loop.
198 | if count == length {
199 | break;
200 | }
201 | }
202 |
203 | // If the count is equal to the desired length, returns the truncated path as a string.
204 | if count == length {
205 | Some(truncated.to_string_lossy().to_string())
206 | } else {
207 | // Otherwise, returns `None`.
208 | None
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/src/utilities/mod.rs:
--------------------------------------------------------------------------------
1 | /// The `directory` module contains functions related to directory operations.
2 | pub mod directory;
3 |
4 | /// The `uuid` module contains functions related to generating UUIDs.
5 | pub mod uuid;
6 |
--------------------------------------------------------------------------------
/src/utilities/uuid.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | // Import the Uuid type from the uuid crate
7 | use uuid::Uuid;
8 |
9 | /// Generates a unique string.
10 | ///
11 | /// This function generates a new unique string using UUID version 4 (random).
12 | ///
13 | /// # Returns
14 | ///
15 | /// A string containing the generated unique identifier.
16 | ///
17 | /// # Examples
18 | ///
19 | /// ```
20 | /// use libmake::utilities::uuid::generate_unique_string;
21 | ///
22 | /// let unique_string = generate_unique_string();
23 | /// println!("Unique string: {}", unique_string);
24 | /// ```
25 | pub fn generate_unique_string() -> String {
26 | // Generate a new UUID v4 (random) and convert it to a string
27 | Uuid::new_v4().to_string()
28 | }
29 |
--------------------------------------------------------------------------------
/src/utils.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | use crate::macro_get_field;
7 | use std::{
8 | env,
9 | fs::{self, File},
10 | io,
11 | path::Path,
12 | };
13 |
14 | /// Reads a file and deserializes its content using the specified deserializer function.
15 | ///
16 | /// # Arguments
17 | ///
18 | /// * `file_path` - The path of the file to read.
19 | /// * `deserializer` - A function that takes a `File` and returns a deserialized value of type `T`.
20 | ///
21 | /// # Returns
22 | ///
23 | /// Returns a `Result>` containing the deserialized value, or an error if one occurs.
24 | ///
25 | fn read_file(
26 | file_path: &Path,
27 | deserializer: F,
28 | ) -> Result>
29 | where
30 | F: FnOnce(File) -> Result>,
31 | {
32 | let file = File::open(file_path)?;
33 | deserializer(file)
34 | }
35 |
36 | /// Reads a CSV file at the given file path and returns the value of
37 | /// the given field.
38 | ///
39 | /// # Arguments
40 | ///
41 | /// * `file_path` - An optional string slice that holds the file path of the CSV file to read.
42 | /// * `field_index` - The index of the field to retrieve.
43 | ///
44 | pub fn get_csv_field(
45 | file_path: Option<&str>,
46 | field_index: usize,
47 | ) -> Option> {
48 | file_path.and_then(|file_path| {
49 | let current_dir = env::current_dir().ok()?;
50 | let file_path = Path::new(¤t_dir).join(file_path);
51 | let file = File::open(file_path).ok()?;
52 | let mut rdr = csv::Reader::from_reader(file);
53 |
54 | let mut values = Vec::new();
55 | for result in rdr.records() {
56 | let record = result.ok()?;
57 | if let Some(field_value) = record.get(field_index) {
58 | values.push(field_value.to_string());
59 | } else {
60 | // Field index is out of range
61 | return None;
62 | }
63 | }
64 | if values.is_empty() {
65 | None
66 | } else {
67 | Some(values)
68 | }
69 | })
70 | }
71 |
72 | macro_get_field!(get_ini_field, serde_ini::from_read);
73 | macro_get_field!(get_json_field, serde_json::from_reader);
74 | macro_get_field!(get_yaml_field, serde_yml::from_reader);
75 |
76 | /// Retrieves a specific field's value from a configuration file.
77 | ///
78 | /// # Arguments
79 | ///
80 | /// * `file_path` - An optional reference to the path of the configuration file.
81 | /// * `file_format` - The format of the configuration file ("json", "yaml", or "ini").
82 | /// * `field_name` - The name of the field to retrieve the value from.
83 | ///
84 | /// # Returns
85 | ///
86 | /// Returns a `Result>` containing the value of the specified field, or an error if one occurs.
87 | ///
88 | pub fn get_config_field(
89 | file_path: Option<&str>,
90 | file_format: Option<&str>,
91 | field_name: &str,
92 | ) -> Result> {
93 | // Ensure file_path is provided
94 | let file_path = file_path.ok_or("File path is not provided")?;
95 |
96 | // Ensure file_format is provided and is either 'json', 'yaml', or 'ini'
97 | let format = file_format.ok_or("File format is not provided")?;
98 | match format {
99 | "ini" => get_ini_field(Some(file_path), field_name),
100 | "json" => get_json_field(Some(file_path), field_name),
101 | "yaml" => get_yaml_field(Some(file_path), field_name),
102 | _ => Err(format!(
103 | "Unsupported file format: {}. Supported formats are 'json', 'yaml', and 'ini'.",
104 | format
105 | )
106 | .into()),
107 | }
108 | }
109 |
110 | /// Creates a directory at the specified path.
111 | ///
112 | /// # Arguments
113 | ///
114 | /// * `path` - The path where the directory should be created.
115 | ///
116 | /// # Errors
117 | ///
118 | /// Returns an `io::Error` if the directory cannot be created. This could be due to
119 | /// various reasons such as insufficient permissions, the directory already existing,
120 | /// or other I/O-related errors.
121 | ///
122 | pub fn create_directory(path: &Path) -> io::Result<()> {
123 | fs::create_dir(path).or_else(|e| match e.kind() {
124 | io::ErrorKind::AlreadyExists => Ok(()),
125 | _ => Err(e),
126 | })
127 | }
128 |
--------------------------------------------------------------------------------
/template/AUTHORS.tpl:
--------------------------------------------------------------------------------
1 | # Authors
2 |
3 | * {author} ({email}) (Original Contributor)
4 |
--------------------------------------------------------------------------------
/template/CONTRIBUTING.tpl:
--------------------------------------------------------------------------------
1 | # Contributing to `{name}`
2 |
3 | Welcome! We're thrilled that you're interested in contributing to the
4 | `{name}` library. Whether you're looking to evangelize, submit feedback,
5 | or contribute code, we appreciate your involvement in making `{name}` a
6 | better tool for everyone. Here's how you can get started.
7 |
8 | ## Evangelize
9 |
10 | One of the simplest ways to help us out is by spreading the word about
11 | {name}. We believe that a bigger, more involved community makes for a
12 | better framework, and that better frameworks make the world a better
13 | place. If you know people who might benefit from using {name}, please
14 | let them know!
15 |
16 | ## How to Contribute
17 |
18 | If you're interested in making a more direct contribution, there are
19 | several ways you can help us improve {name}. Here are some guidelines
20 | for submitting feedback, bug reports, and code contributions.
21 |
22 | ### Feedback
23 |
24 | Your feedback is incredibly valuable to us, and we're always looking for
25 | ways to make {name} better. If you have ideas, suggestions, or questions
26 | about {name}, we'd love to hear them. Here's how you can provide
27 | feedback:
28 |
29 | - Click [here][2] to submit a new feedback.
30 | - Use a descriptive title that clearly summarizes your feedback.
31 | - Provide a detailed description of the issue or suggestion.
32 | - Be patient while we review and respond to your feedback.
33 |
34 | ### Bug Reports
35 |
36 | If you encounter a bug while using {name}, please let us know so we can
37 | fix it. Here's how you can submit a bug report:
38 |
39 | - Click [here][2] to submit a new issue.
40 | - Use a descriptive title that clearly summarizes the bug.
41 | - Provide a detailed description of the issue, including steps to
42 | reproduce it.
43 | - Be patient while we review and respond to your bug report.
44 |
45 | ### Code Contributions
46 |
47 | If you're interested in contributing code to {name}, we're excited to
48 | have your help! Here's what you need to know:
49 |
50 | #### Feature Requests
51 |
52 | If you have an idea for a new feature or improvement, we'd love to hear
53 | it. Here's how you can contribute code for a new feature to {name}:
54 |
55 | - Fork the repo.
56 | - Clone the {name}[1] repo by running:
57 | `git clone {repository}`
58 | - Edit files in the `src/` folder. The `src/` folder contains the source
59 | code for {name}.
60 | - Submit a pull request, and we'll review and merge your changes if they
61 | fit with our vision for {name}.
62 |
63 | #### Submitting Code
64 |
65 | If you've identified a bug or have a specific code improvement in mind,
66 | we welcome your pull requests. Here's how to submit your code changes:
67 |
68 | - Fork the repo.
69 | - Clone the {name} repo by running:
70 | `git clone {repository}`
71 | - Edit files in the `src/` folder. The `src/` folder contains the source
72 | code for {name}.
73 | - Submit a pull request, and we'll review and merge your changes if they
74 | fit with our vision for {name}.
75 |
76 | We hope that this guide has been helpful in explaining how you can
77 | contribute to {name}. Thank you for your interest and involvement in our
78 | project!
79 |
80 | [1]: {repository}
81 | [2]: {repository}/issues/new
82 |
--------------------------------------------------------------------------------
/template/Cargo.tpl:
--------------------------------------------------------------------------------
1 | [package]
2 | # Metadata about the package.
3 | authors = "{author}"
4 | build = "{build}"
5 | categories = [{categories}]
6 | description = "{description}"
7 | documentation = "{documentation}"
8 | edition = "{edition}"
9 | exclude = ["/.git/*", "/.github/*", "/.gitignore", "/.vscode/*"]
10 | homepage = "{homepage}"
11 | keywords = [{keywords}]
12 | license = "{license}"
13 | name = "{name}"
14 | readme = "{readme}"
15 | repository = "{repository}"
16 | rust-version = "{rustversion}"
17 | version = "{version}"
18 | include = [
19 | "/CONTRIBUTING.md",
20 | "/LICENSE-APACHE",
21 | "/LICENSE-MIT",
22 | "/benches/**",
23 | "/build.rs",
24 | "/Cargo.toml",
25 | "/examples/**",
26 | "/README.md",
27 | "/src/**",
28 | "/tests/**"
29 | ]
30 |
31 | [[bench]]
32 | # Benchmarking configuration.
33 | name = "benchmark"
34 | harness = false
35 | path = "benches/criterion.rs"
36 |
37 | [profile.bench]
38 | debug = true
39 |
40 | [dependencies]
41 | # The dependencies of the package.
42 | anyhow = "1.0.83"
43 | dtt = "0.0.6"
44 | env_logger = "0.11.3"
45 | rlg = "0.0.4"
46 | serde = { version = "1.0.201", features = ["derive"] }
47 | serde_json = "1.0.117"
48 | serde_yml = "0.0.5"
49 | toml = "0.8.12"
50 | vrd = "0.0.7"
51 |
52 | [dev-dependencies]
53 | # The development dependencies of the package.
54 | criterion = "0.5.1"
55 |
56 | [lib]
57 | # The library configuration.
58 | crate-type = ["lib"]
59 | name = "{name}"
60 | path = "src/lib.rs"
61 |
62 | [features]
63 | # The features of the package.
64 | default = []
65 |
66 | [package.metadata.docs.rs]
67 | # Configuration for docs.rs.
68 | targets = ["x86_64-unknown-linux-gnu"]
69 | rustdoc-args = ["--generate-link-to-definition"]
70 |
71 | # Linting config
72 | [lints.rust]
73 |
74 | ## Warn
75 | missing_copy_implementations = "warn"
76 | missing_docs = "warn"
77 | unstable_features = "warn"
78 | unused_extern_crates = "warn"
79 | unused_results = "warn"
80 |
81 | ## Allow
82 | bare_trait_objects = "allow"
83 | elided_lifetimes_in_paths = "allow"
84 | non_camel_case_types = "allow"
85 | non_upper_case_globals = "allow"
86 | trivial_bounds = "allow"
87 | unsafe_code = "allow"
88 |
89 | ## Forbid
90 | missing_debug_implementations = "forbid"
91 | non_ascii_idents = "forbid"
92 | unreachable_pub = "forbid"
93 |
94 | ## Deny
95 | dead_code = "deny"
96 | deprecated_in_future = "deny"
97 | ellipsis_inclusive_range_patterns = "deny"
98 | explicit_outlives_requirements = "deny"
99 | future_incompatible = { level = "deny", priority = -1 }
100 | keyword_idents = "deny"
101 | macro_use_extern_crate = "deny"
102 | meta_variable_misuse = "deny"
103 | missing_fragment_specifier = "deny"
104 | noop_method_call = "deny"
105 | pointer_structural_match = "deny"
106 | rust_2018_idioms = { level = "deny", priority = -1 }
107 | rust_2021_compatibility = { level = "deny", priority = -1 }
108 | single_use_lifetimes = "deny"
109 | trivial_casts = "deny"
110 | trivial_numeric_casts = "deny"
111 | unused = { level = "deny", priority = -1 }
112 | unused_features = "deny"
113 | unused_import_braces = "deny"
114 | unused_labels = "deny"
115 | unused_lifetimes = "deny"
116 | unused_macro_rules = "deny"
117 | unused_qualifications = "deny"
118 | variant_size_differences = "deny"
119 |
120 | [package.metadata.clippy]
121 | # Clippy configuration.
122 | warn-lints = ["clippy::all", "clippy::pedantic", "clippy::cargo", "clippy::nursery"]
123 |
124 | [profile.dev]
125 | # Development profile configuration.
126 | codegen-units = 256
127 | debug = true
128 | debug-assertions = true
129 | incremental = true
130 | lto = false
131 | opt-level = 0
132 | overflow-checks = true
133 | panic = 'unwind'
134 | rpath = false
135 | strip = false
136 |
137 | [profile.release]
138 | # Release profile configuration.
139 | codegen-units = 1
140 | debug = false
141 | debug-assertions = false
142 | incremental = false
143 | lto = true
144 | opt-level = "s"
145 | overflow-checks = false
146 | panic = 'abort'
147 | rpath = false
148 | strip = 'symbols'
149 |
150 | [profile.test]
151 | # Test profile configuration.
152 | codegen-units = 256
153 | debug = true
154 | debug-assertions = true
155 | incremental = true
156 | lto = false
157 | opt-level = 0
158 | overflow-checks = true
159 | rpath = false
160 | strip = false
161 |
--------------------------------------------------------------------------------
/template/README.tpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 | # {name}
14 |
15 | {description}
16 |
17 |
18 |
19 |
20 |
21 | [![Made With Rust][made-with-rust-badge]][04] [![Crates.io][crates-badge]][06] [![Lib.rs][libs-badge]][08] [![Docs.rs][docs-badge]][07] [![License][license-badge]][01]
22 |
23 | • [Website][00] • [Documentation][07] • [Report Bug][02] • [Request Feature][02] • [Contributing Guidelines][03]
24 |
25 |
26 |
27 |
28 |
29 | ![divider][divider]
30 |
31 | ## Overview 📖
32 |
33 | {description}
34 |
35 | ## Features ✨
36 |
37 | - Feature 1
38 | - Feature 2
39 | - Feature 3
40 |
41 | ## Getting Started 🚀
42 |
43 | It takes just a few minutes to get up and running with `{name}`.
44 |
45 | ### Installation
46 |
47 | To install `{name}`, you need to have the Rust toolchain installed on
48 | your machine. You can install the Rust toolchain by following the
49 | instructions on the [Rust website][12].
50 |
51 | Once you have the Rust toolchain installed, you can install `{name}`
52 | using the following command:
53 |
54 | ```shell
55 | cargo install {name}
56 | ```
57 |
58 | ### Requirements
59 |
60 | The minimum supported Rust toolchain version is currently Rust
61 | **{rustversion}** or later (stable).
62 |
63 | ### Platform support
64 |
65 | `{name}` is supported and tested on the following platforms:
66 |
67 | ### Tier 1 platforms 🏆
68 |
69 | | | Operating System | Target | Description |
70 | | --- | --- | --- | --- |
71 | | ✅ | Linux | aarch64-unknown-linux-gnu | 64-bit Linux systems on ARM architecture |
72 | | ✅ | Linux | i686-unknown-linux-gnu | 32-bit Linux (kernel 3.2+, glibc 2.17+) |
73 | | ✅ | Linux | x86_64-unknown-linux-gnu | 64-bit Linux (kernel 2.6.32+, glibc 2.11+) |
74 | | ✅ | macOS | x86_64-apple-darwin | 64-bit macOS (10.7 Lion or later) |
75 | | ✅ | Windows | i686-pc-windows-gnu | 32-bit Windows (7 or later) |
76 | | ✅ | Windows | i686-pc-windows-msvc | 32-bit Windows (7 or later) |
77 | | ✅ | Windows | x86_64-pc-windows-gnu | 64-bit Windows (7 or later) |
78 | | ✅ | Windows | x86_64-pc-windows-msvc | 64-bit Windows (7 or later) |
79 |
80 | ### Tier 2 platforms 🥈
81 |
82 | | | Operating System | Target | Description |
83 | | --- | --- | --- | --- |
84 | | ✅ | Linux | aarch64-unknown-linux-musl | 64-bit Linux systems on ARM architecture |
85 | | ✅ | Linux | arm-unknown-linux-gnueabi | ARMv6 Linux (kernel 3.2, glibc 2.17) |
86 | | ✅ | Linux | arm-unknown-linux-gnueabihf | ARMv7 Linux, hardfloat (kernel 3.2, glibc 2.17) |
87 | | ✅ | Linux | armv7-unknown-linux-gnueabihf | ARMv7 Linux, hardfloat (kernel 3.2, glibc 2.17) |
88 | | ✅ | Linux | mips-unknown-linux-gnu | MIPS Linux (kernel 2.6.32+, glibc 2.11+) |
89 | | ✅ | Linux | mips64-unknown-linux-gnuabi64 | MIPS64 Linux (kernel 2.6.32+, glibc 2.11+) |
90 | | ✅ | Linux | mips64el-unknown-linux-gnuabi64 | MIPS64 Linux (kernel 2.6.32+, glibc 2.11+) |
91 | | ✅ | Linux | mipsel-unknown-linux-gnu | MIPS Linux (kernel 2.6.32+, glibc 2.11+) |
92 | | ✅ | macOS | aarch64-apple-darwin | 64-bit macOS (10.7 Lion or later) |
93 | | ✅ | Windows | aarch64-pc-windows-msvc | 64-bit Windows (7 or later) |
94 |
95 | The [GitHub Actions][09] shows the platforms in which the `{name}`
96 | library tests are run.
97 |
98 | ### Documentation
99 |
100 | **Info:** Please check out our [website][00] for more information. You can find our documentation on [docs.rs][07], [lib.rs][08] and
101 | [crates.io][06].
102 |
103 | ## Usage 📖
104 |
105 | To use the `{name}` library in your project, add the following to your
106 | `Cargo.toml` file:
107 |
108 | ```toml
109 | [dependencies]
110 | {name} = {version}
111 | ```
112 |
113 | Add the following to your `main.rs` file:
114 |
115 | ```rust
116 | extern crate {name};
117 | use {name}::*;
118 | ```
119 |
120 | then you can use the functions in your application code.
121 |
122 | ### Examples
123 |
124 | To get started with `{name}`, you can use the examples provided in the
125 | `examples` directory of the project.
126 |
127 | To run the examples, clone the repository and run the following command
128 | in your terminal from the project root directory.
129 |
130 | ```shell
131 | cargo run --example example
132 | ```
133 |
134 | ## Semantic Versioning Policy 🚥
135 |
136 | For transparency into our release cycle and in striving to maintain
137 | backward compatibility, `{name}` follows [semantic versioning][05].
138 |
139 | ## License 📝
140 |
141 | The project is licensed under the terms of {license}.
142 |
143 | ## Contribution 🤝
144 |
145 | We welcome all people who want to contribute. Please see the
146 | [contributing instructions][03] for more information.
147 |
148 | Contributions in any form (issues, pull requests, etc.) to this project
149 | must adhere to the [Rust's Code of Conduct][10].
150 |
151 | Unless you explicitly state otherwise, any contribution intentionally
152 | submitted for inclusion in the work by you, as defined in the
153 | Apache-2.0 license, shall be dual licensed as above, without any
154 | additional terms or conditions.
155 |
156 | ## Acknowledgements 💙
157 |
158 | A big thank you to all the awesome contributors of [{name}][04] for their
159 | help and support.
160 |
161 | A special thank you goes to the [Rust Reddit][11] community for
162 | providing a lot of useful suggestions on how to improve this project.
163 |
164 | [00]: {website} "Website of {name}"
165 | [01]: https://opensource.org/license/apache-2-0/ "Apache License, Version 2.0"
166 | [02]: {repository}/{name}/issues "Issues page of {name}"
167 | [03]: {repository}/{name}/blob/main/CONTRIBUTING.md "Contributing guidelines"
168 | [04]: {repository}/{name}/graphs/contributors "Contributors of {name}"
169 | [05]: http://semver.org/ "Semantic Versioning"
170 | [06]: https://crates.io/crates/{name} "Crates.io page of {name}"
171 | [07]: https://docs.rs/{name} "Docs.rs page of {name}"
172 | [08]: https://lib.rs/crates/{name} "Lib.rs page of {name}"
173 | [09]: {repository}/{name}/actions "GitHub Actions page of {name}"
174 | [10]: https://www.rust-lang.org/policies/code-of-conduct "Rust's Code of Conduct"
175 | [11]: https://www.reddit.com/r/rust/ "Rust Reddit community"
176 | [12]: https://www.rust-lang.org/learn/get-started "Rust installation page"
177 |
178 | [crates-badge]: https://img.shields.io/crates/v/{name}.svg?style=for-the-badge 'Crates.io badge'
179 | [divider]: https://kura.pro/common/images/elements/divider.svg "divider"
180 | [docs-badge]: https://img.shields.io/docsrs/{name}.svg?style=for-the-badge 'Docs.rs badge'
181 | [libs-badge]: https://img.shields.io/badge/lib.rs-v{version}-orange.svg?style=for-the-badge 'Lib.rs badge'
182 | [license-badge]: https://img.shields.io/crates/l/{name}.svg?style=for-the-badge 'License badge'
183 | [made-with-rust-badge]: https://img.shields.io/badge/rust-f04041?style=for-the-badge&labelColor=c0282d&logo=rust 'Made With Rust badge'
184 |
--------------------------------------------------------------------------------
/template/TEMPLATE.tpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 | # {name}
14 |
15 | {description}
16 |
17 |
18 |
19 |
20 |
21 | [![Made With Rust][made-with-rust-badge]][04] [![Crates.io][crates-badge]][05] [![Lib.rs][libs-badge]][07] [![Docs.rs][docs-badge]][06] [![License][license-badge]][01]
22 |
23 | • [Website][00] • [Documentation][06] • [Report Bug][02] • [Request Feature][02] • [Contributing Guidelines][03]
24 |
25 |
26 |
27 |
28 |
29 | ![divider][divider]
30 |
31 | ## Overview 📖
32 |
33 | {description}
34 |
35 | ## Features ✨
36 |
37 | - Feature 1
38 | - Feature 2
39 | - Feature 3
40 |
41 | ## Changelog 📚
42 |
43 | -
44 |
45 | [00]: {website} "Website of {name}"
46 | [01]: https://opensource.org/license/apache-2-0/ "Apache License, Version 2.0"
47 | [02]: {repository}/{name}/issues "Issues page of {name}"
48 | [03]: {repository}/{name}/blob/main/CONTRIBUTING.md "Contributing guidelines of {name}"
49 | [04]: {repository}/{name}/graphs/contributors "Contributors of {name}"
50 | [05]: https://crates.io/crates/{name} "Crates.io page of {name}"
51 | [06]: https://docs.rs/{name} "Docs.rs page of {name}"
52 | [07]: https://lib.rs/crates/{name} "Lib.rs page of {name}"
53 |
54 | [crates-badge]: https://img.shields.io/crates/v/{name}.svg?style=for-the-badge 'Crates.io badge'
55 | [divider]: https://via.placeholder.com/1024x1.png/d8dee4/FFFFFF?text=− "{name}'s divider"
56 | [docs-badge]: https://img.shields.io/docsrs/{name}.svg?style=for-the-badge 'Docs.rs badge'
57 | [libs-badge]: https://img.shields.io/badge/lib.rs-v{version}-orange.svg?style=for-the-badge 'Lib.rs badge'
58 | [license-badge]: https://img.shields.io/crates/l/{name}.svg?style=for-the-badge 'License badge'
59 | [made-with-rust-badge]: https://img.shields.io/badge/rust-f04041?style=for-the-badge&labelColor=c0282d&logo=rust 'Made With Rust badge'
60 |
--------------------------------------------------------------------------------
/template/build.tpl:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // Copyright © 2024 {name}. All rights reserved.
4 | // SPDX-License-Identifier: {license}
5 |
6 | //! This is the main function for the build script.
7 | //!
8 | //! Currently, it only instructs Cargo to re-run this build script if `build.rs` is changed.
9 | fn main() {
10 | // Avoid unnecessary re-building.
11 | println!("cargo:rerun-if-changed=build.rs");
12 | }
13 |
--------------------------------------------------------------------------------
/template/criterion.tpl:
--------------------------------------------------------------------------------
1 | //! # Benchmark: libmake
2 | //!
3 | //! This benchmark tests the performance of the `libmake` crate using the Criterion library.
4 | //! It measures the execution time of the `run` function from the `libmake` crate.
5 | //!
6 | //! ## Purpose
7 | //!
8 | //! The purpose of this benchmark is to assess the execution time of the `run` function
9 | //! from the `{name}` crate under controlled conditions. It helps identify any potential
10 | //! performance bottlenecks and allows for optimization if needed.
11 | //!
12 | //! ## Usage
13 | //!
14 | //! To run this benchmark, ensure that you have the `criterion` and `{name}` crates
15 | //! included as dependencies in your project's `Cargo.toml` file.
16 | //!
17 | //! In your project's code, you can use the `criterion_group` and `criterion_main` macros
18 | //! to define and run benchmarks. In this specific benchmark, the `{name}_benchmark` function
19 | //! is defined to measure the execution time of the `run` function.
20 | //!
21 | //! ```rust
22 | //! extern crate criterion;
23 | //! extern crate {name};
24 | //!
25 | //! use criterion::{criterion_group, criterion_main, Criterion};
26 | //! use {name}::run;
27 | //!
28 | //! fn {name}_benchmark(c: &mut Criterion) {
29 | //! c.bench_function("{name}", |b| b.iter(run));
30 | //! }
31 | //!
32 | //! criterion_group!(benches, {name}_benchmark);
33 | //! criterion_main!(benches);
34 | //! ```
35 | //!
36 | //! Running this benchmark will provide performance metrics for the `run` function
37 | //! from the `{name}` crate, helping you evaluate and optimize its performance.
38 |
39 | #![allow(missing_docs)]
40 |
41 | use criterion::{criterion_group, criterion_main, Criterion};
42 | use {name}::run;
43 |
44 | fn {name}_benchmark(c: &mut Criterion) {
45 | c.bench_function("{name}", |b| b.iter(run));
46 | }
47 |
48 | criterion_group!(benches, {name}_benchmark);
49 | criterion_main!(benches);
50 |
--------------------------------------------------------------------------------
/template/deepsource.tpl:
--------------------------------------------------------------------------------
1 | version = 1
2 |
3 | [[analyzers]]
4 | name = "rust"
5 | enabled = true
6 |
7 | [analyzers.meta]
8 | msrv = "stable"
9 |
--------------------------------------------------------------------------------
/template/deny.tpl:
--------------------------------------------------------------------------------
1 | [licenses]
2 | # The lint level for crates which do not have a detectable license
3 | unlicensed = "deny"
4 |
5 | # List of explicitly allowed licenses
6 | # See https://spdx.org/licenses/ for list of possible licenses
7 | # [possible values: any SPDX 3.7 short identifier (+ optional exception)].
8 | allow = [
9 | "Apache-2.0",
10 | "MIT",
11 | "CC0-1.0",
12 | "ISC",
13 | "0BSD",
14 | "BSD-2-Clause",
15 | "BSD-3-Clause",
16 | "Unlicense",
17 | "Unicode-DFS-2016",
18 | ]
19 |
20 | # List of banned licenses
21 | [bans]
22 | multiple-versions = "deny"
23 |
24 |
25 | # The lint level for licenses considered copyleft
26 | copyleft = "deny"
27 |
28 | # Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
29 | # * both - The license will only be approved if it is both OSI-approved *AND* FSF/Free
30 | # * either - The license will be approved if it is either OSI-approved *OR* FSF/Free
31 | # * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF/Free
32 | # * fsf-only - The license will be approved if is FSF/Free *AND NOT* OSI-approved
33 | # * neither - The license will be denied if is FSF/Free *OR* OSI-approved
34 | allow-osi-fsf-free = "either"
35 |
36 | # The confidence threshold for detecting a license from license text.
37 | # The higher the value, the more closely the license text must be to the
38 | # canonical license text of a valid SPDX license file.
39 | # [possible values: any between 0.0 and 1.0].
40 | confidence-threshold = 0.8
41 |
42 | # The graph highlighting used when creating dotgraphs for crates
43 | # with multiple versions
44 | # * lowest-version - The path to the lowest versioned duplicate is highlighted
45 | # * simplest-path - The path to the version with the fewest edges is highlighted
46 | # * all - Both lowest-version and simplest-path are used
47 | highlight = "all"
48 |
49 | # List of crates that are allowed. Use with care!
50 | allow = []
51 |
52 | # List of crates to deny
53 | deny = [
54 | # Each entry the name of a crate and a version range. If version is
55 | # not specified, all versions will be matched.
56 | ]
57 |
58 | # Certain crates/versions that will be skipped when doing duplicate detection.
59 | skip = []
60 |
61 | # Similarly to `skip` allows you to skip certain crates during duplicate detection,
62 | # unlike skip, it also includes the entire tree of transitive dependencies starting at
63 | # the specified crate, up to a certain depth, which is by default infinite
64 | skip-tree = []
65 |
66 |
67 | [advisories]
68 | notice = "deny"
69 | unmaintained = "deny"
70 | unsound = "deny"
71 | vulnerability = "deny"
--------------------------------------------------------------------------------
/template/example.tpl:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // Copyright © 2024 {name}. All rights reserved.
4 | // SPDX-License-Identifier: "MIT OR Apache-2.0"
5 |
6 |
7 | //! This is an example of how to use the `{name}` crate.
8 |
9 | use {name}::{name}_print;
10 |
11 | fn main() {
12 | {name}_print! {
13 | "Hello, world!"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/template/github/workflows/audit.tpl:
--------------------------------------------------------------------------------
1 | name: 🧪 Audit
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - feat/{name}
8 | pull_request:
9 | branches:
10 | - feat/{name}
11 | release:
12 | types: [created]
13 |
14 | jobs:
15 | dependencies:
16 | name: Audit dependencies
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: hecrj/setup-rust-action@v2
20 | - name: Install cargo-audit
21 | run: cargo install cargo-audit
22 |
23 | - uses: actions/checkout@v4
24 | - name: Resolve dependencies
25 | run: cargo update
26 |
27 | - name: Audit vulnerabilities
28 | run: cargo audit
29 |
--------------------------------------------------------------------------------
/template/github/workflows/check.tpl:
--------------------------------------------------------------------------------
1 | name: 🧪 Check
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - feat/{name}
8 | pull_request:
9 | branches:
10 | - feat/{name}
11 | release:
12 | types: [created]
13 |
14 | jobs:
15 | all:
16 | name: Check
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: hecrj/setup-rust-action@v2
20 | with:
21 | components: clippy
22 | - uses: actions/checkout@v4
23 | - name: Check lints
24 | run: cargo check --all-targets --workspace --all-features
25 |
--------------------------------------------------------------------------------
/template/github/workflows/coverage.tpl:
--------------------------------------------------------------------------------
1 | name: 📶 Coverage
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 |
9 | env:
10 | CARGO_TERM_COLOR: always
11 |
12 | jobs:
13 | coverage:
14 | name: Code Coverage
15 | runs-on: ubuntu-latest
16 | env:
17 | CARGO_INCREMENTAL: "0"
18 | RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests"
19 | RUSTDOCFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests"
20 |
21 | steps:
22 | # Checkout the repository
23 | - name: Checkout repository
24 | uses: actions/checkout@v4
25 |
26 | # Setup Rust nightly
27 | - name: Install Rust
28 | uses: actions-rs/toolchain@v1
29 | id: toolchain
30 | with:
31 | toolchain: nightly
32 | override: true
33 |
34 | # Configure cache for Cargo
35 | - name: Cache Cargo registry, index
36 | uses: actions/cache@v4
37 | id: cache-cargo
38 | with:
39 | path: |
40 | ~/.cargo/registry
41 | ~/.cargo/bin
42 | ~/.cargo/git
43 | key: linux-${{ steps.toolchain.outputs.rustc_hash }}-rust-cov-${{ hashFiles('**/Cargo.lock') }}
44 |
45 | # Run tests with all features
46 | - name: Test (cargo test)
47 | uses: actions-rs/cargo@v1
48 | with:
49 | command: test
50 | args: "--workspace"
51 |
52 | # Install grcov
53 | - uses: actions-rs/grcov@v0.1
54 | id: coverage
55 |
56 | # Upload to Codecov.io
57 | - name: Upload to Codecov.io
58 | uses: codecov/codecov-action@v4
59 | with:
60 | token: ${{ secrets.CODECOV_TOKEN }}
61 | file: ${{ steps.coverage.outputs.report }}
62 |
--------------------------------------------------------------------------------
/template/github/workflows/document.tpl:
--------------------------------------------------------------------------------
1 | name: 🧪 Document
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 | release:
11 | types: [created]
12 |
13 | jobs:
14 | all:
15 | name: Document
16 | if: github.ref == 'refs/heads/main' && github.event_name == 'push'
17 | runs-on: ubuntu-latest
18 | concurrency:
19 | group: ${{ github.workflow }}-${{ github.ref }}
20 | steps:
21 | - uses: hecrj/setup-rust-action@v2
22 | with:
23 | rust-version: nightly
24 |
25 | - uses: actions/checkout@v4
26 |
27 | - name: Update libssl
28 | run: |
29 | sudo apt-get update
30 | sudo apt-get install -y libssl1.1
31 |
32 | - name: Generate documentation for all features and publish it
33 | run: |
34 | RUSTDOCFLAGS="--cfg docsrs" \
35 | cargo doc --no-deps --all-features --workspace
36 | # Write index.html with redirect
37 | echo ' ' > ./target/doc/index.html
38 |
39 | - name: Deploy
40 | uses: actions/upload-artifact@v4
41 | with:
42 | name: documentation
43 | path: target/doc
44 | if-no-files-found: error
45 | retention-days: 1
46 |
47 | - name: Write CNAME file
48 | run: echo '{name}.github.io' > ./target/doc/CNAME
49 |
50 | - name: Deploy to GitHub Pages
51 | uses: peaceiris/actions-gh-pages@v4
52 | with:
53 | cname: true
54 | commit_message: Deploy documentation at ${{ github.sha }}
55 | github_token: ${{ secrets.GITHUB_TOKEN }}
56 | publish_branch: gh-pages
57 | publish_dir: ./target/doc
58 | user_email: actions@users.noreply.github.com
59 | user_name: github-actions
60 |
--------------------------------------------------------------------------------
/template/github/workflows/lint.tpl:
--------------------------------------------------------------------------------
1 | name: 🧪 Lint
2 |
3 | on:
4 | push:
5 | branches:
6 | - feat/{name}
7 | pull_request:
8 | branches:
9 | - feat/{name}
10 | release:
11 | types: [created]
12 |
13 | jobs:
14 | all:
15 | name: Lint
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: hecrj/setup-rust-action@v2
19 | with:
20 | components: clippy
21 | - uses: actions/checkout@v4
22 | - name: Check lints
23 | run: cargo clippy --workspace --all-features --all-targets --no-deps -- -D warnings
24 |
--------------------------------------------------------------------------------
/template/github/workflows/test.tpl:
--------------------------------------------------------------------------------
1 | name: 🧪 Test
2 |
3 | on: [pull_request, push]
4 | jobs:
5 | test-lib:
6 | name: Test library
7 | runs-on: ubuntu-latest
8 | strategy:
9 | matrix:
10 | os: [ubuntu-latest]
11 | toolchain: [stable, nightly]
12 | continue-on-error: true
13 |
14 | steps:
15 | # Checkout the repository
16 | - name: Checkout repository
17 | uses: actions/checkout@v4
18 |
19 | # Setup Rust
20 | - name: Setup Rust
21 | run: |
22 | rustup toolchain add ${{ matrix.toolchain }} --component llvm-tools-preview
23 | rustup override set ${{ matrix.toolchain }}
24 |
25 | # Configure cache
26 | - name: Configure cache
27 | uses: actions/cache@v4
28 | with:
29 | path: |
30 | ~/.cargo/bin/
31 | ~/.cargo/registry/index/
32 | ~/.cargo/registry/cache/
33 | ~/.cargo/git/db/
34 | target/
35 | key: test-${{ runner.os }}-cargo-${{ matrix.toolchain }}-${{ hashFiles('**/Cargo.lock') }}
36 |
37 | # Run tests with all features
38 | - name: Run tests with all features
39 | id: run-tests-all-features
40 | run: cargo test --verbose --workspace --all-features
41 |
--------------------------------------------------------------------------------
/template/gitignore.tpl:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | *.profraw
3 | /.vscode/
4 | /output/
5 | /public/
6 | /target/
7 | build
8 | Icon?
9 | src/.DS_Store
10 | tarpaulin-report.html
--------------------------------------------------------------------------------
/template/lib.tpl:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // Copyright © 2024 {name}. All rights reserved.
4 | // SPDX-License-Identifier: {license}
5 | //!
6 | //! # `{name}` 🦀
7 | //!
8 | //! []({website} "{name} - {description}")
9 | //!
10 | //! {description}
11 | //!
12 | //! [](https://crates.io/crates/{name} "Crates.io")
13 | //! [](https://lib.rs/crates/{name} "Lib.rs")
14 | //! []({license} "{license}")
15 | //! [](https://www.rust-lang.org "Rust")
16 | //!
17 | //! ## Overview
18 | //!
19 | //! {description}
20 | //!
21 | //! ## Features
22 | //!
23 | //! - ...
24 | //! - ...
25 | //! - ...
26 | //!
27 | //! ## Usage
28 | //!
29 | //! Add the following to your `Cargo.toml` file:
30 | //!
31 | //! ```toml
32 | //! [dependencies]
33 | //! {name} = {version}
34 | //! serde = { version = "1.0.197", features = ["derive"] }
35 | //! serde_json = "1.0.115"
36 | //! ```
37 | //!
38 | //! ## Examples
39 | //!
40 | //! Check out the examples folder for helpful snippets of code that
41 | //! demonstrate how to use the `{name}` library. You can also check out
42 | //! the [documentation](https://docs.rs/{name}) for more information on
43 | //! how to use the library.
44 | //!
45 | //! ```rust
46 | //! use {name}::{name};
47 | //!
48 | //! ```
49 | //!
50 | //! ## License
51 | //!
52 | //! The project is licensed under the terms of the {license} license.
53 | //!
54 | #![doc(
55 | html_favicon_url = "",
56 | html_logo_url = "",
57 | html_root_url = "https://docs.rs/{name}"
58 | )]
59 | #![crate_name = "{name}"]
60 | #![crate_type = "lib"]
61 |
62 | /// The `macros` module contains functions for generating macros.
63 | pub mod macros;
64 |
65 | use serde::{Deserialize, Serialize};
66 | use std::error::Error;
67 |
68 | #[non_exhaustive]
69 | #[derive(
70 | Clone,
71 | Debug,
72 | Deserialize,
73 | Eq,
74 | Hash,
75 | Ord,
76 | PartialEq,
77 | PartialOrd,
78 | Serialize,
79 | )]
80 |
81 | #[allow(non_camel_case_types)]
82 | /// `{name}` is a data structure that ...
83 | pub struct {name} {
84 | // Add any data fields needed here
85 | }
86 |
87 | /// This is the main entry point for the `{name}` library.
88 | pub fn run() -> Result<(), Box> {
89 | // Add your code here
90 | let name = "{name}";
91 | println!("Hello, {}!", { name }.to_uppercase());
92 | Ok(())
93 | }
94 |
95 |
96 | impl {name} {
97 | /// Creates a new instance of `{name}`
98 | pub fn new() -> Self {
99 | Self {
100 | // Initialize any data fields here
101 | }
102 | }
103 | }
104 |
105 | impl Default for {name} {
106 | /// Creates a new instance of `{name}` with default values
107 | fn default() -> Self {
108 | Self::new()
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/template/macros.tpl:
--------------------------------------------------------------------------------
1 | //! # Macros for the `{name}` crate.
2 | //!
3 | //! This crate provides the following macros:
4 | //!
5 | //! - `{name}`: The main macro for the `{name}` crate.
6 | //! - `{name}_print`: Prints the arguments to the console.
7 | //! - `{name}_vec`: Creates a new vector of the given elements.
8 | //! - `{name}_map`: Creates a new map of the given key-value pairs.
9 | //! - `{name}_assert`: Checks if the given expression is true.
10 | //! - `{name}_min`: Returns the minimum of the given values.
11 | //! - `{name}_max`: Returns the maximum of the given values.
12 | //! - `{name}_split`: Splits a string into a vector of words.
13 | //! - `{name}_join`: Joins a vector of strings into a single string.
14 | //! - `{name}_print_vec`: Prints a vector of elements to the console.
15 | //!
16 |
17 | /// This macro takes any number of arguments and parses them into a
18 | /// Rust value.
19 | #[macro_export]
20 | macro_rules! {name} {
21 | ($($tt:tt)*) => {
22 | // Parse the arguments into a Rust value.
23 | $crate::parse!($($tt)*)
24 | };
25 | }
26 |
27 | /// This macro prints the arguments to the console.
28 | #[macro_export]
29 | macro_rules! {name}_print {
30 | ($($arg:tt)*) => {
31 | println!("{}", format_args!("{}", $($arg)*));
32 | };
33 | }
34 |
35 | /// This macro creates a new vector of the given elements.
36 | #[macro_export]
37 | macro_rules! {name}_vec {
38 | ($($elem:expr),*) => {{
39 | let mut v = Vec::new();
40 | $(v.push($elem);)*
41 | v
42 | }};
43 | }
44 |
45 | /// This macro creates a new map of the given key-value pairs.
46 | #[macro_export]
47 | macro_rules! {name}_map {
48 | ($($key:expr => $value:expr),*) => {{
49 | use std::collections::HashMap;
50 | let mut m = HashMap::new();
51 | $(m.insert($key, $value);)*
52 | m
53 | }};
54 | }
55 |
56 | /// This macro checks if the given expression is true.
57 | #[macro_export]
58 | macro_rules! {name}_assert {
59 | ($($arg:tt)*) => {
60 | if !$($arg)* {
61 | panic!("Assertion failed!");
62 | }
63 | };
64 | }
65 |
66 | /// This macro returns the minimum of the given values.
67 | #[macro_export]
68 | macro_rules! {name}_min {
69 | ($($x:expr),*) => {{
70 | let mut min = $($x)*;
71 | $(if min > $x { min = $x; })*
72 | min
73 | }};
74 | }
75 |
76 | /// This macro returns the maximum of the given values.
77 | #[macro_export]
78 | macro_rules! {name}_max {
79 | ($($x:expr),*) => {{
80 | let mut max = $($x)*;
81 | $(if max < $x { max = $x; })*
82 | max
83 | }};
84 | }
85 |
86 | /// This macro takes a string and splits it into a vector of words.
87 | #[macro_export]
88 | macro_rules! {name}_split {
89 | ($s:expr) => {{
90 | let mut v = Vec::new();
91 | for w in $s.split_whitespace() {
92 | v.push(w.to_string());
93 | }
94 | v
95 | }};
96 | }
97 |
98 | /// This macro takes a vector of strings and joins them together into a
99 | /// single string.
100 | #[macro_export]
101 | macro_rules! {name}_join {
102 | ($($s:expr),*) => {{
103 | let mut s = String::new();
104 | $(
105 | s += &$s;
106 | )*
107 | s
108 | }};
109 | }
110 |
111 | /// This macro takes a vector of elements and prints them to the
112 | /// console.
113 | #[macro_export]
114 | macro_rules! {name}_print_vec {
115 | ($($v:expr),*) => {{
116 | for v in $($v),* {
117 | println!("{}", v);
118 | }
119 | }};
120 | }
121 |
--------------------------------------------------------------------------------
/template/main.tpl:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // Copyright © 2024 {name}. All rights reserved.
4 | // SPDX-License-Identifier: {license}
5 |
6 | //! This crate contains the main entry point for the `{name}` application.
7 |
8 | /// This is the main entry point for the `{name}` application.
9 | fn main() {
10 | // Call the `run()` function from the `{name}` module.
11 | if let Err(err) = {name}::run() {
12 | eprintln!("Error running {name}: {}", err);
13 | std::process::exit(1);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/template/rustfmt.tpl:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright © 2023 {name}. All rights reserved.
2 | # SPDX-License-Identifier: {license}
3 |
4 | # See https://github.com/rust-lang/rustfmt/blob/master/Configurations.md
5 | # for more configuration options
6 |
7 | comment_width = 72 # Maximum line width for comments
8 | doc_comment_code_block_width = 72 # Maximum line width for code blocks in doc comments
9 | edition = "2021" # Use a single edition only (Edition 2018 or Edition 2021)
10 | empty_item_single_line = true # Put empty items on a single line
11 | force_explicit_abi = true # Force explicit abi
12 | format_code_in_doc_comments = true # Format code snippets in doc comments
13 | format_macro_bodies = true # Format macro bodies
14 | format_macro_matchers = true # Format macro matchers
15 | group_imports = "StdExternalCrate" # Group imports by crate
16 | hard_tabs = false # Use spaces instead of tabs
17 | imports_granularity = "Module" # Group imports by module
18 | imports_layout = "HorizontalVertical" # Layout imports horizontally and vertically
19 | max_width = 72 # Maximum line width
20 | merge_derives = true # Merge derives
21 | newline_style = "Unix" # Prevent carriage returns from being added to the end of lines
22 | normalize_comments = true # Normalize comments
23 | normalize_doc_attributes = true # Normalize doc attributes
24 | overflow_delimited_expr = true # Allow overflowing delimited expressions
25 | remove_nested_parens = true # Remove nested parens
26 | reorder_imports = true # Reorder imports
27 | reorder_modules = true # Reorder modules
28 | tab_spaces = 4 # Use 4 spaces for indentation
29 | use_field_init_shorthand = true # Use field initialization shorthand when possible
30 | use_small_heuristics = "Max" # Use max heuristics
31 | use_try_shorthand = true # Use try shorthand when possible
32 | wrap_comments = true # Wrap comments when line width exceeds max max_width
--------------------------------------------------------------------------------
/template/test.tpl:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 |
4 | use {name}::{name};
5 |
6 | #[test]
7 | fn test_{name}() {
8 | let {name} = {name}::new();
9 | assert_eq!({name}, {name}::default());
10 | }
11 | }
--------------------------------------------------------------------------------
/template/test_test.tpl:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 |
4 | use {name}::{name};
5 |
6 | #[test]
7 | fn test_{name}() {
8 | let {name} = {name}::new();
9 | assert_eq!({name}, {name}::default());
10 | }
11 | }
--------------------------------------------------------------------------------
/tests/data/mylibrary.csv:
--------------------------------------------------------------------------------
1 | author,build,categories,description,documentation,edition,email,homepage,keywords,license,name,output,readme,repository,rustversion,version,website
2 | Me,build.rs,"['category 1', 'category 2']",A library for doing things,https://lib.rs/crates/my_library,2021,test@test.com,https://test.com,"['keyword1', 'keyword2']",MIT OR Apache-2.0,my_library,my_library,README.md,https://github.com/test/test,1.60,0.2.6,https://test.com
3 |
--------------------------------------------------------------------------------
/tests/data/mylibrary.ini:
--------------------------------------------------------------------------------
1 | author = "Me"
2 | build = "build.rs"
3 | categories = ["category 1","category 2","category 3"]
4 | description = "A library for doing things"
5 | documentation = "https://lib.rs/crates/my_library"
6 | edition = "2021"
7 | email = "test@test.com"
8 | homepage = "https://test.com"
9 | keywords = ['keyword 1','keyword 2','keyword 3']
10 | license = "MIT OR Apache-2.0"
11 | name = "my_library"
12 | output = "my_library"
13 | readme = "README.md"
14 | repository = "https://github.com/test/test"
15 | rustversion = "1.60"
16 | version = "0.2.6"
17 | website = "https://test.com"
18 |
--------------------------------------------------------------------------------
/tests/data/mylibrary.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "Me",
3 | "build": "build.rs",
4 | "categories": "['category 1','category 2']",
5 | "description": "A library for doing things",
6 | "documentation": "https://lib.rs/crates/my_library",
7 | "edition": "2021",
8 | "email": "test@test.com",
9 | "homepage": "https://test.com",
10 | "keywords": "['keyword1', 'keyword2']",
11 | "license": "MIT OR Apache-2.0",
12 | "name": "my_library",
13 | "output": "my_library",
14 | "readme": "README.md",
15 | "repository": "https://github.com/test/test",
16 | "rustversion": "1.60",
17 | "version": "0.2.6",
18 | "website": "https://test.com"
19 | }
20 |
--------------------------------------------------------------------------------
/tests/data/mylibrary.toml:
--------------------------------------------------------------------------------
1 | author = "Me"
2 | build = "build.rs"
3 | categories = "'category 1','category 2','category 3'"
4 | description = "A library for doing things"
5 | documentation = "https://lib.rs/crates/my_library"
6 | edition = "2021"
7 | email = "test@test.com"
8 | homepage = "https://test.com"
9 | keywords = "'keyword 1','keyword 2','keyword 3'"
10 | license = "MIT OR Apache-2.0"
11 | name = "my_library"
12 | output = "my_library"
13 | readme = "README.md"
14 | repository = "https://github.com/test/test"
15 | rustversion = "1.60"
16 | version = "0.2.6"
17 | website = "https://test.com"
18 |
--------------------------------------------------------------------------------
/tests/data/mylibrary.yaml:
--------------------------------------------------------------------------------
1 | author: Me
2 | build: build.rs
3 | categories: "'category 1','category 2','category 3'"
4 | description: A library for doing things
5 | documentation: https://lib.rs/crates/my_library
6 | edition: '2021'
7 | email: test@test.com
8 | homepage: https://test.com
9 | keywords: "'keyword 1','keyword 2','keyword 3'"
10 | license: 'MIT OR Apache-2.0'
11 | name: my_library
12 | output: my_library
13 | readme: README.md
14 | repository: https://github.com/test/test
15 | rustversion: '1.60'
16 | version: '0.2.6'
17 | website: https://test.com
18 |
--------------------------------------------------------------------------------
/tests/generators/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright notice and licensing information.
2 | // These lines indicate the copyright of the software and its licensing terms.
3 | // SPDX-License-Identifier: Apache-2.0 OR MIT indicates dual licensing under Apache 2.0 or MIT licenses.
4 | // Copyright © 2023-2024 LibMake. All rights reserved.
5 |
6 | /// The `test_ascii` module contains functionality for generating ASCII art from
7 | /// text using the FIGlet library.
8 | pub mod test_ascii;
9 |
10 | /// The `test_args` module contains functionality for parsing command-line arguments.
11 | pub mod test_args;
12 |
13 | /// The `test_csv` module contains functionality for parsing CSV files.
14 | pub mod test_csv;
15 |
16 | /// The `test_ini` module contains functionality for parsing INI files.
17 | pub mod test_ini;
18 |
19 | /// The `test_json` module contains functionality for parsing JSON files.
20 | pub mod test_json;
21 |
22 | /// The `test_toml` module contains functionality for parsing TOML files.
23 | pub mod test_toml;
24 |
25 | /// The `test_yaml` module contains functionality for parsing YAML files.
26 | pub mod test_yaml;
27 |
--------------------------------------------------------------------------------
/tests/generators/test_ascii.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::{
4 | generators::ascii::{generate_ascii_art, load_standard_font},
5 | macro_ascii,
6 | models::error_ascii_art::AsciiArtError,
7 | };
8 |
9 | #[test]
10 | fn test_generate_ascii_art_success() {
11 | let text = "Hello, world!";
12 | let result = generate_ascii_art(text);
13 | assert!(result.is_ok());
14 | let ascii_art = result.unwrap();
15 | assert!(!ascii_art.is_empty());
16 | }
17 |
18 | #[test]
19 | fn test_generate_ascii_art_empty_text() {
20 | let text = "";
21 | let result = generate_ascii_art(text);
22 | assert!(result.is_err());
23 | assert!(matches!(
24 | result.unwrap_err(),
25 | AsciiArtError::ConversionError
26 | ));
27 | }
28 |
29 | #[test]
30 | fn test_load_standard_font_success() {
31 | let result = load_standard_font();
32 | assert!(result.is_ok());
33 | }
34 |
35 | #[test]
36 | fn test_generate_ascii_art_conversion_error() {
37 | let text = "\u{1F600}"; // Emoji character
38 | let result = generate_ascii_art(text);
39 | assert!(result.is_err());
40 | assert!(matches!(
41 | result.unwrap_err(),
42 | AsciiArtError::ConversionError
43 | ));
44 | }
45 |
46 | #[test]
47 | fn test_generate_ascii_art_multiple_lines() {
48 | let text = "Hello,\nworld!";
49 | let result = generate_ascii_art(text);
50 | assert!(result.is_ok());
51 | let ascii_art = result.unwrap();
52 | assert!(ascii_art.contains('\n'));
53 | }
54 |
55 | #[test]
56 | fn test_generate_ascii_art_special_characters() {
57 | let text = "!@#$%^&*()_+";
58 | let result = generate_ascii_art(text);
59 | assert!(result.is_ok());
60 | let ascii_art = result.unwrap();
61 | assert!(!ascii_art.is_empty());
62 | }
63 |
64 | #[test]
65 | fn test_macro_ascii_success() {
66 | let ascii_art = macro_ascii!("Hello, world!");
67 | assert!(!ascii_art.is_empty());
68 | }
69 |
70 | #[test]
71 | #[should_panic(
72 | expected = "Failed to generate ASCII art: Failed to convert text to ASCII art"
73 | )]
74 | fn test_macro_ascii_empty_text() {
75 | let _ = macro_ascii!("");
76 | }
77 |
78 | #[test]
79 | #[should_panic(
80 | expected = "Failed to generate ASCII art: Failed to convert text to ASCII art"
81 | )]
82 | fn test_macro_ascii_conversion_error() {
83 | let _ = macro_ascii!("\u{1F600}"); // Emoji character
84 | }
85 |
86 | #[test]
87 | fn test_macro_ascii_multiple_lines() {
88 | let ascii_art = macro_ascii!("Hello,\nworld!");
89 | assert!(ascii_art.contains('\n'));
90 | }
91 |
92 | #[test]
93 | fn test_macro_ascii_special_characters() {
94 | let ascii_art = macro_ascii!("!@#$%^&*()_+");
95 | assert!(!ascii_art.is_empty());
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/tests/generators/test_csv.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::generators::csv::generate_from_csv;
4 | use std::fs::File;
5 | use std::io::Write;
6 |
7 | #[test]
8 | fn test_generate_from_csv_valid() {
9 | // Create a temporary CSV file
10 | let csv_content = "\
11 | author,build,categories,description,documentation,edition,email,homepage,keywords,license,name,output,readme,repository,rustversion,version,website\n\
12 | John Doe,cargo build,web,Sample project,,2021,john@example.com,https://example.com,example,Rust-1.0,SampleProject,/tmp/output,README.md,https://github.com/example,1.51.0,0.1.0,https://example.com\n";
13 |
14 | let path = "/tmp/test_valid.csv";
15 | let mut file = File::create(path).unwrap();
16 | file.write_all(csv_content.as_bytes()).unwrap();
17 |
18 | // Call the function and check for success
19 | let result = generate_from_csv(path);
20 | assert!(result.is_ok());
21 |
22 | // Clean up
23 | std::fs::remove_file(path).unwrap();
24 | }
25 |
26 | #[test]
27 | fn test_generate_from_csv_invalid_path() {
28 | let result = generate_from_csv("/invalid/path/to/csv");
29 | assert!(result.is_err());
30 | }
31 |
32 | #[test]
33 | fn test_generate_from_csv_malformed_csv() {
34 | // Create a temporary malformed CSV file
35 | let csv_content = "author,build,categories,description,documentation,edition,email,homepage,keywords,license,name,output,readme,repository,rustversion,version,website\n\
36 | John Doe,cargo build,web,Sample project,,2021,john@example.com,https://example.com,example,Rust-1.0,SampleProject,/tmp/output,README.md,https://github.com/example,1.51.0,0.1.0";
37 |
38 | let path = "/tmp/test_malformed.csv";
39 | let mut file = File::create(path).unwrap();
40 | file.write_all(csv_content.as_bytes()).unwrap();
41 |
42 | // Call the function and check for error
43 | let result = generate_from_csv(path);
44 | assert!(result.is_err());
45 |
46 | // Clean up
47 | std::fs::remove_file(path).unwrap();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/generators/test_ini.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::generators::ini::generate_from_ini;
4 | use std::fs::File;
5 | use std::io::Write;
6 | use tempfile::tempdir;
7 |
8 | #[test]
9 | fn test_generate_from_ini_valid_ini() {
10 | let file_path = "./tests/data/mylibrary.ini";
11 | generate_from_ini(file_path).unwrap();
12 | assert_eq!(true, true);
13 | }
14 |
15 | #[test]
16 | fn test_generate_from_ini_file_not_found() {
17 | let result = generate_from_ini("non_existent_file.ini");
18 | assert!(result.is_err());
19 | }
20 |
21 | #[test]
22 | fn test_generate_from_ini_cannot_read() {
23 | let dir = tempdir().unwrap();
24 | let file_path = dir.path().join("test.ini");
25 |
26 | // Create a directory with the same name to cause a read error
27 | std::fs::create_dir(&file_path).unwrap();
28 |
29 | let result = generate_from_ini(file_path.to_str().unwrap());
30 | assert!(result.is_err());
31 | }
32 |
33 | #[test]
34 | fn test_generate_from_ini_invalid_utf8() {
35 | let dir = tempdir().unwrap();
36 | let file_path = dir.path().join("test.ini");
37 |
38 | // Write invalid UTF-8 data to the file
39 | let mut file = File::create(&file_path).unwrap();
40 | file.write_all(&[0x80, 0x81, 0x82]).unwrap();
41 |
42 | let result = generate_from_ini(file_path.to_str().unwrap());
43 | assert!(result.is_err());
44 | }
45 |
46 | #[test]
47 | fn test_generate_from_ini_parse_error() {
48 | let dir = tempdir().unwrap();
49 | let file_path = dir.path().join("test.ini");
50 |
51 | let invalid_ini_data = r#"
52 | [invalid_section]
53 | invalid_field = "invalid_value"
54 | "#;
55 |
56 | let mut file = File::create(&file_path).unwrap();
57 | file.write_all(invalid_ini_data.as_bytes()).unwrap();
58 |
59 | let result = generate_from_ini(file_path.to_str().unwrap());
60 | assert!(result.is_err());
61 | }
62 |
63 | #[test]
64 | fn test_generate_from_ini_generate_files_error() {
65 | // This test assumes that macro_generate_files! returns an error for certain parameters.
66 | // Adjust the test if necessary based on the actual implementation of the macro.
67 | let dir = tempdir().unwrap();
68 | let file_path = dir.path().join("test.ini");
69 |
70 | let ini_data = r#"
71 | [project]
72 | output = "test_output_dir"
73 | "#;
74 |
75 | let mut file = File::create(&file_path).unwrap();
76 | file.write_all(ini_data.as_bytes()).unwrap();
77 |
78 | // Mocking or adjusting the macro_generate_files! to return an error would be necessary.
79 | // This part of the test may require more advanced setup depending on the macro implementation.
80 |
81 | let result = generate_from_ini(file_path.to_str().unwrap());
82 | assert!(result.is_err());
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/tests/generators/test_json.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::generators::json::generate_from_json;
4 | use std::fs::File;
5 | use std::io::Write;
6 | use tempfile::tempdir;
7 |
8 | #[test]
9 | fn test_generate_from_json_success() {
10 | let file_path = "./tests/data/mylibrary.json";
11 | generate_from_json(file_path).unwrap();
12 | assert_eq!(true, true);
13 | }
14 |
15 | #[test]
16 | fn test_generate_from_json_file_not_found() {
17 | let result = generate_from_json("non_existent_file.json");
18 | assert!(result.is_err());
19 | }
20 |
21 | #[test]
22 | fn test_generate_from_json_cannot_read() {
23 | let dir = tempdir().unwrap();
24 | let file_path = dir.path().join("test.json");
25 |
26 | // Create a directory with the same name to cause a read error
27 | std::fs::create_dir(&file_path).unwrap();
28 |
29 | let result = generate_from_json(file_path.to_str().unwrap());
30 | assert!(result.is_err());
31 | }
32 |
33 | #[test]
34 | fn test_generate_from_json_invalid_utf8() {
35 | let dir = tempdir().unwrap();
36 | let file_path = dir.path().join("test.json");
37 |
38 | // Write invalid UTF-8 data to the file
39 | let mut file = File::create(&file_path).unwrap();
40 | file.write_all(&[0x80, 0x81, 0x82]).unwrap();
41 |
42 | let result = generate_from_json(file_path.to_str().unwrap());
43 | assert!(result.is_err());
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/tests/generators/test_toml.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::generators::toml::generate_from_toml;
4 | use std::fs::File;
5 | use std::io::Write;
6 | use tempfile::tempdir;
7 |
8 | #[test]
9 | fn test_generate_from_toml_success() {
10 | let file_path = "./tests/data/mylibrary.toml";
11 | generate_from_toml(file_path).unwrap();
12 | assert_eq!(true, true);
13 | }
14 |
15 | #[test]
16 | fn test_generate_from_toml_file_not_found() {
17 | let result = generate_from_toml("non_existent_file.toml");
18 | assert!(result.is_err());
19 | }
20 |
21 | #[test]
22 | fn test_generate_from_toml_cannot_read() {
23 | let dir = tempdir().unwrap();
24 | let file_path = dir.path().join("test.toml");
25 |
26 | // Create a directory with the same name to cause a read error
27 | std::fs::create_dir(&file_path).unwrap();
28 |
29 | let result = generate_from_toml(file_path.to_str().unwrap());
30 | assert!(result.is_err());
31 | }
32 |
33 | #[test]
34 | fn test_generate_from_toml_invalid_utf8() {
35 | let dir = tempdir().unwrap();
36 | let file_path = dir.path().join("test.toml");
37 |
38 | // Write invalid UTF-8 data to the file
39 | let mut file = File::create(&file_path).unwrap();
40 | file.write_all(&[0x80, 0x81, 0x82]).unwrap();
41 |
42 | let result = generate_from_toml(file_path.to_str().unwrap());
43 | assert!(result.is_err());
44 | }
45 |
46 | #[test]
47 | fn test_generate_from_toml_deserialize_error() {
48 | let dir = tempdir().unwrap();
49 | let file_path = dir.path().join("test.toml");
50 |
51 | let invalid_toml_data = r#"
52 | invalid_field = "invalid_value"
53 | "#;
54 |
55 | let mut file = File::create(&file_path).unwrap();
56 | file.write_all(invalid_toml_data.as_bytes()).unwrap();
57 |
58 | let result = generate_from_toml(file_path.to_str().unwrap());
59 | assert!(result.is_err());
60 | }
61 |
62 | #[test]
63 | fn test_generate_from_toml_generate_files_error() {
64 | // This test assumes that macro_generate_files! returns an error for certain parameters.
65 | // Adjust the test if necessary based on the actual implementation of the macro.
66 | let dir = tempdir().unwrap();
67 | let file_path = dir.path().join("test.toml");
68 |
69 | let toml_data = r#"
70 | output = "test_output_dir"
71 | "#;
72 |
73 | let mut file = File::create(&file_path).unwrap();
74 | file.write_all(toml_data.as_bytes()).unwrap();
75 |
76 | // Mocking or adjusting the macro_generate_files! to return an error would be necessary.
77 | // This part of the test may require more advanced setup depending on the macro implementation.
78 |
79 | let result = generate_from_toml(file_path.to_str().unwrap());
80 | assert!(result.is_err());
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/tests/generators/test_yaml.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::generators::yaml::generate_from_yaml;
4 | use std::io::Write;
5 | use std::fs::File;
6 | use tempfile::tempdir;
7 |
8 | #[test]
9 | fn test_generate_from_yaml_success() {
10 | let file_path = "./tests/data/mylibrary.yaml";
11 | generate_from_yaml(file_path).unwrap();
12 | assert_eq!(true, true);
13 | }
14 |
15 | #[test]
16 | fn test_generate_from_yaml_file_not_found() {
17 | let result = generate_from_yaml("non_existent_file.yaml");
18 | assert!(result.is_err());
19 | }
20 |
21 | #[test]
22 | fn test_generate_from_yaml_cannot_read() {
23 | let dir = tempdir().unwrap();
24 | let file_path = dir.path().join("test.yaml");
25 |
26 | // Create a directory with the same name to cause a read error
27 | std::fs::create_dir(&file_path).unwrap();
28 |
29 | let result = generate_from_yaml(file_path.to_str().unwrap());
30 | assert!(result.is_err());
31 | }
32 |
33 | #[test]
34 | fn test_generate_from_yaml_invalid_utf8() {
35 | let dir = tempdir().unwrap();
36 | let file_path = dir.path().join("test.yaml");
37 |
38 | // Write invalid UTF-8 data to the file
39 | let mut file = File::create(&file_path).unwrap();
40 | file.write_all(&[0x80, 0x81, 0x82]).unwrap();
41 |
42 | let result = generate_from_yaml(file_path.to_str().unwrap());
43 | assert!(result.is_err());
44 | }
45 |
46 | #[test]
47 | fn test_generate_from_yaml_deserialize_error() {
48 | let dir = tempdir().unwrap();
49 | let file_path = dir.path().join("test.yaml");
50 |
51 | let invalid_yaml_data = r#"
52 | invalid_field: invalid_value
53 | "#;
54 |
55 | let mut file = File::create(&file_path).unwrap();
56 | file.write_all(invalid_yaml_data.as_bytes()).unwrap();
57 |
58 | let result = generate_from_yaml(file_path.to_str().unwrap());
59 | assert!(result.is_err());
60 | }
61 |
62 | #[test]
63 | fn test_generate_from_yaml_generate_files_error() {
64 | // This test assumes that macro_generate_files! returns an error for certain parameters.
65 | // Adjust the test if necessary based on the actual implementation of the macro.
66 | let dir = tempdir().unwrap();
67 | let file_path = dir.path().join("test.yaml");
68 |
69 | let yaml_data = r#"
70 | output: test_output_dir
71 | "#;
72 |
73 | let mut file = File::create(&file_path).unwrap();
74 | file.write_all(yaml_data.as_bytes()).unwrap();
75 |
76 | // Mocking or adjusting the macro_generate_files! to return an error would be necessary.
77 | // This part of the test may require more advanced setup depending on the macro implementation.
78 |
79 | let result = generate_from_yaml(file_path.to_str().unwrap());
80 | assert!(result.is_err());
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/tests/macros/mod.rs:
--------------------------------------------------------------------------------
1 | /// The `test_ascii_macros` module contains tests for the ascii_macros module.
2 | pub mod test_ascii_macros;
3 |
4 | /// The `test_directory_macros` module contains tests for the directory_macros module.
5 | pub mod test_directory_macros;
6 |
7 | /// The `test_file_macros` module contains tests for the file_macros module.
8 | pub mod test_file_macros;
9 |
10 | /// The `test_generator_macros` module contains tests for the generator_macros module.
11 | pub mod test_generator_macros;
12 |
13 | /// The `test_log_macros` module contains tests for the log_macros module.
14 | pub mod test_log_macros;
15 |
16 | /// The `test_utility_macros` module contains tests for the utility_macros module.
17 | pub mod test_utility_macros;
18 |
--------------------------------------------------------------------------------
/tests/macros/test_ascii_macros.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::macro_ascii;
4 |
5 | #[test]
6 | fn test_macro_ascii_success() {
7 | let art = macro_ascii!("Hi");
8 | assert_eq!(art, " _ _ _ \n | | | | (_)\n | |_| | | |\n | _ | | |\n |_| |_| |_|\n \n");
9 | }
10 |
11 | #[test]
12 | #[should_panic(
13 | expected = "Failed to generate ASCII art: Failed to convert text to ASCII art"
14 | )]
15 | fn test_macro_ascii_empty_input() {
16 | let _art = macro_ascii!("");
17 | }
18 |
19 | #[test]
20 | #[should_panic(
21 | expected = "Failed to generate ASCII art: Failed to convert text to ASCII art"
22 | )]
23 | fn test_macro_ascii_invalid_input() {
24 | let _art = macro_ascii!("🦀");
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/macros/test_directory_macros.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::{
4 | macro_check_directory, macro_cleanup_directories,
5 | macro_create_directories,
6 | };
7 | use std::fs;
8 | use std::path::Path;
9 | use tempfile::tempdir;
10 |
11 | #[test]
12 | fn test_macro_check_directory() {
13 | let temp_dir = tempdir().unwrap();
14 | let path = temp_dir.path().join("logs");
15 |
16 | // Test creating a new directory
17 | macro_check_directory!(&path, "logs");
18 | assert!(path.exists() && path.is_dir());
19 |
20 | // Test directory already exists
21 | macro_check_directory!(&path, "logs");
22 | assert!(path.exists() && path.is_dir());
23 | }
24 |
25 | #[test]
26 | fn test_macro_create_directories() {
27 | let temp_dir = tempdir().unwrap();
28 | let path1 = temp_dir.path().join("logs1");
29 | let path2 = temp_dir.path().join("logs2");
30 |
31 | // Test creating multiple directories
32 | macro_create_directories!(&path1, &path2).unwrap();
33 | assert!(path1.exists() && path1.is_dir());
34 | assert!(path2.exists() && path2.is_dir());
35 | }
36 |
37 | #[test]
38 | fn test_macro_cleanup_directories() {
39 | let temp_dir = tempdir().unwrap();
40 | let path1 = temp_dir.path().join("logs1");
41 | let path2 = temp_dir.path().join("logs2");
42 |
43 | // Create directories to clean up
44 | fs::create_dir_all(&path1).unwrap();
45 | fs::create_dir_all(&path2).unwrap();
46 |
47 | // Test cleaning up directories
48 | macro_cleanup_directories!(&path1, &path2);
49 | assert!(!path1.exists());
50 | assert!(!path2.exists());
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/macros/test_file_macros.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::generate_file;
4 | use std::cell::RefCell;
5 |
6 | // Mock generator function
7 | fn mock_generator_success(_: &str) -> Result<(), String> {
8 | Ok(())
9 | }
10 |
11 | // Mock generator function that returns an error
12 | fn mock_generator_error(_: &str) -> Result<(), String> {
13 | Err("Mock error".to_string())
14 | }
15 |
16 | thread_local! {
17 | static LAST_ERROR: RefCell> = const { RefCell::new(None) };
18 | }
19 |
20 | // Mock eprintln! macro to capture the error messages
21 | macro_rules! eprintln {
22 | ($($arg:tt)*) => {
23 | LAST_ERROR.with(|last_error| {
24 | *last_error.borrow_mut() = Some(format!($($arg)*));
25 | });
26 | };
27 | }
28 |
29 | #[test]
30 | fn test_generate_file_success() {
31 | generate_file!(
32 | "test",
33 | "non_empty_value",
34 | mock_generator_success
35 | );
36 | LAST_ERROR.with(|last_error| {
37 | assert!(last_error.borrow().is_none());
38 | });
39 | }
40 |
41 | #[test]
42 | fn test_generate_file_empty_value() {
43 | generate_file!("test", "", mock_generator_success);
44 | LAST_ERROR.with(|last_error| {
45 | assert!(last_error.borrow().is_none());
46 | });
47 | }
48 |
49 | #[test]
50 | fn test_generate_file_error() {
51 | generate_file!("test", "non_empty_value", mock_generator_error);
52 | LAST_ERROR.with(|last_error| {
53 | assert_eq!(
54 | *last_error.borrow(),
55 | Some(
56 | "Error generating test file: Mock error"
57 | .to_string()
58 | )
59 | );
60 | });
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/tests/macros/test_generator_macros.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 |
4 | use libmake::models::model_params::FileGenerationParams;
5 | use std::path::Path;
6 |
7 | use libmake::macro_create_directories;
8 |
9 | use libmake::{
10 | macro_generate_files, macro_generate_from_config,
11 | macro_generate_from_csv, macro_generate_from_json,
12 | macro_generate_from_yaml,
13 | };
14 |
15 | // Unit test for the `create_directory()` function.
16 | #[test]
17 | fn test_create_directory() {
18 | let result = macro_create_directories!("my_library");
19 | match result {
20 | Ok(()) => println!("Directory created successfully!"),
21 | Err(err) => println!("Error creating directory: {}", err),
22 | }
23 | }
24 | // Unit test for the `generate_files()` function.
25 | #[test]
26 | #[allow(clippy::redundant_clone)]
27 | fn test_generate_files() -> Result<(), String> {
28 | let mut params = FileGenerationParams::new();
29 | params.output = Some("my_library".into());
30 | macro_generate_files!(params.clone())?;
31 | Ok(())
32 | }
33 | // Unit test for the `generate_from_csv()` function.
34 | #[test]
35 | fn test_generate_from_csv() -> Result<(), String> {
36 | macro_generate_from_csv!("./tests/data/mylibrary.csv")?;
37 | Ok(())
38 | }
39 | // Unit test for the `generate_from_json()` function.
40 | #[test]
41 | fn test_generate_from_json() -> Result<(), String> {
42 | macro_generate_from_json!("./tests/data/mylibrary.json")?;
43 | Ok(())
44 | }
45 | // Unit test for the `generate_from_yaml()` function.
46 | #[test]
47 | fn test_generate_from_yaml() -> Result<(), String> {
48 | macro_generate_from_yaml!("./tests/data/mylibrary.yaml")?;
49 | Ok(())
50 | }
51 | // Unit test for the `generate_from_config()` function.
52 | #[test]
53 | fn test_generate_from_config() -> Result<(), String> {
54 | macro_generate_from_config!(
55 | "./tests/data/mylibrary.yaml",
56 | "yaml"
57 | )?;
58 | Ok(())
59 | }
60 | // Unit test for the `macro_create_directories!()` macro.
61 | #[test]
62 | fn test_macro_create_directories() {
63 | let result = macro_create_directories!("./target/tmp");
64 | match result {
65 | Ok(()) => println!("Directory created successfully!"),
66 | Err(err) => println!("Error creating directory: {}", err),
67 | }
68 | let _ = std::fs::remove_dir_all("./target/tmp");
69 | }
70 | // Unit test for the `macro_generate_from_csv!()` macro.
71 | #[test]
72 | fn test_macro_generate_from_csv() -> Result<(), String> {
73 | macro_generate_from_csv!("./tests/data/mylibrary.csv")?;
74 | assert!(Path::new("my_library").exists());
75 | Ok(())
76 | }
77 | // Unit test for the `macro_generate_from_json!()` macro.
78 | #[test]
79 | fn test_macro_generate_from_json() -> Result<(), String> {
80 | macro_generate_from_json!("./tests/data/mylibrary.json")?;
81 | assert!(Path::new("my_library").exists());
82 | Ok(())
83 | }
84 | // Unit test for the `macro_generate_from_yaml!()` macro.
85 | #[test]
86 | fn test_macro_generate_from_yaml() -> Result<(), String> {
87 | macro_generate_from_yaml!("./tests/data/mylibrary.yaml")?;
88 | assert!(Path::new("my_library").exists());
89 | Ok(())
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/tests/macros/test_log_macros.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::macro_log_info;
4 |
5 | struct DateTime {
6 | iso_8601: String,
7 | }
8 |
9 | impl DateTime {
10 | fn new() -> Self {
11 | DateTime {
12 | iso_8601: "2024-05-15T12:34:56Z".to_string(),
13 | }
14 | }
15 | }
16 |
17 | struct Random;
18 |
19 | impl Random {
20 | fn default() -> Self {
21 | Random
22 | }
23 |
24 | fn rand(&mut self) -> u64 {
25 | 42 // Mock random number generator returns a fixed value
26 | }
27 | }
28 |
29 | struct Log {
30 | session_id: String,
31 | iso_8601: String,
32 | level: String,
33 | component: String,
34 | description: String,
35 | format: String,
36 | }
37 |
38 | impl Log {
39 | fn new(
40 | session_id: &str,
41 | iso_8601: &str,
42 | level: &str,
43 | component: &str,
44 | description: &str,
45 | format: &str,
46 | ) -> Self {
47 | Log {
48 | session_id: session_id.to_string(),
49 | iso_8601: iso_8601.to_string(),
50 | level: level.to_string(),
51 | component: component.to_string(),
52 | description: description.to_string(),
53 | format: format.to_string(),
54 | }
55 | }
56 | }
57 |
58 | #[test]
59 | fn test_macro_log_info() {
60 | let log = macro_log_info!(
61 | "INFO",
62 | "TestComponent",
63 | "This is a test log",
64 | "TestFormat"
65 | );
66 |
67 | assert_eq!(log.session_id, "42");
68 | assert_eq!(log.iso_8601, "2024-05-15T12:34:56Z");
69 | assert_eq!(log.level, "INFO");
70 | assert_eq!(log.component, "TestComponent");
71 | assert_eq!(log.description, "This is a test log");
72 | assert_eq!(log.format, "TestFormat");
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tests/macros/test_utility_macros.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::macro_get_field;
4 | use serde_json::from_reader;
5 | use std::env;
6 | use std::fs::File;
7 | use std::io::Write;
8 | use std::path::Path;
9 | use tempfile::tempdir;
10 |
11 | fn read_file(
12 | file_path: &Path,
13 | f: F,
14 | ) -> Result>
15 | where
16 | F: FnOnce(File) -> Result>,
17 | {
18 | let file = File::open(file_path)?;
19 | f(file)
20 | }
21 |
22 | macro_get_field!(get_field, from_reader);
23 |
24 | #[test]
25 | fn test_macro_get_field_success() {
26 | let dir = tempdir().unwrap();
27 | let file_path = dir.path().join("test.json");
28 |
29 | let json_data = r#"
30 | {
31 | "name": "Alice",
32 | "age": 30
33 | }
34 | "#;
35 |
36 | let mut file = File::create(&file_path).unwrap();
37 | file.write_all(json_data.as_bytes()).unwrap();
38 |
39 | let result =
40 | get_field(Some(file_path.to_str().unwrap()), "name");
41 | assert_eq!(result.unwrap(), "Alice");
42 |
43 | let result =
44 | get_field(Some(file_path.to_str().unwrap()), "age");
45 | assert_eq!(result.unwrap(), "30");
46 | }
47 |
48 | #[test]
49 | fn test_macro_get_field_field_not_found() {
50 | let dir = tempdir().unwrap();
51 | let file_path = dir.path().join("test.json");
52 |
53 | let json_data = r#"
54 | {
55 | "name": "Alice",
56 | "age": 30
57 | }
58 | "#;
59 |
60 | let mut file = File::create(&file_path).unwrap();
61 | file.write_all(json_data.as_bytes()).unwrap();
62 |
63 | let result =
64 | get_field(Some(file_path.to_str().unwrap()), "address");
65 | assert!(result.is_err());
66 | assert_eq!(
67 | result.unwrap_err().to_string(),
68 | "Field 'address' not found"
69 | );
70 | }
71 |
72 | #[test]
73 | fn test_macro_get_field_no_file_path() {
74 | let result = get_field(None, "name");
75 | assert!(result.is_ok());
76 | assert_eq!(result.unwrap(), "");
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/tests/mod.rs:
--------------------------------------------------------------------------------
1 | /// This module contains the tests for the `macros` module.
2 | pub mod macros;
3 |
4 | /// This module contains the tests for the `models` module.
5 | pub mod models;
6 |
--------------------------------------------------------------------------------
/tests/models/mod.rs:
--------------------------------------------------------------------------------
1 | /// The `test_error_ascii_art` module contains tests for the error_ascii_art module.
2 | pub mod test_error_ascii_art;
3 |
4 | /// The `test_model_params` module contains tests for the model_params module.
5 | pub mod test_model_params;
6 |
--------------------------------------------------------------------------------
/tests/models/test_error_ascii_art.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::models::error_ascii_art::AsciiArtError;
4 | use std::error::Error;
5 |
6 | #[test]
7 | fn test_ascii_art_error_font_load_error() {
8 | let error = AsciiArtError::FontLoadError;
9 | assert_eq!(error.to_string(), "Failed to load FIGfont");
10 | }
11 |
12 | #[test]
13 | fn test_ascii_art_error_conversion_error() {
14 | let error = AsciiArtError::ConversionError;
15 | assert_eq!(
16 | error.to_string(),
17 | "Failed to convert text to ASCII art"
18 | );
19 | }
20 |
21 | #[test]
22 | fn test_ascii_art_error_partial_eq() {
23 | let error1 = AsciiArtError::FontLoadError;
24 | let error2 = AsciiArtError::FontLoadError;
25 | let error3 = AsciiArtError::ConversionError;
26 | assert_eq!(error1, error2);
27 | assert_ne!(error1, error3);
28 | }
29 |
30 | #[test]
31 | fn test_ascii_art_error_source() {
32 | let error = AsciiArtError::FontLoadError;
33 | assert!(error.source().is_none());
34 | }
35 |
36 | #[test]
37 | fn test_ascii_art_error_debug() {
38 | let error = AsciiArtError::FontLoadError;
39 | let debug_output = format!("{:?}", error);
40 | assert_eq!(debug_output, "FontLoadError");
41 | }
42 |
43 | #[test]
44 | fn test_ascii_art_error_clone() {
45 | let error = AsciiArtError::FontLoadError;
46 | let cloned_error = error;
47 | assert_eq!(error, cloned_error);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/models/test_model_params.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::models::model_params::FileGenerationParams;
4 |
5 | #[test]
6 | fn test_file_generation_params_default() {
7 | let params = FileGenerationParams::default_params();
8 | assert_eq!(params.author, Some("John Smith".to_string()));
9 | assert_eq!(params.build, Some("build.rs".to_string()));
10 | assert_eq!(
11 | params.categories,
12 | Some(
13 | "[\"category1\",\"category2\",\"category3\"]"
14 | .to_string()
15 | )
16 | );
17 | assert_eq!(
18 | params.description,
19 | Some("A Rust library for doing cool things".to_string())
20 | );
21 | assert_eq!(
22 | params.documentation,
23 | Some("https://docs.rs/my_library".to_string())
24 | );
25 | assert_eq!(params.edition, Some("2021".to_string()));
26 | assert_eq!(
27 | params.email,
28 | Some("john.smith@example.com".to_string())
29 | );
30 | assert_eq!(
31 | params.homepage,
32 | Some("https://my_library.rs".to_string())
33 | );
34 | assert_eq!(
35 | params.keywords,
36 | Some("[\"rust\",\"library\",\"cool\"]".to_string())
37 | );
38 | assert_eq!(params.license, Some("MIT".to_string()));
39 | assert_eq!(params.name, Some("my_library".to_string()));
40 | assert_eq!(params.output, Some("my_library".to_string()));
41 | assert_eq!(params.readme, Some("README.md".to_string()));
42 | assert_eq!(
43 | params.repository,
44 | Some("https://github.com/example/my_library".to_string())
45 | );
46 | assert_eq!(params.rustversion, Some("1.60".to_string()));
47 | assert_eq!(params.version, Some("0.1.0".to_string()));
48 | assert_eq!(
49 | params.website,
50 | Some("https://example.com/john-smith".to_string())
51 | );
52 | }
53 |
54 | #[test]
55 | fn test_file_generation_params_new() {
56 | let params = FileGenerationParams::new();
57 | assert_eq!(params.author, Some("John Smith".to_string()));
58 | assert_eq!(params.build, Some("build.rs".to_string()));
59 | assert_eq!(
60 | params.categories,
61 | Some(
62 | "[\"category1\",\"category2\",\"category3\"]"
63 | .to_string()
64 | )
65 | );
66 | assert_eq!(
67 | params.description,
68 | Some("A Rust library for doing cool things".to_string())
69 | );
70 | assert_eq!(
71 | params.documentation,
72 | Some("https://docs.rs/my_library".to_string())
73 | );
74 | assert_eq!(params.edition, Some("2021".to_string()));
75 | assert_eq!(
76 | params.email,
77 | Some("john.smith@example.com".to_string())
78 | );
79 | assert_eq!(
80 | params.homepage,
81 | Some("https://my_library.rs".to_string())
82 | );
83 | assert_eq!(
84 | params.keywords,
85 | Some("[\"rust\",\"library\",\"cool\"]".to_string())
86 | );
87 | assert_eq!(params.license, Some("MIT".to_string()));
88 | assert_eq!(params.name, Some("my_library".to_string()));
89 | assert_eq!(params.output, Some("my_library".to_string()));
90 | assert_eq!(params.readme, Some("README.md".to_string()));
91 | assert_eq!(
92 | params.repository,
93 | Some("https://github.com/example/my_library".to_string())
94 | );
95 | assert_eq!(params.rustversion, Some("1.60".to_string()));
96 | assert_eq!(params.version, Some("0.1.0".to_string()));
97 | assert_eq!(
98 | params.website,
99 | Some("https://example.com/john-smith".to_string())
100 | );
101 | }
102 |
103 | #[test]
104 | fn test_file_generation_params_from_args_missing_arg_name() {
105 | let args_str = "\"Jane Doe\" --email \"jane.doe@example.com\"";
106 | let result = FileGenerationParams::from_args(args_str);
107 | assert!(result.is_err());
108 | assert_eq!(
109 | result.unwrap_err(),
110 | "Missing argument value".to_string()
111 | );
112 | }
113 |
114 | #[test]
115 | fn test_file_generation_params_from_args_missing_arg_value() {
116 | let args_str = "--author \"Jane Doe\" --email";
117 | let result = FileGenerationParams::from_args(args_str);
118 | assert!(result.is_err());
119 | assert_eq!(
120 | result.unwrap_err(),
121 | "Missing argument value".to_string()
122 | );
123 | }
124 |
125 | #[test]
126 | fn test_deserialize_name() {
127 | let name = "\"my_project\"";
128 | let deserialized_name: Option =
129 | serde_json::from_str(name).unwrap();
130 | assert_eq!(deserialized_name, Some("my_project".to_string()));
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/tests/test_cli.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::cli::{build, create_arg};
4 |
5 | #[test]
6 | fn test_build_manual_subcommand() {
7 | let matches = build();
8 | assert!(matches.is_ok());
9 | }
10 |
11 | #[test]
12 | fn test_create_arg() {
13 | // Test case 1: Create an argument with all fields
14 | let arg_info = (
15 | "name",
16 | Some("default"),
17 | "help message",
18 | 'n',
19 | "name",
20 | "NAME",
21 | );
22 | let arg = create_arg(arg_info);
23 | assert_eq!(arg.get_id(), "name");
24 | assert_eq!(arg.get_help().unwrap().to_string(), "help message");
25 | assert_eq!(arg.get_short().unwrap(), 'n');
26 | assert_eq!(arg.get_long().unwrap(), "name");
27 |
28 | // Test case 2: Create an argument without a default value
29 | let arg_info =
30 | ("name", None, "help message", 'n', "name", "NAME");
31 | let arg = create_arg(arg_info);
32 | assert_eq!(arg.get_id(), "name");
33 | assert_eq!(arg.get_help().unwrap().to_string(), "help message");
34 | assert_eq!(arg.get_short().unwrap(), 'n');
35 | assert_eq!(arg.get_long().unwrap(), "name");
36 |
37 | // Test case 3: Create an argument with only required fields
38 | let arg_info = ("name", None, "", 'n', "name", "NAME");
39 | let arg = create_arg(arg_info);
40 | assert_eq!(arg.get_id(), "name");
41 | assert_eq!(arg.get_short().unwrap(), 'n');
42 | assert_eq!(arg.get_long().unwrap(), "name");
43 |
44 | // Test case 4: Create an argument with a multi-word long flag
45 | let arg_info =
46 | ("name", None, "help message", 'n', "long-flag", "NAME");
47 | let arg = create_arg(arg_info);
48 | assert_eq!(arg.get_long().unwrap(), "long-flag");
49 |
50 | // Test case 5: Argument with an empty help message
51 | let arg_info = (
52 | "name", None, "", // Empty help message
53 | 'n', "name", "NAME",
54 | );
55 | let arg = create_arg(arg_info);
56 |
57 | // Updated assertion
58 | assert!(arg.get_help().is_some()); // Help should be set, even if empty
59 |
60 | // Optionally, depending on the implementation of StyledStr:
61 | assert_eq!(arg.get_help().unwrap().to_string(), ""); // Check if the help string is indeed empty
62 |
63 | // Test case 6: Long argument name
64 | let arg_info = (
65 | "very-long-argument-name",
66 | None,
67 | "help",
68 | 'v',
69 | "very-long-argument-name",
70 | "NAME",
71 | );
72 | let arg = create_arg(arg_info);
73 | assert_eq!(arg.get_id(), "very-long-argument-name");
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/tests/test_utils.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 |
4 | use libmake::utils::{
5 | get_config_field, get_csv_field, get_json_field, get_yaml_field,
6 | };
7 | // Unit test for the `get_csv_field()` function.
8 | #[test]
9 | fn test_get_csv_field() {
10 | let file_path = "./tests/data/mylibrary.csv";
11 |
12 | // Test with valid field index
13 | let field_index = 0;
14 | let expected_value = Some(vec!["Me".to_string()]);
15 | let actual_value = get_csv_field(Some(file_path), field_index);
16 | assert_eq!(expected_value, actual_value);
17 |
18 | // Test with invalid field index
19 | let field_index = 100;
20 | let expected_value = None;
21 | let actual_value = get_csv_field(Some(file_path), field_index);
22 | assert_eq!(expected_value, actual_value);
23 | }
24 |
25 | // Unit test for the `get_csv_fields()` function.
26 | #[test]
27 | fn test_get_csv_fields() {
28 | let file_path = "./tests/data/mylibrary.csv";
29 |
30 | // Test the function with various input values
31 | assert_eq!(
32 | get_csv_field(Some(file_path), 0),
33 | Some(vec!["Me".to_string()])
34 | );
35 | print!("{:?}", get_csv_field(Some(file_path), 0));
36 | assert_eq!(
37 | get_csv_field(Some(file_path), 1),
38 | Some(vec!["build.rs".to_string()])
39 | );
40 | assert_eq!(
41 | get_csv_field(Some(file_path), 2),
42 | Some(vec!["['category 1', 'category 2']".to_string()])
43 | );
44 | assert_eq!(
45 | get_csv_field(Some(file_path), 3),
46 | Some(vec!["A library for doing things".to_string()])
47 | );
48 | assert_eq!(
49 | get_csv_field(Some(file_path), 4),
50 | Some(vec!["https://lib.rs/crates/my_library".to_string()])
51 | );
52 | assert_eq!(
53 | get_csv_field(Some(file_path), 5),
54 | Some(vec!["2021".to_string()])
55 | );
56 | assert_eq!(
57 | get_csv_field(Some(file_path), 6),
58 | Some(vec!["test@test.com".to_string()])
59 | );
60 | assert_eq!(
61 | get_csv_field(Some(file_path), 7),
62 | Some(vec!["https://test.com".to_string()])
63 | );
64 | assert_eq!(
65 | get_csv_field(Some(file_path), 8),
66 | Some(vec!["['keyword1', 'keyword2']".to_string()])
67 | );
68 | assert_eq!(
69 | get_csv_field(Some(file_path), 9),
70 | Some(vec!["MIT OR Apache-2.0".to_string()])
71 | );
72 | assert_eq!(
73 | get_csv_field(Some(file_path), 10),
74 | Some(vec!["my_library".to_string()])
75 | );
76 | assert_eq!(
77 | get_csv_field(Some(file_path), 11),
78 | Some(vec!["my_library".to_string()])
79 | );
80 | assert_eq!(
81 | get_csv_field(Some(file_path), 12),
82 | Some(vec!["README.md".to_string()])
83 | );
84 | assert_eq!(
85 | get_csv_field(Some(file_path), 13),
86 | Some(vec!["https://github.com/test/test".to_string()])
87 | );
88 | assert_eq!(
89 | get_csv_field(Some(file_path), 14),
90 | Some(vec!["1.60".to_string()])
91 | );
92 | assert_eq!(
93 | get_csv_field(Some(file_path), 15),
94 | Some(vec!["0.2.6".to_string()])
95 | );
96 | assert_eq!(
97 | get_csv_field(Some(file_path), 16),
98 | Some(vec!["https://test.com".to_string()])
99 | );
100 | }
101 |
102 | // Unit test for the `get_json_field()` function.
103 | #[test]
104 | fn test_get_json_field_existing() {
105 | let file_path = Some("./tests/data/mylibrary.json");
106 | let field_name = "name";
107 | let expected_value = Ok("my_library".to_string());
108 | let actual_value = get_json_field(file_path, field_name)
109 | .map_err(|err| err.to_string());
110 | assert_eq!(expected_value, actual_value);
111 | }
112 |
113 | // Unit test for the `get_yaml_field()` function.
114 | #[test]
115 | fn test_get_yaml_field_existing() {
116 | let file_path = Some("./tests/data/mylibrary.yaml");
117 | let field_name = "description";
118 | let expected_value =
119 | Ok("A library for doing things".to_string());
120 | let actual_value = get_yaml_field(file_path, field_name)
121 | .map_err(|err| err.to_string());
122 | assert_eq!(expected_value, actual_value);
123 | }
124 |
125 | // Unit test for the `get_config_field()` function.
126 | // Unit test for the `get_config_field()` function.
127 | #[test]
128 | fn test_get_config_field_existing() {
129 | let file_path = Some("./tests/data/mylibrary.yaml");
130 | let field_name = "license";
131 | let expected_value = "MIT OR Apache-2.0";
132 | let actual_yaml_value =
133 | get_config_field(file_path, Some("yaml"), field_name)
134 | .unwrap_or_else(|_| {
135 | panic!("Failed to get config field: {}", field_name)
136 | });
137 |
138 | assert_eq!(expected_value, actual_yaml_value);
139 |
140 | let json_file_path = Some("./tests/data/mylibrary.json");
141 | let actual_json_value =
142 | get_config_field(json_file_path, Some("json"), field_name)
143 | .map_err(|err| err.to_string())
144 | .unwrap();
145 | assert_eq!(expected_value, actual_json_value);
146 |
147 | // Test with an empty file format
148 | let actual_empty_format_value =
149 | get_config_field(file_path, None, field_name)
150 | .map_err(|err| err.to_string())
151 | .unwrap_err();
152 | assert_eq!(
153 | actual_empty_format_value,
154 | "File format is not provided"
155 | );
156 |
157 | // Test with an unknown file format
158 | let actual_unknown_format_value =
159 | get_config_field(file_path, Some("unknown"), field_name)
160 | .map_err(|err| err.to_string())
161 | .unwrap_err();
162 | assert_eq!(actual_unknown_format_value, "Unsupported file format: unknown. Supported formats are 'json', 'yaml', and 'ini'.");
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/tests/utilities/mod.rs:
--------------------------------------------------------------------------------
1 | /// The `test_directory.rs` module contains tests for the directory module.
2 | pub mod test_directory;
3 |
4 | /// The `test_uuid.rs` module contains tests for the UUID module.
5 | pub mod test_uuid;
6 |
--------------------------------------------------------------------------------
/tests/utilities/test_directory.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::utilities::directory::directory;
4 | use std::fs;
5 | use std::io::Error;
6 | use std::path::Path;
7 | use tempfile::tempdir;
8 |
9 | #[test]
10 | fn test_directory_exists() {
11 | let dir = tempdir().unwrap();
12 | let path = dir.path().join("logs");
13 |
14 | fs::create_dir(&path).unwrap();
15 | let result = directory(&path, "logs");
16 | assert!(result.is_ok());
17 | assert_eq!(result.unwrap(), "");
18 | }
19 |
20 | #[test]
21 | fn test_directory_create() {
22 | let dir = tempdir().unwrap();
23 | let path = dir.path().join("logs");
24 |
25 | let result = directory(&path, "logs");
26 | assert!(result.is_ok());
27 | assert_eq!(result.unwrap(), "");
28 | assert!(path.exists());
29 | }
30 |
31 | #[test]
32 | fn test_directory_not_a_directory() {
33 | let dir = tempdir().unwrap();
34 | let file_path = dir.path().join("not_a_directory");
35 |
36 | fs::File::create(&file_path).unwrap();
37 | let result = directory(&file_path, "not_a_directory");
38 | assert!(result.is_err());
39 | assert_eq!(result.unwrap_err(), "❌ Error: not_a_directory is not a directory.");
40 | }
41 |
42 | #[test]
43 | fn test_move_output_directory() {
44 | let dir = tempdir().unwrap();
45 | let out_dir = dir.path().join("out");
46 |
47 | fs::create_dir(&out_dir).unwrap();
48 | let result = move_output_directory("site_name", &out_dir);
49 | assert!(result.is_ok());
50 |
51 | let public_dir = dir.path().join("public");
52 | let new_project_dir = public_dir.join("site_name");
53 | assert!(new_project_dir.exists());
54 | }
55 |
56 | #[test]
57 | fn test_cleanup_directory() {
58 | let dir = tempdir().unwrap();
59 | let cleanup_dir = dir.path().join("cleanup");
60 |
61 | fs::create_dir(&cleanup_dir).unwrap();
62 | let result = cleanup_directory(&[cleanup_dir.as_path()]);
63 | assert!(result.is_ok());
64 | assert!(!cleanup_dir.exists());
65 | }
66 |
67 | #[test]
68 | fn test_create_directory() {
69 | let dir = tempdir().unwrap();
70 | let create_dir = dir.path().join("create");
71 |
72 | let result = create_directory(&[create_dir.as_path()]);
73 | assert!(result.is_ok());
74 | assert!(create_dir.exists());
75 | }
76 |
77 | #[test]
78 | fn test_truncate_path() {
79 | let path = Path::new("/a/b/c/d/e");
80 |
81 | let result = truncate(&path, 3);
82 | assert_eq!(result, Some("c/d/e".to_string()));
83 |
84 | let result = truncate(&path, 0);
85 | assert_eq!(result, None);
86 |
87 | let result = truncate(&path, 10);
88 | assert_eq!(result, None);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/tests/utilities/test_uuid.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use libmake::utilities::uuid::generate_unique_string;
4 | use uuid::Uuid;
5 |
6 | #[test]
7 | fn test_generate_unique_string_format() {
8 | let unique_string = generate_unique_string();
9 | let uuid = Uuid::parse_str(&unique_string);
10 | assert!(uuid.is_ok(), "Generated string is not a valid UUID");
11 | }
12 |
13 | #[test]
14 | fn test_generate_unique_string_uniqueness() {
15 | let unique_string1 = generate_unique_string();
16 | let unique_string2 = generate_unique_string();
17 | assert_ne!(unique_string1, unique_string2, "Generated strings are not unique");
18 | }
19 | }
20 |
--------------------------------------------------------------------------------