boB Rudis
5 years ago
45 changed files with 1135 additions and 963 deletions
@ -1,25 +0,0 @@ |
|||
// |
|||
// Alerts.swift |
|||
// RSwitch |
|||
// |
|||
// Created by hrbrmstr on 8/24/19. |
|||
// Copyright © 2019 Bob Rudis. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
import Cocoa |
|||
|
|||
// 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) |
|||
} |
@ -1,157 +0,0 @@ |
|||
// |
|||
// Menu.swift |
|||
// RSwitch |
|||
// |
|||
// Created by hrbrmstr on 8/24/19. |
|||
// Copyright © 2019 Bob Rudis. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
import Cocoa |
|||
|
|||
extension AppDelegate: NSMenuDelegate { |
|||
|
|||
func menuWillOpen(_ menu: NSMenu) { |
|||
|
|||
if (menu != self.statusMenu) { return } |
|||
|
|||
// clear the menu |
|||
menu.removeAllItems() |
|||
|
|||
// add selection to open frameworks dir in Finder |
|||
menu.addItem(NSMenuItem(title: "Open R Frameworks Directory", action: #selector(openFrameworksDir), keyEquivalent: "")) |
|||
menu.addItem(NSMenuItem.separator()) |
|||
|
|||
menu.addItem(NSMenuItem(title: "Current R Version:", action: nil, keyEquivalent: "")) |
|||
|
|||
// populate installed versions |
|||
let fm = FileManager.default |
|||
var targetPath:String? = nil |
|||
|
|||
do { |
|||
|
|||
// gets a directory listing |
|||
let entries = try fm.contentsOfDirectory(atPath: app_dirs.macos_r_framework) |
|||
|
|||
// retrieves all versions (excludes hidden files and the Current alias |
|||
let versions = entries.sorted().filter { !($0.hasPrefix(".")) && !($0 == "Current") } |
|||
let hasCurrent = entries.filter { $0 == "Current" } |
|||
|
|||
// if there was a Current alias (prbly shld alert if not) |
|||
if (hasCurrent.count > 0) { |
|||
|
|||
// get where Current points to |
|||
let furl = NSURL(fileURLWithPath: app_dirs.macos_r_framework + "/" + "Current") |
|||
|
|||
if (furl.fileReferenceURL() != nil) { |
|||
do { |
|||
let fdat = try NSURL(resolvingAliasFileAt: furl as URL, options: []) |
|||
targetPath = fdat.lastPathComponent! |
|||
} catch { |
|||
targetPath = furl.path |
|||
} |
|||
} |
|||
|
|||
// populate menu items with all installed R versions, ensuring we |
|||
// put a checkbox next to the one that is Current |
|||
var i = 1 |
|||
for version in versions { |
|||
let keynum = (i < 10) ? String(i) : "" |
|||
let item = NSMenuItem(title: version, action: #selector(handleSwitch), keyEquivalent: keynum) |
|||
item.isEnabled = true |
|||
if (version == targetPath) { item.state = NSControl.StateValue.on } |
|||
item.representedObject = version |
|||
menu.addItem(item) |
|||
i = i + 1 |
|||
} |
|||
|
|||
} |
|||
|
|||
} catch { |
|||
quitAlert("Failed to list contents of R framework directory. You either do not have R installed or have incorrect permissions set on " + app_dirs.macos_r_framework) |
|||
} |
|||
|
|||
// Add items to download latest r-devel tarball and latest macOS daily |
|||
menu.addItem(NSMenuItem.separator()) |
|||
|
|||
let rdevelItem = NSMenuItem(title: NSLocalizedString("Download latest R-devel tarball", comment: "Download latest tarball item"), action: self.rdevel_enabled ? #selector(download_latest_tarball) : nil, keyEquivalent: "") |
|||
rdevelItem.isEnabled = self.rdevel_enabled |
|||
menu.addItem(rdevelItem) |
|||
|
|||
let rstudioItem = NSMenuItem(title: NSLocalizedString("Download latest RStudio daily build", comment: "Download latest RStudio item"), action: self.rstudio_enabled ? #selector(download_latest_rstudio) : nil, keyEquivalent: "") |
|||
rstudioItem.isEnabled = self.rstudio_enabled |
|||
menu.addItem(rstudioItem) |
|||
|
|||
// Add items to open variosu R for macOS pages |
|||
|
|||
menu.addItem(NSMenuItem.separator()) |
|||
|
|||
let webDropdown = NSMenuItem(title: "Web resources", action: nil, keyEquivalent: "") |
|||
let webSub = NSMenu() |
|||
|
|||
menu.addItem(webDropdown) |
|||
menu.setSubmenu(webSub, for: webDropdown) |
|||
|
|||
webSub.addItem(NSMenuItem(title: NSLocalizedString("R for macOS Developers…", comment: "macOS Dev Page item"), action: #selector(browse_r_macos_dev_page), keyEquivalent: "")) |
|||
webSub.addItem(NSMenuItem(title: NSLocalizedString("R for macOS CRAN…", comment: "macOS CRAN Page item"), action: #selector(browse_r_macos_cran_page), keyEquivalent: "")) |
|||
webSub.addItem(NSMenuItem(title: NSLocalizedString("R-SIG-Mac Archives…", comment: "R-SIG-Mac Page item"), action: #selector(browse_r_sig_mac_page), keyEquivalent: "")) |
|||
webSub.addItem(NSMenuItem(title: NSLocalizedString("R-devel News…", comment: "R-devel News Page item"), action: #selector(browse_r_devel_news_page), keyEquivalent: "")) |
|||
webSub.addItem(NSMenuItem(title: NSLocalizedString("R Installation/Admin macOS Section…", comment: "R Install Page item"), action: #selector(browse_r_admin_macos_page), keyEquivalent: "")) |
|||
webSub.addItem(NSMenuItem.separator()) |
|||
webSub.addItem(NSMenuItem(title: NSLocalizedString("RStudio macOS Dailies…", comment: "RStudio macOS Dailies Page item"), action: #selector(browse_rstudio_mac_dailies_page), keyEquivalent: "")) |
|||
webSub.addItem(NSMenuItem(title: NSLocalizedString("R StackOverflow…", comment: "R StackOverflow Page item"), action: #selector(browse_r_stackoverflow_page), keyEquivalent: "")) |
|||
webSub.addItem(NSMenuItem(title: NSLocalizedString("RStudio Community…", comment: "RStudio Community Page item"), action: #selector(browse_rstudio_community_page), keyEquivalent: "")) |
|||
|
|||
let running_rstudios = NSWorkspace.shared.runningApplications.filter { |
|||
$0.bundleIdentifier == "org.rstudio.RStudio" |
|||
} |
|||
|
|||
let running_rapps = NSWorkspace.shared.runningApplications.filter { |
|||
$0.bundleIdentifier == "org.R-project.R" |
|||
} |
|||
|
|||
if ((running_rstudios.count) + (running_rapps.count) > 0) { |
|||
|
|||
menu.addItem(NSMenuItem.separator()) |
|||
|
|||
let switchToDropdown = NSMenuItem(title: "Switch to", action: nil, keyEquivalent: "") |
|||
let switchToSub = NSMenu() |
|||
|
|||
menu.addItem(switchToDropdown) |
|||
menu.setSubmenu(switchToSub, for: switchToDropdown) |
|||
|
|||
for app in running_rstudios + running_rapps { |
|||
let args = getArgs(app.processIdentifier)! |
|||
let title = app.localizedName! + (args.count > 1 ? " : " + (args[1] as! NSString).lastPathComponent.replacingOccurrences(of: ".Rproj", with: "") : "") |
|||
let mi = NSMenuItem(title: title, action: #selector(switch_to), keyEquivalent: "") |
|||
|
|||
mi.representedObject = app |
|||
switchToSub.addItem(mi) |
|||
} |
|||
|
|||
} |
|||
|
|||
// Add launchers |
|||
menu.addItem(NSMenuItem.separator()) |
|||
|
|||
let launch_r = "Launch R GUI" + (NSEvent.modifierFlags.contains(NSEvent.ModifierFlags.control) ? " (new instance)" : "") |
|||
let launch_rstudio = "Launch RStudio" + (NSEvent.modifierFlags.contains(NSEvent.ModifierFlags.control) ? " (new instance)" : "") |
|||
|
|||
menu.addItem(NSMenuItem(title: NSLocalizedString(launch_r, comment: "Launch R GUI item"), action: #selector(launchRApp), keyEquivalent: "")) |
|||
menu.addItem(NSMenuItem(title: NSLocalizedString(launch_rstudio, comment: "Launch RStudio item"), action: #selector(launchRStudio), keyEquivalent: "")) |
|||
|
|||
// Add a About item |
|||
menu.addItem(NSMenuItem.separator()) |
|||
menu.addItem(NSMenuItem(title: NSLocalizedString("Check for update…", comment: "Check for update item"), action: #selector(checkForUpdate), keyEquivalent: "")) |
|||
|
|||
// Add a About item |
|||
menu.addItem(NSMenuItem.separator()) |
|||
menu.addItem(NSMenuItem(title: NSLocalizedString("About RSwitch…", comment: "About menu item"), action: #selector(about), keyEquivalent: "")) |
|||
|
|||
// Add a Quit item |
|||
menu.addItem(NSMenuItem.separator()) |
|||
menu.addItem(quitItem) |
|||
|
|||
} |
|||
|
|||
} |
@ -1,66 +0,0 @@ |
|||
// |
|||
// Utils.swift |
|||
// RSwitch |
|||
// |
|||
// Created by hrbrmstr on 8/24/19. |
|||
// Copyright © 2019 Bob Rudis. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
import Cocoa |
|||
|
|||
public func browse(_ urlString : String) { |
|||
let url = URL(string: urlString)! |
|||
NSWorkspace.shared.open(url) |
|||
} |
|||
|
|||
extension AppDelegate { |
|||
|
|||
struct app_urls { |
|||
static let mac_r_project = "https://mac.r-project.org/" |
|||
static let macos_cran = "https://cran.rstudio.org/bin/macosx/" |
|||
static let r_sig_mac = "https://stat.ethz.ch/pipermail/r-sig-mac/" |
|||
static let rstudio_dailies = "https://dailies.rstudio.com/rstudio/oss/mac/" |
|||
static let latest_rstudio_dailies = "https://www.rstudio.org/download/latest/daily/desktop/mac/RStudio-latest.dmg" |
|||
static let r_admin_macos = "https://cran.rstudio.org/doc/manuals/R-admin.html#Installing-R-under-macOS" |
|||
static let r_devel_news = "https://developer.r-project.org/blosxom.cgi/R-devel/NEWS" |
|||
static let r_stackoverflow = "https://stackoverflow.com/questions/tagged/r" |
|||
static let rstudio_community = "https://community.rstudio.com/" |
|||
static let version_check = "https://rud.is/rswitch/releases/current-version.txt" |
|||
static let releases = "https://git.rud.is/hrbrmstr/RSwitch/releases" |
|||
} |
|||
|
|||
@objc func browse_r_macos_dev_page(_ sender: NSMenuItem?) { browse(app_urls.mac_r_project) } |
|||
@objc func browse_r_macos_cran_page(_ sender: NSMenuItem?) { browse(app_urls.macos_cran) } |
|||
@objc func browse_r_sig_mac_page(_ sender: NSMenuItem?) { browse(app_urls.r_sig_mac) } |
|||
@objc func browse_rstudio_mac_dailies_page(_ sender: NSMenuItem?) { browse(app_urls.rstudio_dailies) } |
|||
@objc func browse_r_admin_macos_page(_ sender: NSMenuItem?) { browse(app_urls.r_admin_macos) } |
|||
@objc func browse_r_devel_news_page(_ sender: NSMenuItem?) { browse(app_urls.r_devel_news) } |
|||
@objc func browse_r_stackoverflow_page(_ sender: NSMenuItem?) { browse(app_urls.r_stackoverflow) } |
|||
@objc func browse_rstudio_community_page(_ sender: NSMenuItem?) { browse(app_urls.rstudio_community) } |
|||
|
|||
// Show about dialog |
|||
@objc func about(_ sender: NSMenuItem?) { abtController.showWindow(self) } |
|||
|
|||
// Show the framework dir in a new Finder window |
|||
@objc func openFrameworksDir(_ sender: NSMenuItem?) { NSWorkspace.shared.openFile(app_dirs.macos_r_framework, withApplication: "Finder") } |
|||
|
|||
// Launch RStudio |
|||
@objc func launchRStudio(_ sender: NSMenuItem?) { |
|||
if (NSEvent.modifierFlags.contains(NSEvent.ModifierFlags.control)) { |
|||
NSWorkspace.shared.launchApplication(withBundleIdentifier: "org.rstudio.RStudio", options: NSWorkspace.LaunchOptions.newInstance, additionalEventParamDescriptor: nil, launchIdentifier: nil) |
|||
} else { |
|||
NSWorkspace.shared.launchApplication("RStudio.app") |
|||
} |
|||
} |
|||
|
|||
// Launch R.app |
|||
@objc func launchRApp(_ sender: NSMenuItem?) { |
|||
if (NSEvent.modifierFlags.contains(NSEvent.ModifierFlags.control)) { |
|||
NSWorkspace.shared.launchApplication(withBundleIdentifier: "org.R-project.R", options: NSWorkspace.LaunchOptions.newInstance, additionalEventParamDescriptor: nil, launchIdentifier: nil) |
|||
} else { |
|||
NSWorkspace.shared.launchApplication("R.app") |
|||
} |
|||
} |
|||
|
|||
} |
@ -1,6 +1,13 @@ |
|||
|
|||
import Cocoa |
|||
|
|||
extension AppDelegate { |
|||
|
|||
// Show about dialog |
|||
@objc func about(_ sender: NSMenuItem?) { abtController.showWindow(self) } |
|||
|
|||
} |
|||
|
|||
class AboutViewController: NSViewController { |
|||
|
|||
override func viewDidLoad() { |
@ -0,0 +1,27 @@ |
|||
// |
|||
// AppAlerts.swift |
|||
// RSwitch |
|||
// |
|||
// Created by hrbrmstr on 8/30/19. |
|||
// Copyright © 2019 Bob Rudis. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
import Cocoa |
|||
|
|||
public class AppAlerts { |
|||
// Show an informational alert |
|||
public static 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 static func quitAlert(_ message: String, _ extra: String? = nil) { |
|||
infoAlert(message, "The application will now quit.", style: NSAlert.Style.critical) |
|||
NSApp.terminate(nil) |
|||
} |
|||
} |
@ -0,0 +1,64 @@ |
|||
// |
|||
// Menu.swift |
|||
// RSwitch |
|||
// |
|||
// Created by hrbrmstr on 8/24/19. |
|||
// Copyright © 2019 Bob Rudis. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
import Cocoa |
|||
|
|||
extension AppDelegate: NSMenuDelegate { |
|||
|
|||
func menuWillOpen(_ menu: NSMenu) { |
|||
|
|||
if (menu != self.statusMenu) { return } |
|||
|
|||
// clear the menu |
|||
menu.removeAllItems() |
|||
|
|||
// add selection to open frameworks dir in Finder |
|||
menu.addItem(NSMenuItem(title: "Open R Frameworks Directory", action: #selector(openFrameworksDir), keyEquivalent: "")) |
|||
menu.addItem(NSMenuItem.separator()) |
|||
|
|||
menu.addItem(NSMenuItem(title: "Current R Version:", action: nil, keyEquivalent: "")) |
|||
|
|||
// populate installed versions |
|||
populateRVersionsMenu(menu: menu) |
|||
|
|||
// Add items to download latest r-devel tarball and latest macOS daily |
|||
menu.addItem(NSMenuItem.separator()) |
|||
|
|||
let rdevelItem = NSMenuItem(title: NSLocalizedString("Download latest R-devel tarball", comment: "Download latest tarball item"), action: self.rdevel_enabled ? #selector(download_latest_tarball) : nil, keyEquivalent: "") |
|||
rdevelItem.isEnabled = self.rdevel_enabled |
|||
menu.addItem(rdevelItem) |
|||
|
|||
let rstudioItem = NSMenuItem(title: NSLocalizedString("Download latest RStudio daily build", comment: "Download latest RStudio item"), action: self.rstudio_enabled ? #selector(download_latest_rstudio) : nil, keyEquivalent: "") |
|||
rstudioItem.isEnabled = self.rstudio_enabled |
|||
menu.addItem(rstudioItem) |
|||
|
|||
// Add items to open variosu R for macOS pages |
|||
BrowseMenuAction.populateWebItems(menu: menu) |
|||
|
|||
// Add running apps |
|||
populateRunningApps(menu: menu) |
|||
|
|||
// Add launchers |
|||
populateLaunchers(menu: menu) |
|||
|
|||
// Add a Check for update |
|||
menu.addItem(NSMenuItem.separator()) |
|||
menu.addItem(NSMenuItem(title: NSLocalizedString("Check for update…", comment: "Check for update item"), action: #selector(checkForUpdate), keyEquivalent: "")) |
|||
|
|||
// Add an About item |
|||
menu.addItem(NSMenuItem.separator()) |
|||
menu.addItem(NSMenuItem(title: NSLocalizedString("About RSwitch…", comment: "About menu item"), action: #selector(about), keyEquivalent: "")) |
|||
|
|||
// Add a Quit item |
|||
menu.addItem(NSMenuItem.separator()) |
|||
menu.addItem(NSMenuItem(title: "Quit", action: #selector(NSApp.terminate), keyEquivalent: "q")) |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,74 @@ |
|||
// |
|||
// MenuAction.swift |
|||
// RSwitch |
|||
// |
|||
// Created by hrbrmstr on 8/30/19. |
|||
// Copyright © 2019 Bob Rudis. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
import Cocoa |
|||
|
|||
extension AppDelegate { |
|||
|
|||
@objc func browseFromMenu(_ sender: NSMenuItem) { |
|||
let url = (sender.representedObject as! BrowseMenuAction).url |
|||
NSWorkspace.shared.open(url) |
|||
} |
|||
|
|||
} |
|||
|
|||
class BrowseMenuAction { |
|||
|
|||
public var title : String |
|||
public var selector : Selector |
|||
public var keyEquivalent : String |
|||
public var url : URL |
|||
|
|||
private static let webItemsR = [ |
|||
BrowseMenuAction(title: "R for macOS Developer's…", url: "https://mac.r-project.org/"), |
|||
BrowseMenuAction(title: "R for macOS CRAN…", url: "https://cran.rstudio.org/bin/macosx/"), |
|||
BrowseMenuAction(title: "R-SIG-Mac Archives…", url: "https://stat.ethz.ch/pipermail/r-sig-mac/"), |
|||
BrowseMenuAction(title: "R-devel News…", url: "https://developer.r-project.org/blosxom.cgi/R-devel/NEWS"), |
|||
BrowseMenuAction(title: "R Installation/Admin macOS Section…", url: "https://cran.rstudio.org/doc/manuals/R-admin.html#Installing-R-under-macOS"), |
|||
] |
|||
|
|||
private static let webItemsExt = [ |
|||
BrowseMenuAction(title: "RStudio macOS Dailies…", url: "https://dailies.rstudio.com/rstudio/oss/mac/"), |
|||
BrowseMenuAction(title: "R StackOverflow…", url: "https://stackoverflow.com/questions/tagged/r"), |
|||
BrowseMenuAction(title: "RStudio Community…", url: "https://community.rstudio.com/") |
|||
] |
|||
|
|||
init(title: String, url: String, selector: String = "browseFromMenu", keyEquivalent: String = "") { |
|||
self.title = title |
|||
self.url = URL(string: url)! |
|||
self.selector = Selector((selector+":")) |
|||
self.keyEquivalent = keyEquivalent |
|||
print(self.selector) |
|||
} |
|||
|
|||
public func asMenuItem() -> NSMenuItem { |
|||
let mi = NSMenuItem(title: title, action: selector, keyEquivalent: keyEquivalent) |
|||
mi.representedObject = self |
|||
return(mi) |
|||
} |
|||
|
|||
public static func populateWebItems(menu : NSMenu) { |
|||
|
|||
menu.addItem(NSMenuItem.separator()) |
|||
|
|||
let webDropdown = NSMenuItem(title: "Web resources", action: nil, keyEquivalent: "") |
|||
let webSub = NSMenu() |
|||
|
|||
menu.addItem(webDropdown) |
|||
menu.setSubmenu(webSub, for: webDropdown) |
|||
for item in webItemsR { webSub.addItem(item.asMenuItem()) } |
|||
|
|||
webSub.addItem(NSMenuItem.separator()) |
|||
for item in webItemsExt { webSub.addItem(item.asMenuItem()) } |
|||
|
|||
} |
|||
|
|||
|
|||
} |
|||
|
@ -0,0 +1,51 @@ |
|||
// |
|||
// LaunchUtils.swift |
|||
// RSwitch |
|||
// |
|||
// Created by hrbrmstr on 8/30/19. |
|||
// Copyright © 2019 Bob Rudis. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
import Cocoa |
|||
|
|||
extension AppDelegate { |
|||
|
|||
struct bundleIds { |
|||
static let rstudio = "org.rstudio.RStudio" |
|||
static let r_base = "org.R-project.R" |
|||
} |
|||
|
|||
struct appNames { |
|||
static let R = "R.app" |
|||
static let RStudio = "RStudio.app" |
|||
} |
|||
|
|||
// Launch R.app |
|||
@objc func launchRApp(_ sender: NSMenuItem?) { |
|||
if (NSEvent.modifierFlags.contains(NSEvent.ModifierFlags.control)) { |
|||
NSWorkspace.shared.launchApplication(withBundleIdentifier: bundleIds.r_base, options: NSWorkspace.LaunchOptions.newInstance, additionalEventParamDescriptor: nil, launchIdentifier: nil) |
|||
} else { |
|||
NSWorkspace.shared.launchApplication(appNames.R) |
|||
} |
|||
} |
|||
// Launch RStudio |
|||
@objc func launchRStudio(_ sender: NSMenuItem?) { |
|||
if (NSEvent.modifierFlags.contains(NSEvent.ModifierFlags.control)) { |
|||
NSWorkspace.shared.launchApplication(withBundleIdentifier: bundleIds.rstudio, options: NSWorkspace.LaunchOptions.newInstance, additionalEventParamDescriptor: nil, launchIdentifier: nil) |
|||
} else { |
|||
NSWorkspace.shared.launchApplication(appNames.RStudio) |
|||
} |
|||
} |
|||
|
|||
func populateLaunchers(menu : NSMenu) { |
|||
menu.addItem(NSMenuItem.separator()) |
|||
|
|||
let launch_r = "Launch R GUI" + (NSEvent.modifierFlags.contains(NSEvent.ModifierFlags.control) ? " (new instance)" : "") |
|||
let launch_rstudio = "Launch RStudio" + (NSEvent.modifierFlags.contains(NSEvent.ModifierFlags.control) ? " (new instance)" : "") |
|||
|
|||
menu.addItem(NSMenuItem(title: launch_r, action: #selector(launchRApp), keyEquivalent: "")) |
|||
menu.addItem(NSMenuItem(title: launch_rstudio, action: #selector(launchRStudio), keyEquivalent: "")) |
|||
} |
|||
|
|||
} |
@ -0,0 +1,22 @@ |
|||
// |
|||
// Utils.swift |
|||
// RSwitch |
|||
// |
|||
// Created by hrbrmstr on 8/24/19. |
|||
// Copyright © 2019 Bob Rudis. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
import Cocoa |
|||
|
|||
|
|||
extension AppDelegate { |
|||
|
|||
struct app_urls { |
|||
static let rstudio_dailies = "https://dailies.rstudio.com/rstudio/oss/mac/" |
|||
static let latest_rstudio_dailies = "https://www.rstudio.org/download/latest/daily/desktop/mac/RStudio-latest.dmg" |
|||
static let version_check = "https://rud.is/rswitch/releases/current-version.txt" |
|||
static let releases = "https://git.rud.is/hrbrmstr/RSwitch/releases" |
|||
} |
|||
|
|||
} |
@ -0,0 +1,106 @@ |
|||
// |
|||
// VersionsUtils.swift |
|||
// RSwitch |
|||
// |
|||
// Created by hrbrmstr on 8/30/19. |
|||
// Copyright © 2019 Bob Rudis. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
import Cocoa |
|||
|
|||
extension AppDelegate { |
|||
|
|||
// Show the framework dir in a new Finder window |
|||
@objc func openFrameworksDir(_ sender: NSMenuItem?) { |
|||
NSWorkspace.shared.openFile(app_dirs.macos_r_framework, withApplication: "Finder") |
|||
} |
|||
|
|||
func populateRVersionsMenu(menu : NSMenu) { |
|||
|
|||
let fm = FileManager.default |
|||
var targetPath:String? = nil |
|||
|
|||
do { |
|||
|
|||
// gets a directory listing |
|||
let entries = try fm.contentsOfDirectory(atPath: app_dirs.macos_r_framework) |
|||
|
|||
// retrieves all versions (excludes hidden files and the Current alias |
|||
let versions = entries.sorted().filter { !($0.hasPrefix(".")) && !($0 == "Current") } |
|||
let hasCurrent = entries.filter { $0 == "Current" } |
|||
|
|||
// if there was a Current alias (prbly shld alert if not) |
|||
if (hasCurrent.count > 0) { |
|||
|
|||
// get where Current points to |
|||
let furl = NSURL(fileURLWithPath: app_dirs.macos_r_framework + "/" + "Current") |
|||
|
|||
if (furl.fileReferenceURL() != nil) { |
|||
do { |
|||
let fdat = try NSURL(resolvingAliasFileAt: furl as URL, options: []) |
|||
targetPath = fdat.lastPathComponent! |
|||
} catch { |
|||
targetPath = furl.path |
|||
} |
|||
} |
|||
|
|||
// populate menu items with all installed R versions, ensuring we |
|||
// put a checkbox next to the one that is Current |
|||
var i = 1 |
|||
for version in versions { |
|||
let keynum = (i < 10) ? String(i) : "" |
|||
let item = NSMenuItem(title: version, action: #selector(handleRSwitch), keyEquivalent: keynum) |
|||
item.isEnabled = true |
|||
if (version == targetPath) { item.state = NSControl.StateValue.on } |
|||
item.representedObject = version |
|||
menu.addItem(item) |
|||
i = i + 1 |
|||
} |
|||
|
|||
} |
|||
|
|||
} catch { |
|||
AppAlerts.quitAlert("Failed to list contents of R framework directory. You either do not have R installed or have incorrect permissions set on " + app_dirs.macos_r_framework) |
|||
} |
|||
|
|||
} |
|||
|
|||
func populateRunningApps(menu : NSMenu) { |
|||
|
|||
// gather running RStudio instances |
|||
let running_rstudios = NSWorkspace.shared.runningApplications.filter { |
|||
$0.bundleIdentifier == bundleIds.rstudio |
|||
} |
|||
|
|||
// gather running R GUI instances |
|||
let running_rapps = NSWorkspace.shared.runningApplications.filter { |
|||
$0.bundleIdentifier == bundleIds.r_base |
|||
} |
|||
|
|||
// if we have any running instances of anything |
|||
if ((running_rstudios.count) + (running_rapps.count) > 0) { |
|||
|
|||
menu.addItem(NSMenuItem.separator()) |
|||
|
|||
let switchToDropdown = NSMenuItem(title: "Switch to", action: nil, keyEquivalent: "") |
|||
let switchToSub = NSMenu() |
|||
|
|||
menu.addItem(switchToDropdown) |
|||
menu.setSubmenu(switchToSub, for: switchToDropdown) |
|||
|
|||
// populate RStudio first (it'll be in launch order) then R GUI |
|||
for app in running_rstudios + running_rapps { |
|||
let args = getArgs(app.processIdentifier)! |
|||
let title = app.localizedName! + (args.count > 1 ? " : " + (args[1] as! NSString).lastPathComponent.replacingOccurrences(of: ".Rproj", with: "") : "") |
|||
let mi = NSMenuItem(title: title, action: #selector(switch_to), keyEquivalent: "") |
|||
|
|||
mi.representedObject = app |
|||
switchToSub.addItem(mi) |
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,6 @@ |
|||
library(tree) |
|||
install.packages("tree") |
|||
library(tree) |
|||
tree |
|||
fs::dir_tree(path = "/Library/Frameworks/R.framework/Versions/3.5", recurse = 2) |
|||
fs::dir_tree(path = "/Library/Frameworks/R.framework/Versions/3.5", recurse = 1) |
Loading…
Reference in new issue