set.gui.path: Declare GUI's Active Document

set.gui.pathR Documentation

Declare GUI's Active Document

Description

set.gui.path() can be used to implement this.path() for arbitrary GUIs. This is similar to set.sys.path() which can be used to implement sys.path() for arbitrary \sourcelink-like functions.

Usage

set.gui.path(...)

thisPathNotExistsError(..., call. = TRUE, domain = NULL,
                       call = .getCurrentCall())

thisPathNotFoundError(..., call. = TRUE, domain = NULL,
                      call = .getCurrentCall())

Arguments

..., call., domain, call

See details.

Details

thisPathNotExistsError() and thisPathNotFoundError() are provided for use inside set.gui.path(), and should not be used elsewhere.

If no arguments are passed to set.gui.path(), the default behaviour will be restored.

If one argument is passed to set.gui.path(), it must be a function that returns the path of the active document in your GUI. It must accept the following arguments: (verbose, original, for.msg, contents) (default values are unnecessary). This makes sense for a GUI which can edit and run R code from several different documents such as RGui, \RStudio, \Positron, \VSCode + \REditorSupport, and \Emacs + \ESS.

If two or three arguments are passed to set.gui.path(), they must be the name of the GUI, the path of the active document, and optionally a function to get the contents of the document. If provided, the function must accept at least one argument which will be the normalized path of the document. This makes sense for a GUI which can edit and run R code from only one document such as \Jupyter and shell.

It is best to call this function as a user hook.

setHook(packageEvent("@R_PACKAGE_NAME@"),
function(pkgname, pkgpath)
{
    @R_PACKAGE_NAME@::set.gui.path(<...>)
}, action = "prepend")

An example for a GUI which can run code from multiple documents:

evalq(envir = new.env(parent = .BaseNamespaceEnv), {
    .guiname <- "myGui"
    .custom_gui_path <- function(verbose, original, for.msg, contents) {
        if (verbose)
            cat("Source: document in", .guiname, "\n")

        ## your GUI needs to know which document is active
        ## and some way to retrieve that document from R
        doc <- <.myGui_activeDocument()>

        ## if no documents are open, 'doc' should be NULL
        ## or some other object to represent no documents open
        if (is.null(doc)) {
            if (for.msg)
                NA_character_
            else stop(@R_PACKAGE_NAME@::thisPathNotExistsError(
                "R is running from ", .guiname, " with no documents open\n",
                " (or document has no path)"))
        }
        else if (contents) {
            ## somehow, get and return the contents of the document
            <doc$contents>
        }
        else {
            ## somehow, get the path of the document
            path <- <doc$path>
            if (nzchar(path)) {
                ## if the path is not normalized, this will normalize it
                if (isTRUE(original))
                    path
                else normalizePath(path, "/", TRUE)
                # ## otherwise, you could just do:
                # path
            }
            else if (for.msg)
                ## return "Untitled" possibly translated
                gettext("Untitled", domain = "RGui", trim = FALSE)
            else
                stop(@R_PACKAGE_NAME@::thisPathNotFoundError(
                    "document in ", .guiname, " does not exist"))
        }
    }
    ## recommended to prevent tampering
    lockEnvironment(environment(), bindings = TRUE)
    setHook(packageEvent("@R_PACKAGE_NAME@"),
    function(pkgname, pkgpath) {
        @R_PACKAGE_NAME@::set.gui.path(.custom_gui_path)
    }, action = "prepend")
})

An example for a GUI which can run code from only one document:

evalq(envir = new.env(parent = .BaseNamespaceEnv), {
    .guiname <- "myGui"
    .path <- "~/example.R"
    .custom_get_contents <- function(path) {
        ## get the contents of the document
        readLines(path, warn = FALSE)
    }
    ## recommended to prevent tampering
    lockEnvironment(environment(), bindings = TRUE)
    setHook(packageEvent("@R_PACKAGE_NAME@"), function(pkgname, pkgpath) {
        @R_PACKAGE_NAME@::set.gui.path(.guiname, .path, .custom_get_contents)
    }, action = "prepend")
    # ## if your GUI does not have/need a .custom_get_contents
    # ## function, then this works just as well:
    # setHook(packageEvent("@R_PACKAGE_NAME@"), function(pkgname, pkgpath) {
    #     @R_PACKAGE_NAME@::set.gui.path(.guiname, .path)
    # }, action = "prepend")
})

Value

a list of the previous settings for set.gui.path(), similar to \codelink3base:optionsoptions().


ArcadeAntics/this.path documentation built on July 27, 2024, 12:05 a.m.