[Sciviews-commits] r85 - in komodo/SciViews-K/content: . js js/tools

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Fri Jan 2 15:46:58 CET 2009


Author: prezez
Date: 2009-01-02 15:46:58 +0100 (Fri, 02 Jan 2009)
New Revision: 85

Added:
   komodo/SciViews-K/content/js/tools/io.js
Modified:
   komodo/SciViews-K/content/js/r.js
   komodo/SciViews-K/content/js/sciviews.js
   komodo/SciViews-K/content/js/tools/array.js
   komodo/SciViews-K/content/js/tools/strings.js
   komodo/SciViews-K/content/overlay.xul
Log:
Various changes: source to R via temp files, code sending improvements, modified package handling functions,
new tools/io.js script with (encoding aware) file read/write functions, and many other small changes.

Modified: komodo/SciViews-K/content/js/r.js
===================================================================
--- komodo/SciViews-K/content/js/r.js	2009-01-02 14:24:09 UTC (rev 84)
+++ komodo/SciViews-K/content/js/r.js	2009-01-02 14:46:58 UTC (rev 85)
@@ -14,12 +14,13 @@
 // sv.r.escape(); // Escape R calculation or multiline mode
 // sv.r.setwd(); // Set the working dir (choose or set to current buffer)
 // sv.r.run(); // Run current selection or line in R and goto next line
-// sv.r.runEnter(); // Run current line to pos in R and add a line feed
+// sv.r.runEnter(breakLine = false); // Run current line to pos in R and add a line feed
 // sv.r.source(what); // Source various part of current buffer to R
 // sv.r.send(what); // Send various part of current buffer to R
+// sv.r.addHistory(data, cmd); // Add current command to R's history, used as a procfun in sv.socket.rCommand call
 // sv.r.display(topic, what); // Display 'topic' according to 'what' type
 // sv.r.helpStart(); // Start R help in the default browser
-// sv.r.help(topic); // Get help in R for 'topic', 'topic' is facultative
+// sv.r.help(topic, package); // Get help in R for 'topic', 'topic' is facultative
 // sv.r.example(topic); // Run example in R for 'topic' (facultative)
 // sv.r.search(topic); // Search R help for 'topic'
 // sv.r.search_select(topics); // Callback function: display a list of
@@ -30,7 +31,7 @@
 // sv.r.data_select(data); // Callback function for sv.r.data()
 // sv.r.browseVignettes(); // Open a web page listing all installed vignettes
 // sv.r.saveWorkspace(file, title); // Save data in a .Rdata file
-// sv.r.loadWorkspace(file, title); // Load data from a .RData file
+// sv.r.loadWorkspace(file, attach); //  Load the content of a .RData file into the workspace, or attach it
 // sv.r.saveHistory(file, title); // Save the history in a file
 // sv.r.loadHistory(file, title); // Load the history from a file
 // sv.r.saveGraph(type, file, title, height, width, method);
@@ -42,9 +43,9 @@
 // sv.r.pkg.CRANmirror(); // Select preferred CRAN mirror
 // sv.r.pkg.available(); // List available R packages on selected repositories
 // sv.r.pkg.installed(); // List installed R packages
-// sv.r.pkg.install(); // Install one R package from the repositories
-// sv.r.pkg.install_select(pkgs); // Callback function for sv.r.pkg.install()
-// sv.r.pkg.installDef(); // Call the default package installation routine of R
+// sv.r.pkg.install(); // Install R package(s) from the repositories
+//sv.r.pkg.chooseCRANMirror(andInstall); // replacement for .CRANmirror, optionally calls .install after execution
+
 // sv.r.pkg.installLocal(); // Install one or more R packages from local files
 // sv.r.pkg.installSV(); // Install the Sciviews bundle from CRAN
 // sv.r.pkg.installSVrforge(); // Install development versions of SciViews
@@ -63,19 +64,30 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 // Define the 'sv.r' namespace
-if (typeof(sv.r) == 'undefined') sv.r = { RMinVersion: "2.7.0" };
+if (typeof(sv.r) == 'undefined')
+	sv.r = {
+		RMinVersion: "2.7.0",
+		sep: ";;"
+	};
 
+// TODO: get R encoding after server starts:
+//sv.r.init = function(cmd) {
+//}
+
 // Evaluate code in R
 sv.r.eval = function(cmd) {
+
+	cmd = cmd.trim();
 	// Store the current R command
 	if (sv.socket.prompt == ":> ") {
 		// Special case for q() and quit() => use sv.r.quit() instead
-		if (cmd == "q()" | cmd == "quit()") return(sv.r.quit());
+		if (cmd.search(/^q(?:uit)?\s*\(\s*\)$/) > -1) return(sv.r.quit());
 		// This is a new command
 		sv.socket.cmd = cmd;
 	} else {
 		// We continue previous multiline command
-		sv.socket.cmd += '\n' + cmd;
+		//sv.socket.cmd += '\n' + cmd;
+		sv.socket.cmd += '' + cmd;
 	}
 	if (sv.socket.cmdout) {
 		if (sv.socket.prompt == ":> ") {
@@ -85,7 +97,8 @@
 			sv.cmdout.append(cmd);
 		}
 	}
-	var res = sv.socket.rCommand('<<<e>>>' + cmd, sv.socket.cmdout);
+	var res = sv.socket.rCommand('<<<e>>>' + cmd, sv.socket.cmdout, null, sv.r.addHistory, sv.socket.cmd);
+
 	return(res);
 }
 
