Learn R Programming

mvbutils (version 2.5.4)

fixr: Editing functions, text objects, and scriptlets

Description

fixr opens a function, (or text object, or scriptlet for making a single object of any type) in your preferred text editor. Control returns immediately to the R{} command line, so you can keep working in R{} and can be editing several objects simultaneously (cf edit). A session-duration list of objects being edited is maintained, so that each object can be easily sourced back into its rightful workspace. These objects will be updated automatically on file-change if you've run autoedit( TRUE), or manually by calling FF(). There is an optional automatic text backup facility. readr also opens a file in your text editor, but in read-only mode, and doesn't update the backups or the list of objects being edited. fixtext is a shorthand form for forcing creation of a text object rather than the default of a function. For non-function and non-text objects, you can edit a scriptlet that creates the object and is stored as its source attribute. The object is updated whenever the scriptlet is changed, by running the scriptlet; see separate section below.

Usage

# Usually: fixr( x) or fixr( x, new.doc=T)
  fixr( x, new=FALSE, install=FALSE, what, fixing, pkg=NULL, character.only=FALSE, new.doc=FALSE)
  # fixtext really has exact same args as fixr, but technically its args are:
  fixtext( x, ...)
  # Usually: readr( x) but exact same args as fixr
  readr( x, ...)
  FF() # manual check and update
  autoedit( do=TRUE) # stick this line in your .First

Arguments

x
a quoted or unquoted name of a function, text object, or general object. You can also write mypack$myfun, or mypack::myfun, or mypack:::myfun, or ..mypack$myfun, to simultaneously set the pkg
character.only
(logical) if TRUE, x is treated as a string naming the object to be edited, rather than the unquoted object name.
new.doc
(logical) if TRUE, add skeleton plain-text R-style documentatation, as per add.flatdoc.to. Also use this to create an empty scriptlet for a general (non-function, non-text) object.
new
(logical, seldom used) if TRUE, edit a blank function template rather than any existing copy in the search path. New edit will go into .GlobalEnv unless argument pkg is set.
install
(logical, rarely used) logical indicating whether to go through the process of asking you about your editor
what
(logical, rarely used) if no pre-existing x, then fixr creates an empty function template by default. Set what="" to create an empty character vector instead-- or just use fixtext.
fixing
(logical, rarely used) FALSE for read-only (i.e. just opening editor to examine the object)
pkg
(string or environment) if non-NULL, then specifies in which package a specific maintained package (see maintain.packages) x should be looked for.
do
(logical) TRUE => automatically update objects from altered files; FALSE => don't.
...
other arguments, except what in fixtext, and fixing in readr, are passed to fixr.

Scriptlets for general objects

fixr can edit an object of any type, within reason; more precisely, it can edit a "scriptlet" of R{} code that generates the object. The scriptlet is evaluated as soon as FF detects a changed file, and the result is assigned to the object. Only the first complete expression in a scriptlet is evaluated; use braces to group multiple expressions. The scriptlet should not include the assignment to the final object; e.g., the scriptlet for myobj should be something like 1:10, not myobj <- 1:10. Evaluation takes place in a temporary environment inheriting from .GlobalEnv, so side-effect assignments during the scriptlet are discarded. The scriptlet itself is stored as the "source" attribute of the object, of class cat. Two cases I find useful are:
  • instructions to create data.frames or matrices by reading from a text file, and maybe doing some initial processing;
  • expressions for complicated calls with particular datasets to model-fitting functions such asglm.
