[Sciviews-commits] r484 - in pkg: SciViews SciViews/R svMisc svMisc/R svMisc/man

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Sun Jul 8 17:35:35 CEST 2012


Author: phgrosjean
Date: 2012-07-08 17:35:35 +0200 (Sun, 08 Jul 2012)
New Revision: 484

Modified:
   pkg/SciViews/R/misc.R
   pkg/SciViews/TODO
   pkg/svMisc/DESCRIPTION
   pkg/svMisc/R/fileEdit.R
   pkg/svMisc/R/isJGR.R
   pkg/svMisc/R/svMisc-internal.R
   pkg/svMisc/man/fileEdit.Rd
Log:
Further changes to fileEdit() to increase its compatibility with utils::file.edit()

Modified: pkg/SciViews/R/misc.R
===================================================================
--- pkg/SciViews/R/misc.R	2012-07-07 16:28:09 UTC (rev 483)
+++ pkg/SciViews/R/misc.R	2012-07-08 15:35:35 UTC (rev 484)
@@ -12,6 +12,8 @@
 ## Testing is.null(obj) is not enough to decide if an object is empty, because
 ## there may be like numeric(0), character(0), etc. The right way to do so is
 ## to use if (!length(obj)), but it would be more intuitive to define:
+## TODO: isEmpty is a generic function (or even S4?) in filehash that does
+##       something different => change the name!
 isEmpty <- function (x) return(!length(x))
 
 ifElse <- get("ifelse", envir = baseenv())

Modified: pkg/SciViews/TODO
===================================================================
--- pkg/SciViews/TODO	2012-07-07 16:28:09 UTC (rev 483)
+++ pkg/SciViews/TODO	2012-07-08 15:35:35 UTC (rev 484)
@@ -1,5 +1,20 @@
 = SciViews To Do list
 
+* Change isEmpty because clash with a generic in filehash. permutations()
+defined in gtools and e1071 and do something different! Also, combine() is
+defined in both gdata and randomForests. It should really be a generic with the
+gdata version being the default and the randomForest version being
+combine.randomForest(). nobs() in gdata and stats are both S3 generics defined
+a little bit differently... but their default, at least, do something very
+different! There is also object.size() in gdata and utils. In this case, the
+version in gdata is compatible with the one in utils, but it is vectorized.
+For gplots, there is lowess() which is also defined in stats. Indeed, in gplots
+it is a S3 generic with lowess.default() being the same as the function in stats
+=> it is fine! For Rweka, LogitBoost() is also defined in caTools. These seem
+very different and should be named differently too!
+A clash for Args() between gdata and svMisc is solved, because the function in
+svMisc is renamed argsTip().
+
 * Rd files for character, file and misc.
 
 * Refine panel.xxx() functions to avoid warning in case we provide non-par

Modified: pkg/svMisc/DESCRIPTION
===================================================================
--- pkg/svMisc/DESCRIPTION	2012-07-07 16:28:09 UTC (rev 483)
+++ pkg/svMisc/DESCRIPTION	2012-07-08 15:35:35 UTC (rev 484)
@@ -13,7 +13,7 @@
 Maintainer: Philippe Grosjean <phgrosjean at sciviews.org>
 Imports: utils, methods, tools
 Depends: R (>= 2.11.0)
-Suggests: svUnit
+Suggests: svUnit, rJava
 Description: Supporting functions for the GUI API (various utilitary functions)
 License: GPL-2
 URL: http://www.sciviews.org/SciViews-R