@@ -97,6 +110,8 @@
 	var res = sv.socket.rCommand(preCode + cmd, false);
 	return(res);
 }
+
+
 // Tests:
 //sv.r.evalHidden("Sys.sleep(5); cat('done\n')");
 //sv.r.evalHidden("Sys.sleep(5); cat('done\n')", earlyExit = true);
@@ -124,38 +139,58 @@
 }
 
 // Set the current working directory (to current buffer dir, or ask for it)
-sv.r.setwd = function(ask) {
-	var res = false;
-	if (ask == null) {
-		// Set R working directory to current buffer path
-		var kv = ko.views.manager.currentView;
-		if (!kv) return; // No current view, do nothing!
-		kv.setFocus();
-		if(kv.document.isUntitled) {
-			alert("File is not saved yet. Unable to get its directory!");
+sv.r.setwd = function (ask) {
+    var res = false;
+
+	var kv = ko.views.manager.currentView;
+	if (!kv) {
+		return false;
+	}
+
+	kv.setFocus();
+
+    if (ask == null) {
+        if (!kv.document.isUntitled) {
+            //alert("File is not saved yet. Unable to get its directory!");
+            res = sv.r.eval(".odir <- setwd(\"" + kv.document.file.dirName.replace(/\\/g, "/") + "\")");
+			res = true;
+        }
+    } else if (ask == "session") {
+        res = sv.r.eval(".odir <- setwd(getOption(\"R.initdir\"))");
+		res = true;
+    } else if (ask == "previous") {
+        res = sv.r.eval("if (exists(\".odir\")) .odir <- setwd(.odir); getwd()");
+		res = true;
+    }
+
+	if (!res){
+		// try to set current project dir ar default directory
+		var ap = ko.projects.manager.getCurrentProject();
+		if (ap != null) {
+			dir = ko.projects.getDefaultDirectory(ap);
+		} else if (!kv.document.isUntitled) {
+			// if not, look for current file directory
+			dir = kv.document.file.dirName;
 		} else {
-			// Make sure path name is in Unix convention under Windows
-			res = sv.r.eval('.odir <- setwd("' +
-				kv.document.file.dirName.replace(/\\/g, "//") + '")');
+			dir = "";
 		}
-	} else if (ask == "session") {
-		// Switch back to the session directory defined in 'R.initdir' option
-		res = sv.r.eval('.odir <- setwd(getOption("R.initdir"))');
-	} else if (ask == "previous") {
-		// Produce an error in R if .odir is not defined, but it is fine!
-		res = sv.r.eval('if (exists(".odir")) .odir <- setwd(.odir); getwd()');
-	} else {
-		// TODO: a graphical setwd()
-		alert("Graphical selection of R working dir... not implemented yet!");
-	}
-	return(res);
+
+		dir = ko.filepicker.getFolder(dir, "Choose working directory");
+
+		if (dir != null) {
+			res = sv.r.eval(".odir <- setwd(\"" + dir.replace(/\\/g, "/") + "\")");
+		}
+		res = true;
+    }
+
+    return res;
 }
 
 // Run current selection or line buffer in R
 sv.r.run = function() {
 	try {
 		var kv = ko.views.manager.currentView;
-		if (!kv) return; // No current view, do nothing!
+		if (!kv) return false; // No current view, do nothing!
 		kv.setFocus();
 		var ke = kv.scimoz;
 		var currentLine = ke.lineFromPosition(ke.currentPos);
@@ -166,7 +201,8 @@
 			while (ke.selText.replace(/^\s*$/, "") == "") {
 				//Are we at the last line?
 				currentLine = ke.lineFromPosition(ke.currentPos);
-				if( currentLine == ( ke.lineCount - 1 ) ) { return; }
+				if( currentLine == ( ke.lineCount - 1 ) )
+					return false;
 				// Select next line
 				ke.lineDown();
 				ke.home();
@@ -176,116 +212,120 @@
 		var res = sv.r.eval(ke.selText);
 		ke.lineDown();
 		ke.homeDisplay();
-	} catch(e) { return(e); }
-	return(res);
+	} catch(e) {
+		return e;
+	}
+	return res;
 }
 
-// Run current line up to position and add line feed
-sv.r.runEnter = function() {
+// Run current line up to position and optionally add line feed
+sv.r.runEnter = function(breakLine) {
 	try {
 		var res = false;
 		var kv = ko.views.manager.currentView;
-		if (!kv) return; // No current view, do nothing!
+		if (!kv)
+			return false; // No current view, do nothing!
 		kv.setFocus();
 		var ke = kv.scimoz;
 		if (ke.selText == "") {	// Only proceed if selection is empty
-			var pos = ke.currentPos;
-			ke.homeExtend();
-			if (ke.selText != "") res = sv.r.eval(ke.selText);
-			// Add a line feed at pos
-			ke.gotoPos(pos);
-			ke.newLine();
+			// get text from a line and move caret to the eol
+			// do we want to break line here or execute it to the end?
+			var text = sv.getTextRange(breakLine? "linetobegin" : "line", true);
+
+			ko.commands.doCommand('cmd_newlineExtra');
+			if (text != "") res = sv.r.eval(text);
 		}
-	} catch(e) { return(e); }
-	return(res);
+	} catch(e) {
+		return e;
+	}
+	return res;
 }
 
-// Source the whole content of the current buffer
+// Source the current buffer or some part of it
 sv.r.source = function(what) {
 	var res = false;
 	try {
 		var kv = ko.views.manager.currentView;
-		if (!kv) return; // No current view, do nothing!
+		if (!kv)
+			return false; // No current view, do nothing!
 		kv.setFocus();
 		var ke = kv.scimoz;
+
+		var file = kv.document.file.path.replace(/\\/g, "/");
+
 		if (what == null) what = "all"; // Default value
-		// Special case: if "all", then, try sourcing the original file directly
-		// (if saved, or ask to save it)
-		if (what == "all") {
-			// Is this file saved?
-			if (kv.document.isUntitled) {
-				var answer = ko.dialogs.okCancel("File has not been saved" +
-					" yet. Would you like to save it now?", "OK");
-				if (answer == "OK") {
-					ko.commands.doCommand('cmd_save');
-					// Check if it saved now
-					if (!kv.document.isDirty) {
-						// Source it (make sure its name is in Unix convention
-						// under Windows)
-						res = sv.r.eval('source("' +
-							kv.document.file.path.replace(/\\/g, "//") + '")');
-						ko.statusBar.AddMessage("Document sourced in R...",
-							"R", 5000, true);
-					}
-				}
-			} else if (kv.document.isDirty) { // Are last changes saved?
-				var answer = ko.dialogs.okCancel("Changes have not been saved" +
-					" yet. Would you like to save now?", "OK");
-				if (answer == "OK") {
-					ko.commands.doCommand('cmd_save');
-					// Check if it saved now
-					if (!kv.document.isDirty) {
-						// Source it (make sure its name is in Unix convention
-						// under Windows)
-						res = sv.r.eval('source("' +
-							kv.document.file.path.replace(/\\/g, "//") + '")');
-						ko.statusBar.AddMessage("Document sourced in R...",
-							"R", 5000, true);
-					}
-				}
-			} else {
-				// The document is saved => proceed with sourcing it
-				// (make sure its name is in Unix convention under Windows)
-				res = sv.r.eval('source("' +
-					kv.document.file.path.replace(/\\/g, "//") + '")');
-				ko.statusBar.AddMessage("Document sourced in R...",
-					"R", 5000, true);
-			}
+
+		// Special case: if "all" and document is saved, source the original file
+		if (what == "all" && !(kv.document.isUntitled || kv.document.isDirty)) {
+			res = sv.r.eval('source("' + file +  '", encoding = "' + kv.encoding + '")');
+		} else {
+
+			// else, save all or part in the temporary file and source that file.
+			// After executing, tell R to delete it.
+			var code = (what == "all")? ke.text : sv.getTextRange(what);
+			sv.cmdout.clear();
+			sv.cmdout.append(':> source("' + file + '*") # unsaved buffer: ' + what);
+
+			sv.r.evalCallback(
+				// ask R about temporary filename. There should be easier way to do it.
+				"cat(tempfile('sv'))",
+				function(file, text) {
+					sv.io.writefile(file, text, 'utf-8', false);
+
+					file = file.replace(/\\/g, "/");
+					res = sv.r.evalCallback(
+						'source("' + file + '", encoding = "utf-8"); unlink("' + file + '");',
+						sv.cmdout.append
+					);
+				},
+				code);
+
 		}
-		// We will make a copy of the selected code in a temp file
-		// and source it in R
-		var code = sv.getPart(what, what != "all", true); // Copy to clipboard
-		res = sv.r.eval('clipsource()');
-		// If not selected all, para or block, then, change position
-		if (what != "all" & what != "para" & what != "block") {
-			var kv = ko.views.manager.currentView;
-			kv.setFocus();
-			var ke = kv.scimoz;
-			ke.lineDown();
-			ke.homeDisplay();
-		}
-	} catch(e) { return(e); }
-	return(res);
+	} catch(e) {
+		return e;
+	}
+	return res;
 }
 
-// Send whole or a part of the current buffer to R, place cursor at next line
+// Send whole or a part of the current buffer to R
+// place cursor at next line
 sv.r.send = function(what) {
+	var res = false;
+	var kv = ko.views.manager.currentView;
+	if (!kv)
+		return false; // No current view, do nothing!
+	kv.setFocus();
+	var ke = kv.scimoz;
+
 	try {
-		if (what == null) what = "all"; // Default value
-		var code = sv.getPart(what, what != "all"); // Change sel if not 'all'
-		var res = sv.r.eval(code);
-		// If not selected all, para or block, then, change position
-		if (what != "all" & what != "para" & what != "block") {
-			var kv = ko.views.manager.currentView;
-			kv.setFocus();
-			var ke = kv.scimoz;
-			ke.lineDown();
-			ke.homeDisplay();
+		if (!what)
+			what = "all"; // Default value
+
+		var code = sv.getTextRange(what, true);
+		if (code) {
+			res = sv.r.eval(code);
 		}
-	} catch(e) { return(e); }
-	return(res);
+		if (what == "line" || what == "linetoend" || what == "para")
+			ke.charRight();
+
+	} catch(e) {
+		return e;
+	}
+	return res;
 }
 
+// Add current command to R's history,
+// used as a procfun in sv.socket.rCommand call
+sv.r.addHistory = function(data, cmd) {
+	if (sv.socket.prompt == ":> ") {
+		var quotedCmd = cmd.trim();
+		quotedCmd = quotedCmd.replace(/([\\"'])/g, "\\$1").replace(/[\r\n]+/, "\\n").replace("\t", " ");
+
+		sv.socket.rCommand("<<<H>>>" + ".sv.tmp <- strsplit(\"" + quotedCmd + "\", \"\\\\s*([\\r\\n]|<<<n>>>)+\\\\s*\", perl = T)[[1]]; .sv.tmp <- .sv.tmp[.sv.tmp != \"\"]; lapply(.sv.tmp, function(x) {.Internal(addhistory((x))) }); rm(.sv.tmp);", false);
+	}
+}
+
+
 // Display R objects in different ways
 // TODO: allow custom methods + arguments + forcevisible + affect to var
 sv.r.display = function(topic, what) {
@@ -327,16 +367,30 @@
 }
 
 // Get help in R (HTML format)
-sv.r.help = function(topic) {
+sv.r.help = function(topic, pkg) {
 	var res = false;
-	if (typeof(topic) == "undefined" | topic == "") topic = sv.getText();
-	if (topic == "") {
-		alert("Nothing is selected!");
+	if (!topic && !pkg) {
+		if (typeof(topic) == "undefined" || topic == "")
+			topic = sv.getText();
+
+		if (topic == "") {
+			// let's not cry so much about an empty selection
+			ko.statusBar.AddMessage("Selection is empty...", "R", 1000, false);
+			//alert("Nothing is selected!");
+		}
+
 	} else {
-		res = sv.r.evalCallback('cat(unclass(help("' + topic +
-			'", htmlhelp = TRUE)))', sv.browseURI);
+		var cmd = '';
+
+		cmd += pkg? ' package = "' + pkg + '", ' : "";
+		cmd += topic? ' topic = "' + topic + '", ' : "";
+
+		// TODO: error handling when package does not exists
+		res = sv.r.evalCallback('cat(unclass(help(' + cmd + ' htmlhelp = TRUE)))', sv.browseURI);
+
 		ko.statusBar.AddMessage("R help asked for '" + topic + "'",
 			"R", 5000, true);
+
 	}
 	return(res);
 }
@@ -365,7 +419,7 @@
 		"Pattern", topic, "Search R help", "okRsearchPattern");
 	if (topic != null & topic != "") {
 		// Get list of matching items and evaluate it with sv.r.search_select()
-		res = sv.r.evalCallback('cat(apropos("' + topic + '"), sep = "\n")',
+		res = sv.r.evalCallback('cat(apropos("' + topic + '"), sep = "' + sv.r.sep + '")',
 			sv.r.search_select);
 		ko.statusBar.AddMessage("Searching R help for '" + topic + "'",
 			"R", 5000, true);
@@ -380,7 +434,7 @@
 	if (sv.tools.strings.removeLastCRLF(topics) == "") {
 		alert("No item found in R help!");
 	} else {	// Something is returned
-		var items = topics.split("\n");
+		var items = topics.split(sv.r.sep);
 		if (items.length == 1) {
 			// Only one item, show help for it
 			res = sv.r.help(sv.tools.strings.removeLastCRLF(topics));
@@ -474,15 +528,17 @@
   sv.r.eval('save.image("' + file + '")');
 }
 
-// Load the content of a .RData file in the workspace
-sv.r.loadWorkspace = function(file, title) {
+// Load the content of a .RData file into the workspace, or attach it
+sv.r.loadWorkspace = function(file, attach) {
   // Ask for the filename if not provided
-  if (typeof(file) == "undefined") {
-	if (typeof(title) == "undefined") { title = 'Load an .RData file'; }
-	file = ko.filepicker.openFile("", ".RData", title);
-	if (file == null) return;	// User clicked cancel
+  if (!file) {
+	//file = ko.filepicker.openFile("", ".RData", title);
+	file = sv.fileOpen("", ".RData", 'Load an .RData file', ['R workspace (*.RData)|*.RData'], true);
+	alert(typeof file)
+	if (!file)
+		return;	// User clicked cancel
   }
-  sv.r.eval('load("' + file + '")');
+  sv.r.eval((attach? "attach" : "load" ) + '("' + file.replace(/\\/g, "/") + '")');
 }
 
 // Save the history in a file
@@ -493,7 +549,7 @@
 	file = ko.filepicker.saveFile("", ".Rhistory", title);
 	if (file == null) return;	// User clicked cancel
   }
-  sv.r.eval('savehistory("' + file + '")');
+  sv.r.eval('savehistory("' + file.replace(/\\/g, "/") + '")');
 }
 
 // Load the history from a file
@@ -504,10 +560,9 @@
 	file = ko.filepicker.openFile("", ".Rhistory", title);
 	if (file == null) return;	// User clicked cancel
   }
-  sv.r.eval('loadhistory("' + file + '")');
+  sv.r.eval('loadhistory("' + file.replace(/\\/g, "/") + '")');
 }
 
-
 // There is also dev.copy2pdf() copy2eps() + savePlot windows and X11(type = "Cairo")
 sv.r.saveGraph = function(type, file, title, height, width, method) {
   if (typeof(type) == "undefined") { type = "png256"; }
@@ -526,7 +581,7 @@
 	if (file == null) return;	// User clicked cancel
   }
   // Save the current device in R using dev2bitmap()... needs gostscript!
-  sv.r.eval('dev2bitmap("' + file + '", type = "' + type + '", height = ' + height +
+  sv.r.eval('dev2bitmap("' + file.replace(/\\/g, "/") + '", type = "' + type + '", height = ' + height +
 	', width = ' + width + ', method = "' + method + '")');
 }
 
@@ -607,31 +662,31 @@
 // Load one R package
 sv.r.pkg.load = function() {
 	var res = false;
-	// Get list of installed R packages that are not loaded yet
-	res = sv.r.evalCallback('.tmp <- .packages(all.available = TRUE);' +
-		'cat(.tmp[!.tmp %in% .packages()], sep = "\n"); rm(.tmp)',
-		sv.r.pkg.load_select);
 	ko.statusBar.AddMessage("Listing available R packages... please wait",
 		"R", 20000, true);
-	return(res);
-}
 
-// The callback for sv.r.pkg.load
-sv.r.pkg.load_select = function(pkgs) {
-	ko.statusBar.AddMessage("", "R");
-	var res = false;
-	if (sv.tools.strings.removeLastCRLF(pkgs) == "") {
-		alert("All installed R packages seem to be already loaded!");
-	} else {	// Something is returned
-		var items = pkgs.split("\n");
-		// Select the item you want in the list
-		var topic = ko.dialogs.selectFromList("Load R package",
-			"Select one R package to load:", items, "one");
-		if (topic != null) {
-			res = sv.r.eval('library(' +
-				(sv.tools.strings.removeLastCRLF(topic.join(''))) + ')');
-		}
-	}
+	// Get list of installed R packages that are not loaded yet
+	res = sv.r.evalCallback('.tmp <- .packages(all.available = TRUE);' +
+		'cat(.tmp[!.tmp %in% .packages()], sep = "' + sv.r.sep + '"); rm(.tmp)',
+		function(pkgs) {
+			ko.statusBar.AddMessage("", "R");
+			var res = false;
+			if (pkgs.trim() == "") {
+				alert("All installed R packages seem to be already loaded!");
+			} else {	// Something is returned
+				var items = pkgs.split(sv.r.sep);
+				// Select the item you want in the list
+				var topic = ko.dialogs.selectFromList("Load R package",
+					"Select R package(s) to load:", items);
+				if (topic != null) {
+
+					res = sv.r.eval('cat(paste(lapply(c("' + topic.join('", "') + '"), function(pkg) {	res <- try(library(package = pkg, character.only = TRUE)); 	paste ("Package", sQuote(pkg), if (inherits(res, "try-error")) "could not be loaded"  else "loaded")	}), collapse = "\\n"), "\\n")');
+
+				}
+			}
+			return(res);
+		});
+
 	return(res);
 }
 
@@ -639,8 +694,9 @@
 sv.r.pkg.unload = function() {
 	var res = false;
 	// Get list of loaded packages, minus required ones we cannot unload
+
 	res = sv.r.evalCallback('.tmp <- .packages();' +
-		'cat(.tmp[!.tmp %in% c(.required, "base")], sep = "\n"); rm(.tmp)',
+		'cat(.tmp[!.tmp %in% c(if (exists(".required")) .required else NULL, "base")], sep = "' + sv.r.sep + '"); rm(.tmp)',
 		sv.r.pkg.unload_select);
 	ko.statusBar.AddMessage("Listing loaded R packages... please wait",
 		"R", 20000, true);
@@ -654,13 +710,12 @@
 	if (sv.tools.strings.removeLastCRLF(pkgs) == "") {
 		alert("None of the loaded packages are safe to unload!");
 	} else {	// Something is returned
-		var items = pkgs.split("\n");
+		var items = pkgs.split(sv.r.sep);
 		// Select the item you want in the list
 		var topic = ko.dialogs.selectFromList("Unload R package",
 			"Select one R package to unload:", items, "one");
 		if (topic != null) {
-			res = sv.r.eval('detach("package:' +
-				(sv.tools.strings.removeLastCRLF(topic.join(''))) + '")');
+            res = sv.r.eval("detach(\"package:" + topic[0].trim()+ "\")");
 		}
 	}
 	return(res);
@@ -672,7 +727,7 @@
 	// Get list of all packages, minus required and recommended ones we cannot remove
 	res = sv.r.evalCallback('.tmp <- installed.packages(); ' +
 		'.tmp <- rownames(.tmp)[is.na(.tmp[, "Priority"])]; ' +
-		'cat(.tmp[!.tmp %in% c(.required, "svMisc", "svIDE", "svGUI", "svSocket", "svIO", "svViews", "svWidgets", "svDialogs")], sep = "\n"); rm(.tmp)',
+		'cat(.tmp[!.tmp %in% c(if (exists(".required")) .required else NULL, "svMisc", "svIDE", "svGUI", "svSocket", "svIO", "svViews", "svWidgets", "svDialogs")], sep = "' + sv.r.sep + '"); rm(.tmp)',
 		sv.r.pkg.remove_select);
 	ko.statusBar.AddMessage("Listing removable R packages... please wait",
 		"R", 20000, true);
@@ -686,7 +741,7 @@
 	if (sv.tools.strings.removeLastCRLF(pkgs) == "") {
 		alert("None of the installed R packages are safe to remove!");
 	} else {	// Something is returned
-		var items = pkgs.split("\n");
+		var items = pkgs.split(sv.r.sep);
 		// Select the item you want in the list
 		var topic = ko.dialogs.selectFromList("Remove R package",
 			"Select one R package to remove:", items, "one");
@@ -707,39 +762,6 @@
 	return(res);
 }
 
-// Install one R package
-// TODO: allow installing more than one package at a time
-sv.r.pkg.install = function() {
-	var res = false;
-	// Get list of all packages, minus required and recommended ones we cannot remove
-	res = sv.r.evalCallback('cat(rownames(available.packages()), sep = "\n")',
-		sv.r.pkg.install_select);
-	ko.statusBar.AddMessage("Listing available R packages... please wait",
-		"R", 60000, true);
-	return(res);
-}
-
-// The callback for sv.r.pkg.install
-sv.r.pkg.install_select = function(pkgs) {
-	ko.statusBar.AddMessage("", "R");
-	var res = false;
-	if (sv.tools.strings.removeLastCRLF(pkgs) == "") {
-		alert("Don't find available R packages!");
-	} else {	// Something is returned
-		var items = pkgs.split("\n");
-		// Select the item you want in the list
-		var topic = ko.dialogs.selectFromList("Install R package",
-			"Select one R package to install:", items, "one");
-		if (topic != null) {
-			var pkg = (sv.tools.strings.removeLastCRLF(topic.join('')));
-			res = sv.r.eval('install.packages("' + pkg + '")');
-			ko.statusBar.AddMessage("Install package and dependencies... please wait",
-				"R", 60000, true);
-		}
-	}
-	return(res);
-}
-
 // Select repositories
 // TODO: a Komodo version of this that returns pure R code
 sv.r.pkg.repositories = function() {
@@ -748,19 +770,87 @@
 }
 
 // Select CRAN mirror
-// TODO: a Komodo version of this that returns pure R code
 sv.r.pkg.CRANmirror = function() {
-	var res = sv.r.eval('chooseCRANmirror(TRUE)');
+	sv.r.pkg.chooseCRANMirror(false);
+}
+
+sv.r.pkg.install = function(isCRANMirrorSet) {
+	var res = false;
+	if (!isCRANMirrorSet) {
+		res = sv.r.evalCallback("cat(getOption(\"repos\")[\"CRAN\"])",
+			function(cran) {
+					var res = false;
+					if (cran.trim() == "@CRAN@") {
+						res = sv.r.pkg.chooseCRANMirror("install");
+					} else {
+						res = sv.r.pkg.install(true);
+					}
+					return (res);
+			}
+		);
+
+	} else {
+		ko.statusBar.AddMessage("Listing available R packages... please wait",
+				"R", 20000, true);
+		res = sv.r.evalCallback('cat(available.packages()[,1], sep="' + sv.r.sep + '")',
+				function(pkgs) {
+					ko.statusBar.AddMessage("", "R");
+					var res = false;
+					if (pkgs.trim() == "") {
+						alert("Error?");
+					} else {
+						var items = pkgs.split(sv.r.sep);
+						items = ko.dialogs.selectFromList("Install R package",
+							"Select package(s) to install:", items);
+
+						if (items != null) {
+							items = '"' + items.join('", "') + '"';
+							ko.statusBar.AddMessage("Installing packages... please wait", "R");
+							sv.socket.rCommand("install.packages(c(" + items + "))",
+								true, null, function(data) {
+									ko.statusBar.AddMessage("", "R");
+								}
+							);
+						}
+					}
+					return(res);
+				}
+		);
+	}
 	return(res);
 }
 
-// Install packages (the default R version)
-// TODO: merge this with sv.r.pkg.install, but allow more than one package
-sv.r.pkg.installDef = function() {
+// replacement for .CRANmirror, optionally calls .install after execution
+sv.r.pkg.chooseCRANMirror = function(andInstall) {
 	var res = false;
-	res = sv.r.eval('install.packages()');
-	ko.statusBar.AddMessage("Listing available R packages... please wait",
-		"R", 5000, true);
+	res = sv.r.evalCallback(
+		'.sv.tmp <- getCRANmirrors(all = FALSE, local.only = FALSE);cat(.sv.tmp$Name[.sv.tmp$OK == 1], sep="' + sv.r.sep + '"); rm(.sv.tmp)',
+		function(repos) {
+			ko.statusBar.AddMessage("", "R");
+			var res = false;
+
+			if (repos.trim() == "") {
+				alert("Error getting CRAN Mirrors list.");
+			} else {
+				var items = repos.split(sv.r.sep);
+				items = ko.dialogs.selectFromList("CRAN mirrors",
+					"Select CRAN mirror to use:", items, "one");
+
+				if (items != null) {
+					res = sv.r.evalCallback(".sv.tmp <- getCRANmirrors(all = FALSE, local.only = FALSE); .sv.repos <- getOption(\"repos\"); .sv.repos[\"CRAN\"] <- gsub(\"/$\", \"\", .sv.tmp$URL[.sv.tmp$Name == \"" + items[0] + "\"]); options(repos =.sv.repos); rm(.sv.repos, .sv.tmp); cat(getOption(\"repos\")['CRAN']);",
+						function(url) {
+							ko.statusBar.AddMessage("Current CRAN mirror is set to " + url, "R", 5000, false);
+							if (andInstall)
+								sv.r.pkg.install(true);
+						},
+						andInstall);
+				}
+			}
+			return(res);
+		}
+	);
+	ko.statusBar.AddMessage("Retrieving CRAN mirrors list... please wait",
+		"R", 20000, true);
 	return(res);
 }
 
@@ -770,15 +860,23 @@
 sv.r.pkg.installLocal = function() {
 	var res = false;
 	// Get list of files to install
-	var files = ko.filepicker.openFiles(null, null,
-		"Select R package(s) to install (.tar.gz, .zip or .tgz)");
+	//var files = ko.filepicker.openFiles(null, null,
+	//	"Select R package(s) to install (.tar.gz, .zip or .tgz)");
+
+	var files = sv.fileOpen(null, null, "Select R package(s) to install",
+		['Zip archive (*.zip)|*.zip', 'Gzip archive (*.tgz;*.tar.gz)|*.tgz;*.tar.gz'], true);
+
+
 	if (files != null) {
 		var cmd = "install.packages("
-		if (files.length == 1) {
-			cmd += '"' + files.join("") + '", repos = NULL)';
+
+		if (typeof(files) == "object") {
+			cmd += 'c("' + files.join('", "').replace(/\\/g, "/") + '")';
 		} else {
-			cmd += 'c("' + files.join('", "') + '", repos = NULL))';
+			cmd += '"' + files.replace(/\\/g, "/") + '"';
 		}
+		cmd += ', repos = NULL)';
+
 		res = sv.r.eval(cmd);
 		ko.statusBar.AddMessage("Installing R package(s)... please wait",
 			"R", 5000, true);

Modified: komodo/SciViews-K/content/js/sciviews.js
===================================================================
--- komodo/SciViews-K/content/js/sciviews.js	2009-01-02 14:24:09 UTC (rev 84)
+++ komodo/SciViews-K/content/js/sciviews.js	2009-01-02 14:46:58 UTC (rev 85)
@@ -14,6 +14,10 @@
 // sv.getLine(); // Get current line in the active buffer
 // sv.getPart(what, resel, clipboard); // Get a part of text in the buffer
             // or copy it to the clipboard (reset selection if resel == false)
+
+// sv.getTextRange(what, gotoend, select); // Get a part of text in the buffer, but do not operate on selection
+// sv.fileOpen(directory, filename, title, filter, multiple); // file open dialog, more custimizable replacement for ko.filepicker.open
+
 // sv.browseURI(URI, internal); // Show URI in internal or external browser
 // sv.showFile(path, readonly); // Show a file in Komodo, possibly as read-only
 // sv.helpURL(URL); // Display URL help in the default browser
@@ -28,11 +32,12 @@
 // OpenKore Command Output management ('sv.cmdout' namespace)
 // sv.cmdout.append(str, newline); // Append text to the Command Output pane
 // sv.cmdout.clear(); // Clear the Command Output pane
-//
+// sv.cmdout.message(msg, timeout); // // Display message on the Command Output pane's bar
+
 ////////////////////////////////////////////////////////////////////////////////
 
 if (typeof(sv) == 'undefined') {
-	sv = {
+	var sv = {
 		// TODO: set this automatically according to the plugin version
 		version: 0.6,
 		release: 5,
@@ -91,6 +96,7 @@
 	return(currentLine);
 };
 
+
 // Select a part of text in the current buffer and return it
 sv.getPart = function(what, resel, clipboard) {
 	var text = "";
@@ -162,6 +168,176 @@
 	return(text);
 };
 
+
+// Select a part of text in the current buffer and return it
+// differs from sv.getPart that it does not touch the selection
+sv.getTextRange = function(what, gotoend, select) {
+	var text = "";
+	var kv = ko.views.manager.currentView;
+	if (!kv) {
+		return "";
+	}
+	kv.setFocus();
+	var ke = kv.scimoz;
+	// retain these so we can reset the selection after the extraction
+	var curPos = ke.currentPos;
+	var curLine = ke.lineFromPosition(curPos);
+
+	var pStart = Math.min (ke.anchor, curPos);
+	var pEnd = Math.max (ke.anchor, curPos);
+
+	// Depending on 'what', we select different parts of the file
+	// By default, we keep current selection
+	switch(what) {
+	case "sel":
+	   // Simply retain current selection
+	   break;
+	case "function":
+	   // Select an entire R function
+	   // TODO: 	what to do if cursor if outside any function?
+	   // 		currently all of the current level is selected in such case
+	   var funcRx = /function\s*\(/;
+	   var l0, l1;
+		// go up from curLine until line matches funcRx
+	   for (l0 = curLine; l0 >= 0
+			&& ke.getTextRange(pStart = ke.positionFromLine(l0),
+			   ke.getLineEndPosition(l0)).search(funcRx) == -1;
+			l0--) {
+	   }
+	   // get line number corresponding to last element of the function's fold level
+	   l1 = ke.getLastChild(curLine, ke.getFoldLevel(l0));
+	   pEnd = ke.getLineEndPosition(l1);
+
+	   break;
+	case "block":
+		// Select all content between two bookmarks
+		var Mark1, Mark2;
+		Mark1 = ke.markerPrevious(curLine, -1);
+		if (Mark1 == -1)	Mark1 = 0;
+		Mark2 = ke.markerNext(curLine, -1);
+		if (Mark2 == -1)	Mark2 = ke.lineCount - 1;
+
+		pStart = ke.positionFromLine(Mark1);
+		pEnd = ke.getLineEndPosition(Mark2);
+
+	   break;
+	case "para":
+	   // Select the entire paragraph
+	   // go up from curLine until
+	   for (var i = curLine; i >= 0
+			&& ke.lineLength(i) > 0
+			&& ke.getTextRange(
+			   pStart = ke.positionFromLine(i),
+			   ke.getLineEndPosition(i)).trim() != "";
+			i--) {		}
+
+	   for (var i = curLine; i <= ke.lineCount
+			&& ke.lineLength(i) > 0
+			&& ke.getTextRange(ke.positionFromLine(i),
+			   pEnd = ke.getLineEndPosition(i)).trim() != "";
+			i++) {		}
+
+	   break;
+	case "line":
+		 // Select whole current line
+		pStart = ke.positionFromLine(curLine);
+		pEnd = ke.getLineEndPosition(curLine);
+	   break;
+	case "linetobegin":
+	   // Select line content from beginning to anchor
+	   pStart = ke.positionFromLine(curLine);
+	   break;
+	case "linetoend":
+	   // Select line from anchor to end of line
+	   pEnd = ke.getLineEndPosition(curLine);
+	   break;
+	case "end":
+	   // take text from current line to the end
+	   pStart = ke.positionFromLine(curLine);
+	   pEnd = ke.textLength;
+
+	   break;
+	case "all":
+	default:
+	   // Take everything
+	   text = ke.text;
+	}
+
+	if (what != "all") {
+		text = ke.getTextRange(pStart, pEnd).trim();
+		if (gotoend) {
+			ke.gotoPos(pEnd);
+		}
+		if (select) {
+			ke.setSel(pStart, pEnd);
+		}
+	}
+
+	return(text);
+}
+
+
+// file open dialog, more custimizable replacement for ko.filepicker.open
+sv.fileOpen = function(directory, filename, title, filter, multiple) {
+	const nsIFilePicker = Components.interfaces.nsIFilePicker;
+
+	var fp = Components.classes["@mozilla.org/filepicker;1"]
+	  .createInstance(nsIFilePicker);
+
+	if (!title)
+	  title = "Open file";
+
+	var mode = multiple? nsIFilePicker.modeOpenMultiple : nsIFilePicker.modeOpen;
+
+	fp.init(window, title, mode);
+
+	if (filter) {
+	  if (typeof(filter) == "string") {
+		filter = filter.split(',');
+	  }
+
+	  var fi;
+	  for (var i = 0; i  < filter.length; i++) {
+		fi = filter[i].split("|");
+		if (fi.length == 1)
+		  fi[1] = fi[0];
+		fp.appendFilter(fi[0], fi[1]);
+	  }
+	}
+
+  fp.appendFilters(nsIFilePicker.filterAll);
+
+  if (directory) {
+	var lf = Components.classes["@mozilla.org/file/local;1"].
+			createInstance(Components.interfaces.nsILocalFile);
+	lf.initWithPath(directory);
+	fp.displayDirectory = lf;
+  }
+  if (filename) {
+	   fp.defaultString = filename;
+  }
+
+  var rv = fp.show();
+
+  if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
+	var path;
+	if (multiple) {
+		var files = fp.files;
+		path = new Array();
+		while (files.hasMoreElements()) {
[TRUNCATED]

To get the complete diff run:
    svnlook diff /svnroot/sciviews -r 85


More information about the Sciviews-commits mailing list