diff --git a/.Rbuildignore b/.Rbuildignore index c4e8cd9..5900d83 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -4,4 +4,25 @@ ^\.Rhistory$ ^\.RData$ ^\.DS_Store$ -^vignettes/ +^_pkgdown\.yml$ +^pkgdown$ +^\.github$ +^codecov\.yml$ +^\.lintr$ +^\.pre-commit-config\.yaml$ +^CRAN-SUBMISSION$ +^cran-comments\.md$ +^CONTRIBUTING\.md$ +^docs$ +^doc$ +^\.github/workflows/.*\.yaml$ +^LICENSE\.md$ +^codemeta\.json$ +^revdep$ +^vignettes/articles$ +^\.git$ +^.*\.Rproj$ +^data-raw$ +^CODE_OF_CONDUCT\.md$ +^CHANGELOG\.md$ +^\.Renviron$ diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml new file mode 100644 index 0000000..8d99b34 --- /dev/null +++ b/.github/workflows/R-CMD-check.yaml @@ -0,0 +1,49 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main] + pull_request: + branches: [main] + +name: R-CMD-check + +jobs: + R-CMD-check: + runs-on: ${{ matrix.config.os }} + + name: ${{ matrix.config.os }} (${{ matrix.config.r }}) + + strategy: + fail-fast: false + matrix: + config: + - {os: macOS-latest, r: 'release'} + - {os: windows-latest, r: 'release'} + - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} + - {os: ubuntu-latest, r: 'release'} + - {os: ubuntu-latest, r: 'oldrel-1'} + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{ matrix.config.r }} + http-user-agent: ${{ matrix.config.http-user-agent }} + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::rcmdcheck + needs: check + + - uses: r-lib/actions/check-r-package@v2 + with: + upload-snapshots: true diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..f60d047 --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,32 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +name: lint + +jobs: + lint: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::lintr, local::. + needs: lint + + - name: Lint + run: lintr::lint_package() + shell: Rscript {0} + env: + LINTR_ERROR_ON_LINT: true diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml new file mode 100644 index 0000000..98fa9cb --- /dev/null +++ b/.github/workflows/pkgdown.yaml @@ -0,0 +1,44 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + tags: ['*'] + +name: pkgdown + +jobs: + pkgdown: + runs-on: ubuntu-latest + # Only restrict concurrency for non-PR jobs + concurrency: + group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::pkgdown, local::. + needs: website + + - name: Build site + run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) + shell: Rscript {0} + + - name: Deploy to GitHub pages πŸš€ + if: github.event_name != 'pull_request' + uses: JamesIves/github-pages-deploy-action@v4.4.1 + with: + clean: false + branch: gh-pages + folder: docs diff --git a/.github/workflows/pr-commands.yaml b/.github/workflows/pr-commands.yaml new file mode 100644 index 0000000..c06dd16 --- /dev/null +++ b/.github/workflows/pr-commands.yaml @@ -0,0 +1,81 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + issue_comment: + types: [created] + +name: Commands + +jobs: + document: + if: ${{ github.event.issue.pull_request && (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER') && startsWith(github.event.comment.body, '/document') }} + name: document + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/pr-fetch@v2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::roxygen2 + needs: pr-document + + - name: Document + run: roxygen2::roxygenise() + shell: Rscript {0} + + - name: commit + run: | + git config --local user.name "$GITHUB_ACTOR" + git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" + git add man/\* NAMESPACE + git commit -m 'Document' + shell: bash + + - uses: r-lib/actions/pr-push@v2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + style: + if: ${{ github.event.issue.pull_request && (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER') && startsWith(github.event.comment.body, '/style') }} + name: style + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v3 + + - uses: r-lib/actions/pr-fetch@v2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - uses: r-lib/actions/setup-r@v2 + + - name: Install dependencies + run: install.packages("styler") + shell: Rscript {0} + + - name: Style + run: styler::style_pkg() + shell: Rscript {0} + + - name: commit + run: | + git config --local user.name "$GITHUB_ACTOR" + git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" + git add \*.R + git commit -m 'Style' + shell: bash + + - uses: r-lib/actions/pr-push@v2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml new file mode 100644 index 0000000..07badcc --- /dev/null +++ b/.github/workflows/test-coverage.yaml @@ -0,0 +1,50 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +name: test-coverage + +jobs: + test-coverage: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::covr + needs: coverage + + - name: Test coverage + run: | + covr::codecov( + quiet = FALSE, + clean = FALSE, + install_path = file.path(Sys.getenv("RUNNER_TEMP"), "package") + ) + shell: Rscript {0} + + - name: Show testthat output + if: always() + run: | + ## -------------------------------------------------------------------- + find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \; || true + shell: bash + + - name: Upload test results + if: failure() + uses: actions/upload-artifact@v4 + with: + name: coverage-test-failures + path: ${{ runner.temp }}/package diff --git a/.lintr b/.lintr new file mode 100644 index 0000000..43ff386 --- /dev/null +++ b/.lintr @@ -0,0 +1,11 @@ +linters: linters_with_defaults( + line_length_linter(120), + commented_code_linter = NULL, + indentation_linter = NULL + ) +exclusions: list( + "inst/", + "man/", + "vignettes/" + ) +encoding: "UTF-8" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..bcdec60 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,19 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + +- repo: https://github.com/lorenzwalthert/precommit + rev: v0.3.2.9007 + hooks: + - id: style-files + args: [--style_pkg=styler, --style_fun=tidyverse_style] + - id: lintr + - id: readme-rmd-rendered + - id: parsable-R + - id: no-browser-statement + - id: deps-in-desc diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..b4f5637 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +dfr@esmad.ipp.pt. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..463aff4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,158 @@ +# Contributing to myrpackage + +Thank you for considering contributing to myrpackage! This document provides guidelines for contributing to the project. + +## Code of Conduct + +Please note that the myrpackage project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. + +## How to Contribute + +### Reporting Bugs + +If you find a bug, please create an issue on GitHub with the following information: + +1. A clear title and description +2. Steps to reproduce the behavior +3. Expected behavior +4. Actual behavior +5. Environment details (R version, package version, OS) +6. If possible, a minimal reproducible example + +### Suggesting Enhancements + +For feature requests, please create an issue on GitHub with: + +1. A clear title and description +2. Why this feature would be useful +3. Example code showing how the feature would be used +4. Any relevant references or context + +### Pull Requests + +1. Fork the repository +2. Create a new branch for your feature or bugfix +3. Make your changes +4. Add tests for your changes +5. Ensure all tests pass with `devtools::test()` +6. Update documentation with `devtools::document()` +7. Run R CMD check with `devtools::check()` +8. Submit a pull request + +## Development Workflow + +### Setting Up Development Environment + +1. Clone the repository +2. Open the project in RStudio (or your preferred R IDE) +3. Install development dependencies: + +```r +# Install development dependencies +devtools::install_dev_deps() + +# Install the package in development mode +devtools::load_all() +``` + +### Running Tests + +```r +# Run all tests +devtools::test() + +# Run specific tests +testthat::test_file("tests/testthat/test-hello.R") + +# Check test coverage +covr::package_coverage() +``` + +### Documentation + +```r +# Generate documentation +devtools::document() + +# Preview documentation +devtools::dev_help("hello") + +# Build vignettes +devtools::build_vignettes() + +# Build README +devtools::build_readme() +``` + +### Code Style + +We follow the [tidyverse style guide](https://style.tidyverse.org/). Please ensure your code adheres to this style. + +You can use the following tools to check and fix style issues: + +```r +# Check code style +lintr::lint_package() + +# Auto-format code +styler::style_pkg() +``` + +### Commit Messages + +Please use clear and descriptive commit messages. We recommend following the [conventional commits](https://www.conventionalcommits.org/) specification: + +- `feat`: A new feature +- `fix`: A bug fix +- `docs`: Documentation changes +- `style`: Changes that do not affect code behavior (formatting, etc.) +- `refactor`: Code changes that neither fix a bug nor add a feature +- `test`: Adding or fixing tests +- `chore`: Changes to the build process or auxiliary tools + +### Pre-commit Checks + +Before committing, please run: + +```r +# Document the package +devtools::document() + +# Run tests +devtools::test() + +# Run R CMD check +devtools::check() +``` + +## Release Process + +1. Update version number in DESCRIPTION +2. Update NEWS.md with changes +3. Run full checks: + +```r +devtools::check() +rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran")) +``` + +4. Build the package: + +```r +devtools::build() +``` + +5. Tag the release in Git: + +```r +usethis::use_git_tag("v0.1.0") +``` + +## Getting Help + +If you need help or have questions, you can: + +- Open an issue on GitHub +- Reach out to the package maintainer: Diogo Ribeiro (dfr@esmad.ipp.pt) + +Thank you for contributing! diff --git a/DESCRIPTION b/DESCRIPTION index 8e7014d..5496e7f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -8,4 +8,21 @@ Description: A short description of what the package does. License: MIT + file LICENSE Encoding: UTF-8 LazyData: true -RoxygenNote: 7.3.0 +Roxygen: list(markdown = TRUE) +RoxygenNote: 7.3.1 +Suggests: + covr, + knitr, + lintr, + pkgdown, + rmarkdown, + styler, + testthat (>= 3.0.0), + usethis, + withr +Config/testthat/edition: 3 +VignetteBuilder: knitr +URL: https://github.com/DiogoRibeiro7/myrpackage, https://diogoribeiro7.github.io/myrpackage/ +BugReports: https://github.com/DiogoRibeiro7/myrpackage/issues +Depends: + R (>= 4.0) diff --git a/LICENSE b/LICENSE index 414c491..8f37772 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,2 @@ -MIT License - -Copyright (c) 2025 Diogo Ribeiro - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +YEAR: 2025 +COPYRIGHT HOLDER: Diogo Ribeiro diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..c825aa9 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2025 Diogo Ribeiro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 0000000..a7def15 --- /dev/null +++ b/NEWS.md @@ -0,0 +1,24 @@ +# myrpackage NEWS + +## myrpackage 0.0.0.9000 (Development version) + +### New features + +* Added `hello()` function for multilingual greetings +* Added `goodbye()` function for multilingual farewells +* Added comprehensive documentation and examples +* Added unit tests for all functions + +### Package structure + +* Initial package setup with proper R package structure +* Added vignette for package introduction +* Added continuous integration with GitHub Actions +* Added code coverage tracking +* Added package website with pkgdown + +### Improvements + +* Added input validation to all functions +* Added support for multiple languages (English, Spanish, French, Portuguese) +* Added proper documentation with roxygen2 diff --git a/R/goodbye.R b/R/goodbye.R index 29ee221..1bde84a 100644 --- a/R/goodbye.R +++ b/R/goodbye.R @@ -1,9 +1,61 @@ #' Say Goodbye #' -#' This function prints a friendly farewell. +#' This function prints a friendly farewell. It can be customized with +#' different names and languages. #' -#' @return No return value, called for side effects. +#' @param name Character string. The name to bid farewell to. Default is "world". +#' @param language Character string. The language for the farewell. +#' Supported languages: "english" (default), "spanish", "french", "portuguese". +#' @param exclamation Logical. Whether to add an exclamation mark. Default is TRUE. +#' +#' @return A character string containing the farewell message. #' @export -goodbye <- function() { - print("Goodbye, world!") +#' +#' @examples +#' goodbye() +#' goodbye("R Users") +#' goodbye("amigos", language = "spanish") +#' goodbye("mes amis", language = "french", exclamation = FALSE) +#' +#' @seealso \code{\link{hello}} for a greeting function +goodbye <- function(name = "world", language = "english", exclamation = TRUE) { + # Input validation + if (!is.character(name) || length(name) != 1) { + stop("'name' must be a single character string") + } + + if (!is.character(language) || length(language) != 1) { + stop("'language' must be a single character string") + } + + if (!is.logical(exclamation) || length(exclamation) != 1) { + stop("'exclamation' must be a single logical value") + } + + # Select farewell based on language + farewell <- switch( + tolower(language), + english = "Goodbye", + spanish = "Adi\u00f3s", # Using Unicode escape for 'Γ³' + french = "Au revoir", + portuguese = "Adeus", + # Default to English if language not supported + "Goodbye" + ) + + # Construct the farewell + result <- paste0(farewell, ", ", name) + + # Add exclamation mark if requested + if (exclamation) { + result <- paste0(result, "!") + } else { + result <- paste0(result, ".") + } + + # Print the farewell and return it invisibly + cat(result, "\n") + + # Return the farewell + invisible(result) } diff --git a/R/hello.R b/R/hello.R index 0f1ccb3..da32df9 100644 --- a/R/hello.R +++ b/R/hello.R @@ -1,9 +1,61 @@ #' Say Hello #' -#' This function prints a friendly greeting. +#' This function prints a friendly greeting. It can be customized with +#' different names and languages. #' -#' @return No return value, called for side effects. +#' @param name Character string. The name to greet. Default is "world". +#' @param language Character string. The language for the greeting. +#' Supported languages: "english" (default), "spanish", "french", "portuguese". +#' @param exclamation Logical. Whether to add an exclamation mark. Default is TRUE. +#' +#' @return A character string containing the greeting. #' @export -hello <- function() { - print("Hello, world!") +#' +#' @examples +#' hello() +#' hello("R Users") +#' hello("amigos", language = "spanish") +#' hello("mes amis", language = "french", exclamation = FALSE) +#' +#' @seealso \code{\link{goodbye}} for a farewell function +hello <- function(name = "world", language = "english", exclamation = TRUE) { + # Input validation + if (!is.character(name) || length(name) != 1) { + stop("'name' must be a single character string") + } + + if (!is.character(language) || length(language) != 1) { + stop("'language' must be a single character string") + } + + if (!is.logical(exclamation) || length(exclamation) != 1) { + stop("'exclamation' must be a single logical value") + } + + # Select greeting based on language + greeting <- switch( + tolower(language), + english = "Hello", + spanish = "Hola", + french = "Bonjour", + portuguese = "Ol\u00e1", # Using Unicode escape for 'Γ‘' + # Default to English if language not supported + "Hello" + ) + + # Construct the greeting + result <- paste0(greeting, ", ", name) + + # Add exclamation mark if requested + if (exclamation) { + result <- paste0(result, "!") + } else { + result <- paste0(result, ".") + } + + # Print the greeting and return it invisibly + cat(result, "\n") + + # Return the greeting + invisible(result) } diff --git a/R/lifecycle.R b/R/lifecycle.R new file mode 100644 index 0000000..f1558c4 --- /dev/null +++ b/R/lifecycle.R @@ -0,0 +1,14 @@ +#' Life cycle badges for myrpackage functions +#' +#' @description +#' myrpackage uses lifecycle badges to help users understand the stability of +#' the functions and features it provides. +#' +#' - `stable`: The function is considered stable and will not undergo major changes. +#' - `experimental`: The function is in early stages of development and may change in future versions. +#' - `deprecated`: The function is deprecated and will be removed in a future version. +#' - `superseded`: The function has been replaced by a newer alternative. +#' +#' @name myrpackage-lifecycle +#' @keywords internal +NULL diff --git a/R/myrpackage-package.R b/R/myrpackage-package.R new file mode 100644 index 0000000..72ba6e6 --- /dev/null +++ b/R/myrpackage-package.R @@ -0,0 +1,19 @@ +#' @keywords internal +"_PACKAGE" + +#' myrpackage: A Minimal R Package +#' +#' @description +#' A minimal R package that provides greeting functions. +#' This package is designed to demonstrate proper R package structure +#' and documentation practices. +#' +#' @section Main functions: +#' \itemize{ +#' \item \code{\link{hello}} - Say hello in various languages +#' \item \code{\link{goodbye}} - Say goodbye in various languages +#' } +#' +#' @docType package +#' @name myrpackage-package +NULL diff --git a/README.md b/README.md index 43a5e35..5b58761 100644 --- a/README.md +++ b/README.md @@ -1,141 +1,145 @@ # myrpackage -A starter R package scaffold, structured for publication on [CRAN](https://cran.r-project.org/), with boilerplate files and metadata to begin development immediately. + +[![R-CMD-check](https://github.com/DiogoRibeiro7/myrpackage/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/DiogoRibeiro7/myrpackage/actions/workflows/R-CMD-check.yaml) +[![Codecov test coverage](https://codecov.io/gh/DiogoRibeiro7/myrpackage/branch/main/graph/badge.svg)](https://codecov.io/gh/DiogoRibeiro7/myrpackage?branch=main) +[![CRAN status](https://www.r-pkg.org/badges/version/myrpackage)](https://CRAN.R-project.org/package=myrpackage) +[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) + ---- +A minimal R package scaffold, structured for publication on [CRAN](https://cran.r-project.org/), with boilerplate files and metadata to begin development immediately. -## πŸ“ File Tree +## Installation -```text -myrpackage/ -β”œβ”€β”€ DESCRIPTION # Package metadata -β”œβ”€β”€ NAMESPACE # Generated from roxygen2 docs -β”œβ”€β”€ R/ -β”‚ β”œβ”€β”€ hello.R # Example R function with documentation -β”‚ └── goodbye.R # Another example function -β”œβ”€β”€ man/ -β”‚ β”œβ”€β”€ hello.Rd # Generated manual file -β”‚ └── goodbye.Rd # Manual for goodbye -β”œβ”€β”€ tests/ -β”‚ └── testthat/ -β”‚ β”œβ”€β”€ test-hello.R # Unit test -β”‚ └── test-goodbye.R # Unit test -β”‚ └── testthat.R # Testthat runner setup -β”œβ”€β”€ vignettes/ -β”‚ └── intro.Rmd # Long-form documentation (optional) -β”œβ”€β”€ .Rbuildignore # Files ignored during build -β”œβ”€β”€ .gitignore # Git ignore rules -β”œβ”€β”€ inst/ -β”‚ └── CITATION # Citation information -β”œβ”€β”€ LICENSE # Open-source license (MIT recommended) -└── README.md # Project overview and usage +You can install the development version of myrpackage from [GitHub](https://github.com/) with: + +```r +# install.packages("devtools") +devtools::install_github("DiogoRibeiro7/myrpackage") ``` ---- +## Usage -## πŸ“¦ DESCRIPTION (Example) +### Basic Examples ```r -Package: myrpackage -Type: Package -Title: What the Package Does (One Line, Title Case) -Version: 0.0.0.9000 -Authors@R: - person(given = "First", family = "Last", email = "your@email.com", role = c("aut", "cre")) -Description: A short description of what the package does. -License: MIT + file LICENSE -Encoding: UTF-8 -LazyData: true -RoxygenNote: 7.3.0 -``` +library(myrpackage) ---- +# Say hello with default parameters +hello() +#> Hello, world! -## πŸ“„ R/hello.R +# Say hello to someone specific +hello("R Users") +#> Hello, R Users! -```r -#' Say Hello -#' -#' This function prints a friendly greeting. -#' -#' @return No return value, called for side effects. -#' @export -hello <- function() { - print("Hello, world!") -} -``` ---- +# Say hello in different languages +hello("amigos", language = "spanish") +#> Hola, amigos! -## πŸ“„ R/goodbye.R +hello("mes amis", language = "french") +#> Bonjour, mes amis! -```r -#' Say Goodbye -#' -#' This function prints a friendly farewell. -#' -#' @return No return value, called for side effects. -#' @export -goodbye <- function() { - print("Goodbye, world!") -} +# Say goodbye +goodbye() +#> Goodbye, world! + +goodbye("friends", language = "portuguese") +#> Adeus, friends! ``` ---- -## πŸ§ͺ tests/testthat/test-hello.R -```r -test_that("hello() prints correctly", { - expect_output(hello(), "Hello, world!") -}) +## Features + +- 🌐 Multilingual greeting and farewell functions +- πŸ“¦ Proper R package structure +- πŸ“„ Comprehensive documentation +- πŸ§ͺ Complete test coverage +- πŸ”„ Continuous Integration workflow + +## Package Structure + ``` +myrpackage/ +β”œβ”€β”€ DESCRIPTION # Package metadata +β”œβ”€β”€ NAMESPACE # Exported functions +β”œβ”€β”€ R/ # R source code +β”‚ β”œβ”€β”€ hello.R # Hello function +β”‚ β”œβ”€β”€ goodbye.R # Goodbye function +β”‚ β”œβ”€β”€ lifecycle.R # Lifecycle definitions +β”‚ └── myrpackage-package.R # Package documentation +β”œβ”€β”€ man/ # Documentation +β”œβ”€β”€ tests/ # Tests +β”‚ └── testthat/ # Unit tests +β”œβ”€β”€ vignettes/ # Long-form documentation +β”‚ └── intro.Rmd # Introduction vignette +β”œβ”€β”€ .Rbuildignore # Build exclusions +β”œβ”€β”€ .github/ # GitHub configuration +β”‚ └── workflows/ # CI/CD workflows +β”œβ”€β”€ inst/ # Installed files +β”‚ └── CITATION # Citation information +└── LICENSE # MIT license +``` + +## Development ---- +### Getting Started -## πŸ“„ tests/testthat.R +1. Clone the repository +2. Open the project in RStudio or your preferred R environment +3. Install development dependencies with `devtools::install_dev_deps()` + +### Running Tests ```r -library(testthat) -library(myrpackage) +# Run tests +devtools::test() -test_check("myrpackage") +# Check test coverage +covr::package_coverage() ``` ---- +### Building Documentation + +```r +# Generate documentation +devtools::document() -## πŸ“„ .Rbuildignore +# Build vignettes +devtools::build_vignettes() -```text -^README\.md$ -^\.gitignore$ -^\.Rproj\.user$ -^\.Rhistory$ -^\.RData$ -^\.DS_Store$ -^vignettes/ +# Preview package website +pkgdown::build_site() ``` ---- +### Quality Checks -## πŸ“„ LICENSE (MIT Example) +```r +# Run R CMD check +devtools::check() -``` -MIT License +# Check package with more stringent CRAN checks +rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran")) -Copyright (c) 2025 Diogo Ribeiro +# Lint code +lintr::lint_package() -Permission is hereby granted, free of charge, to any person obtaining a copy... +# Style code +styler::style_pkg() ``` ---- -## πŸ“‘ Citation +## Contributing -To cite this package, run `citation("myrpackage")` in R. This will display the bibliographic information from `inst/CITATION`. +Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details. +## License ---- +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. -## πŸ“„ vignettes/intro.Rmd (Optional) +## Citation -````rmd ---- -title: "Getting Started with myrpackage" -output: rmarkdown::html_vignette +To cite this package, please use: + +```r +citation("myrpackage") +``` diff --git a/_pkgdown.yml b/_pkgdown.yml new file mode 100644 index 0000000..896cf95 --- /dev/null +++ b/_pkgdown.yml @@ -0,0 +1,65 @@ +url: https://diogoribeiro7.github.io/myrpackage/ + +template: + bootstrap: 5 + bootswatch: cosmo + bslib: + primary: "#0054AD" + navbar-light-brand-color: "#0054AD" + navbar-light-brand-hover-color: "#0054AD" + navbar-light-active-color: "#0054AD" + navbar-light-hover-color: "#0054AD" + navbar-light-color: "#0054AD" + +development: + mode: auto + +authors: + Diogo Ribeiro: + href: "https://github.com/DiogoRibeiro7" + +navbar: + structure: + left: [intro, reference, articles, news, tutorials] + right: [search, github] + components: + articles: + text: Articles + menu: + - text: Getting Started + href: articles/intro.html + reference: + text: Reference + href: reference/index.html + github: + icon: fab fa-github fa-lg + href: https://github.com/DiogoRibeiro7/myrpackage + news: + text: News + href: news/index.html + +reference: + - title: "Main Functions" + desc: > + The core greeting functions of the package + contents: + - hello + - goodbye + - title: "Package Information" + desc: "Documentation about the package itself" + contents: + - myrpackage-package + - myrpackage-lifecycle + +home: + sidebar: + structure: [links, license, community, citation, authors, dev] + components: + citation: + title: Citation + text: If you use this package, please cite it. + community: + title: Community + text: > + If you have questions or issues about the package, please file an issue on + [GitHub](https://github.com/DiogoRibeiro7/myrpackage/issues). diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..04c5585 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,14 @@ +comment: false + +coverage: + status: + project: + default: + target: auto + threshold: 1% + informational: true + patch: + default: + target: auto + threshold: 1% + informational: true diff --git a/cran-comments.md b/cran-comments.md new file mode 100644 index 0000000..7bbd321 --- /dev/null +++ b/cran-comments.md @@ -0,0 +1,17 @@ +# CRAN submission comments + +## Test environments +* local R installation, R 4.3.1 +* ubuntu 22.04 (on GitHub Actions), R devel, R release, R oldrel-1 +* windows-latest (on GitHub Actions), R release +* macOS-latest (on GitHub Actions), R release + +## R CMD check results + +0 errors | 0 warnings | 0 notes + +* This is a new release. + +## Downstream dependencies + +There are currently no downstream dependencies for this package. diff --git a/inst/CITATION b/inst/CITATION index 3eb1ee1..1ee4ef2 100644 --- a/inst/CITATION +++ b/inst/CITATION @@ -1,16 +1,26 @@ citHeader("To cite myrpackage in publications use:") +year <- format(Sys.Date(), "%Y") +version <- meta$Version + bibentry( - "Manual", + bibtype = "Manual", title = "myrpackage: A Minimal R Package", author = person(given = "Diogo", family = "Ribeiro", email = "dfr@esmad.ipp.pt", role = c("aut", "cre"), comment = c(ORCID = "0009-0001-2022-7072", affiliation = "ESMAD - Instituto PolitΓ©cnico do Porto")), - year = format(Sys.Date(), "%Y"), - note = "R package version 0.0.0.9000", - url = "https://github.com/DiogoRibeiro7/myrpackage" + year = year, + note = paste("R package version", version), + url = "https://github.com/DiogoRibeiro7/myrpackage", + doi = "", # Add DOI when available + textVersion = paste0( + "Ribeiro, D. (", year, "). ", + "myrpackage: A Minimal R Package. ", + "R package version ", version, ". ", + "https://github.com/DiogoRibeiro7/myrpackage" + ) ) -citFooter("Please cite this package when using it.") +citFooter("Please cite this package when using it for data analysis or research.") diff --git a/man/goodbye.Rd b/man/goodbye.Rd index 732ea89..0f0a714 100644 --- a/man/goodbye.Rd +++ b/man/goodbye.Rd @@ -1,6 +1,30 @@ \name{goodbye} \alias{goodbye} \title{Say Goodbye} -\usage{goodbye()} -\description{This function prints a friendly farewell.} -\examples{goodbye()} +\usage{ +goodbye(name = "world", language = "english", exclamation = TRUE) +} +\arguments{ +\item{name}{Character string. The name to bid farewell to. Default is "world".} + +\item{language}{Character string. The language for the farewell. +Supported languages: "english" (default), "spanish", "french", "portuguese".} + +\item{exclamation}{Logical. Whether to add an exclamation mark. Default is TRUE.} +} +\value{ +A character string containing the farewell message. +} +\description{ +This function prints a friendly farewell. It can be customized with +different names and languages. +} +\examples{ +goodbye() +goodbye("R Users") +goodbye("amigos", language = "spanish") +goodbye("mes amis", language = "french", exclamation = FALSE) +} +\seealso{ +\code{\link[myrpackage]{hello}} for a greeting function +} diff --git a/man/hello.Rd b/man/hello.Rd index 7f5d9c2..0d860ee 100644 --- a/man/hello.Rd +++ b/man/hello.Rd @@ -1,6 +1,30 @@ \name{hello} \alias{hello} \title{Say Hello} -\usage{hello()} -\description{This function prints a friendly greeting.} -\examples{hello()} +\usage{ +hello(name = "world", language = "english", exclamation = TRUE) +} +\arguments{ +\item{name}{Character string. The name to greet. Default is "world".} + +\item{language}{Character string. The language for the greeting. +Supported languages: "english" (default), "spanish", "french", "portuguese".} + +\item{exclamation}{Logical. Whether to add an exclamation mark. Default is TRUE.} +} +\value{ +A character string containing the greeting. +} +\description{ +This function prints a friendly greeting. It can be customized with +different names and languages. +} +\examples{ +hello() +hello("R Users") +hello("amigos", language = "spanish") +hello("mes amis", language = "french", exclamation = FALSE) +} +\seealso{ +\code{\link[myrpackage]{goodbye}} for a farewell function +} diff --git a/myrpackage.Rproj b/myrpackage.Rproj new file mode 100644 index 0000000..7c6a6c1 --- /dev/null +++ b/myrpackage.Rproj @@ -0,0 +1,22 @@ +Version: 1.0 + +RestoreWorkspace: No +SaveWorkspace: No +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Knitr +LaTeX: pdfLaTeX + +AutoAppendNewline: Yes +StripTrailingWhitespace: Yes +LineEndingConversion: Posix + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source +PackageRoxygenize: rd,collate,namespace diff --git a/tests/testthat/test-goodbye.R b/tests/testthat/test-goodbye.R index 266d648..3f45b6b 100644 --- a/tests/testthat/test-goodbye.R +++ b/tests/testthat/test-goodbye.R @@ -1,3 +1,59 @@ -test_that("goodbye() prints correctly", { +test_that("goodbye() prints correctly with default arguments", { + # Test the default output expect_output(goodbye(), "Goodbye, world!") + + # Test that the invisible return value is correct + expect_equal(suppressMessages(goodbye()), "Goodbye, world!") +}) + +test_that("goodbye() accepts custom name parameter", { + # Test with a custom name + expect_output(goodbye("R Users"), "Goodbye, R Users!") +}) + +test_that("goodbye() supports different languages", { + # Test English (default) + expect_output(goodbye(language = "english"), "Goodbye, world!") + + # Test Spanish + expect_output(goodbye(language = "spanish"), "AdiΓ³s, world!") + + # Test French + expect_output(goodbye(language = "french"), "Au revoir, world!") + + # Test Portuguese + expect_output(goodbye(language = "portuguese"), "Adeus, world!") + + # Test unknown language (should default to English) + expect_output(goodbye(language = "german"), "Goodbye, world!") +}) + +test_that("goodbye() correctly handles exclamation parameter", { + # Test with exclamation = TRUE (default) + expect_output(goodbye(exclamation = TRUE), "Goodbye, world!") + + # Test with exclamation = FALSE + expect_output(goodbye(exclamation = FALSE), "Goodbye, world.") +}) + +test_that("goodbye() validates input parameters", { + # Test invalid name parameter + expect_error(goodbye(name = c("world", "everyone")), "'name' must be a single character string") + expect_error(goodbye(name = 123), "'name' must be a single character string") + + # Test invalid language parameter + expect_error(goodbye(language = c("english", "spanish")), "'language' must be a single character string") + expect_error(goodbye(language = 123), "'language' must be a single character string") + + # Test invalid exclamation parameter + expect_error(goodbye(exclamation = c(TRUE, FALSE)), "'exclamation' must be a single logical value") + expect_error(goodbye(exclamation = "yes"), "'exclamation' must be a single logical value") +}) + +test_that("goodbye() works with all combinations of parameters", { + # Test with all parameters customized + expect_output( + goodbye(name = "friends", language = "spanish", exclamation = FALSE), + "AdiΓ³s, friends." + ) }) diff --git a/tests/testthat/test-hello.R b/tests/testthat/test-hello.R index acd4d1f..3f45b6b 100644 --- a/tests/testthat/test-hello.R +++ b/tests/testthat/test-hello.R @@ -1,3 +1,59 @@ -test_that("hello() prints correctly", { - expect_output(hello(), "Hello, world!") +test_that("goodbye() prints correctly with default arguments", { + # Test the default output + expect_output(goodbye(), "Goodbye, world!") + + # Test that the invisible return value is correct + expect_equal(suppressMessages(goodbye()), "Goodbye, world!") +}) + +test_that("goodbye() accepts custom name parameter", { + # Test with a custom name + expect_output(goodbye("R Users"), "Goodbye, R Users!") +}) + +test_that("goodbye() supports different languages", { + # Test English (default) + expect_output(goodbye(language = "english"), "Goodbye, world!") + + # Test Spanish + expect_output(goodbye(language = "spanish"), "AdiΓ³s, world!") + + # Test French + expect_output(goodbye(language = "french"), "Au revoir, world!") + + # Test Portuguese + expect_output(goodbye(language = "portuguese"), "Adeus, world!") + + # Test unknown language (should default to English) + expect_output(goodbye(language = "german"), "Goodbye, world!") +}) + +test_that("goodbye() correctly handles exclamation parameter", { + # Test with exclamation = TRUE (default) + expect_output(goodbye(exclamation = TRUE), "Goodbye, world!") + + # Test with exclamation = FALSE + expect_output(goodbye(exclamation = FALSE), "Goodbye, world.") +}) + +test_that("goodbye() validates input parameters", { + # Test invalid name parameter + expect_error(goodbye(name = c("world", "everyone")), "'name' must be a single character string") + expect_error(goodbye(name = 123), "'name' must be a single character string") + + # Test invalid language parameter + expect_error(goodbye(language = c("english", "spanish")), "'language' must be a single character string") + expect_error(goodbye(language = 123), "'language' must be a single character string") + + # Test invalid exclamation parameter + expect_error(goodbye(exclamation = c(TRUE, FALSE)), "'exclamation' must be a single logical value") + expect_error(goodbye(exclamation = "yes"), "'exclamation' must be a single logical value") +}) + +test_that("goodbye() works with all combinations of parameters", { + # Test with all parameters customized + expect_output( + goodbye(name = "friends", language = "spanish", exclamation = FALSE), + "AdiΓ³s, friends." + ) }) diff --git a/vignettes/intro.Rmd b/vignettes/intro.Rmd index 8ccf557..f3236e8 100644 --- a/vignettes/intro.Rmd +++ b/vignettes/intro.Rmd @@ -1,14 +1,114 @@ --- title: "Getting Started with myrpackage" +author: "Diogo Ribeiro" +date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{Getting Started} + %\VignetteIndexEntry{Getting Started with myrpackage} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- -```{r setup, include = FALSE} +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} library(myrpackage) ``` -This is an introduction to using the package. +## Introduction + +The `myrpackage` package provides simple greeting functions that demonstrate proper R package structure and documentation. This vignette introduces the main functionality of the package and shows examples of how to use it. + +## Basic Usage + +The package contains two main functions: + +- `hello()`: Say hello in various languages +- `goodbye()`: Say goodbye in various languages + +### Saying Hello + +The `hello()` function generates a friendly greeting. By default, it says "Hello, world!": + +```{r} +hello() +``` + +You can customize the greeting with a different name: + +```{r} +hello("R Users") +``` + +### Multilingual Greetings + +Both functions support multiple languages. Currently supported languages are: + +- English (default) +- Spanish +- French +- Portuguese + +Here are examples of greetings in different languages: + +```{r} +hello("amigos", language = "spanish") +hello("mes amis", language = "french") +hello("amigos", language = "portuguese") +``` + +### Customizing Punctuation + +You can also control whether the greeting ends with an exclamation mark: + +```{r} +hello(exclamation = TRUE) # Default +hello(exclamation = FALSE) +``` + +### Saying Goodbye + +The `goodbye()` function works similarly to `hello()`, but provides farewell messages: + +```{r} +goodbye() +goodbye("R Users") +goodbye("amigos", language = "spanish") +goodbye("mes amis", language = "french", exclamation = FALSE) +``` + +## Advanced Usage + +Both functions perform input validation to ensure proper usage: + +```{r, error=TRUE} +# These will generate errors: +hello(name = c("world", "everyone")) +hello(language = 123) +hello(exclamation = "yes") +``` + +## Further Reading + +For complete details about function arguments and behavior, refer to the function documentation: + +```{r, eval=FALSE} +?hello +?goodbye +``` + +## Conclusion + +`myrpackage` is a simple demonstration package that showcases proper R package development practices. It includes: + +- Well-documented functions +- Comprehensive tests +- Properly structured package components +- Vignettes for user documentation + +While the functionality is minimal, the package structure follows best practices for R package development.