Modified: pkg/svMisc/R/fileEdit.R
===================================================================
--- pkg/svMisc/R/fileEdit.R	2012-07-07 16:28:09 UTC (rev 483)
+++ pkg/svMisc/R/fileEdit.R	2012-07-08 15:35:35 UTC (rev 484)
@@ -1,10 +1,62 @@
-fileEdit <- function (file, template = NULL, replace = FALSE, wait = FALSE,
-editor = getOption("fileEditor"))
+fileEdit <- function (..., title = files, editor = getOption("fileEditor"),
+file.encoding = "", template = NULL, replace = FALSE, wait = FALSE)
 {
+    ## Rework files, title and template
+	files <- c(...)
+	lf <- length(files)
+	if (!length(files)) {
+		warning("You must provide at least one file path")
+		return(invisible(FALSE))
+	}	
+	title <- rep(as.character(title), len = lf)
+	if (length(template))
+		template <- rep(as.character(template), len = lf)
+	
+	## If the file(s) do not exist or must be replaced,
+	## create them (possibly from template)
+	toReplace <- (isTRUE(as.logical(replace)) | !file.exists(files)) 
+	if (length(toReplace)) {
+		newFiles <- files[toReplace]
+		if (length(template)) template <- template[toReplace]
+		for (i in 1:length(newFiles)) {
+			if (!length(template) || !nzchar(template[i])) {
+				file.create(newFiles[i])
+			} else if (file.exists(template[i])) {
+				file.copy(template[i], newFiles[i], overwrite = TRUE,
+					copy.mode = FALSE)
+			} else { # Template file not found!
+				warning("Template file '", template[i],
+					'" not found, starting from an empty file')
+				file.create(newFiles[i])
+			}
+		}    		
+	}
+	files <- normalizePath(files)
+	
+	## Manage file encoding
+	if (nzchar(file.encoding) && file.encoding != "native.enc") {
+        tfile <- file
+        for (i in seq_along(file)) {
+            tfile <- tempfile()
+            con <- file(file[i], encoding = file.encoding)
+            writeLines(readLines(con), tfile)
+            close(con)
+            file[i] <- tfile
+        }
+    }
+	
+	## There are a few shortcuts for editors that need to be expanded
+	if (length(editor) && is.character(editor))
+		editor <- switch(tolower(editor),
+			textedit = "open -e -n -W \"%s\"",
+			textwrangler = "edit --wait --resume \"%s\"",
+			bbedit = "edit --wait --resume \"%s\"",
+			editor)
+	
 	## Fallback to "editor", in case no fileEditor is provided
-	if (isWin()) {
-		if (!length(editor)) editor <- getOption("editor")
-	} else if (!grepl("%s", editor)) {
+	if (!length(editor)) {
+		editor <- getOption("editor")
+	} else if (!isWin() && is.character(editor) && !grepl("%s", editor)) {
 		cmd <- paste('which ', '"', editor, '"', sep = "")
 		if (!length(system(cmd, intern = TRUE))) {
 			## Fall back to the default editor (if any)
@@ -12,45 +64,143 @@
 		}	
 	}
 	
-	## If the file does not exists, create one (possibly from template)
-	if (isTRUE(replace) || !file.exists(file)) {
-		if (!length(template)) {
-			file.create(file)
-		} else if (file.exists(template)) {
-			file.copy(template, file, overwrite = TRUE, copy.mode = FALSE)
-		} else { # Template file not found!
-			warning("Template file '", template,
-				'" not found, starting from an empty file')
-			file.create(file)
+	## If not in interactive mode, or expressly no editor provided
+	## We don't edit!
+	if (!interactive() || !length(editor) ||
+		(!is.function(editor) && !nzchar(editor))) {
+		## Do nothing, issue, a warning!
+		warning("Cannot edit files: no editor or not in interactive mode")
+		return(invisible(FALSE))
+	}
+	
+	## Special cases... where we prefer the internal editor
+	## Note: just change editor a little bit to make sure to avoid internal!
+	wait <- isTRUE(as.logical(wait))
+	if (is.character(editor) &&
+		editor %in% c("notepad", "internal", "vi", "open -e -n -W \"%s\"")) {
+		done <- FALSE
+		## 1) JGR
+		if (isJGR()) {
+			for (i in 1:lf)
+				.fileEditJGR(files[i], title = title[i], wait = wait) 
+			done <- TRUE
+		## 2) Windows Rgui
+		} else if (isRgui()) {
+			for (i in 1:lf)
+				.fileEditRgui(files[i], title = title[i], wait = wait)	
+			done <- TRUE
+		## 3) R.app and wait == FALSE (we cannot wait the end of edition using
+		##    the internal R.app editor!) 
+		} else if (isAqua() && !wait) {
+			## Note that, here, the editor in use is the one defined in the
+			## R.app preference dialog box!
+			for (i in 1:lf)
+				file.edit(files[i], title = title[i], fileEncoding = "")
+			done <- TRUE
 		}
+		if (done) return(invisible(TRUE))
 	}
-
-	if (!interactive() || editor == "") {
-		## Do nothing, issue, a warning!
-		warning("Cannot edit '", basename(file),
-			"': no editor or not in interactive mode")
-		return(FALSE)
+	
+	## In any other case, we use the defined editor
+	if (is.function(editor)) {
+		## Here, we need a special editor function that is able to wait!
+		res <- try(editor(file = file, title = title, wait = wait),
+			silent = TRUE)
 	} else {
+		## Construct the command...
 		if (grepl("%s", editor)) {
-			cmd <- sprintf(editor, normalizePath(file))
+			cmds <- sprintf(editor, files)
 		} else {
-			cmd <- paste('"', editor, '" "', normalizePath(file), '"', sep = "")
+			cmds <- paste('"', editor, '" "', files, '"', sep = "")
 		}
-		wait <- isTRUE(as.logical(wait))
-		if (wait) {
-			message("Editing the file '", basename(file),
-			"'... Close the editor to continue!")
+		if (isMac()) msg <- "'... Close the editor (Cmd-Q) to continue!" else
+			msg <- "'... Close the editor to continue!"
+		for (i in 1:length(cmds)) {
+			if (wait) message("Editing the file '", basename(files[i]), msg)
 			flush.console()
+			if (isWin()) {
+				res <- try(system(cmds[i], ignore.stdout = TRUE,
+					ignore.stderr = TRUE, wait = wait, minimized = FALSE,
+					invisible = FALSE, show.output.on.console = FALSE),
+					silent = TRUE)
+			} else {
+				res <- try(system(cmds[i], ignore.stdout = TRUE,
+					ignore.stderr = TRUE, wait = wait), silent = TRUE)
+			}
+			if (inherits(res, "try-error")) break
 		}
-		if (isWin()) {
-			res <- try(system(cmd, ignore.stdout = TRUE, ignore.stderr = TRUE,
-				wait = wait, minimized = FALSE, invisible = FALSE,
-				show.output.on.console = FALSE), silent = TRUE)
-		} else {
-			res <- try(system(cmd, ignore.stdout = TRUE, ignore.stderr = TRUE,
-				wait = wait), silent = TRUE)
+	}
+	if (inherits(res, "try-error")) {
+		warning(as.character(res))  # Transform the error into a warning
+		return(invisible(FALSE))
+	} else return(invisible(TRUE))
+}
+
+.fileEditJGR <- function (file, title = file, wait = FALSE) 
+{
+    ## Check arguments
+	file <- as.character(file)
+	if (length(title) != 1) stop("Only one item for 'file' is accepted")
+	title <- as.character(title)
+	if (length(title) != 1) stop("Only one item for 'title' is accepted")
+	
+	## Check if JGR is operating
+	if (!isJGR()) {
+        message(".fileEditJGR() cannot be used outside JGR.\n")
+        return(invisible(NULL))
+    }
+	
+	## Create a new editor window and open the file in it
+	## Note that, if JGR is loaded, rJava is there too. So .jnew is available!
+	editor <- rJava::.jnew('org/rosuda/JGR/editor/Editor', as.character(file)[1])
+	## Set the title
+	if (title != file) editor$setTitle(title)
+	
+	## Do we wait that the file is edited?
+	if (isTRUE(as.logical(wait))) {
+		message("Editing file '", basename(file),
+			"'... Close the editor to continue!")
+		while(editor$isVisible()) {
+			editor$setState(0L)  # Make sure it is not iconized
+			editor$toFront()     # Make the editor the frontmost window
+			Sys.sleep(0.3)         # Wait for 0.3 sec
 		}
-		return(invisible(!inherits(res, "try-error")))
 	}
-}
- 
\ No newline at end of file
+	return(invisible(editor))
+} 
+
+.fileEditRgui <- function (file, title = file, wait = FALSE) 
+{
+    ## Avoid errors in R CMD check about missing getWindowsHandles() function
+	if (!isWin()) getWindowsHandles <- function(...) return()
+	
+	## Check arguments
+	file <- as.character(file)
+	if (length(title) != 1) stop("Only one item for 'file' is accepted")
+	title <- as.character(title)
+	if (length(title) != 1) stop("Only one item for 'title' is accepted")
+	
+	## Check if we are in RGui
+	if (!isRgui()) {
+        message(".fileEditRgui() cannot be used outside Rgui.\n")
+        return(invisible(NULL))
+    }
+	
+	## Edit file in an Rgui internal editor and track its existence
+	## if wait == TRUE
+	hdl <- getWindowsHandles()
+	file.edit(file, title = title, editor = "internal", fileEncoding = "")
+	hdl2 <- getWindowsHandles()
+	editor <- hdl2[!hdl2 %in% hdl]
+	
+	## Do we wait that the file is edited?
+	if (isTRUE(as.logical(wait)) && length(editor) == 1) {
+		message("Editing file '", basename(file),
+			"'... Close the editor to continue!")
+		flush.console()
+		while(editor %in% getWindowsHandles(minimized = TRUE))
+			Sys.sleep(0.3)         # Wait for 0.3 sec
+	}
+
+	return(invisible(editor))
+} 

Modified: pkg/svMisc/R/isJGR.R
===================================================================
--- pkg/svMisc/R/isJGR.R	2012-07-07 16:28:09 UTC (rev 483)
+++ pkg/svMisc/R/isJGR.R	2012-07-08 15:35:35 UTC (rev 484)
@@ -1,2 +1,6 @@
-isJGR <- function ()
-	("package:JGR" %in% search())
+isJGR <- function () {
+	## Search for .jgr.works on the whoile search path, starting from GlobalEnv
+	if (exists(".jgr.works", envir = .GlobalEnv, inherits = TRUE)) {
+		get(".jgr.works", envir = .GlobalEnv, inherits = TRUE)
+	} else FALSE  # JGR is probably not (correctly) installed
+}

Modified: pkg/svMisc/R/svMisc-internal.R
===================================================================
--- pkg/svMisc/R/svMisc-internal.R	2012-07-07 16:28:09 UTC (rev 483)
+++ pkg/svMisc/R/svMisc-internal.R	2012-07-08 15:35:35 UTC (rev 484)
@@ -10,24 +10,31 @@
 				if (pfdir == "") pfdir <- "c:\\program files"
 				fEdit <- paste(pfdir, "\\Notepad++\\notepad++.exe", sep = "")
 				## ... otherwise, fallback to notepad.exe
-				if (!file.exists(fEdit)) fEdit <- "notepad.exe"
+				if (!file.exists(fEdit)) fEdit <- "notepad"  # Default for Rterm
 			} else if (isMac()) {
+				## Note that, in R.app, one cannot edit and wait for it is done
+				## So, I always define a different editor, but fall back to
+				## internal R.app if internal.if.possible is TRUE
 				## First check if 'edit' is there
 				## (open files in TextWrangler or BBEdit)
 				if (length(system("which edit", intern = TRUE))) {
-					fEdit <- "edit --wait --resume \"%s\""
+					fEdit <- "textwrangler"
 				} else { # Fall back to the default text editor
 					## Note: use "open -e -n -W \"%s\"" to force use of TextEdit
-					fEdit <- "open -t -n -W \"%s\""
-				}
+					fEdit <- "textedit"
+				}			
 			} else { # This is unix
-				## First check if gedit is there...
+				## First check if gedit or kate is there... This is different
+				## from file.edit() and editor that looks directly to EDITOR!
 				if (length(system("which gedit", intern = TRUE))) {
 					fEdit <- "gedit"
 				} else if (length(system("which kate", intern = TRUE))) {
 					fEdit <- "kate"
 				} else { # Fall back to something that is likely to be installed
-					fEdit <- "vi"
+					## Look id EDITOR or VISUAL environment variable is defined
+					fEdit <- Sys.getenv("EDITOR")
+					if (nzchar(fEdit)) fEdit <- Sys.getenv("VISUAL")
+					if (nzchar(fEdit)) fEdit <- "vi"
 				}
 			}
 			options(fileEditor = fEdit)

Modified: pkg/svMisc/man/fileEdit.Rd
===================================================================
--- pkg/svMisc/man/fileEdit.Rd	2012-07-07 16:28:09 UTC (rev 483)
+++ pkg/svMisc/man/fileEdit.Rd	2012-07-08 15:35:35 UTC (rev 484)
@@ -9,24 +9,33 @@
 }
 
 \usage{
-fileEdit(file, template = NULL, replace = FALSE, wait = FALSE,
-    editor = getOption("fileEditor"))
+fileEdit(..., title = files, editor = getOption("fileEditor"), file.encoding = "",
+    template = NULL, replace = FALSE, wait = FALSE)
 }
 
 \arguments{
-  \item{file}{ path to the file to edit. }
-  \item{template}{ a file to use as template if \code{file} must be created.
-    If \code{NULL}, an empty file is created. }
-  \item{replace}{ force replacement of \code{file} if \code{template} is not null. }
-  \item{wait}{ wait for edition to complete. }
+  \item{\dots}{ path to one or more files to edit. }
+  \item{title}{ the title of the editor window (not honoured by all editors,
+    most external editors only display the file name or path). }
   \item{editor}{ editor to use. Either the name of the program, or a string
     containing the command to run, using \%s as replacement tag where to place
-    the filename in the command. }
+    the filename in the command, or a function with 'file', 'title' and 'wait'
+    arguments to delegate process of the files. }
+  \item{file.encoding}{ encoding of the files. If \code{""} or \code{native.enc},
+    the files are considered as being already in the right encoding. }
+  \item{template}{ one or more files to use as template if files must be created.
+    If \code{NULL}, an empty file is created. This argument is recycled for all
+    files to edit. }
+  \item{replace}{ force replacement of files if \code{template} is not null. }
+  \item{wait}{ wait for edition to complete. If more than one file is edited,
+    the program waits sequentially for each file to be edited in turn (with a
+    message in the R console). }
+
 }
 
 \value{
-  The function returns \code{TRUE} if it was able to edit the file or
-  \code{FALSE} otherwise, invisibly.
+  The function returns \code{TRUE} if it was able to edit the files or
+  \code{FALSE} otherwise, invisibly. Encountered errors are reported as warnings.
 }
 
 \note{
@@ -39,7 +48,9 @@
   there is a gedit plugin to submit code directly to R:
   \url{http://rgedit.sourceforge.net/}. Since, gedit natively supports a lot
   of different syntax highlighting, including R, and is lightweight but feature
-  rich, it is recommended as default text editor for \code{fileEdit()} on Unixes.
+  rich, it is recommended as default text editor for \code{fileEdit()} on
+  Unixes. If JGR is run and the editor is "vi" or "internal", then the internal
+  JGR editor is used, otherwise, the provided editor is chosen.
   
   On Mac OS X, if the "edit" program exists, it is used (it is the command line
   program installed by TextWrangler or BBEdit, see
@@ -49,39 +60,46 @@
   installed freely. It can be configured to highlight and submit R code. see
   \url{http://macsci.jelmerborst.nl/files/textwrangler_and_r.php} for
   instructions. It features also several tools that makes it a much better
-  choice than TextEdit for \code{fileEdit()} on Mac OS X.
+  choice than TextEdit for \code{fileEdit()} on Mac OS X. Specify "textwrangler"
+  or "bbedit" to force using these programs. The default value is "textedit",
+  the Mac default text editor, but on R.app, and with \code{wait = FALSE}, the
+  internal R.app editor is used instead in that case. If JGR is run, and the
+  editor is "textedit", "internal" or "vi", then, the internal JGR editor is
+  used instead.
   
   On Windows, if Notepad++ is installed in its default location, it is used,
-  otherwise, the default "notepad.exe" is used. Notepad++ is a free text editor
-  that is much better suited to edit code or text files that the default
-  Windows' notepad application, in particular because it can handle various line
-  end types (Unix, Mac or Windows) and encodings. It also supports syntax
-  highlighting, code completion and much more. So, it is strongly recommended to
-  install it (see \url{http://notepad-plus-plus.org/}) and use it with
-  \code{fileEdit()}. There is also a plugin to submit code to R directly from
-  Notepad++: \url{http://sourceforge.net/projects/npptor/}.
+  otherwise, the default "notepad" is used in Rterm and the internal editors are
+  chosen for Rgui. Notepad++ is a free text editor that is much better suited to
+  edit code or text files that the default Windows' notepad application, in
+  particular because it can handle various line end types (Unix, Mac or Windows)
+  and encodings. It also supports syntax highlighting, code completion and much
+  more. So, it is strongly recommended to install it (see
+  \url{http://notepad-plus-plus.org/}) and use it with \code{fileEdit()}. There
+  is also a plugin to submit code to R directly from Notepad++:
+  \url{http://sourceforge.net/projects/npptor/}.
   
   Of course, you can use your own text editor, just indicate it in the
   \code{fileEditor} option. Note, however, that you should use only lighweight
   and fast starting programs. Also, for the \code{wait = TRUE} argument of
   \code{fileEdit()}, you must check that R waits for the editor to be closed
-  before furter processing code. In some cases, a little command line program is
-  used to start a larger application (like Komodo Edit/IDE), or the program
-  deleguates to an existing instances and exits immediatelly, even if the file
-  is still edited. These programs are not recommended at all for
+  before further processing code. In some cases, a little command line program
+  is used to start a larger application (like for Komodo Edit/IDE), or the
+  program delegates to an existing instances and exits immediatelly, even if the
+  file is still edited. Such editors are not recommended at all for
   \code{fileEdit()}.
   
   If you want to use files that are compatibles between all platforms supported
   by R itself, you should think about using ASCII encoding as much as possible
   and the Windows style of line-ending. That way, you ensure that all the
   default editors will handle those files correctly, including the broken
-  default editor on Windows, notepad.exe, which does not understand at all Mac
+  default editor on Windows, notepad, which does not understand at all Mac
   or Unix line ends!
 }
 
 \author{ Philippe Grosjean <phgrosjean at sciviews.org> }
 
-\seealso{ \code{\link{systemFile}}, \code{\link[base]{file.path}}, \code{\link[base]{file.exists}} }
+\seealso{ \code{\link{systemFile}}, \code{\link[base]{file.path}},
+  \code{\link[base]{file.exists}}, \code{\link[utils]{file.edit}}  }
 
 \examples{
 \dontrun{



More information about the Sciviews-commits mailing list