Skip to content

Commit

Permalink
Merge pull request #190 from jmbarbone/170-todo-ext
Browse files Browse the repository at this point in the history
170 todo ext
  • Loading branch information
jmbarbone committed Jun 4, 2023
2 parents 6c42378 + 2a7c972 commit 09c36f7
Show file tree
Hide file tree
Showing 9 changed files with 229 additions and 35 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/pkgdown.yaml
Expand Up @@ -19,6 +19,8 @@ jobs:
group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: write
steps:
- uses: actions/checkout@v3

Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
@@ -1,5 +1,9 @@
# mark (development version)

* improvements in `todos()` and `fixmes()`
* File extension an now be set [#170](https://github.com/jmbarbone/mark/issues/170), which by default includes `qmd` ([#163]((https://github.com/jmbarbone/mark/issues/104))) and `py` files
* new parameter `ignore` to ignore any files

# mark 0.6.0

## New features
Expand Down
1 change: 1 addition & 0 deletions R/mark-package.R
Expand Up @@ -12,6 +12,7 @@ op.mark <- list( # nolint: object_name_linter.
# control for check_interactive() to return interactive() or TRUE
mark.check_interactive = TRUE,
mark.note.width = NULL,
mark.todos.ext = c("R", "Rmd", "qmd", "md", "py"),
mark.todos.force = FALSE,

mark.days_in_month = 30,
Expand Down
115 changes: 89 additions & 26 deletions R/todo.R → R/todos.R
Expand Up @@ -2,55 +2,105 @@
#'
#' Search for `#`` TODO` tags
#'
#' @details
#' Calls `git grep -in "[#] TODO"` to find any lines of a `.R` or `.Rmd` file
#' with a comment.
#' @details Searches for `TODO` comments in files. Extensions with `md`, `Rmd`,
#' and `qmd` specifically search for a `<-- TODO * -->` string, whereas
#' everything else is found with `# TODO`.
#'
#' @param pattern A character string containing a regular expression to filter
#' for comments after tags; default `NULL` does not filter
#' @param path The file directory to search for the tags
#' @param ... Additional parameters passed to `grep` (Except for `pattern`, `x`,
#' and `value`)
#' for comments after tags; default `NULL` does not filter
#' @param path Where to search for the todos. If this is a directory, paths
#' matching the `ext` will be included. If a file, `ext` is ignored.
#' @param force If `TRUE` will force searching for files in directories that do
#' not contain an `.Rproj` file. This can be controlled with the option
#' `mark.todos.force`
#' @param ext A vector of file extensions to search for todos. Ignored when
#' `path` is not a directory or when `NULL`.
#' @param ignore A regular expression for files to ignore. Ignored if `path` is
#' not a directory or when `NULL`.
#' @param ... Additional parameters passed to `grep` (Except for `pattern`, `x`,
#' and `value`)
#'
#' @return `NULL` if none are found, otherwise a `data.frame` with the line
#' number, file name, and TODO comment.
#'
#' @export
#' @examples
#' \dontrun{
#' file <- tempfile()
#' writeLines(c(
#' "# TODO make x longer",
#' "x <- 1:10",
#' "length(x)",
#' "# TODO add another example",
#' "# FIXME This is a fixme"
#' ), file)
#' todos(path = file)
#' todos("example", path = file)
#' fixmes(path = file)
#' file.remove(file)
#' }
#' @name todos
NULL

#' @rdname todos
#' @export
todos <- function(
pattern = NULL,
path = ".",
force = getOption("mark.todos.force", FALSE),
force = getOption("mark.todos.force"),
ext = getOption("mark.todos.ext"),
ignore = NULL,
...
) {
do_todo("todo", pattern = pattern, path = path, force = force, ...)
do_todo(
"todo",
pattern = pattern,
path = path,
force = force,
ext = ext,
ignore = ignore,
...
)
}

#' @rdname todos
#' @export
fixmes <- function(
pattern = NULL,
path = ".",
force = getOption("mark.todos.force", FALSE),
force = getOption("mark.todos.force"),
ext = getOption("mark.todos.ext"),
ignore = NULL,
...
) {
do_todo("fixme", pattern = pattern, path = path, force = force, ...)
do_todo(
"fixme",
pattern = pattern,
path = path,
force = force,
ext = ext,
ignore = ignore,
...
)
}

do_todo <- function(text, pattern = NULL, path = path, force = FALSE, ...) { # nolint: cyclocomp_linter, line_length_linter.
# fs::dir_ls() would be a lot quicker but would be a new dependency

do_todo <- function( # nolint: cyclocomp_linter.
text,
pattern = NULL,
path = ".",
force = getOption("mark.todos.force"),
ext = getOption("mark.todos.ext"),
ignore = NULL,
...
) {
if (missing(path) || length(path) != 1 || !is.character(path)) {
stop(cond_do_todo_path())
}

stopifnot(file.exists(path), length(text) == 1L)

files <- if (is_dir(path)) {
# when will path be "" ? cusing nzchar() instead
ls <- list(...)

if (is_dir(path)) {
if (
!has_char(path) ||
!(force || length(list.files(path, pattern = "\\.Rproj$")))
Expand All @@ -59,19 +109,27 @@ do_todo <- function(text, pattern = NULL, path = path, force = FALSE, ...) { # n
return(invisible(NULL))
}

list.files(
files <- list.files(
path,
pattern = "\\.r(md)?$",
recursive = TRUE,
ignore.case = TRUE,
full.names = TRUE
)
} else {
if (!grepl(path, pattern = "\\.r(md)?$", ignore.case = TRUE)) {
stop(cond_do_todo_path_r())

if (!is.null(ext)) {
files <- files[tolower(tools::file_ext(files)) %in% tolower(ext)]
}

path
if (!is.null(ignore)) {
params <- ls
params$pattern <- ignore
params$x <- files
params$invert <- TRUE
params$value <- TRUE
files <- do.call(grep, params)
}
} else {
files <- path
}

finds <- lapply(
Expand All @@ -96,9 +154,10 @@ do_todo <- function(text, pattern = NULL, path = path, force = FALSE, ...) { # n
out <- quick_df(c(
file = list(rep(names(finds), vap_int(finds, nrow))),
set_names(as.list(Reduce(rbind, finds)), c("line", text))
))[, c("line", "file", text)]
))

ind <- grepl("\\.rmd$", out[["file"]], ignore.case = TRUE)
out <- out[, c("line", "file", text)]
ind <- tolower(tools::file_ext(out[["file"]])) %in% c("md", "qmd", "rmd")

if (any(ind)) {
# quick fix for Rmd files
Expand All @@ -112,7 +171,11 @@ do_todo <- function(text, pattern = NULL, path = path, force = FALSE, ...) { # n
)

if (!is.null(pattern)) {
out <- out[grep(pattern, out[[text]], value = FALSE, ...), ]
params <- ls
params$pattern <- pattern
params$x <- out[[text]]
params$value <- FALSE
out <- out[do.call(grep, params), , drop = FALSE]
attr(out, "row.names") <- seq_along(attr(out, "row.names")) # nolint: object_name_linter, line_length_linter.
}

Expand Down
2 changes: 1 addition & 1 deletion man/reexports.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 34 additions & 6 deletions man/todos.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

88 changes: 88 additions & 0 deletions tests/testthat/_snaps/diff-time.md
@@ -0,0 +1,88 @@
# snaps

Code
diff_time(x, y)
Output
Time differences in seconds
[1] 8640000

---

Code
diff_time_days(x, y)
Output
Time differences in days
[1] 100

---

Code
diff_time_dyears(x, y)
Output
Time differences in years (365 days)
[1] 0.2739726

---

Code
diff_time_hours(x, y)
Output
Time differences in hours
[1] 2400

---

Code
diff_time_mins(x, y)
Output
Time differences in minutes
[1] 144000

---

Code
diff_time_months(x, y)
Output
Time differences in months (30 days)
[1] 3.333333

---

Code
diff_time_myears(x, y)
Output
Time differences in years (30-day months)
[1] 0.2777778

---

Code
diff_time_secs(x, y)
Output
Time differences in seconds
[1] 8640000

---

Code
diff_time_weeks(x, y)
Output
Time differences in weeks
[1] 14.28571

---

Code
diff_time_wyears(x, y)
Output
Time differences in years (52 weeks)
[1] 0.2747253

---

Code
diff_time_years(x, y)
Output
Time differences in years (365 days)
[1] 0.2739726

2 changes: 1 addition & 1 deletion tests/testthat/_snaps/todos.md
@@ -1,4 +1,4 @@
# todo() errors and messages
# todos() errors and messages

Code
todos(path = path)
Expand Down

0 comments on commit 09c36f7

Please sign in to comment.