浏览代码

Release

master v1.7.0
boB Rudis 4 年前
父节点
当前提交
41e68c4b3f
找不到此签名对应的密钥 GPG 密钥 ID: 1D7529BE14E2BBA9
  1. 4
      NEWS.md
  2. 二进制
      RSwitch.xcworkspace/xcuserdata/hrbrmstr.xcuserdatad/UserInterfaceState.xcuserstate
  3. 18
      RSwitch/Swift/Downloaders/DownloadFromRStudioServer.swift
  4. 3
      RSwitch/Swift/Notify.swift
  5. 34
      RSwitch/Swift/RStudioServerSessionWebViewController.swift
  6. 44
      RSwitch/Swift/Utils/Associations.swift
  7. 1
      RSwitch/Swift/Utils/urls.swift
  8. 66
      RSwitch/Swift/exportPopupViewController.swift
  9. 34
      RSwitch/Swift/plotPopupViewController.swift
  10. 64
      guide/_site/index.html
  11. 二进制
      guide/_site/r-macos-downloads.png
  12. 二进制
      guide/_site/rswitch-prefs.png
  13. 12
      guide/_site/site_libs/header-attrs-2.1/header-attrs.js
  14. 2
      guide/_site/site_libs/navigation-1.1/codefolding.js
  15. 二进制
      guide/_site/web-resources.png
  16. 65
      guide/index.Rmd
  17. 二进制
      guide/rswitch-1.5.0-prefs.png
  18. 二进制
      guide/rswitch-1.5.0-resources-reorg.png
  19. 二进制
      guide/rswitch-prefs.png
  20. 二进制
      guide/web-resources.png
  21. 二进制
      releases/RSwitch-1.7.0.app.zip
  22. 1
      rswitch-cmd/main.swift

4
NEWS.md

@ -1,6 +1,10 @@
# 1.7.0
- Added checks for network availability
- Added command-line switcher
- Supports file uploads to and exports from RStudio Server
- Added more web resource URLs
- Added Preference to always check/force that RStudio owns .R and .Rmd files
# 1.4.0

二进制
RSwitch.xcworkspace/xcuserdata/hrbrmstr.xcuserdatad/UserInterfaceState.xcuserstate

二进制文件未显示。

18
RSwitch/Swift/Downloaders/DownloadFromRStudioServer.swift

