├── .Rbuildignore
├── .Renviron
├── .Rprofile
├── .github
└── workflows
│ └── r-checks.yml
├── .gitignore
├── .vscode
├── settings.json
└── tasks.json
├── DESCRIPTION
├── NAMESPACE
├── NEWS.md
├── R
├── check_arg.R
├── check_dreamerr_calls.R
├── dreamerr.R
├── misc_funs.R
├── onLoad.R
└── stop.R
├── README.md
├── docs
├── 404.html
├── articles
│ ├── check_arg_call.png
│ ├── dreamerr_introduction.html
│ ├── dreamerr_introduction_files
│ │ └── figure-html
│ │ │ └── unnamed-chunk-5-1.png
│ ├── forming_a_type.png
│ ├── images
│ │ ├── check_arg_call.png
│ │ └── forming_a_type.png
│ └── index.html
├── authors.html
├── bootstrap-toc.css
├── bootstrap-toc.js
├── docsearch.css
├── docsearch.js
├── index.html
├── link.svg
├── news
│ └── index.html
├── pkgdown.css
├── pkgdown.js
├── pkgdown.yml
├── reference
│ ├── Rplot001.png
│ ├── Rplot002.png
│ ├── Rplot003.png
│ ├── Rplot004.png
│ ├── Rplot005.png
│ ├── check_arg-1.png
│ ├── check_arg-2.png
│ ├── check_arg-3.png
│ ├── check_arg-4.png
│ ├── check_arg-5.png
│ ├── check_arg.html
│ ├── check_expr.html
│ ├── dreamerr-package.html
│ ├── enumerate_items.html
│ ├── fit_screen.html
│ ├── fsignif.html
│ ├── ifsingle.html
│ ├── index.html
│ ├── n_times.html
│ ├── package_stats.html
│ ├── plural.html
│ ├── setDreamerr_check.html
│ ├── setDreamerr_dev.mode.html
│ ├── setDreamerr_show_stack.html
│ ├── set_check.html
│ ├── set_up.html
│ ├── sfill.html
│ ├── stop_hook.html
│ ├── stop_up.html
│ ├── suggest_item.html
│ └── validate_dots.html
└── sitemap.xml
├── man
├── check_arg.Rd
├── check_expr.Rd
├── dreamerr-package.Rd
├── enumerate_items.Rd
├── fit_screen.Rd
├── fsignif.Rd
├── ifsingle.Rd
├── n_times.Rd
├── package_stats.Rd
├── plural.Rd
├── setDreamerr_check.Rd
├── setDreamerr_dev.mode.Rd
├── setDreamerr_show_stack.Rd
├── set_check.Rd
├── set_up.Rd
├── sfill.Rd
├── stop_hook.Rd
├── stop_up.Rd
├── suggest_item.Rd
└── validate_dots.Rd
├── tests
└── tests_dreamerr.R
└── vignettes
├── dreamerr_introduction.Rmd
└── images
├── check_arg_call.png
└── forming_a_type.png
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^.*\.Rproj$
2 | ^\.Rproj\.user$
3 | Rplots.pdf
4 | ^\.Renviron$
5 | ^\.Rprofile$
6 | ^\.vscode$
7 | ^docs$
8 | ^\.github$
9 |
--------------------------------------------------------------------------------
/.Renviron:
--------------------------------------------------------------------------------
1 |
2 | package_ROOT = TRUE
3 |
--------------------------------------------------------------------------------
/.Rprofile:
--------------------------------------------------------------------------------
1 |
2 |
3 | local({
4 | # 0-dep function to silently load (and install if needed) packages at startup
5 | load_pkg = function(...){
6 | mc = match.call(expand.dots = FALSE)
7 | mc_dots = mc[["..."]]
8 |
9 | for(i in seq_along(mc_dots)){
10 | pkg_i = mc_dots[[i]]
11 | pkg_name = if(is.character(pkg_i)) pkg_i else deparse(pkg_i)
12 |
13 | if(!requireNamespace(pkg_name, quietly = TRUE)){
14 | ok = try(utils::install.packages(pkg_name, repos = "https://cloud.r-project.org/"))
15 | if(inherits(ok, "try-error")){
16 | stop("Could not install package `", pkg_name, "`. Please fix the problem manually.")
17 | }
18 | }
19 |
20 | suppressWarnings(suppressPackageStartupMessages(library(pkg_name, character.only = TRUE)))
21 | }
22 | }
23 |
24 | # add packages to load here: eg load_pkg(fixest, stringmagic)
25 |
26 | # Replacing View with datadive
27 | if(requireNamespace("datadive", quietly = TRUE)){
28 | assign("View", datadive::app_explore, .GlobalEnv)
29 | }
30 |
31 | # VSCode specific
32 | # adapted from: https://github.com/REditorSupport/vscode-R/wiki/Interacting-with-R-terminals
33 | # => no error if file is missing
34 | if (interactive() && Sys.getenv("RSTUDIO") == "") {
35 | Sys.setenv(TERM_PROGRAM = "vscode")
36 | HOME = if(.Platform$OS.type == "windows") "USERPROFILE" else "HOME"
37 | my_file = file.path(Sys.getenv(HOME), ".vscode-R", "init.R")
38 | if(file.exists(my_file)){
39 | source(my_file)
40 | options(vsc.rstudioapi = TRUE)
41 | }
42 | }
43 | })
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.github/workflows/r-checks.yml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main, master]
6 | pull_request:
7 | branches: [main, master]
8 |
9 | name: R-CMD-check
10 |
11 | jobs:
12 | R-CMD-check:
13 | runs-on: ${{ matrix.config.os }}
14 |
15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
16 |
17 | strategy:
18 | fail-fast: false
19 | matrix:
20 | config:
21 | - {os: macos-latest, r: 'release'}
22 | - {os: windows-latest, r: 'release'}
23 | - {os: ubuntu-latest, r: 'release'}
24 |
25 | env:
26 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
27 | R_KEEP_PKG_SOURCE: yes
28 |
29 | steps:
30 | - uses: actions/checkout@v3
31 |
32 | - uses: r-lib/actions/setup-pandoc@v2
33 |
34 | - uses: r-lib/actions/setup-r@v2
35 | with:
36 | r-version: ${{ matrix.config.r }}
37 | http-user-agent: ${{ matrix.config.http-user-agent }}
38 | use-public-rspm: true
39 |
40 | - uses: r-lib/actions/setup-r-dependencies@v2
41 | with:
42 | extra-packages: any::rcmdcheck
43 | needs: check
44 |
45 | - uses: r-lib/actions/check-r-package@v2
46 | with:
47 | upload-snapshots: true
48 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .RData
4 | .Ruserdata
5 | Rplots.pdf
6 | dreamerr.Rproj
7 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cmake.configureOnOpen": true
3 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | // This task has been automatically generated by
4 | // {$userHome}/.vscode/scripts/setup-r-projects
5 | //
6 | // When the VSCode folder is open, this task opens a split terminal
7 | // with git bash on the left and R terminal on the right
8 | //
9 | // This task is automatically added to the project only if an R folder is there
10 | // or the workspace root contains an .R file, or at least one direct childern folder
11 | // contains an .R file
12 | //
13 | // See ctrl+shift+P -> Tasks: Open user tasks -> "Setup R projects watcher"
14 | //
15 |
16 | "version": "2.0.0",
17 | "tasks": [
18 | {
19 | "label": "Create terminals",
20 | "dependsOn": [
21 | "git bash",
22 | "R-term"
23 | ],
24 | "runOptions": {
25 | "runOn": "folderOpen"
26 | }
27 | },
28 | {
29 | "type": "R",
30 | "code": [
31 | "devtools::install()"
32 | ],
33 | "group": "build",
34 | "problemMatcher": [],
35 | "label": "R: Install"
36 | }
37 | ]
38 | }
39 |
40 |
41 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: dreamerr
2 | Type: Package
3 | Title: Error Handling Made Easy
4 | Version: 1.5.0
5 | Authors@R: person("Laurent", "Berge", email = "laurent.berge@u-bordeaux.fr", role = c("aut", "cre"))
6 | Imports: Formula, utils, stringmagic(>= 1.2.0)
7 | Suggests: knitr, rmarkdown, stats, graphics
8 | Description: Set of tools to facilitate package development and make R a more user-friendly place. Mostly for developers (or anyone who writes/shares functions). Provides a simple, powerful and flexible way to check the arguments passed to functions.
9 | The developer can easily describe the type of argument needed. If the user provides a wrong argument, then an informative error message is prompted with the requested type and the problem clearly stated--saving the user a lot of time in debugging.
10 | License: GPL-3
11 | Encoding: UTF-8
12 | VignetteBuilder: knitr
13 | BugReports: https://github.com/lrberge/dreamerr/issues
14 | RoxygenNote: 7.3.2
15 | Roxygen: list(markdown = TRUE)
16 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Functions to export -- main
4 | export(check_arg, check_arg_plus, check_set_arg)
5 | export(check_value, check_value_plus, check_set_value)
6 | export(check_expr)
7 | export(validate_dots)
8 |
9 | # hook related functions
10 | export(set_hook, stop_hook, warn_hook, check_expr_hook)
11 | export(generate_set_hook, generate_stop_hook, generate_warn_hook,
12 | generate_check_expr_hook, generate_get_hook)
13 |
14 | # stop/warn
15 | export(stop_up, warn_up, stopi, warni)
16 |
17 | # misc
18 | export(fit_screen, suggest_item)
19 |
20 | # Other, deprecated following stringmagic integration
21 | export(n_letter, n_th, n_times)
22 | export(signif_plus, fsignif)
23 | export(ifsingle, ifunit, plural, plural_len, enumerate_items)
24 | export(sfill)
25 |
26 | # Setter/Getter
27 | export(setDreamerr_check, setDreamerr_dev.mode, setDreamerr_show_stack)
28 | export(set_up, set_check)
29 |
30 | # Goodies
31 | export(package_stats)
32 |
33 |
34 | #
35 | # IMPORTS
36 | #
37 |
38 | importFrom(Formula, Formula)
39 | importFrom(utils, find)
40 | importFrom(stringmagic, sma, string_magic)
41 |
42 |
43 |
--------------------------------------------------------------------------------
/NEWS.md:
--------------------------------------------------------------------------------
1 |
2 | # dreamerr 1.5.0
3 |
4 | ## New features
5 |
6 | - the argument `.message` of the `check_` functions is now interpolated with `string_magic()`
7 |
8 | ## User-level changes
9 |
10 | - the type `l0` has been removed. Now `check_arg(x, "vector")` (or the like) receiving something 0-length in input will not send an error (in the previous version, `l0` was required). Vector length can still be checked with the `len(a,b)` mechanism (thanks to @kylebutts for early bug reports).
11 |
12 | ## Minor changes
13 |
14 | - to increase clarity, now the problem leading to an error is displayed in a newline with the prefix `PROBLEM` in uppercase
15 |
16 | - improve clarity of error messages involving lower than/greater than
17 |
18 | - improve the number of items suggested by `suggest_item`
19 |
20 | ## Bug fixes
21 |
22 | - fix display problem in `fsignif`
23 |
24 | - increase the requirement of `stringmagic` version to be compatible with R v3.5.0
25 |
26 | - the `check_arg` family of functions now correctly reports the full call stack when requested
27 |
28 | - fix bug: wrong argument name displayed when `check_value` was used with the argument `.arg_name` and an error was produced because a variable was missing in a formula. Thanks to @kylebutts, #4.
29 |
30 | # dreamerr 1.4.0
31 |
32 | ## New functions
33 |
34 | - New set of `hook` error and warning functions for reporting in complex internal functions. These are `set_hook` to set a function as the hook and `stop_hook`/`warn_hook` error and warning functions used to report as if they were called from the hooked function.
35 |
36 | - `warni` and `stopi` for warning and stop functions with character interpolation using [stringmagic](https://github.com/lrberge/stringmagic)
37 |
38 | ## New type
39 |
40 | - The type `path` has been added to `check_arg`. It is used to check paths.
41 |
42 | ## Improvements
43 |
44 | - All warning and stop functions gain string interpolation with [stringmagic](https://github.com/lrberge/stringmagic).
45 |
46 |
47 | # dreamerr 1.3.0
48 |
49 | ## Bug fixes
50 |
51 | - fixes `fit_screen` so that it does not mess with white spaces.
52 |
53 | ## Name changes
54 |
55 | - Functions `check_arg_plus` and `check_value_plus` become `check_set_arg` and `check_set_value` to improve clarity.
56 |
57 | ## Improvements
58 |
59 | - `fsignif` now displays trailing 0s appropriately and is neutral to character vectors (instead of throwing an error).
60 |
61 | - the comparison types now can evaluate values from the calling frame:
62 | ```r
63 | z = 32
64 | x = 77
65 | try(check_value(x, "numeric scalar LE{z}"))
66 | #> Error: in check_value(x, "numeric scalar LE{z}"):
67 | #> Value 'x' must be a numeric scalar lower than, or equal to, 32. Problem: it is strictly greater than 32.
68 | ```
69 |
70 | - `stop_up` now accepts the argument msg which is an extra message displayed right after the error message.
71 |
72 | # dreamerr 1.2.3
73 |
74 | #### Bug fixes
75 |
76 | - in `check_arg_plus` conversion of factors to characters now works properly.
77 |
78 | - Fix bug in `stop_up` when the argument `up` was not appropriately set by the user.
79 |
80 | - fix bug in `sfill` regarding the combined usage of `anchor` and `right` in special circumstances.
81 |
82 | #### New features
83 |
84 | - now `sfill` accepts 0-length vectors.
85 |
86 | - new exported function: `fit_screen`.
87 |
88 |
89 | # dreamerr 1.2.2
90 |
91 | #### Bug fixes
92 |
93 | - fix bugs in `sfill`:
94 |
95 | * when an anchor was provided and all characters before that were of the same length.
96 |
97 | * when an anchor was provided and the fill was from the right.
98 |
99 | #### User visible changes
100 |
101 | - `check_`family: objects are now returned invisibly.
102 |
103 | - new function `fsignif` which is an alias of `signif_plus`.
104 |
105 | # dreamerr 1.2.1
106 |
107 | #### Bug fixes
108 |
109 | - Bug when using commas or parentheses in arguments `.prefix` or `.argname` of `check_value`.
110 | - Bug in the error message in `check_value` when the argument could not be evaluated.
111 | - Bug introduced in the previous version, when checking types or equality with the option "no na"
112 |
113 |
114 | #### User visible changes
115 |
116 | - `validate_dots`: nicer messages.
117 |
118 | # dreamerr 1.2.0
119 |
120 | #### Important changes (no retro compatibility)
121 |
122 | - IMPORTANT CHANGE: Now by default, there is `NA` tolerance for the main classes `vector` and `matrix` (opposite to the previous behavior). The new keywords `NO NA` replace the former keywords `NA OK` for these classes.
123 | ```
124 | test = function(x){
125 | check_arg(x, "numeric vector")
126 | }
127 | # Before (version <= 1.1.0)
128 | test(c(5, NA)) # => Error
129 | # Now (version >= 1.2.0)
130 | test(c(5, NA)) # => is OK
131 | ```
132 |
133 | - IMPORTANT CHANGE: values of 0 or 1 are not valid by default anymore when the `logical` type is requested.
134 | ```
135 | test = function(x){
136 | check_arg(x, "logical scalar")
137 | }
138 | # Before (version <= 1.1.0)
139 | test(0) # => is OK
140 | # Now (version >= 1.2.0)
141 | test(0) # => Error, must be logical
142 | ```
143 | The new behavior is equivalent to the previous behavior when the type was `strict logical`. Now strict logical has been removed and `loose logical` has been introduced which accepts 0 and 1. Why this change? I remarked that when you allow arguments of very different types, one of which was a logical scalar, it was really useful to distinguish between them safely using `isTRUE` or `is.logical`. With the previous default behavior you could have a 0 or 1 that would prevent you from doing that. Of course you could use `strict logical` to trigger that behavior but it was non-intuitive.
144 |
145 | #### New features
146 |
147 | - In `check_value`: you can use the new argument `.prefix` to design the error message.
148 |
149 | - Function `check_value_plus` now returns the value of the element it has checked and possibly modified.
150 | ```
151 | x = "t"
152 | y = check_value_plus(x, "match(This, Is, Raw)")
153 | y # => "This"
154 | fml = ~head(Petal.Length)
155 | z = check_value_plus(fml[[2]], "evalset numeric vector", .data = iris)
156 | z
157 | ```
158 |
159 | - `sfill` now accepts NAs.
160 |
161 | #### Other changes
162 |
163 | - Error messages in `check_value` have been improved.
164 |
165 | - `enumerate_items` now returns the empty string when 0-length vectors are in input.
166 |
167 | #### Bug correction
168 |
169 | - The main class `match` could lead the argument to lose its attributes (like names), now corrected.
170 |
171 | - Vectors containing only NAs when NAs are tolerated could lead to a wrong error message, now corrected.
172 |
173 | - Bug when `check_value_plus` was called from the global environment and an error was triggered.
174 |
175 | - Bug when `check_value` was called and `.arg_name` was provided.
176 |
177 | - Bug when the "`...`" argument contained `NULL` values.
178 |
179 | - The developer mode now never applies to functions from packages using dreamerr
180 |
181 | - Behavior of argument `nmax` in `enumerate_items` is fixed.
182 |
183 | - Type conversion of matrices returned a vector, now corrected.
184 |
185 |
186 | # dreamerr 1.1.0
187 |
188 | #### New functions
189 |
190 | - `sfill`: formatting function for strings. Fills a character string up to the required length. Helps to form nice messages.
191 |
192 | - `set_up`: sets the argument `up` semi-globally (i.e. throughout all calls within a function).
193 |
194 | - `set_check`: turns on/off argument checking semi-globally (i.e. throughout all calls within a function).
195 |
196 | #### New features
197 |
198 | - When devising your own message (with argument `.message`), you can use the special character `__ARG__`. If found, it will be replaced by the appropriate argument name.
199 |
200 | #### User visible changes
201 |
202 | - Message informing no NA tolerance in the types is prompted only when the error comes from NA values.
203 |
204 | - The developer mode catches more errors and provide more suggestions.
205 |
206 | - `check_value` now doesn't throw an error for missing `.x`.
207 |
208 | #### Change in argument names
209 |
210 | - `.call_up` becomes `.up` -- retro-compatibility is NOT ensured.
211 |
212 | #### Bug correction
213 |
214 | - Small bug that could occur for the types `"integer scalar na ok"` with the argument equal to `NA`.
215 |
216 | - Important bug when using features requiring evaluations in the environment. Now the default environment is set up appropriately.
217 |
218 | - Bug when using `var(data,env)` in a `formula` class with missing `data`.
219 |
220 | - Very sneaky bug when badly forming a call to `check_arg` to check `...` in nested functions is now caught.
221 |
222 | - In `enumerate_items`, when there were many elements, `quote = TRUE` led to quote the `XX others` that shouldn't be quoted. Now corrected.
223 |
224 | - In the `formula` class, if a variable was passed as a `Formula` (notice the capital F), this caused an error if one-sidedness or two-sidedness were to be checked.
225 |
226 | - Bug when in `n_letter` when negative numbers are in. This bug propagated into `check_arg`.
227 |
228 |
229 | # dreamerr 1.0.0
230 |
231 | This package is the outcome of over a decade of coding and developing packages in R. As a package developer I always wanted my code to be "safe": so that if a user provides arguments of the good type the functions always work, and if there's an argument of the wrong type then an informative error message is shown.
232 |
233 | The big problem is that error handling is extremely time consuming, especially if you want to specify informative error messages stating clearly where the problem comes from. This problem is compounded when you want to offer the user flexible arguments that can be of many types. To do error handling properly in such situations is a nightmare: you end up with big if/else trees with a lot of different messages. And it doesn't improve the speed of your code! So you have little incentives to invest time in proper error handling.
234 |
235 | This is why I developed this function. It's one line of code, and it does all the work for you. From the developer side it's super simple, and from the user side, s/he ends up with extremely informative error messages therefore saving a lot of time in debugging.
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
--------------------------------------------------------------------------------
/R/dreamerr.R:
--------------------------------------------------------------------------------
1 |
2 |
3 | #' Error Handling Made Easy
4 | #'
5 | #' The main purpose of this package is twofold: i) to facilitate the developer's life, and ii) to provide to the users meaningful, useful error messages. These objectives are accomplished with a single function: \code{\link[dreamerr]{check_arg}}. That function checks the arguments given by the user: it offers a compact syntax such that complex arguments can be simply stated by the developer. In turn, if the user provides an argument of the wrong type then an informative error message will be buit, stating the expected type and where the error comes from--saving the user quite some time in debugging.
6 | #'
7 | #' Thus you can very easily make your package look professional with \code{\link[dreamerr]{check_arg}} (checking arguments properly \emph{is} professional).
8 | #'
9 | #' It also offers a set of small tools to provide informative messages to the users. See \code{\link[dreamerr]{stop_up}} and \code{\link[dreamerr:stop_up]{warn_up}} to throw errors and warnings in the appropriate location. There are many tools to form messages: \code{\link[dreamerr]{enumerate_items}} to form textual list of elements (with many options including conjugating verbs, etc...), \code{\link[dreamerr]{plural}} to conjugate verbs depending on the argument, and \code{\link[dreamerr:n_times]{n_letter}}, \code{\link[dreamerr:n_times]{n_th}}, \code{\link[dreamerr]{n_times}} to write integers in words (which usually looks nicer).
10 | #'
11 | #' To sum up in a few words, this package was created to enhance the user experience and facilitate package development.
12 | #'
13 | #'
14 | "_PACKAGE"
15 |
--------------------------------------------------------------------------------
/R/onLoad.R:
--------------------------------------------------------------------------------
1 |
2 |
3 | #
4 | # compatibility
5 | #
6 |
7 | if(!exists("str2lang", asNamespace("base"))){
8 | str2lang = function(x){
9 | parse(text = x, keep.source = FALSE)[[1]]
10 | }
11 | }
12 |
13 |
14 | #
15 | # startup
16 | #
17 |
18 |
19 | .onLoad <- function(libname, pkgname){
20 | # setting some options
21 |
22 | options("dreamerr_check" = TRUE)
23 | options("dreamerr_dev.mode" = FALSE)
24 |
25 | fix_pkgwdown_path()
26 |
27 | invisible()
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # dreamerr: Error Handling Made Easy
5 |
6 |
7 |
8 |
9 |
10 |
11 | This package is addressed to developers or anyone writing functions (therefore almost everyone).
12 |
13 | It intends to increase R's user-friendliness and has two main objectives:
14 |
15 | 1. to provide to the developer a simple and intuitive, yet powerful and flexible, way to check the arguments passed to a function
16 | 2. to offer informative error messages to the user, in the case s/he passes arguments of the wrong type, stating clearly the problem, therefore saving their precious time in debugging
17 |
18 | These two goals can be achieved with a single line: `check_arg(arg_name, "expected type")`.
19 |
20 | This package aims to be the end of R's sometimes cryptic error messages, like the infamous
21 |
22 | ```
23 | Error in xj[i] : invalid subscript type 'closure'
24 | ```
25 |
26 | Below is a motivating example, for more details see the [introduction](https://CRAN.R-project.org/package=dreamerr/vignettes/dreamerr_introduction.html).
27 |
28 | ## Motivating example
29 |
30 | To illustrate the usefulness, let's rewrite the `lm()` function with some error handling and compare the results without/with error handling. In this simple example, we just add argument checking to the first two arguments of `lm`.
31 |
32 | ```r
33 | lm_check = function(formula, data){
34 |
35 | # data: can be missing, if provided, it must be a data.frame or a list with names
36 | # (a data.frame is a named list, but the two types are added for clarity)
37 | check_arg(data, "data.frame | named list")
38 |
39 | # formula:
40 | # - must be a two-sided formula (ts)
41 | # - must be given by the user (mbt: must be there)
42 | # - the variables of the formula must be in the data set or in the environment (var(data, env))
43 | check_arg(formula, "ts formula var(data, env) mbt", .data = data)
44 |
45 | # Now the call to lm
46 | lm(formula, data)
47 | }
48 | ```
49 |
50 | As we can see each argument is checked with one line, and the types are rather explicit since natural language is used.
51 |
52 | Now let's compare the two functions. First without error handling (`lm`'s default):
53 |
54 | ```r
55 | # No argument
56 | lm()
57 | #> Error in terms.formula(formula, data = data) :
58 | #> argument is not a valid model
59 |
60 | # Problems in the formula
61 | lm(~Sepal.Width, iris)
62 | #> Error in lm.fit(x, y, offset = offset, singular.ok = singular.ok, ...) :
63 | #> incompatible dimensions
64 |
65 | lm(1+1, iris)
66 | #> Error in formula.default(object, env = baseenv()) : invalid formula
67 |
68 | lm(1+"a", iris)
69 | #> Error in 1 + "a" : non-numeric argument to binary operator
70 |
71 | lm(moien, iris)
72 | #> Error in stats::model.frame(formula = moien, data = iris, drop.unused.levels = TRUE) :
73 | #> object 'moien' not found
74 |
75 | # Problem in the data
76 | lm(Sepal.Length~Sepal.Width, pt)
77 | #> Error in as.data.frame.default(data, optional = TRUE) :
78 | #> cannot coerce class ‘"function"’ to a data.frame
79 |
80 | lm(Sepal.Length ~ Sepal.Width, 1:5)
81 | #> Error in eval(predvars, data, env) :
82 | #> numeric 'envir' arg not of length one
83 |
84 | # Mistake in the variable name
85 | lm(Sopal.Length~Sepal.Width, iris)
86 | #> Error in eval(predvars, data, env) : object 'Sopal.Length' not found
87 |
88 | ```
89 |
90 | As we can see, the error messages are not really explicit. It's not easy to find: i) what the problem is, ii) which function really drives the error, iii) which argument is involved. It is therefore at best difficult, at worst impossible, to solve the problem from the error messages.
91 |
92 | Now with error handling:
93 |
94 | ```r
95 | # No argument
96 | lm_check()
97 | #> Error : in lm_check():
98 | #> Argument 'formula' is required. Problem: it is missing.
99 |
100 | # Problems in the formula
101 | lm_check(~Sepal.Width, iris)
102 | #> Error : in lm_check(~Sepal.Width, iris):
103 | #> Argument 'formula' must be a two-sided formula. Problem: it is currently only one-sided.
104 |
105 | lm_check(1 + 1, iris)
106 | #> Error : in lm_check(1 + 1, iris):
107 | #> Argument 'formula' must be a two-sided formula. Problem: it is not a formula (instead it is a vector).
108 |
109 | lm_check(1 + "a", iris)
110 | #> Error : in lm_check(1 + "a", iris):
111 | #> Argument 'formula' (equal to '1 + "a"') could not be evaluated. Problem: non-numeric argument to binary operator.
112 |
113 | lm_check(moien, iris)
114 | #> Error : in lm_check(moien, iris):
115 | #> Argument 'formula' (equal to 'moien') could not be evaluated. Problem: object 'moien' not found.
116 |
117 | # Problem in the data
118 | lm_check(Sepal.Length ~ Sepal.Width, pt)
119 | #> Error : in lm_check(Sepal.Length ~ Sepal.Width, pt):
120 | #> Argument 'data' must be either: i) a data.frame, or ii) a named list. Problem: it is not a data.frame nor a list
121 | #> (instead it is a function).
122 |
123 | lm_check(Sepal.Length ~ Sepal.Width, 1:5)
124 | #> Error : in lm_check(Sepal.Length ~ Sepal.Width, 1:...:
125 | #> Argument 'data' must be either: i) a data.frame, or ii) a named list. Problem: it is not a data.frame nor a list
126 | #> (instead it is a vector).
127 |
128 | # Mistake in the variable name
129 | lm_check(Sopal.Length ~ Sepal.Width, iris)
130 | #> Error : in lm_check(Sopal.Length ~ Sepal.Width, iris):
131 | #> The argument 'formula' is a formula whose variables must be in the data set (given in argument 'data') or in the
132 | #> environment. Problem: the variable 'Sopal.Length' isn't there.
133 |
134 | ```
135 |
136 | Now the error messages are explicit: we know where the problem comes from, the function `lm_check` is always shown as the root cause of the problem. The problematic argument is also explicitly mentioned. What the argument is expected to be is reminded and the mismatch with the actual argument is clearly mentioned after `Problem:`. Note that even nasty evaluation problems are caught.
137 |
138 | Debugging a call to `lm_check` is a piece of cake (especially compared to a direct call to `lm`): a lot of time is saved, the function looks a lot more user-friendly... with just two damn lines of code.
139 |
140 |
141 |
142 | ## A note on performance
143 |
144 | You may wonder: how much argument checking would slow down my code? Well, not much. Even not at all to be honest.
145 |
146 | Although the function `check_arg` supports literally over hundreds of different types, it has been highly optimized, meaning its performance cost is close to 0. Talking numbers, in a moderately slow computer (2.6GHz) it is in the ballpark of 20 micro seconds for missing arguments (i.e. not provided by the user) and of 70 micro seconds for simple checks of non-missing arguments. So you end up with a cost of 1s if you check 20K to 50K arguments, which seems reasonnably fast.
147 |
148 | In any case, the user can always set argument checking off with `setDreamerr_check(FALSE)`. So no reason not to make your functions user-friendly!
149 |
150 |
--------------------------------------------------------------------------------
/docs/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This functions checks the evaluation of an expression and, if an error is thrown,
64 | captures it and integrates the captured message after a custom error message.
Character scalars. The values of ... will be coerced with the function
83 | string_magic.
84 | This means that string interpolation is allowed. Ex: "Arg. {arg} should be positive"
85 | leads to "Arg. power should be positive" if arg is equal to "power".
86 |
If argument verbatim is TRUE, the values are instead coereced with paste0.
87 |
88 |
89 |
clean
90 |
Character vector, default is missing. If provided, the function
91 | string_clean
92 | is applied to the captured error message to clean it when necessary. Each element
93 | of the vector should be of the form "pat => rep" with pat a regular expression
94 | to be replace and rep the replacement.
95 |
96 |
97 |
up
98 |
Integer, default is 0. It is used to construct the call in the error message.
99 | By default the call reported is the function containing check_expr. If you want to
100 | report a function higher in the stack, use up = 1, or higher.
101 |
102 |
103 |
arg_name
104 |
Character scalar, default is missing. Used when the expression in
105 | expr leads to an error and the custom message is missing (i.e. no element is
106 | provided in ...). In that case, the default message is: "The argument {arg_name} could not be evaluated.".
107 | The default value for arg_name is deparse(substitute(expr)), if this guess is wrong,
108 | use arg_name.
109 |
110 |
111 |
verbatim
112 |
Logical scalar, default is FALSE. By default the elements of ...
113 | allow string interpolation with "{}" using stringmagic.
114 | If TRUE, no interpolation is performed.
115 |
116 |
117 |
namespace
118 |
Character scalar giving the namespace for which the hooks are valid. Only useful
119 | when hook functions are used in a package.
120 |
121 |
122 |
123 |
Details
124 |
The purpose of this functions is to provide useful error messages to the user.
125 |
126 |
127 |
Functions
128 |
129 |
check_expr_hook(): As check_expr but sets the error call at the level of the hooked function
130 |
generate_check_expr_hook(): Generates a package specific check_expr_hook function
The main purpose of this package is twofold: i) to facilitate the developer's life, and ii) to provide to the users meaningful, useful error messages. These objectives are accomplished with a single function: check_arg. That function checks the arguments given by the user: it offers a compact syntax such that complex arguments can be simply stated by the developer. In turn, if the user provides an argument of the wrong type then an informative error message will be buit, stating the expected type and where the error comes from--saving the user quite some time in debugging.
63 |
64 |
65 |
66 |
67 |
Details
68 |
Thus you can very easily make your package look professional with check_arg (checking arguments properly is professional).
69 |
It also offers a set of small tools to provide informative messages to the users. See stop_up and warn_up to throw errors and warnings in the appropriate location. There are many tools to form messages: enumerate_items to form textual list of elements (with many options including conjugating verbs, etc...), plural to conjugate verbs depending on the argument, and n_letter, n_th, n_times to write integers in words (which usually looks nicer).
70 |
To sum up in a few words, this package was created to enhance the user experience and facilitate package development.
Formatting of numbers, when they are to appear in messages. Displays only significant digits in a "nice way" and adds commas to separate thousands. It does much less than the format function, but also a bit more though.
63 |
64 |
65 |
66 |
fsignif(x, s =2, r =0, commas =TRUE)
67 |
68 | signif_plus
69 |
70 |
71 |
72 |
Format
73 |
An object of class function of length 1.
74 |
75 |
76 |
Arguments
77 |
x
78 |
A numeric vector.
79 |
80 |
81 |
s
82 |
The number of significant digits to be displayed. Defaults to 2. All digits not in the decimal are always shown.
83 |
84 |
85 |
r
86 |
For large values, the number of digits after the decimals to be displayed (beyond the number of significant digits). Defaults to 0. It is useful to suggest that a number is not an integer.
87 |
88 |
89 |
commas
90 |
Whether or not to add commas to separate thousands. Defaults to TRUE.
91 |
92 |
93 |
94 |
Value
95 |
96 |
97 |
It returns a character vector of the same length as the input.
98 |
99 |
100 |
101 |
Examples
102 |
103 | x=rnorm(1e5)
104 | x[sample(1e5, 1e4, TRUE)]=NA
105 |
106 | # Dumb function telling the number of NA values
107 | tell_na=function(x)message("x contains ", fsignif(sum(is.na(x))), " NA values.")
108 |
109 | tell_na(x)
110 | #> x contains 9,473 NA values.
111 |
112 | # Some differences with signif:
113 | show_diff=function(x, d=2)cat("signif(x, ", d, ") -> ", signif(x, d),
114 | " vs fsignif(x, ", d, ") -> ",
115 | fsignif(x, d), "\n", sep ="")
116 |
117 | # Main difference is for large numbers
118 | show_diff(95123.125)
119 | #> signif(x, 2) -> 95000 vs fsignif(x, 2) -> 95,123
120 | show_diff(95123.125, 7)
121 | #> signif(x, 7) -> 95123.12 vs fsignif(x, 7) -> 95,123.12
122 |
123 | # Identical for small numbers
124 | show_diff(pi/500)
125 | #> signif(x, 2) -> 0.0063 vs fsignif(x, 2) -> 0.0063
126 |
127 |
128 |
Summary statistics of a packages: number of lines, number of functions, etc...
63 |
64 |
65 |
66 |
package_stats()
67 |
68 |
69 |
70 |
Value
71 |
72 |
73 |
Doesn't return anything, just a prompt in the console.
74 |
75 |
76 |
Details
77 |
This function looks for files in the R/ and src/ folders and gives some stats. If there is no R/ folder directly accessible from the working directory, there will be no stats displayed.
78 |
Why this function? Well, it's just some goodies for package developers trying to be user-friendly!
79 |
The number of documentation lines (and number of words) corresponds to the number of non-empty roxygen documentation lines. So if you don't document your code with roxygen, well, this stat won't prompt.
80 |
Code lines correspond to non-commented, non-empty lines (by non empty: at least one letter must appear).
81 |
Comment lines are non-empty comments.
82 |
83 |
84 |
85 |
Examples
86 |
87 | package_stats()
88 | #> Your project doesn't look like a package... Sorry, no stats!
89 |
90 |
This function allows to disable, or re-enable, all calls to check_arg within any function. Useful only when running (very) large loops (>100K iter.) over small functions that use dreamerr's check_arg.
63 |
64 |
65 |
66 |
setDreamerr_check(check =TRUE)
67 |
68 |
69 |
70 |
Arguments
71 |
check
72 |
Strict logical: either TRUE of FALSE. Default is TRUE.
73 |
74 |
75 |
76 |
Author
77 |
Laurent Berge
78 |
79 |
80 |
81 |
Examples
82 |
83 | # Let's create a small function that returns the argument
84 | # if it is a single character string, and throws an error
85 | # otherwise:
86 |
87 | test=function(x){
88 | check_arg(x, "scalar character")
89 | x
90 | }
91 |
92 | # works:
93 | test("hey")
94 | #> [1] "hey"
95 | # error:
96 | try(test(55))
97 | #> Error : in test(55):
98 | #> Argument `x` must be a character scalar.
99 | #> PROBLEM: it is not of type character (instead it is of type 'numeric').
100 |
101 | # Now we disable argument checking
102 | setDreamerr_check(FALSE)
103 | # works (although it shouldn't!):
104 | test(55)
105 | #> [1] 55
106 |
107 | # re-setting argument checking on:
108 | setDreamerr_check(TRUE)
109 |
110 |
111 |
112 |
113 |
114 |
115 |
117 |
118 |
119 |
120 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/docs/sitemap.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /404.html
5 |
6 |
7 | /articles/dreamerr_introduction.html
8 |
9 |
10 | /articles/index.html
11 |
12 |
13 | /authors.html
14 |
15 |
16 | /index.html
17 |
18 |
19 | /news/index.html
20 |
21 |
22 | /reference/check_arg.html
23 |
24 |
25 | /reference/check_expr.html
26 |
27 |
28 | /reference/dreamerr-package.html
29 |
30 |
31 | /reference/enumerate_items.html
32 |
33 |
34 | /reference/fit_screen.html
35 |
36 |
37 | /reference/fsignif.html
38 |
39 |
40 | /reference/ifsingle.html
41 |
42 |
43 | /reference/index.html
44 |
45 |
46 | /reference/n_times.html
47 |
48 |
49 | /reference/package_stats.html
50 |
51 |
52 | /reference/plural.html
53 |
54 |
55 | /reference/setDreamerr_check.html
56 |
57 |
58 | /reference/setDreamerr_dev.mode.html
59 |
60 |
61 | /reference/setDreamerr_show_stack.html
62 |
63 |
64 | /reference/set_check.html
65 |
66 |
67 | /reference/set_up.html
68 |
69 |
70 | /reference/sfill.html
71 |
72 |
73 | /reference/stop_hook.html
74 |
75 |
76 | /reference/stop_up.html
77 |
78 |
79 | /reference/suggest_item.html
80 |
81 |
82 | /reference/validate_dots.html
83 |
84 |
85 |
--------------------------------------------------------------------------------
/man/check_expr.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/stop.R
3 | \name{check_expr}
4 | \alias{check_expr}
5 | \alias{check_expr_hook}
6 | \alias{generate_check_expr_hook}
7 | \title{Checks the evaluation of an expression}
8 | \usage{
9 | check_expr(expr, ..., clean, up = 0, arg_name, verbatim = FALSE)
10 |
11 | check_expr_hook(expr, ..., clean, arg_name, verbatim = FALSE)
12 |
13 | generate_check_expr_hook(namespace)
14 | }
15 | \arguments{
16 | \item{expr}{An expression to be evaluated.}
17 |
18 | \item{...}{Character scalars. The values of \code{...} will be coerced with the function
19 | \href{https://lrberge.github.io/stringmagic/articles/guide_string_magic.html}{string_magic}.
20 | This means that string interpolation is allowed. Ex: \code{"Arg. {arg} should be positive"}
21 | leads to \code{"Arg. power should be positive"} if \code{arg} is equal to "power".
22 |
23 | If argument \code{verbatim} is \code{TRUE}, the values are instead coereced with \code{paste0}.}
24 |
25 | \item{clean}{Character vector, default is missing. If provided, the function
26 | \href{https://lrberge.github.io/stringmagic/reference/string_clean.html}{\code{string_clean}}
27 | is applied to the \emph{captured error message} to clean it when necessary. Each element
28 | of the vector should be of the form \code{"pat => rep"} with pat a regular expression
29 | to be replace and \code{rep} the replacement.}
30 |
31 | \item{up}{Integer, default is 0. It is used to construct the call in the error message.
32 | By default the call reported is the function containing \code{check_expr}. If you want to
33 | report a function higher in the stack, use \code{up = 1}, or higher.}
34 |
35 | \item{arg_name}{Character scalar, default is missing. Used when the expression in
36 | \code{expr} leads to an error and the custom message is missing (i.e. no element is
37 | provided in \code{...}). In that case, the default message is: "The argument \verb{\{}arg_name\verb{\}} could not be evaluated.".
38 | The default value for \code{arg_name} is \code{deparse(substitute(expr))}, if this guess is wrong,
39 | use \code{arg_name}.}
40 |
41 | \item{verbatim}{Logical scalar, default is \code{FALSE}. By default the elements of \code{...}
42 | allow string interpolation with "\code{{}}" using \href{https://github.com/lrberge/stringmagic}{stringmagic}.
43 | If \code{TRUE}, no interpolation is performed.}
44 |
45 | \item{namespace}{Character scalar giving the namespace for which the hooks are valid. Only useful
46 | when hook functions are used in a package.}
47 | }
48 | \description{
49 | This functions checks the evaluation of an expression and, if an error is thrown,
50 | captures it and integrates the captured message after a custom error message.
51 | }
52 | \details{
53 | The purpose of this functions is to provide useful error messages to the user.
54 | }
55 | \section{Functions}{
56 | \itemize{
57 | \item \code{check_expr_hook()}: As \code{check_expr} but sets the error call at the level of the hooked function
58 |
59 | \item \code{generate_check_expr_hook()}: Generates a package specific \code{check_expr_hook} function
60 |
61 | }}
62 | \examples{
63 |
64 | test = function(x, y){
65 | check_expr(mean(x, y), "Computing the mean didn't work:")
66 | }
67 |
68 |
69 | }
70 | \seealso{
71 | For general argument checking, see \code{\link[=check_arg]{check_arg()}} and \code{\link[=check_set_arg]{check_set_arg()}}.
72 | }
73 | \author{
74 | Laurent Berge
75 | }
76 |
--------------------------------------------------------------------------------
/man/dreamerr-package.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/dreamerr.R
3 | \docType{package}
4 | \name{dreamerr-package}
5 | \alias{dreamerr}
6 | \alias{dreamerr-package}
7 | \title{Error Handling Made Easy}
8 | \description{
9 | The main purpose of this package is twofold: i) to facilitate the developer's life, and ii) to provide to the users meaningful, useful error messages. These objectives are accomplished with a single function: \code{\link[dreamerr]{check_arg}}. That function checks the arguments given by the user: it offers a compact syntax such that complex arguments can be simply stated by the developer. In turn, if the user provides an argument of the wrong type then an informative error message will be buit, stating the expected type and where the error comes from--saving the user quite some time in debugging.
10 | }
11 | \details{
12 | Thus you can very easily make your package look professional with \code{\link[dreamerr]{check_arg}} (checking arguments properly \emph{is} professional).
13 |
14 | It also offers a set of small tools to provide informative messages to the users. See \code{\link[dreamerr]{stop_up}} and \code{\link[dreamerr:stop_up]{warn_up}} to throw errors and warnings in the appropriate location. There are many tools to form messages: \code{\link[dreamerr]{enumerate_items}} to form textual list of elements (with many options including conjugating verbs, etc...), \code{\link[dreamerr]{plural}} to conjugate verbs depending on the argument, and \code{\link[dreamerr:n_times]{n_letter}}, \code{\link[dreamerr:n_times]{n_th}}, \code{\link[dreamerr]{n_times}} to write integers in words (which usually looks nicer).
15 |
16 | To sum up in a few words, this package was created to enhance the user experience and facilitate package development.
17 | }
18 | \seealso{
19 | Useful links:
20 | \itemize{
21 | \item Report bugs at \url{https://github.com/lrberge/dreamerr/issues}
22 | }
23 |
24 | }
25 | \author{
26 | \strong{Maintainer}: Laurent Berge \email{laurent.berge@u-bordeaux.fr}
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/man/enumerate_items.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/misc_funs.R
3 | \name{enumerate_items}
4 | \alias{enumerate_items}
5 | \title{Enumerates the elements of a vector}
6 | \usage{
7 | enumerate_items(
8 | x,
9 | type,
10 | verb = FALSE,
11 | s = FALSE,
12 | past = FALSE,
13 | or = FALSE,
14 | start_verb = FALSE,
15 | quote = FALSE,
16 | enum = FALSE,
17 | other = "",
18 | nmax = 7
19 | )
20 | }
21 | \arguments{
22 | \item{x}{A vector.}
23 |
24 | \item{type}{A single character string, optional. If this argument is used, it supersedes all other arguments. It compactly provides the arguments of the function: it must be like \code{"arg1.arg2.arg3"}, i.e. a list of arguments separated by a point. The arguments are: "s" (to add a starting s if \code{length(x)>1}), "or" (to have "or" instead of "and"), "start" (to place the verb at the start instead of in the end), "quote" (to quote the elements of the vector), "enum" (to make an enumeration), "past" (to put the verb in past tense), a verb (i.e. anything different from the previous codes is a verb). Use \code{other(XX)} to set the argument \code{other} to \code{XX}. See details and examples.}
25 |
26 | \item{verb}{Default is \code{FALSE}. If provided, a verb is added at the end of the string, at the appropriate form. You add the verb at the start of the string using the argument \code{start_verb}. Valid verbs are: "be", "is", "has", "have", and any other verb with a regular form.}
27 |
28 | \item{s}{Logical, default is \code{FALSE}. If \code{TRUE} a \code{s} is added at the beginning of the string if the length of \code{x} is greater than one.}
29 |
30 | \item{past}{Logical, default is \code{FALSE}. If \code{TRUE} the verb is put at the past tense.}
31 |
32 | \item{or}{Logical, default is \code{FALSE}. If \code{TRUE} the two last items of the vector are separated by "or" instead of "and".}
33 |
34 | \item{start_verb}{Logical, default is \code{FALSE}. If \code{TRUE} the verb is placed at the beginning of the string instead of the end.}
35 |
36 | \item{quote}{Logical, default is \code{FALSE}. If \code{TRUE} all items are put in between single quotes.}
37 |
38 | \item{enum}{Logical, default is \code{FALSE}. If provided, an enumeration of the items of \code{x} is created. The possible values are "i", "I", "1", "a" and "A". Example: \code{x = c(5, 3, 12)}, \code{enum = "i"} will lead to "i) 5, ii) 3, and iii) 12".}
39 |
40 | \item{other}{Character scalar, defaults to the empty string: \code{""}. If there are more than \code{nmax} elements, then the character string will end with \code{"and XX others"} with \code{XX} the number of remaining items. Use this argument to change what is between the \code{and} and the \code{XX}. E.g. if \code{other = "any of"}, then you would get \code{"... and any of 15 others"} instead of \code{"... and 15 others"}.}
41 |
42 | \item{nmax}{Integer, default is 7. If \code{x} contains more than \code{nmax} items, then these items are grouped into an "other" group.}
43 | }
44 | \value{
45 | It returns a character string of lentgh one.
46 | }
47 | \description{
48 | Transforms a vector into a single character string enumerating the values of the vector. Many options exist to customize the result. The main purpose of this function is to ease the creation of user-level messages.
49 | }
50 | \section{The argument \code{type}}{
51 |
52 | The argument \code{type} is a "super argument". When provided, it supersedes all other arguments. It offers a compact way to give the arguments to the function.
53 |
54 | Its sytax is as follows: \code{"arg1.arg2.arg2"}, where \code{argX} is an argument code. The codes are "s", "past", "or", "start", "quote", "enum" -- they refer to the function arguments. If you want to add a verb, since it can have a free-form, it is deduced as the argument not equal to the previous codes. For example, if you have \code{type = "s.contain"}, this is identical to calling the function with \code{s = TRUE} and \code{verb = "contain"}.
55 |
56 | A note on \code{enum}. The argument \code{enum} can be equal to "i", "I", "a", "A" or "1". When you include it in \code{type}, by default "i" is used. If you want another one, add it in the code. For example \code{type = "is.enum a.past"} is identical to calling the function with \code{verb = "is"}, \code{past = TRUE} and \code{enum = "a"}.
57 | }
58 |
59 | \examples{
60 |
61 | # Let's say you write an error/information message to the user
62 | # I just use the "type" argument but you can obtain the
63 | # same results by using regular arguments
64 |
65 | x = c("x1", "height", "width")
66 | message("The variable", enumerate_items(x, "s.is"), " not in the data set.")
67 | # Now just the first item
68 | message("The variable", enumerate_items(x[1], "s.is"), " not in the data set.")
69 |
70 | # Past
71 | message("The variable", enumerate_items(x, "s.is.past"), " not found.")
72 | message("The variable", enumerate_items(x[1], "s.is.past"), " not found.")
73 |
74 | # Verb first
75 | message("The problematic variable", enumerate_items(x, "s.is.start.quote"), ".")
76 | message("The problematic variable", enumerate_items(x[1], "s.is.start.quote"), ".")
77 |
78 | # covid times
79 | todo = c("wash your hands", "stay home", "code")
80 | message("You should: ", enumerate_items(todo[c(1, 1, 2, 3)], "enum 1"), "!")
81 | message("You should: ", enumerate_items(todo, "enum.or"), "?")
82 |
83 |
84 | }
85 | \author{
86 | Laurent Berge
87 | }
88 |
--------------------------------------------------------------------------------
/man/fit_screen.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/misc_funs.R
3 | \name{fit_screen}
4 | \alias{fit_screen}
5 | \title{Nicely fits a message in the current R console}
6 | \usage{
7 | fit_screen(msg, width = NULL, leading_ws = TRUE, leader = "")
8 | }
9 | \arguments{
10 | \item{msg}{Text message: character vector.}
11 |
12 | \item{width}{A number between 0 and 1, or an integer. The maximum width of the screen the message should take.
13 | Numbers between 0 and 1 represent a fraction of the screen. You can also refer to the
14 | screen width with the special variable \code{.sw}. Integers represent the number of characters
15 | and cannot be lower than 15. Default is \code{min(120, 0.95*.sw)} (the min between 120 characters and
16 | 90\% of the screen width).}
17 |
18 | \item{leading_ws}{Logical, default is \code{TRUE}. Whether to keep the leading
19 | white spaces when the line is cut.}
20 |
21 | \item{leader}{Character scalar, default is the empty string. If provided, this
22 | value will be placed in front of every line.}
23 | }
24 | \value{
25 | It returns a single character vector with line breaks at the appropriate width.
26 | }
27 | \description{
28 | Utility to display long messages with nice formatting. This function cuts the message to fit the current screen width of the R console. Words are never cut in the middle.
29 | }
30 | \details{
31 | This function does not handle tabulations.
32 | }
33 | \examples{
34 |
35 | # A long message of two lines with a few leading spaces
36 | msg = enumerate_items(state.name, nmax = Inf)
37 | msg = paste0(" ", gsub("Michigan, ", "\n", msg))
38 |
39 | # by default the message takes 95\% of the screen
40 | cat(fit_screen(msg))
41 |
42 | # Now we reduce it to 50\%
43 | cat(fit_screen(msg, 0.5))
44 |
45 | # we add leading_ws = FALSE to avoid the continuation of leading WS
46 | cat(fit_screen(msg, 0.5, FALSE))
47 |
48 | # We add "#> " in front of each line
49 | cat(fit_screen(msg, 0.5, leader = "#> "))
50 |
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/man/fsignif.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/misc_funs.R
3 | \docType{data}
4 | \name{fsignif}
5 | \alias{fsignif}
6 | \alias{signif_plus}
7 | \title{Formatting numbers with display of significant digits}
8 | \format{
9 | An object of class \code{function} of length 1.
10 | }
11 | \usage{
12 | fsignif(x, s = 2, r = 0, commas = TRUE)
13 |
14 | signif_plus
15 | }
16 | \arguments{
17 | \item{x}{A numeric vector.}
18 |
19 | \item{s}{The number of significant digits to be displayed. Defaults to 2. All digits not in the decimal are always shown.}
20 |
21 | \item{r}{For large values, the number of digits after the decimals to be displayed (beyond the number of significant digits). Defaults to 0. It is useful to suggest that a number is not an integer.}
22 |
23 | \item{commas}{Whether or not to add commas to separate thousands. Defaults to \code{TRUE}.}
24 | }
25 | \value{
26 | It returns a character vector of the same length as the input.
27 | }
28 | \description{
29 | Formatting of numbers, when they are to appear in messages. Displays only significant digits in a "nice way" and adds commas to separate thousands. It does much less than the \code{\link[base]{format}} function, but also a bit more though.
30 | }
31 | \examples{
32 |
33 | x = rnorm(1e5)
34 | x[sample(1e5, 1e4, TRUE)] = NA
35 |
36 | # Dumb function telling the number of NA values
37 | tell_na = function(x) message("x contains ", fsignif(sum(is.na(x))), " NA values.")
38 |
39 | tell_na(x)
40 |
41 | # Some differences with signif:
42 | show_diff = function(x, d = 2) cat("signif(x, ", d, ") -> ", signif(x, d),
43 | " vs fsignif(x, ", d, ") -> ",
44 | fsignif(x, d), "\n", sep = "")
45 |
46 | # Main difference is for large numbers
47 | show_diff(95123.125)
48 | show_diff(95123.125, 7)
49 |
50 | # Identical for small numbers
51 | show_diff(pi / 500)
52 |
53 |
54 | }
55 | \keyword{datasets}
56 |
--------------------------------------------------------------------------------
/man/ifsingle.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/misc_funs.R
3 | \name{ifsingle}
4 | \alias{ifsingle}
5 | \alias{ifunit}
6 | \title{Conditional element selection}
7 | \usage{
8 | ifsingle(x, yes, no)
9 |
10 | ifunit(x, yes, no)
11 | }
12 | \arguments{
13 | \item{x}{A vector (\code{ifsingle}) or a numeric of length 1 (\code{ifunit}).}
14 |
15 | \item{yes}{Something of length 1. Result if the condition is fulfilled.}
16 |
17 | \item{no}{Something of length 1. Result if the condition is not fulfilled.}
18 | }
19 | \value{
20 | Returns something of length 1.
21 | }
22 | \description{
23 | Tiny functions shorter, and hopefully more explicit, than \code{ifelse}.
24 | }
25 | \details{
26 | Yes, \code{ifunit} is identical to \code{ifelse(test == 1, yes, no)}. And regarding \code{ifsingle}, it is identical to \code{ifelse(length(test) == 1, yes, no)}.
27 |
28 | Why writing these functions then? Actually, I've found that they make the code more explicit, and this helps!
29 | }
30 | \section{Functions}{
31 | \itemize{
32 | \item \code{ifunit()}: Conditional element selection depending on whether \code{x} is equal to unity or not.
33 |
34 | }}
35 | \examples{
36 |
37 | # Let's create an error message when NAs are present
38 | my_crossprod = function(mat){
39 | if(anyNA(mat)){
40 | row_na = which(rowSums(is.na(mat)) > 0)
41 | n_na = length(row_na)
42 | stop("In argument 'mat': ", n_letter(n_na), " row", plural(n_na, "s.contain"),
43 | " NA values (", ifelse(n_na<=3, "", "e.g. "), "row",
44 | enumerate_items(head(row_na, 3), "s"), ").
45 | Please remove ", ifunit(n_na, "it", "them"), " first.")
46 | }
47 | crossprod(mat)
48 | }
49 |
50 | mat = matrix(rnorm(30), 10, 3)
51 | mat4 = mat1 = mat
52 | mat4[c(1, 7, 13, 28)] = NA
53 | mat1[7] = NA
54 |
55 | # Error raised because of NA: informative (and nice) messages
56 | try(my_crossprod(mat4))
57 | try(my_crossprod(mat1))
58 |
59 |
60 | }
61 | \author{
62 | Laurent Berge
63 | }
64 |
--------------------------------------------------------------------------------
/man/n_times.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/misc_funs.R
3 | \name{n_times}
4 | \alias{n_times}
5 | \alias{n_th}
6 | \alias{n_letter}
7 | \title{Numbers in letters}
8 | \usage{
9 | n_times(n)
10 |
11 | n_th(n)
12 |
13 | n_letter(n)
14 | }
15 | \arguments{
16 | \item{n}{An integer vector.}
17 | }
18 | \value{
19 | It returns a character vector of length one.
20 | }
21 | \description{
22 | Set of (tiny) functions that convert integers into words.
23 | }
24 | \section{Functions}{
25 | \itemize{
26 | \item \code{n_th()}: Transforms the integer \code{n} to \code{nth} appropiately.
27 |
28 | \item \code{n_letter()}: Transforms small integers to words.
29 |
30 | }}
31 | \examples{
32 |
33 | find = function(v, x){
34 | if(x \%in\% v){
35 | message("The number ", n_letter(x), " appears ", n_times(sum(v == x)),
36 | ", the first occurrence is the ", n_th(which(v==x)[1]), " element.")
37 | } else message("The number ", n_letter(x), " was not found.")
38 | }
39 |
40 | v = sample(100, 500, TRUE)
41 | find(v, 6)
42 |
43 |
44 |
45 | }
46 | \author{
47 | Laurent Berge
48 | }
49 |
--------------------------------------------------------------------------------
/man/package_stats.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/misc_funs.R
3 | \name{package_stats}
4 | \alias{package_stats}
5 | \title{Provides package statistics}
6 | \usage{
7 | package_stats()
8 | }
9 | \value{
10 | Doesn't return anything, just a prompt in the console.
11 | }
12 | \description{
13 | Summary statistics of a packages: number of lines, number of functions, etc...
14 | }
15 | \details{
16 | This function looks for files in the \code{R/} and \code{src/} folders and gives some stats. If there is no \code{R/} folder directly accessible from the working directory, there will be no stats displayed.
17 |
18 | Why this function? Well, it's just some goodies for package developers trying to be user-friendly!
19 |
20 | The number of documentation lines (and number of words) corresponds to the number of non-empty roxygen documentation lines. So if you don't document your code with roxygen, well, this stat won't prompt.
21 |
22 | Code lines correspond to non-commented, non-empty lines (by non empty: at least one letter must appear).
23 |
24 | Comment lines are non-empty comments.
25 | }
26 | \examples{
27 |
28 | package_stats()
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/man/plural.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/misc_funs.R
3 | \name{plural}
4 | \alias{plural}
5 | \alias{plural_len}
6 | \title{Adds an s and/or a singular/plural verb depending on the argument's length}
7 | \usage{
8 | plural(x, type, s, verb = FALSE, past = FALSE)
9 |
10 | plural_len(x, type, s, verb = FALSE, past = FALSE)
11 | }
12 | \arguments{
13 | \item{x}{An integer of length one (\code{plural}) or a vector \code{plural_len}.}
14 |
15 | \item{type}{Character string, default is missing. If \code{type = "s.is.past"} it means that an "s" will be added if \code{x} is greater than 1 (or of length greater than one for \code{plural_len}); it will be followed by the verb "to be" in past tense in singular or plural form depending on \code{x}. This argument must be made of keywords separated by points without space, the keywords are "s", "past" and a verb (i.e. any thing different than "s" and "past"). Missing keywords mean their value is equal to \code{FALSE}.}
16 |
17 | \item{s}{Logical, used only if the argument type is missing. Whether to add an "s" if the form of \code{x} is plural. Default is missing: equals to \code{TRUE} if no other argument is provided, \code{FALSE} otherwise.}
18 |
19 | \item{verb}{Character string or \code{FALSE}, used only if the argument type is missing. The verb to be inserted in singular or plural depending on the value of \code{x}. default is \code{FALSE}.}
20 |
21 | \item{past}{Logical, used only if the argument type is missing. Whether the verb should be in past tense. Default is \code{FALSE}.}
22 | }
23 | \value{
24 | Returns a character string of length one.
25 | }
26 | \description{
27 | Utilities to write user-level messages. These functions add an \sQuote{s} or a verb at the appropriate form depending on whether the argument is equal to unity (\code{plural}) or of length one (\code{plural_len}).
28 | }
29 | \section{Functions}{
30 | \itemize{
31 | \item \code{plural_len()}: Adds an s and conjugate a verb depending on the length of \code{x}
32 |
33 | }}
34 | \examples{
35 |
36 | # Let's create an error message when NAs are present
37 | my_crossprod = function(mat){
38 | if(anyNA(mat)){
39 | row_na = which(rowSums(is.na(mat)) > 0)
40 | n_na = length(row_na)
41 | stop("In argument 'mat': ", n_letter(n_na), " row", plural(n_na, "s.contain"),
42 | " NA values (", ifelse(n_na<=3, "", "e.g. "), "row",
43 | enumerate_items(head(row_na, 3), "s"),
44 | "). Please remove ", ifunit(n_na, "it", "them"), " first.")
45 | }
46 | crossprod(mat)
47 | }
48 |
49 | mat = matrix(rnorm(30), 10, 3)
50 | mat4 = mat1 = mat
51 | mat4[c(1, 7, 13, 28)] = NA
52 | mat1[7] = NA
53 |
54 | # Error raised because of NA: informative (and nice) messages
55 | try(my_crossprod(mat4))
56 | try(my_crossprod(mat1))
57 |
58 | }
59 | \author{
60 | Laurent Berge
61 | }
62 |
--------------------------------------------------------------------------------
/man/setDreamerr_check.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/stop.R
3 | \name{setDreamerr_check}
4 | \alias{setDreamerr_check}
5 | \title{Sets dreamerr argument checking functions on or off}
6 | \usage{
7 | setDreamerr_check(check = TRUE)
8 | }
9 | \arguments{
10 | \item{check}{Strict logical: either \code{TRUE} of \code{FALSE}. Default is \code{TRUE}.}
11 | }
12 | \description{
13 | This function allows to disable, or re-enable, all calls to \code{\link[dreamerr]{check_arg}} within any function. Useful only when running (very) large loops (>100K iter.) over small functions that use dreamerr's \code{\link[dreamerr]{check_arg}}.
14 | }
15 | \examples{
16 |
17 | # Let's create a small function that returns the argument
18 | # if it is a single character string, and throws an error
19 | # otherwise:
20 |
21 | test = function(x){
22 | check_arg(x, "scalar character")
23 | x
24 | }
25 |
26 | # works:
27 | test("hey")
28 | # error:
29 | try(test(55))
30 |
31 | # Now we disable argument checking
32 | setDreamerr_check(FALSE)
33 | # works (although it shouldn't!):
34 | test(55)
35 |
36 | # re-setting argument checking on:
37 | setDreamerr_check(TRUE)
38 |
39 |
40 | }
41 | \author{
42 | Laurent Berge
43 | }
44 |
--------------------------------------------------------------------------------
/man/setDreamerr_dev.mode.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/stop.R
3 | \name{setDreamerr_dev.mode}
4 | \alias{setDreamerr_dev.mode}
5 | \title{Sets the developer mode to help form check_arg calls}
6 | \usage{
7 | setDreamerr_dev.mode(dev.mode = FALSE)
8 | }
9 | \arguments{
10 | \item{dev.mode}{A logical, default is \code{FALSE}.}
11 | }
12 | \description{
13 | Turns on/off a full fledged checking of calls to \code{\link[dreamerr]{check_arg}}. If on, it enables the developer mode which checks extensively calls to check_arg, allowing to find any problem. If a problem is found, it is pinpointed and the associated help is referred to.
14 | }
15 | \details{
16 | Since this mode ensures a detailed cheking of all \code{\link[dreamerr]{check_arg}} calls, it is thus a strain on performance and should be always turned off otherwise needed.
17 | }
18 | \examples{
19 |
20 | # If you're new to check_arg, given the many types available,
21 | # it's very common to make mistakes when creating check_arg calls.
22 | # The developer mode ensures that any problematic call is spotted
23 | # and the problem is clearly stated
24 | #
25 | # Note that since this mode ensures a detailed cheking of the call
26 | # it is thus a strain on performance and should be always turned off
27 | # otherwise needed.
28 | #
29 |
30 | # Setting the developer mode on:
31 | setDreamerr_dev.mode(TRUE)
32 |
33 | # Creating some 'wrong' calls => the problem is pinpointed
34 |
35 | test = function(x) check_arg(x, "integer scalar", "numeric vector")
36 | try(test())
37 |
38 | test = function(...) check_arg("numeric vector", ...)
39 | try(test())
40 |
41 | test = function(x) check_arg(x$a, "numeric vector")
42 | try(test())
43 |
44 | test = function(x) check_arg(x, "numeric vector integer")
45 | try(test())
46 |
47 | test = function(x) check_arg(x, "vector len(,)")
48 | try(test())
49 |
50 | # etc...
51 |
52 | # Setting the developer mode off:
53 | setDreamerr_dev.mode(FALSE)
54 |
55 |
56 | }
57 | \seealso{
58 | \code{\link[dreamerr]{check_arg}}
59 | }
60 | \author{
61 | Laurent Berge
62 | }
63 |
--------------------------------------------------------------------------------
/man/setDreamerr_show_stack.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/stop.R
3 | \name{setDreamerr_show_stack}
4 | \alias{setDreamerr_show_stack}
5 | \title{Settings telling whether or not to display the full call stack on errors}
6 | \usage{
7 | setDreamerr_show_stack(show_full_stack = FALSE)
8 | }
9 | \arguments{
10 | \item{show_full_stack}{Logical scalar, default is \code{FALSE}. If \code{TRUE}, then
11 | errors generated by dreamerr functions (like \code{\link[=stop_up]{stop_up()}}/\code{\link[=stopi]{stopi()}}) will display
12 | the full call stack.}
13 | }
14 | \description{
15 | Errors generated with dreamerr functions only shows the call to which
16 | the error should point to. If \code{setDreamerr_show_stack} is set to TRUE,
17 | error will display the full call stack instead.
18 | }
19 | \examples{
20 |
21 | # Let's create a toy example of a function relying on an internal function
22 | # for the heavy lifting (although here it's pretty light!)
23 | make_sum = function(a, b){
24 | make_sum_internal(a, b)
25 | }
26 |
27 | make_sum_internal = function(a, b){
28 | if(!is.numeric(a)) stop_up("arg. 'a' must be numeric!")
29 | a + b
30 | }
31 |
32 | # By default if you feed stg non numeric, the call shown is
33 | # make_sum, and not make_sum_internal, since the user could not
34 | # care less of the internal structure of your functions
35 |
36 | try(make_sum("five", 55))
37 |
38 | # Now with setDreamerr_show_stack(TRUE), you would get the full call stack
39 | setDreamerr_show_stack(TRUE)
40 | try(make_sum("five", 55))
41 |
42 |
43 |
44 | }
45 | \author{
46 | Laurent Berge
47 | }
48 |
--------------------------------------------------------------------------------
/man/set_check.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/stop.R
3 | \name{set_check}
4 | \alias{set_check}
5 | \title{Sets argument checking on/off "semi-globally"}
6 | \usage{
7 | set_check(x)
8 | }
9 | \arguments{
10 | \item{x}{A logical scalar, no default.}
11 | }
12 | \description{
13 | You can allow your users to turn off argument checking within your function by using \code{set_check}. Only the functions \code{\link[dreamerr]{check_arg}} nd \code{\link[dreamerr:check_arg]{check_value}} can be turned off that way.
14 | }
15 | \details{
16 | This function can be useful if you develop a function that may be used in large range loops (>100K). In such situations, it may be good to still check all arguments, but to offer the user to turn this checking off with an extra argument (named \code{arg.check} for instance). Doing so you would achieve the feat of i) having a user-friendly function thanks to argument checking and, ii) still achieve high performance in large loops (although the computational footprint of argument checking is quite low (around 30 micro seconds for missing arguments to 80 micro seconds for non-missing arguments of simple type)).
17 | }
18 | \examples{
19 |
20 | # Let's give an example
21 | test_check = function(x, y, arg.check = TRUE){
22 | set_check(arg.check)
23 | check_arg(x, y, "numeric scalar")
24 | x + y
25 | }
26 |
27 | # Works: argument checking on
28 | test_check(1, 2)
29 |
30 | # If mistake, nice error msg
31 | try(test_check(1, "a"))
32 |
33 | # Now argument checking turned off
34 | test_check(1, 2, FALSE)
35 | # But if mistake: "not nice" error message
36 | try(test_check(1, "a", FALSE))
37 |
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/man/set_up.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/stop.R
3 | \name{set_up}
4 | \alias{set_up}
5 | \title{Sets "semi-globally" the 'up' argument of dreamerr's functions}
6 | \usage{
7 | set_up(.up = 1)
8 | }
9 | \arguments{
10 | \item{.up}{An integer greater or equal to 0.}
11 | }
12 | \description{
13 | When \code{\link[dreamerr]{check_arg}} (or \code{\link[dreamerr]{stop_up}}) is used in non user-level functions, the argument \code{.up} is used to provide an appropriate error message referencing the right function.
14 | }
15 | \details{
16 | To avoid repeating the argument \code{.up} in each \code{check_arg} call, you can set it (kind of) "globally" with \code{set_up}.
17 |
18 | The function \code{set_up} does not set the argument \code{up} globally, but only for all calls to \code{check_arg} and \code{check_value} within the same function.
19 | }
20 | \examples{
21 |
22 | # Example with computation being made within a non user-level function
23 |
24 | sum_fun = function(x, y){
25 | my_internal(x, y, sum = TRUE)
26 | }
27 |
28 | diff_fun = function(x, y){
29 | my_internal(x, y, sum = FALSE)
30 | }
31 |
32 | my_internal = function(x, y, sum){
33 | set_up(1) # => errors will be at the user-level function
34 | check_arg(x, y, "numeric scalar mbt")
35 |
36 | # Identical to calling
37 | # check_arg(x, y, "numeric scalar mbt", .up = 1)
38 |
39 | if(sum) return(x + y)
40 | return(x - y)
41 | }
42 |
43 | # we check it works
44 | sum_fun(5, 6)
45 | diff_fun(5, 6)
46 |
47 | # Let's throw some errors
48 | try(sum_fun(5))
49 | try(sum_fun(5, 1:5))
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/man/sfill.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/misc_funs.R
3 | \name{sfill}
4 | \alias{sfill}
5 | \title{Fills a string vector with a symbol}
6 | \usage{
7 | sfill(x = "", n = NULL, symbol = " ", right = FALSE, anchor, na = "NA")
8 | }
9 | \arguments{
10 | \item{x}{A character vector.}
11 |
12 | \item{n}{A positive integer giving the total expected length of each character string. Can be NULL (default). If \code{NULL}, then \code{n} is set to the maximum number of characters in \code{x} (i.e. \code{max(nchar(x))}).}
13 |
14 | \item{symbol}{Character scalar, default to \code{" "}. The symbol used to fill.}
15 |
16 | \item{right}{Logical, default is \code{FALSE}. Whether the character vector should be filled on the left( default) or on the right.}
17 |
18 | \item{anchor}{Character scalar, can be missing. If provided, the filling is done up to this anchor. See examples.}
19 |
20 | \item{na}{Character that will replace any NA value in input. Default is "NA".}
21 | }
22 | \value{
23 | Returns a character vector of the same length as \code{x}.
24 | }
25 | \description{
26 | Fills a string vector with a user-provided symbol, up to the required length.
27 | }
28 | \examples{
29 |
30 | # Some self-explaining examples
31 | x = c("hello", "I", "am", "No-one")
32 | cat(sep = "\n", sfill(x))
33 | cat(sep = "\n", sfill(x, symbol = "."))
34 | cat(sep = "\n", sfill(x, symbol = ".", n = 15))
35 | cat(sep = "\n", sfill(x, symbol = ".", right = TRUE))
36 |
37 | cat(sep = "\n", paste(sfill(x, symbol = ".", right = TRUE), ":", 1:4))
38 |
39 | # Argument 'anchor' can be useful when using numeric vectors
40 | x = c(-15.5, 1253, 32.52, 665.542)
41 | cat(sep = "\n", sfill(x))
42 | cat(sep = "\n", sfill(x, anchor = "."))
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/man/stop_hook.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/stop.R
3 | \name{generate_set_hook}
4 | \alias{generate_set_hook}
5 | \alias{generate_stop_hook}
6 | \alias{generate_warn_hook}
7 | \alias{set_hook}
8 | \alias{generate_get_hook}
9 | \alias{stop_hook}
10 | \alias{warn_hook}
11 | \title{Error displaying a call located at a hook location}
12 | \usage{
13 | generate_set_hook(namespace)
14 |
15 | generate_stop_hook(namespace)
16 |
17 | generate_warn_hook(namespace)
18 |
19 | set_hook()
20 |
21 | generate_get_hook(namespace)
22 |
23 | stop_hook(..., msg = NULL, envir = parent.frame(), verbatim = FALSE)
24 |
25 | warn_hook(..., envir = parent.frame(), immediate. = FALSE, verbatim = FALSE)
26 | }
27 | \arguments{
28 | \item{namespace}{Character scalar giving the namespace for which the hooks are valid. Only useful
29 | when hook functions are used in a package.}
30 |
31 | \item{...}{Objects that will be coerced to character and will compose the error message.}
32 |
33 | \item{msg}{A character vector, default is \code{NULL}. If provided, this message will be displayed right under the error message. This is mostly useful when the text contains formatting because the function \code{\link{stop}} used to send the error message erases any formatting.}
34 |
35 | \item{envir}{An environment, default is \code{parent.frame()}. Only relevant if the error/warning message contains
36 | interpolation (interpolation is performed with \href{https://github.com/lrberge/stringmagic}{stringmagic}). It tells
37 | where the variables to be interpolated should be found. In general you should not worry about this argument.}
38 |
39 | \item{verbatim}{Logical scalar, default is \code{FALSE}. By default the error/warning message allows variable
40 | interpolation with \href{https://github.com/lrberge/stringmagic}{stringmagic}. To disable interpolation,
41 | use \code{verbatim = TRUE}.}
42 |
43 | \item{immediate.}{Whether the warning message should be prompted directly. Defaults to \code{FALSE}.}
44 | }
45 | \description{
46 | When devising complex functions, errors or warnings can be deeply nested in internal
47 | function calls while the user-relevant call is way up the stack. In such cases, these "hook"
48 | functions facilitate the creation of error/warnings informative for the user.
49 | }
50 | \details{
51 | These functions are useful when developing complex functions relying on nested internal functions.
52 | It is important for the user to know where the errors/warnings come from for quick debugging.
53 | This "_hook" family of functions write the call of the user-level function even if the errors
54 | happen at the level of the internal functions.
55 |
56 | If you need these functions within a package, you need to generate the \code{set_hook}, \code{stop_hook} and
57 | \code{warn_hook} functions so that they set, and look up for, hooks speficic to your function. This ensures that
58 | if other functions outside your package also use hooks, there will be no conflict. The only thing to do
59 | is to write this somewhere in the package files:
60 |
61 | \if{html}{\out{