boB Rudis преди 5 години
родител
ревизия
0c9d8b74f2
No known key found for this signature in database GPG ключ ID: 1D7529BE14E2BBA9
  1. 7
      NEWS.md
  2. 8
      README.md
  3. 7
      RSwitch.xcodeproj/project.pbxproj
  4. 107
      RSwitch/AppDelegate.swift
  5. 2
      RSwitch/Base.lproj/Main.storyboard
  6. Двоични данни
      releases/RSwitch-1.3.0.app.zip
  7. Двоични данни
      rswitch.png

7
NEWS.md

@ -1,3 +1,10 @@
# 1.3.0
- revamped app icon
- revamped menubar icon (shld work better on light/dark switching)
- handles existing filenames in a cleaner fashion
- more informative download alerts
# 1.2.0
- numbered key equivalents (up to 9)

8
README.md

@ -3,13 +3,15 @@
![Minimum macOS Target](https://img.shields.io/badge/macOS-10.14%2B-blue)
![License](https://img.shields.io/badge/License-MIT-blue.svg)
![](rswitch.png)
# RSwitch
Change 'Current' R version on macOS
## Description
At the bottom of the [R for macOS Developer's Page](http://mac.r-project.org/) there's mention of an "other binary" called "RSwitch" that is _"a small GUI that allows you to switch between R versions quickly (if you have multiple versions of R framework installed)."_ Said switching requires you to use the "tar.gz" versions of R from the R for macOS Developer's Page since the official CRAN binary installers clean up after themselves quite nicely to prevent potentially wacky behavior.
At the bottom of the [R for macOS Developer's Page](https://mac.r-project.org/) there's mention of an "other binary" called "RSwitch" that is _"a small GUI that allows you to switch between R versions quickly (if you have multiple versions of R framework installed)."_ Said switching requires you to use the "tar.gz" versions of R from the R for macOS Developer's Page since the official CRAN binary installers clean up after themselves quite nicely to prevent potentially wacky behavior.
All this GUI does is change the `Current` alias target in `/Library/Frameworks/R.framework/Versions` to the appropriate version. You can do that from the command line but the switcher GUI was created so that means some folks prefer click-switching.
@ -58,10 +60,10 @@ This codebase has been uploaded to the following authoritative social coding sit
## TODO
- Clean up the icon (which is "dial" by IconMark from the Noun Project). This means having it look better in the menu bar in dark/light mode _including_ the highlight mode for it. Possibly means getting a visible "R" on it somewhere.
- Better/prettier alerting (which also means more sanity checks)
- Allow hiding of the app icon? (not sure this is a good idea, tho…pls discuss in an issue!)
- (add your own TODO suggestions via PR)
- <strike>Clean up the icon (which is "dial" by IconMark from the Noun Project). This means having it look better in the menu bar in dark/light mode _including_ the highlight mode for it. Possibly means getting a visible "R" on it somewhere.</strike>
- <strike>Better/prettier alerting (which also means more sanity checks)</strike>
- <strike>Add Cmd-1, -2, -3, (etc) key equivalents in the menu bar for fast selection (one reason why ^^ might not be a good idea)</strike>
- <strike>Add an "about" box (mostly to ensure IconMark gets more credit than a comment and README)</strike>

7
RSwitch.xcodeproj/project.pbxproj

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@ -85,7 +85,6 @@
53FF56D90FA7100C1726A4F7 /* Pods-RSwitch.debug.xcconfig */,
574911021B3B7938E36AB013 /* Pods-RSwitch.release.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
@ -355,7 +354,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 1.2.0;
MARKETING_VERSION = 1.3.0;
PRODUCT_BUNDLE_IDENTIFIER = is.rud.bob.RSwitch;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -379,7 +378,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 1.2.0;
MARKETING_VERSION = 1.3.0;
PRODUCT_BUNDLE_IDENTIFIER = is.rud.bob.RSwitch;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

107
RSwitch/AppDelegate.swift

@ -3,25 +3,17 @@ import SwiftSoup
// Show an informational alert
public func infoAlert(_ message: String, _ extra: String? = nil, style: NSAlert.Style = NSAlert.Style.informational) {
let alert = NSAlert()
alert.messageText = message
if extra != nil { alert.informativeText = extra! }
alert.alertStyle = style
alert.runModal()
}
// Show an informational alert and then quit
public func quitAlert(_ message: String, _ extra: String? = nil) {
infoAlert(message, "The application will now quit.", style: NSAlert.Style.critical)
NSApp.terminate(nil)
}
@NSApplicationMain
@ -30,9 +22,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {
var mainStoryboard: NSStoryboard!
var abtController: NSWindowController!
// Where the official R installs go
let macos_r_framework_dir = "/Library/Frameworks/R.framework/Versions"
let macos_r_framework_dir = "/Library/Frameworks/R.framework/Versions" // Where the official R installs go
let mac_r_project_url = "https://mac.r-project.org/"
let macos_cran_url = "https://cran.rstudio.org/bin/macosx/"
let r_sig_mac_url = "https://stat.ethz.ch/pipermail/r-sig-mac/"
let rstudio_dailies_url = "https://dailies.rstudio.com/rstudio/oss/mac/"
// Get the bar setup
let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
@ -87,25 +81,25 @@ class AppDelegate: NSObject, NSApplicationDelegate {
// browse macOS dev page
@objc func browse_r_macos_dev_page(_ sender: NSMenuItem?) {
let url = URL(string: "https://mac.r-project.org/")!
let url = URL(string: mac_r_project_url)!
NSWorkspace.shared.open(url)
}
// browse macOS dev page
@objc func browse_r_macos_cran_page(_ sender: NSMenuItem?) {
let url = URL(string: "https://cran.rstudio.org/bin/macosx/")!
let url = URL(string: macos_cran_url)!
NSWorkspace.shared.open(url)
}
// browse macOS dev page
@objc func browse_r_sig_mac_page(_ sender: NSMenuItem?) {
let url = URL(string: "https://stat.ethz.ch/pipermail/r-sig-mac/")!
let url = URL(string: r_sig_mac_url)!
NSWorkspace.shared.open(url)
}
// browse RStudio macOS Dailies
@objc func browse_rstudio_mac_dailies_page(_ sender: NSMenuItem?) {
let url = URL(string: "https://dailies.rstudio.com/rstudio/oss/mac/")!
let url = URL(string: rstudio_dailies_url)!
NSWorkspace.shared.open(url)
}
@ -122,7 +116,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
// Download latest rstudio daily build
@objc func download_latest_rstudio(_ sender: NSMenuItem?) {
let url = URL(string: "https://dailies.rstudio.com/rstudio/oss/mac/")
let url = URL(string: rstudio_dailies_url)
do {
let html = try String.init(contentsOf: url!)
@ -133,33 +127,31 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let dlurl = URL(string: href)!
let dldir = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
var dlfile = dldir
dlfile.appendPathComponent(dlurl.lastPathComponent)
let task = URLSession.shared.downloadTask(with: dlurl) { (tempURL, response, error) in
if let tempURL = tempURL, error == nil {
if ((response as? HTTPURLResponse)?.statusCode == 200) {
do {
try FileManager.default.copyItem(at: tempURL, to: dlfile)
NSWorkspace.shared.openFile(dldir.path, withApplication: "Finder")
DispatchQueue.main.async { infoAlert("Download of latest RStudio daily successful.") }
} catch {
DispatchQueue.main.async { infoAlert("Error downloading and saving latest RStudio daily.") }
if (FileManager.default.fileExists(atPath: dlfile.relativePath)) {
infoAlert("A local copy of the latest RStudio daily already exists. Please remove or rename it if you wish to re-download it.")
} else {
let task = URLSession.shared.downloadTask(with: dlurl) { (tempURL, response, error) in
if let tempURL = tempURL, error == nil {
if ((response as? HTTPURLResponse)?.statusCode == 200) {
do {
try FileManager.default.copyItem(at: tempURL, to: dlfile)
NSWorkspace.shared.openFile(dldir.path, withApplication: "Finder")
DispatchQueue.main.async { infoAlert("Download of latest RStudio daily (" + dlurl.lastPathComponent + ") successful.") }
} catch {
DispatchQueue.main.async { infoAlert("Error downloading and saving latest RStudio daily.") }
}
} else {
DispatchQueue.main.async { infoAlert("Latest RStudio daily not found.") }
}
} else {
DispatchQueue.main.async { infoAlert("Latest RStudio daily not found.") }
DispatchQueue.main.async { infoAlert("Error downloading latest RStudio daily.") }
}
} else {
DispatchQueue.main.async { infoAlert("Error downloading latest RStudio daily.") }
}
task.resume()
}
task.resume()
} catch {
DispatchQueue.main.async { infoAlert("Error downloading latrest RStudio daily.") }
}
@ -172,33 +164,32 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let url = URL(string: "https://mac.r-project.org/el-capitan/R-devel/R-devel-el-capitan-sa-x86_64.tar.gz")!
let dldir = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
var dlfile = dldir
dlfile.appendPathComponent("R-devel-el-capitan-sa-x86_64.tar.gz")
let task = URLSession.shared.downloadTask(with: url) { (tempURL, response, error) in
if let tempURL = tempURL, error == nil {
if ((response as? HTTPURLResponse)?.statusCode == 200) {
do {
try FileManager.default.copyItem(at: tempURL, to: dlfile)
NSWorkspace.shared.openFile(dldir.path, withApplication: "Finder")
DispatchQueue.main.async { infoAlert("Download of latest r-devel successful.") }
} catch {
DispatchQueue.main.async { infoAlert("Error downloading and saving latest r-devel .") }
if (FileManager.default.fileExists(atPath: dlfile.relativePath)) {
infoAlert("R-devel tarball already exists. Please remove or rename it before downloading.")
} else {
let task = URLSession.shared.downloadTask(with: url) { (tempURL, response, error) in
if let tempURL = tempURL, error == nil {
if ((response as? HTTPURLResponse)?.statusCode == 200) {
do {
try FileManager.default.copyItem(at: tempURL, to: dlfile)
NSWorkspace.shared.openFile(dldir.path, withApplication: "Finder")
DispatchQueue.main.async { infoAlert("Download of latest r-devel successful.") }
} catch {
DispatchQueue.main.async { infoAlert("Error downloading and saving latest r-devel .") }
}
} else {
DispatchQueue.main.async { infoAlert("Latest r-devel file not found.") }
}
} else {
DispatchQueue.main.async { infoAlert("Error downloading latest r-devel .") }
}
} else {
DispatchQueue.main.async { infoAlert("Latest r-devel file not found.") }
}
} else {
DispatchQueue.main.async { infoAlert("Error downloading latest r-devel .") }
}
task.resume()
}
task.resume()
}
}

2
RSwitch/Base.lproj/Main.storyboard

@ -741,7 +741,7 @@
<attributedString key="textStorage">
<fragment>
<string key="content">
RSwitch v1.2.0
RSwitch v1.3.0
Copyright © 2019 Bob Rudis

Двоични данни
releases/RSwitch-1.3.0.app.zip

Binary file not shown.

Двоични данни
rswitch.png

Binary file not shown.

След

Ширина:  |  Височина:  |  Големина: 69 KiB

Зареждане…
Отказ
Запис