@@ -39,10 +39,10 @@ open_rs_doc <- function(path, line = -1L, col = -1L, move_cursor = TRUE) {
3939# ' @name open_rs_doc
4040# ' @export
4141active_rs_doc <- function () {
42- if (! interactive() && ! rstudioapi :: isAvailable ()) {
42+ if (! interactive() && ! is_rstudio ()) {
4343 return (" Non-existing doc" )
4444 }
45- if (! rstudioapi :: isAvailable ()) {
45+ if (! is_rstudio ()) {
4646 cli :: cli_abort(" Not in RStudio." )
4747 }
4848 unsaved_doc <- tryCatch(rstudioapi :: documentPath(), error = function (e ) TRUE )
@@ -79,20 +79,21 @@ active_rs_doc_copy <- function(new = NULL, ..., old = NULL) {
7979 cli :: cli_abort(" Unsaved document, focus on the saved doc you want to save." )
8080 }
8181
82- if (! fs :: path_ext(old ) %in% c(" R" , " qmd" , " Rmd" )) {
83- cli :: cli_abort(" Only R docs for now" )
82+ if (! fs :: path_ext(old ) %in% c(" md " , " R" , " qmd" , " Rmd" )) {
83+ cli :: cli_abort(" Only R and md docs for now" )
8484 }
8585 old_path_file <- fs :: path_ext_remove(fs :: path_file(old ))
86- if (stringr :: str_detect(old , " r-profile|Rprofile" )) {
86+
87+ if (grepl(" r-profile|Rprofile" , old )) {
8788 cli :: cli_abort(" Attempting to copy Rprofile (focus on the document you want)" )
8889 }
8990 if (is.null(new )) {
9091 new_name <- paste0(old_path_file , " -new" )
9192 } else {
92- new_name <- stringr :: str_remove( new , " \\ .R|\\ .qmd| \\ .Rmd$ " )
93+ new_name <- sub( " \\ .R|\\ .[Rq]?md$ " , " " , new )
9394 }
9495 # Hack to ensure file/file.R will be correctly renamed.
95- new_path <- stringr :: str_replace( old , paste0(old_path_file , " \\ ." ), paste0(new_name , " ." ))
96+ new_path <- sub( paste0(old_path_file , " \\ ." ), paste0(new_name , " ." ), old )
9697
9798 copied <- file.copy(old , new_path , overwrite = FALSE )
9899 if (copied ) {
@@ -124,7 +125,7 @@ active_rs_doc_copy <- function(new = NULL, ..., old = NULL) {
124125# ' @examplesIf FALSE
125126# ' active_rs_doc_delete()
126127active_rs_doc_delete <- function () {
127- if (! rlang :: is_interactive() || ! rstudioapi :: isAvailable ()) {
128+ if (! rlang :: is_interactive() || ! is_rstudio ()) {
128129 cli :: cli_abort(c(" Can't delete files in non-interactive sessions." ))
129130 }
130131 doc <- active_rs_doc()
@@ -140,7 +141,7 @@ active_rs_doc_delete <- function() {
140141 if (fs :: is_dir(elems $ full_path )) {
141142 cli :: cli_abort(" Must be a file" , .internal = TRUE )
142143 }
143- if (interactive() && rstudioapi :: isAvailable ()) {
144+ if (interactive() && is_rstudio ()) {
144145 rstudioapi :: documentSave()
145146 }
146147 cli :: cli_inform(c(
@@ -211,7 +212,7 @@ active_rs_doc_delete <- function() {
211212 parent_dir <- fs :: path_file(fs :: path_dir(elems $ full_path ))
212213
213214 if (grepl(" ^temp" , fs :: path_file(elems $ rel_path )) ||
214- (! parent_dir %in% c(" tests" , " testthat" ) && grepl(" ^test-" , fs :: path_file(elems $ rel_path )))) {
215+ (! parent_dir %in% c(" tests" , " testthat" ) && grepl(" ^test-" , fs :: path_file(elems $ rel_path )))) {
215216 reasons_deleting <- c(reasons_deleting , " it has the temp- prefix." )
216217 will_delete <- append(will_delete , TRUE )
217218 }
@@ -256,7 +257,7 @@ active_rs_doc_delete <- function() {
256257 cli :: cli_inform(c(
257258 " v" = " Deleted the active document {.val {elems$rel_path}} because {reasons_deleting}." ,
258259 # FIXME (upstream) the color div doesn't go all the way r-lib/cli#694
259- " i" = paste(cli :: col_grey(" The deleted file" ), " {.path {elems$full_path}}" , cli :: col_grey(" contents are returned invisibly in case you need them." ))
260+ " i" = paste(cli :: col_grey(" The deleted file" ), " {.path {elems$full_path}}" , cli :: col_grey(" contents are returned invisibly in case you need them." ))
260261 ))
261262 contents <- readLines(elems $ full_path , encoding = " UTF-8" )
262263 fs :: file_delete(elems $ full_path )
@@ -361,3 +362,36 @@ normalize_proj_and_path <- function(path, call = caller_env()) {
361362 full_path = full_path
362363 )
363364}
365+
366+ # ' Open Files Pane at current document location
367+ # '
368+ # ' Easily navigate to active file document.
369+ # '
370+ # ' Wrapper around [executeCommand("activateFiles")][rstudioapi::executeCommand()] +
371+ # ' [rstudioapi::filesPaneNavigate()] + [rstudioapi::getActiveDocumentContext()]
372+ # '
373+ # ' @param path A path to file to navigate to (default active document).
374+ # '
375+ # ' @returns NULL, called for its side effects.
376+ # ' @export
377+ active_rs_doc_nav <- function (path = active_rs_doc()) {
378+ if (! is_rstudio() || ! interactive()) {
379+ cli :: cli_abort(" Must use in RStudio interactive sessions." )
380+ }
381+ if (is.null(path )) {
382+ cli :: cli_abort(" Can't navigate to an unsaved file!" )
383+ }
384+ if (fs :: is_file(path )) {
385+ dir <- fs :: path_dir(path )
386+ } else if (fs :: is_dir(path )) {
387+ dir <- path
388+ } else {
389+ cli :: cli_abort(" {.arg path} must be an existing file or directory." )
390+ }
391+ rstudioapi :: executeCommand(" activateFiles" )
392+ rstudioapi :: filesPaneNavigate(dir )
393+ cli :: cli_inform(c(
394+ " v" = " Navigated to {.path {dir}} in RStudio Files Pane."
395+ ))
396+ invisible ()
397+ }
0 commit comments