Note that the second case is not meant to be evaluated immediately-- I often just want to save a call, not the result of the call. The solution is to wrap the statement in a call to quote() or expression(). { # Brace needed because several expressions are involved raw.data <- read.table( "bigfile.txt", header=TRUE, row=NULL) # Condense date/time char fields into something more useful: raw.data <- within( raw.data, { Time <- strptime( paste( DATE, TIME, sep=' '), format="%Y-%m-%d %H:%M:%S") rm( DATE, TIME) }) raw.data } To edit a new general object myobj, call fixr( myobj, what=list()); it doesn't matter whether myobj will actually be a list. If you forget the what argument, you can just replace the function template with your scriptlet; the fixr paradigm for general objects is the same as for functions. However, omitting what=list() can lead to problems if your scriptlet fails to parse. If you want to use fixr to edit a general object that wasn't created with fixr, just set new.doc=TRUE; you shouldn't need the what argument. If you're calling fixr on an object that already has a scriptlet, the scriptlet will appear and you edit that. You can use the debug package on scriptlets. To turn debugging on/off, use mtrace( eval.scriptlet) and mtrace( eval.scriptlet, F). Currently, there is no way to select particular scriptlets; either all are debugged (during updating) or none are. The backup files for general objects show the scriptlet, not the result.

Details

When fixr is run for the first time (or if you set install=TRUE), it will ask you for some basic information about your text editor. In particular, you'll need to know what to type at a command prompt to invoke your text editor on a specific file; in Windows, you can usually find this by copying the Properties/Shortcut/Target field of a shortcut, followed by a space and the filename. After supplying these details, fixr will launch the editor and print a message showing some options ("backup.fix", "edit.scratchdir" and "program.editor"), that will need to be set in your .First. function. You should now be able to do that via fixr(.First). Changes to the temporary files used for editing can be checked for automatically whenever a valid R{} command is typed (e.g. by typing 0; alone doesn't work). To set this up, call autoedit() once per session, e.g. in your .First. The manual version of this is FF(). If any file changes are detected, the code is sourced back in and the appropriate function(s) are modified. FF tries to write functions back into the workspace they came from, which might not be .GlobalEnv. If not, you'll be asked whether you want to Save that workspace (provided it's a task-- see cd). FF should still put the function in the right place, even if you've called cd after calling fixr (unless you've detached the original task) or if you moved it. If something goes wrong during an automatic call to FF (very unusual), the automatic-call feature will stop working. To get it back in the current R{} session, do autoedit(F) and then autoedit(T). It will come back anyway in a new R{} session. readr requires a similar installation process. To get the read-only feature, you'll need to add some kind of option/switch on the command line that invokes your text editor; not all text editors support this feature. Similarly to fixr, you'll need to set options( program.reader=<>) in your .First; the installation process will tell you what to use. fixr, and of course fixtext, will also edit character vectors. If the object to be edited exists beforehand and has a class attribute, fixr will not change its class; otherwise, the class will be set to "cat". This means that print invokes the print.cat method, which displays text more readably than the default. Any other attributes on character vectors are stripped. fixr creates a blank function template if the object doesn't exist already, or if new=TRUE. If you want to create a new character vector as opposed to a new function, call fixtext, or equivalently set what="" when you call fixr. If the function has attributes, it's wrapped in a structure(...) construct. If a doc attribute exists, it's printed as free-form text at the end of the file, and the call to structure will end with a line similar to: ,doc=flatdoc( EOF="<>")) When the file is sourced back in, that line will cause the rest of the file-- which should be free-format text, with no escape characters etc.-- to be read in as a doc attribute, which can be displayed by help. If you want to add plain-text documentation, you can also add these lines yourself-- see flatdoc. Calling fixr( myfun, new.doc=TRUE) sets up a documentation template that you can fill in, ready for later conversion to Rd format in a package (see mvbutils.packaging.tools). If the function was being mtraced (see help(package=debug)), FF will re-apply mtrace after loading the edited version. If there is a problem with parsing, the source attribute of the function is updated to the new code, but the function body is invisibly replaced with a stop call, stating that parsing failed. The list of functions being edited by fixr is stored in the variable fix.list in the mvb.session.info environment. When you quit and restart R{}, the function files you have been using will stay open in the editor, but fix.list will be empty; hence, updating the file "myfun.r" will not update the corresponding R{} function. If this happens, just type fixr(myfun) in R{} and when your editor asks you if you want to replace the on-screen version, say no. Save the file again (some editors require a token modification, such as space-then-delete, first) and R{} will notice the update. An automatic text backup facility is available from fixr: see ?get.backup. The backup system also allows you to sort functions by edit date; see ?fix.order. Backup currently only works for functions and character objects.

See Also

.First, edit, cd, get.backup, fix.order, move