@ -10,50 +10,40 @@ import Foundation
import Cocoa
func download_from_studio_server(fromRS : String, toFS : String) {
NSLog("download from rstudio server")
let rsURL = URL(string: fromRS)!
let fsURL = URL(string: toFS)!
URLSession.shared.configuration.timeoutIntervalForRequest = 300.0
//URLSession.shared.downloadTask(with: <#T##URLRequest#>)
let task = URLSession.shared.downloadTask(with: rsURL) {
localURL, urlResponse, error in
if (error != nil) {
NSLog("dler \(String(describing: error))")
NSLog("Error exporting from RStudio Server; \(String(describing: error))")
} else {
if let localURL = localURL {
NSLog("We've got the data");
if (FileManager.default.fileExists(atPath: fsURL.path)) {
NSLog("Deleting old file")
do {
try FileManager.default.removeItem(at: fsURL)
} catch {
NSLog("error deleting old file")
NSLog("Error removing file during RStudio Server export; \(error)")
}
}
do {
NSLog("Trying to move the data from \(localURL) to \(fsURL)");
try FileManager.default.moveItem(at: localURL, to: fsURL)
NSWorkspace.shared.openFile(
fsURL.deletingLastPathComponent().absoluteString, withApplication: "Finder"
)
NSWorkspace.shared.openFile(fsURL.deletingLastPathComponent().absoluteString, withApplication: "Finder")
NSWorkspace.shared.activateFileViewerSelecting([fsURL])
} catch {
NSLog("Move Error \(error)")
NSLog("Error moving RStudio Server export file; \(error)")
}
}

3
RSwitch/Swift/Notify.swift

@ -49,13 +49,10 @@ extension AppDelegate : NSUserNotificationCenterDelegate {
}
func userNotificationCenter(_ center: NSUserNotificationCenter, shouldPresent notification: NSUserNotification) -> Bool {
print("should present")
return(true)
}
func userNotificationCenter(_ center: NSUserNotificationCenter, didActivate notification: NSUserNotification) {
print("did activate")
print(notification)
}
}

34
RSwitch/Swift/RStudioServerSessionWebViewController.swift

@ -51,9 +51,6 @@ class RstudioServerSessionWebViewController: NSViewController, NSWindowDelegate
extension RstudioServerSessionWebViewController: WKUIDelegate {
func webView(_ webView: WKWebView, runOpenPanelWith parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping ([URL]?) -> Void) {
NSLog("PANELING!")
print("PANELING!")
let openPanel = NSOpenPanel()
@ -79,9 +76,7 @@ extension RstudioServerSessionWebViewController: WKUIDelegate {
let u = URL(string: navigationAction.request.url!.absoluteString)!
if ((u.urlComponents?.path.starts(with: "/export/")) != nil) {
NSLog("Navigation action thing: " + navigationAction.request.url!.absoluteString)
let exportWindowController = NSStoryboard(name: "Main", bundle: nil).instantiateController(withIdentifier: "exportPopupPanel") as! ExportWebViewController
let exportWV = (exportWindowController.contentViewController as! exportPopupViewController)
@ -89,42 +84,25 @@ extension RstudioServerSessionWebViewController: WKUIDelegate {
exportWV.view.window?.title = navigationAction.request.url!.absoluteString
exportWV.setupWebView(configuration: configuration)
//exportWindowController.showWindow(self)
NSLog("Before exportWV.loadWebView")
// exportWV.loadWebView(urlIn: navigationAction.request.url!.absoluteString)
exportWV.loadWebView(urlIn: "")
NSLog("After exportWV.loadWebView")
let urlPath = navigationAction.request.url!.absoluteString
NSLog("loadWebView: \(urlPath)")
// Check for "/export/"
// If export, then get bring up a Save Panel and then download the file to that location
if let url = URL(string: urlPath) {
NSLog("URL path: \(url.path)")
if (url.path.starts(with: "/export")) {
NSLog(" Name: " + url.queryParameters["name"]!)
let savePanel = NSSavePanel()
savePanel.canCreateDirectories = true
savePanel.nameFieldStringValue = url.queryParameters["name"]!
savePanel.beginSheetModal(for:self.view.window!) { (response) in
if (response == NSApplication.ModalResponse.OK) {
if (response == NSApplication.ModalResponse.OK) {
download_from_studio_server(fromRS: url.absoluteString, toFS: savePanel.url!.absoluteString)
} else {
NSLog("Don't do anything!")
}
savePanel.close()
}

44
RSwitch/Swift/Utils/Associations.swift

@ -12,45 +12,27 @@ import ApplicationServices
class FileAssociationUtils {
public static func getHandlers() {
let workspace = NSWorkspace.shared;
let setResR : String = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, "R" as CFString, nil)?.takeRetainedValue() as String? ?? "";
NSLog("UTI of .R extension: " + setResR);
let handlerR : String = LSCopyDefaultRoleHandlerForContentType(setResR as CFString, LSRolesMask.all)?.takeRetainedValue() as String? ?? "";
NSLog("Bundle ID of handler for .R files is: [" + handlerR + "]");
let rAppUrl : URL = (workspace.urlForApplication(withBundleIdentifier: handlerR))!.appendingPathComponent("Contents/Info.plist");
NSLog("The Info.plist for the app that handles .R files is: " + rAppUrl.absoluteString);
let rAppDict : NSDictionary = NSDictionary(contentsOf: rAppUrl)!;
NSLog("The name of the app that handles .R files is: " + (rAppDict.object(forKey: "CFBundleName") as! String));
let setResRmd : String = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, "Rmd" as CFString, nil)?.takeRetainedValue() as String? ?? "";
NSLog("UTI of .Rmd extension: " + setResRmd);
let handlerRmd : String = LSCopyDefaultRoleHandlerForContentType(setResRmd as CFString, LSRolesMask.all)?.takeRetainedValue() as String? ?? "";
NSLog("Bundle ID of handler for .Rmd files is: [" + handlerRmd + "]");
let rmdAppUrl : URL = (workspace.urlForApplication(withBundleIdentifier: handlerRmd))!.appendingPathComponent("Contents/Info.plist");
NSLog("The Info.plist for the app that handles .Rmd files is: " + rmdAppUrl.absoluteString);
let rmdAppDict : NSDictionary = NSDictionary(contentsOf: rmdAppUrl)!;
NSLog("The name of the app that handles .Rmd files is: " + (rmdAppDict.object(forKey: "CFBundleName") as! String));
}
// public static func getHandlers() {
//
// let workspace = NSWorkspace.shared;
//
// let setResR : String = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, "R" as CFString, nil)?.takeRetainedValue() as String? ?? "";
// let handlerR : String = LSCopyDefaultRoleHandlerForContentType(setResR as CFString, LSRolesMask.all)?.takeRetainedValue() as String? ?? "";
// let rAppUrl : URL = (workspace.urlForApplication(withBundleIdentifier: handlerR))!.appendingPathComponent("Contents/Info.plist");
// let rAppDict : NSDictionary = NSDictionary(contentsOf: rAppUrl)!;
// let setResRmd : String = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, "Rmd" as CFString, nil)?.takeRetainedValue() as String? ?? "";
// let handlerRmd : String = LSCopyDefaultRoleHandlerForContentType(setResRmd as CFString, LSRolesMask.all)?.takeRetainedValue() as String? ?? "";
// let rmdAppUrl : URL = (workspace.urlForApplication(withBundleIdentifier: handlerRmd))!.appendingPathComponent("Contents/Info.plist");
// let rmdAppDict : NSDictionary = NSDictionary(contentsOf: rmdAppUrl)!;
// }
public static func setHandlers() {
let setResR : String = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, "R" as CFString, nil)?.takeRetainedValue() as String? ?? "";
//NSLog("UTI of .R extension: " + setResR);
LSSetDefaultRoleHandlerForContentType(setResR as CFString, LSRolesMask.all, "org.rstudio.RStudio" as CFString);
let setResRmd : String = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, "Rmd" as CFString, nil)?.takeRetainedValue() as String? ?? "";
//NSLog("UTI of .Rmd extension: " + setResRmd);
LSSetDefaultRoleHandlerForContentType(setResRmd as CFString, LSRolesMask.all, "org.rstudio.RStudio" as CFString);

1
RSwitch/Swift/Utils/urls.swift

@ -18,7 +18,6 @@ class QueryParameters {
let queryItems: [URLQueryItem]
init(url: URL?) {
queryItems = URLComponents(string: url?.absoluteString ?? "")?.queryItems ?? []
print(queryItems)
}
subscript(name: String) -> String? {
return queryItems.first(where: { $0.name == name })?.value

66
RSwitch/Swift/exportPopupViewController.swift

@ -33,41 +33,29 @@ class exportPopupViewController: NSViewController {
func loadWebView(urlIn: String) {
urlPath = urlIn
NSLog("loadWebView: \(urlPath)")
// Check for "/export/"
// If export, then get bring up a Save Panel and then download the file to that location
if let url = URL(string: urlPath) {
NSLog("URL path: \(url.path)")
if (url.path.starts(with: "/export")) {
NSLog(" Name: " + url.queryParameters["name"]!)
let savePanel = NSSavePanel()
savePanel.canCreateDirectories = true
savePanel.nameFieldStringValue = url.queryParameters["name"]!
savePanel.beginSheetModal(for:self.view.window!) { (response) in
if (response == NSApplication.ModalResponse.OK) {
download_from_studio_server(fromRS: url.absoluteString, toFS: savePanel.url!.absoluteString)
} else {
NSLog("Don't do anything!")
}
savePanel.close()
}
}
}
// urlPath = urlIn
//
// // Check for "/export/"
// // If export, then get bring up a Save Panel and then download the file to that location
//
// if let url = URL(string: urlPath) {
//
// if (url.path.starts(with: "/export")) {
//
// let savePanel = NSSavePanel()
//
// savePanel.canCreateDirectories = true
// savePanel.nameFieldStringValue = url.queryParameters["name"]!
// savePanel.beginSheetModal(for:self.view.window!) { (response) in
// if (response == NSApplication.ModalResponse.OK) {
// download_from_studio_server(fromRS: url.absoluteString, toFS: savePanel.url!.absoluteString)
// }
// savePanel.close()
// }
//
// }
//
// }
}
@ -88,13 +76,9 @@ extension exportPopupViewController: WKUIDelegate {
extension exportPopupViewController: WKNavigationDelegate {
open func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("Export DID START \(String(describing: webView.url))")
}
open func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { }
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("Export DID FINISH \(String(describing: webView.url))")
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { }
}

34
RSwitch/Swift/plotPopupViewController.swift

@ -33,25 +33,13 @@ class plotPopupViewController: NSViewController {
urlPath = urlIn
NSLog(urlPath)
// Check for "/export/"
// If export, then get bring up a Save Panel and then download the file to that location
if let url = URL(string: urlPath) {
let urlRequest = URLRequest(url: url)
NSLog("URL path: " + url.path)
if (url.path.starts(with: "/export")) {
NSLog(" Name: " + url.queryParameters["name"]!)
DispatchQueue.main.async {
self.webView.removeFromSuperview()
}
} else {
webView.load(urlRequest)
@ -75,20 +63,6 @@ extension plotPopupViewController: WKUIDelegate {
func webView(_ webView: WKWebView, runOpenPanelWith parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping ([URL]?) -> Void) {
NSLog("savePanel!")
let savePanel = NSSavePanel()
savePanel.canCreateDirectories = true
savePanel.beginSheetModal(for:self.view.window!) { (response) in
if (response == NSApplication.ModalResponse.OK) {
completionHandler([savePanel.url!])
} else {
completionHandler(nil)
}
savePanel.close()
}
}
@ -96,13 +70,9 @@ extension plotPopupViewController: WKUIDelegate {
extension plotPopupViewController: WKNavigationDelegate {
open func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("DID START")
}
open func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("DID FINISH")
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { }
}

64
guide/_site/index.html

@ -1,11 +1,10 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="pandoc" />
<meta http-equiv="X-UA-Compatible" content="IE=EDGE" />
@ -14,6 +13,7 @@
<title>Using RSwitch</title>
<script src="site_libs/header-attrs-2.1/header-attrs.js"></script>
<script src="site_libs/jquery-1.11.3/jquery.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="site_libs/bootstrap-3.3.5/css/darkly.min.css" rel="stylesheet" />
@ -87,7 +87,6 @@ code {
}
img {
max-width:100%;
height: auto;
}
.tabbed-pane {
padding-top: 12px;
@ -236,6 +235,7 @@ $(document).ready(function () {
border: none;
display: inline-block;
border-radius: 4px;
background-color: transparent;
}
.tabset-dropdown > .nav-tabs.nav-tabs-open > li {
@ -264,6 +264,12 @@ $(document).ready(function () {
}
}
@media print {
.toc-content {
/* see https://github.com/w3c/csswg-drafts/issues/4434 */
float: right;
}
}
.toc-content {
padding-left: 30px;
@ -376,8 +382,9 @@ div.tocify {
<h2>Credits</h2>
<p>Many thanks to the following folks for their contributions to the project to help make RSwitch better for everyone:</p>
<ul>
<li><a href="https://github.com/guiastrennec">Benjamin Guiastrennec</a> for suggesting improvements to the documentation regarding how to use the installer packages from the <a href="https://mac.r-project.org/">R for macOS Developer’s Page</a> without clobbering existing R Framework installs.</li>
<li><a href="https://github.com/guiastrennec">Benjamin Guiastrennec</a> for suggesting improvements to the documentation regarding how to use the installer packages from the <a href="https://mac.r-project.org/">R for macOS Developer’s Page</a> without clobbering existing R Framework installs and also for encouraging support for RStudio Sever file uploads and exports.</li>
<li><a href="https://github.com/xvrdm">Xavier Adam</a> for <a href="https://github.com/hrbrmstr/RSwitch/pull/4">adding books to the RSwitch library</a>.</li>
<li><a href="https://github.com/pat-s">Patrick Schratz</a> for encourging the development of a command-line switcher to make it easier to use in automation (and sans mouse).</li>
</ul>
</div>
<div id="basiccore-usage" class="section level2">
@ -391,6 +398,8 @@ div.tocify {
├── 3.5
├── 3.6
├── 3.7
├── 4.0
├── 4.1
└── Current</code></pre>
<p>The “R Framework” is, well, <em>R</em> on your macOS system. All of the necessary supporting libraries, code, pacakges, configuration elements, etc. exist in the framework directory. Here is the top-level contents of the <code>3.5</code> version of the R Framework:</p>
<pre class="r"><code>fs::dir_tree(path = &quot;/Library/Frameworks/R.framework/Versions/3.5&quot;, recurse = 1)</code></pre>
@ -456,17 +465,16 @@ div.tocify {
<li><code>Resources@ -&gt; Versions/Current/Resources</code></li>
<li><code>Versions/</code></li>
</ul>
<p>For the most control, you can install a coexisting version of R <strong>oldrel</strong>-1, <strong>oldrel</strong> (as of the date this document was created those would be R 3.4 and R 3.5), current <strong>release</strong> (R 3.6) and <strong>devel</strong> (3.7) by hand by going to the <a href="https://mac.r-project.org/">R for macOS Developer’s Page</a> and downloading the <code>tar.gz</code> version of those distributions:</p>
<p>For the most control, you can install a coexisting version of R <strong>oldrel</strong>-1, <strong>oldrel</strong> (as of the date this document was created those would be R 3.5 and R 3.6), current <strong>release</strong> (R 4.0) and <strong>devel</strong> (4.1) by hand by going to <a href="https://mac.r-project.org/">R for macOS</a> and downloading the <code>tar.gz</code> version of those distributions:</p>
<p><img src="r-macos-downloads.png" /></p>
<p>Here are direct <code>https</code> links to the tarballs:</p>
<ul>
<li><a href="https://mac.r-project.org/mavericks/R-3.4-branch/R-3.4-branch-mavericks-sa-x86_64.tar.gz">R 3.4</a> (oldrel-1)</li>
<li><a href="https://mac.r-project.org/el-capitan/R-3.5-branch/R-3.5-branch-el-capitan-sa-x86_64.tar.gz">R 3.5</a> (oldrel)</li>
<li><a href="https://mac.r-project.org/el-capitan/R-3.6-branch/R-3.6-branch-el-capitan-sa-x86_64.tar.gz">R 3.6</a> (current)</li>
<li><a href="https://mac.r-project.org/el-capitan/R-devel/R-devel-el-capitan-sa-x86_64.tar.gz">R 3.7</a> (devel)</li>
<li><a href="https://mac.r-project.org/el-capitan/R-3.6-branch/R-3.6-branch-el-capitan-sa-x86_64.tar.gz">R 3.6</a> (oldrel)</li>
<li><a href="https://mac.r-project.org/high-sierra/R-4.0-branch/x86_64/R-4.0-branch.tar.gz">R 4.0</a> (current)</li>
<li><a href="https://mac.r-project.org/high-sierra/R-devel/x86_64/R-devel.tar.gz">R 4.1</a> (devel)</li>
</ul>
<p>Once downloaded, you can fire up a terminal prompt, head to the root directory (i.e. <code>cd /</code>) and run <code>tar -xvzf path-to-thing-you-just-downloaded</code> to lay out the contents of the tarball onto the filesystem. You can also use the <code>.pkg</code> versions if you prefer a clicky-installer wizard, but these installers will remove any previous versions of the framework (kinda defeating the purpose). You can still use the <code>.pkg</code> format by heading over to the command line and using <code>pkgutil --forget</code> to prevent said clobbering behavior (as noted in <a href="https://cran.rstudio.org/doc/manuals/R-admin.html#Uninstalling-under-macOS">Section 4.2</a> of <em>R Installation and Administration</em>. For example:</p>
<pre class="bash"><code>sudo pkgutil --forget org.r-project.R.el-capitan.fw.pkg \
<pre class="bash"><code>sudo pkgutil --forget org.r-project.R.el-capitan.fw.pkg \ # may need to use high-sierra vs el-capitan
--forget org.r-project.x86_64.tcltk.x11 \
--forget org.r-project.x86_64.texinfo \
--forget org.r-project.R.el-capitan.GUI.pkg</code></pre>
@ -491,7 +499,7 @@ div.tocify {
<div id="getting-help-or-resources-from-the-internet" class="section level2">
<h2>Getting Help or Resources from the Internet</h2>
<p>Since RSwitch is designed to help you work with R on macOS it seemed only fitting to provide some handy links to resources like the R for macOS page, the CRAN R page, RStudio dailies link, etc. They’re all available via the fairly obvious sub-menu:</p>
<p><img src="rswitch-1.5.0-resources-reorg.png" /></p>
<p><img src="web-resources.png" /></p>
<p>and each item will open up in your default web browser. (File an issue if you’d like more links added)</p>
</div>
<div id="even-moar-switching" class="section level2">
@ -518,18 +526,46 @@ div.tocify {
<p><img src="rswitch-1.5.0-rstudio-server-new.png" /></p>
<p>and you can then launch a task-specific browser for each instance you have defined:</p>
<p><img src="rswitch-1.5.0-rstudio-example.png" /></p>
<p>This allows you to keep RStudio Server work separate from your internet browsing, creating a more focused workspace that you never have to worry about accidentally closing. Window size &amp; position are preserved across launches, too.</p>
<p>This allows you to keep RStudio Server work separate from your internet browsing, creating a more focused workspace that you never have to worry about accidentally closing. Window size &amp; position are preserved across launches, too and the keystrokes you are used to in RStudio Desktop on macOS are the same in this task-specific browser.</p>
<p>File uploads and downloads (“exports”) are also now supported.</p>
</div>
<div id="have-it-your-way" class="section level2">
<h2>Have It Your Way</h2>
<p>There’s a new minimal preferences system for showing/hiding the dock icon and for enabling background checks for and notifications when new RStudio Dailies are available:</p>
<p><img src="rswitch-1.5.0-prefs.png" /></p>
<p>There’s a minimal preferences system for showing/hiding the dock icon and for enabling background checks for and notifications when new RStudio Dailies are available.</p>
<p><img src="rswitch-prefs.png" /></p>
<p>Another (new) preference is “Ensure RStudio opens R/Rmd files”. Xcode and other developer-oriented programs seem to love to takeover either <code>.R</code> and <code>.Rmd</code> (sometimes both) and loading Xcode can take a while. Setting this preference will enable an hourly check for who owns those extensions and forces them back to RStudio in the event they are changed.</p>
</div>
<div id="always-on" class="section level2">
<h2>Always On</h2>
<p>If you like RSwitch enough to keep it running all the time, just drag the item to the “Login Items” table of your user in the “Users &amp; Groups” pane of “System Preferences”</p>
<p><img src="users-n-grps.png" /></p>
</div>
<div id="taking-commandline" class="section level2">
<h2>Taking Command(line)</h2>
<p>There’s a new command-line switcher for folks who would rather not interact with a menu to change R versions. <code>RSwitch.app</code> comes with <code>rswitch-cmd</code> tucked into <code>/Applications/RSwitch.app/Contents/Resources/</code>. You can make it easier to type by making a symbolic link in <code>/usr/local/bin/</code> (or your preferred path that’s on <code>$PATH</code>):</p>
<pre class="shell"><code>$ ln -s /Applications/RSwitch.app/Contents/Resources/rswitch-cmd /usr/local/bin/rswitch</code></pre>
<p>Firing off just <code>rswitch</code> will bring up a list of available R installs with an asterisk signifying which one is active:</p>
<pre class="shell"><code>$ rswitch
2.14 (incomplete)
3.5
3.6
3.7
4.0 *
4.1</code></pre>
<p>Just call it with the version you want to switch to and you are ready to go (you can also use <code>--list</code> or <code>-l</code> if you like typing more than you need to):</p>
<pre class="shell"><code>$ rswitch 4.1
$ rswitch --list
2.14 (incomplete)
3.5
3.6
3.7
4.0
4.1 *</code></pre>
<p>You’ll receive an error message if the version specified cannot be found:</p>
<pre class="shell"><code>$ rswitch 4.4
R version 4.4 not found.</code></pre>
<p>All non-successful operations will set a non-zero exit code in the event you are using the command-line utility in scripts.</p>
</div>
<div id="getting-help" class="section level2">
<h2>Getting Help</h2>
<p>If you’re having trouble with RSwitch or have a feature request, head on over to any of the following social coding sites and file an issue:</p>

二进制
guide/_site/r-macos-downloads.png

二进制文件未显示。

之前

宽度:  |  高度:  |  大小: 204 KiB

之后

宽度:  |  高度:  |  大小: 346 KiB

二进制
guide/_site/rswitch-prefs.png

二进制文件未显示。

之后

宽度:  |  高度:  |  大小: 354 KiB

12
guide/_site/site_libs/header-attrs-2.1/header-attrs.js

@ -0,0 +1,12 @@
// Pandoc 2.9 adds attributes on both header and div. We remove the former (to
// be compatible with the behavior of Pandoc < 2.8).
document.addEventListener('DOMContentLoaded', function(e) {
var hs = document.querySelectorAll("div.section[class*='level'] > :first-child");
var i, h, a;
for (i = 0; i < hs.length; i++) {
h = hs[i];
if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6
a = h.attributes;
while (a.length > 0) h.removeAttribute(a[0].name);
}
});

2
guide/_site/site_libs/navigation-1.1/codefolding.js

@ -22,7 +22,7 @@ window.initializeCodeFolding = function(show) {
// create a collapsable div to wrap the code in
var div = $('<div class="collapse r-code-collapse"></div>');
if (show)
if (show || $(this)[0].classList.contains('fold-show'))
div.addClass('in');
var id = 'rcode-643E0F36' + currentIndex++;
div.attr('id', id);

二进制
guide/_site/web-resources.png

二进制文件未显示。

之后

宽度:  |  高度:  |  大小: 693 KiB

65
guide/index.Rmd

@ -17,8 +17,9 @@ RSwitch is a macOS menubar application that works on macOS 10.14+ and provides h
Many thanks to the following folks for their contributions to the project to help make RSwitch better for everyone:
- [Benjamin Guiastrennec](https://github.com/guiastrennec) for suggesting improvements to the documentation regarding how to use the installer packages from the [R for macOS Developer's Page](https://mac.r-project.org/) without clobbering existing R Framework installs.
- [Benjamin Guiastrennec](https://github.com/guiastrennec) for suggesting improvements to the documentation regarding how to use the installer packages from the [R for macOS Developer's Page](https://mac.r-project.org/) without clobbering existing R Framework installs and also for encouraging support for RStudio Sever file uploads and exports.
- [Xavier Adam](https://github.com/xvrdm) for [adding books to the RSwitch library](https://github.com/hrbrmstr/RSwitch/pull/4).
- [Patrick Schratz](https://github.com/pat-s) for encourging the development of a command-line switcher to make it easier to use in automation (and sans mouse).
## Basic/Core Usage
@ -57,14 +58,14 @@ For the most control, you can install a coexisting version of R **oldrel**-1, **
Here are direct `https` links to the tarballs:
- [R 3.6](https://mac.r-project.org/el-capitan/R-3.6-branch/R-3.6-branch-el-capitan-sa-x86_64.tar.gz) (current)
- [R 4.0](https://mac.r-project.org/el-capitan/R-3.6-branch/R-4.0-branch-el-capitan-sa-x86_64.tar.gz) (current)
- [R 4.1](https://mac.r-project.org/el-capitan/R-devel/R-devel-el-capitan-sa-x86_64.tar.gz) (devel)
- [R 3.6](https://mac.r-project.org/el-capitan/R-3.6-branch/R-3.6-branch-el-capitan-sa-x86_64.tar.gz) (oldrel)
- [R 4.0](https://mac.r-project.org/high-sierra/R-4.0-branch/x86_64/R-4.0-branch.tar.gz) (current)
- [R 4.1](https://mac.r-project.org/high-sierra/R-devel/x86_64/R-devel.tar.gz) (devel)
Once downloaded, you can fire up a terminal prompt, head to the root directory (i.e. `cd /`) and run `tar -xvzf path-to-thing-you-just-downloaded` to lay out the contents of the tarball onto the filesystem. You can also use the `.pkg` versions if you prefer a clicky-installer wizard, but these installers will remove any previous versions of the framework (kinda defeating the purpose). You can still use the `.pkg` format by heading over to the command line and using `pkgutil --forget` to prevent said clobbering behavior (as noted in [Section 4.2](https://cran.rstudio.org/doc/manuals/R-admin.html#Uninstalling-under-macOS) of _R Installation and Administration_. For example:
```{bash eval=FALSE}
sudo pkgutil --forget org.r-project.R.el-capitan.fw.pkg \
sudo pkgutil --forget org.r-project.R.el-capitan.fw.pkg \ # may need to use high-sierra vs el-capitan
--forget org.r-project.x86_64.tcltk.x11 \
--forget org.r-project.x86_64.texinfo \
--forget org.r-project.R.el-capitan.GUI.pkg
@ -100,7 +101,7 @@ and the Finder will open up to `~/Downloads` with the target file selected.
Since RSwitch is designed to help you work with R on macOS it seemed only fitting to provide some handy links to resources like the R for macOS page, the CRAN R page, RStudio dailies link, etc. They're all available via the fairly obvious sub-menu:
![](rswitch-1.5.0-resources-reorg.png)
![](web-resources.png)
and each item will open up in your default web browser. (File an issue if you'd like more links added)
@ -138,13 +139,17 @@ and you can then launch a task-specific browser for each instance you have defin
![](rswitch-1.5.0-rstudio-example.png)
This allows you to keep RStudio Server work separate from your internet browsing, creating a more focused workspace that you never have to worry about accidentally closing. Window size & position are preserved across launches, too.
This allows you to keep RStudio Server work separate from your internet browsing, creating a more focused workspace that you never have to worry about accidentally closing. Window size & position are preserved across launches, too and the keystrokes you are used to in RStudio Desktop on macOS are the same in this task-specific browser.
File uploads and downloads ("exports") are also now supported.
## Have It Your Way
There's a new minimal preferences system for showing/hiding the dock icon and for enabling background checks for and notifications when new RStudio Dailies are available:
There's a minimal preferences system for showing/hiding the dock icon and for enabling background checks for and notifications when new RStudio Dailies are available.
![](rswitch-prefs.png)
![](rswitch-1.5.0-prefs.png)
Another (new) preference is "Ensure RStudio opens R/Rmd files". Xcode and other developer-oriented programs seem to love to takeover either `.R` and `.Rmd` (sometimes both) and loading Xcode can take a while. Setting this preference will enable an hourly check for who owns those extensions and forces them back to RStudio in the event they are changed.
## Always On
@ -152,6 +157,48 @@ If you like RSwitch enough to keep it running all the time, just drag the item t
![](users-n-grps.png)
## Taking Command(line)
There's a new command-line switcher for folks who would rather not interact with a menu to change R versions. `RSwitch.app` comes with `rswitch-cmd` tucked into `/Applications/RSwitch.app/Contents/Resources/`. You can make it easier to type by making a symbolic link in `/usr/local/bin/` (or your preferred path that's on `$PATH`):
```shell
$ ln -s /Applications/RSwitch.app/Contents/Resources/rswitch-cmd /usr/local/bin/rswitch
```
Firing off just `rswitch` will bring up a list of available R installs with an asterisk signifying which one is active:
```shell
$ rswitch
2.14 (incomplete)
3.5
3.6
3.7
4.0 *
4.1
```
Just call it with the version you want to switch to and you are ready to go (you can also use `--list` or `-l` if you like typing more than you need to):
```shell
$ rswitch 4.1
$ rswitch --list
2.14 (incomplete)
3.5
3.6
3.7
4.0
4.1 *
```
You'll receive an error message if the version specified cannot be found:
```shell
$ rswitch 4.4
R version 4.4 not found.
```
All non-successful operations will set a non-zero exit code in the event you are using the command-line utility in scripts.
## Getting Help
If you're having trouble with RSwitch or have a feature request, head on over to any of the following social coding sites and file an issue:

二进制
guide/rswitch-1.5.0-prefs.png

二进制文件未显示。

之前

宽度:  |  高度:  |  大小: 355 KiB

二进制
guide/rswitch-1.5.0-resources-reorg.png

二进制文件未显示。

之前

宽度:  |  高度:  |  大小: 690 KiB

二进制
guide/rswitch-prefs.png

二进制文件未显示。

之后

宽度:  |  高度:  |  大小: 354 KiB

二进制
guide/web-resources.png

二进制文件未显示。

之后

宽度:  |  高度:  |  大小: 693 KiB

二进制
releases/RSwitch-1.7.0.app.zip

二进制文件未显示。

1
rswitch-cmd/main.swift

@ -49,6 +49,7 @@ struct RSwitch: ParsableCommand {
if (!versions.contains(rversion!)) {
print("R version " + rversion! + " not found.", to: &outputStream)
Darwin.exit(3)
} else {
if (rversion! == targetPath) {
print("Current R version already points to " + targetPath)

正在加载...
取消
保存