Compare commits

...

9 Commits

  1. 8
      NEWS.md
  2. 14
      Pods/Pods.xcodeproj/project.pbxproj
  3. 24
      Pods/Pods.xcodeproj/xcuserdata/hrbrmstr.xcuserdatad/xcschemes/Just.xcscheme
  4. 2
      Pods/Pods.xcodeproj/xcuserdata/hrbrmstr.xcuserdatad/xcschemes/Pods-RSwitch.xcscheme
  5. 11
      Pods/Target Support Files/Just/Just.debug.xcconfig
  6. 11
      Pods/Target Support Files/Just/Just.release.xcconfig
  7. 235
      RSwitch.xcodeproj/project.pbxproj
  8. 78
      RSwitch.xcodeproj/xcshareddata/xcschemes/RSwitch.xcscheme
  9. 13
      RSwitch.xcodeproj/xcuserdata/hrbrmstr.xcuserdatad/xcschemes/xcschememanagement.plist
  10. 16
      RSwitch.xcworkspace/xcshareddata/swiftpm/Package.resolved
  11. BIN
      RSwitch.xcworkspace/xcuserdata/hrbrmstr.xcuserdatad/UserInterfaceState.xcuserstate
  12. 60
      RSwitch/Base.lproj/Main.storyboard
  13. 2
      RSwitch/Info.plist
  14. 17
      RSwitch/Swift/AppDelegate.swift
  15. 57
      RSwitch/Swift/Downloaders/DownloadFromRStudioServer.swift
  16. 2
      RSwitch/Swift/Downloaders/DownloadRStudio.swift
  17. 3
      RSwitch/Swift/Downloaders/DownloadTarball.swift
  18. 22
      RSwitch/Swift/ExportWebViewController.swift
  19. 1
      RSwitch/Swift/HandleRSwitch.swift
  20. 18
      RSwitch/Swift/Menu.swift
  21. 25
      RSwitch/Swift/MenuActions/BrowseMenuAction.swift
  22. 4
      RSwitch/Swift/MenuActions/RStudioServerAction.swift
  23. 27
      RSwitch/Swift/Notify.swift
  24. 83
      RSwitch/Swift/RStudioServerSessionWebViewController.swift
  25. 41
      RSwitch/Swift/Utils/Associations.swift
  26. 12
      RSwitch/Swift/Utils/Preferences.swift
  27. 51
      RSwitch/Swift/Utils/Reachable.swift
  28. 25
      RSwitch/Swift/Utils/urls.swift
  29. 84
      RSwitch/Swift/exportPopupViewController.swift
  30. 29
      RSwitch/Swift/plotPopupViewController.swift
  31. 64
      guide/_site/index.html
  32. BIN
      guide/_site/r-macos-downloads.png
  33. BIN
      guide/_site/rswitch-prefs.png
  34. 12
      guide/_site/site_libs/header-attrs-2.1/header-attrs.js
  35. 2
      guide/_site/site_libs/navigation-1.1/codefolding.js
  36. BIN
      guide/_site/web-resources.png
  37. 68
      guide/index.Rmd
  38. BIN
      guide/r-macos-downloads.png
  39. BIN
      guide/rswitch-1.5.0-prefs.png
  40. BIN
      guide/rswitch-1.5.0-resources-reorg.png
  41. BIN
      guide/rswitch-prefs.png
  42. BIN
      guide/web-resources.png
  43. BIN
      releases/RSwitch-1.7.0.app.zip
  44. 22
      rswitch-cmd/Info.plist
  45. 91
      rswitch-cmd/main.swift

8
NEWS.md

@ -1,3 +1,11 @@
# 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
- Use Notification Center vs alerts for everything but super-fatal errors

14
Pods/Pods.xcodeproj/project.pbxproj

@ -30,14 +30,14 @@
4F000B9DE332C7D2340B760411896249 /* Pods-RSwitch-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-RSwitch-umbrella.h"; sourceTree = "<group>"; };
574603E2D7597AEEB79587D7C3889AA1 /* Just.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Just.xcconfig; sourceTree = "<group>"; };
5A65C21E7E55D2FB16F3F2767B0063C7 /* Just-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Just-dummy.m"; sourceTree = "<group>"; };
5D52FFF81A1E26634DAD54B2BE7CBA99 /* Pods_RSwitch.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_RSwitch.framework; path = "Pods-RSwitch.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
5D52FFF81A1E26634DAD54B2BE7CBA99 /* Pods_RSwitch.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RSwitch.framework; sourceTree = BUILT_PRODUCTS_DIR; };
614B6A9B3F94B8D815819AA921D78D95 /* Just-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Just-prefix.pch"; sourceTree = "<group>"; };
6848EDAB880F7E2D2B180B0D25F67504 /* Just.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Just.modulemap; sourceTree = "<group>"; };
6B076A7E6A9514F7BC8853C054606452 /* Just-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Just-umbrella.h"; sourceTree = "<group>"; };
6B5F1D02B43D15E9D5752784305E1A5D /* Pods-RSwitch.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-RSwitch.debug.xcconfig"; sourceTree = "<group>"; };
7B194431FBE08FAA54D43A7D8C27124C /* Pods-RSwitch-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-RSwitch-Info.plist"; sourceTree = "<group>"; };
9A212383B73C76EDF23FB6126214CAB4 /* Just.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Just.framework; path = Just.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
9A212383B73C76EDF23FB6126214CAB4 /* Just.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Just.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
ACB677C58AE332368BBEB1AF0A6918B1 /* Pods-RSwitch-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-RSwitch-acknowledgements.plist"; sourceTree = "<group>"; };
B39AAB51B4D348DDE0A772879510BD57 /* Pods-RSwitch-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-RSwitch-frameworks.sh"; sourceTree = "<group>"; };
B8F0FBF810ECE65109C95E0C8BBB893F /* Just.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Just.swift; path = Sources/Just/Just.swift; sourceTree = "<group>"; };
@ -131,7 +131,6 @@
B8F0FBF810ECE65109C95E0C8BBB893F /* Just.swift */,
46872DBB8C34D63DE630A92868138E93 /* Support Files */,
);
name = Just;
path = Just;
sourceTree = "<group>";
};
@ -228,7 +227,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1100;
LastUpgradeCheck = 1100;
LastUpgradeCheck = 1120;
};
buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */;
compatibilityVersion = "Xcode 10.0";
@ -236,6 +235,7 @@
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = CF1408CF629C7361332E53B88F7BD30C;
productRefGroup = 623DD1C81238D9DB831E4CF39661DBBE /* Products */;
@ -363,7 +363,6 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 574603E2D7597AEEB79587D7C3889AA1 /* Just.xcconfig */;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_ENABLE_OBJC_WEAK = NO;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
@ -461,7 +460,6 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 574603E2D7597AEEB79587D7C3889AA1 /* Just.xcconfig */;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_ENABLE_OBJC_WEAK = NO;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
@ -500,7 +498,6 @@
baseConfigurationReference = D722B0A61F22FDFBDEF11F24016B4D1D /* Pods-RSwitch.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_ENABLE_OBJC_WEAK = NO;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
@ -540,7 +537,6 @@
baseConfigurationReference = 6B5F1D02B43D15E9D5752784305E1A5D /* Pods-RSwitch.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_ENABLE_OBJC_WEAK = NO;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";

24
Pods/Pods.xcodeproj/xcuserdata/hrbrmstr.xcuserdatad/xcschemes/Just.xcscheme

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1100"
LastUpgradeVersion = "1150"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForAnalyzing = "YES"
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES">
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "CE86A5B255D405184FBF7B919824D937"
@ -23,14 +23,15 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<AdditionalOptions>
</AdditionalOptions>
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
@ -38,17 +39,14 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
buildConfiguration = "Debug"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES">
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">

2
Pods/Pods.xcodeproj/xcuserdata/hrbrmstr.xcuserdatad/xcschemes/Pods-RSwitch.xcscheme

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1100"
LastUpgradeVersion = "1150"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

11
Pods/Target Support Files/Just/Just.debug.xcconfig

@ -0,0 +1,11 @@
CODE_SIGN_IDENTITY =
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Just
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/Just
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

11
Pods/Target Support Files/Just/Just.release.xcconfig

@ -0,0 +1,11 @@
CODE_SIGN_IDENTITY =
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Just
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/Just
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

235
RSwitch.xcodeproj/project.pbxproj

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objectVersion = 52;
objects = {
/* Begin PBXBuildFile section */
@ -19,6 +19,11 @@
010A1C1423215B0900E32A9A /* SessionWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 010A1C1323215B0900E32A9A /* SessionWindowController.swift */; };
0117C9E0232270F0004BC889 /* RStudioUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0117C9DF232270F0004BC889 /* RStudioUtils.swift */; };
011951B4231F00A000B62C3A /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011951B3231F00A000B62C3A /* Preferences.swift */; };
01575A37245443D7004A5715 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01575A36245443D7004A5715 /* main.swift */; };
01575A3B245445B2004A5715 /* rswitch-cmd in Resources */ = {isa = PBXBuildFile; fileRef = 01575A34245443D7004A5715 /* rswitch-cmd */; };
01575A4024544892004A5715 /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = 01575A3F24544892004A5715 /* ArgumentParser */; };
01575A4324544DA6004A5715 /* RVersions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01975549231BD919003FAD7B /* RVersions.swift */; };
01575A4424544F49004A5715 /* AppAlerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198B99F231970ED003F7578 /* AppAlerts.swift */; };
0178970D230ED25100F8F5BC /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0178970C230ED25100F8F5BC /* AboutViewController.swift */; };
018A8C3B2312C7BC0006E87D /* libprocInfo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 018A8C3A2312C7BC0006E87D /* libprocInfo.a */; };
018A8C3F2312CB480006E87D /* procHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 018A8C3E2312CB480006E87D /* procHelper.m */; };
@ -27,6 +32,8 @@
0198B99E23196689003F7578 /* BrowseMenuAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198B99D23196689003F7578 /* BrowseMenuAction.swift */; };
0198B9A0231970ED003F7578 /* AppAlerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198B99F231970ED003F7578 /* AppAlerts.swift */; };
0198B9AA23197D3A003F7578 /* Running.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198B9A923197D3A003F7578 /* Running.swift */; };
01A4F40A23F3084E005B88C2 /* Reachable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01A4F40923F3084E005B88C2 /* Reachable.swift */; };
01A4F40C23F30DB4005B88C2 /* Associations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01A4F40B23F30DB4005B88C2 /* Associations.swift */; };
01B611EC232176A200432807 /* NewSessionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B611EB232176A200432807 /* NewSessionViewController.swift */; };
01D3E43A232119DD00E3BC02 /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D3E439232119DD00E3BC02 /* WebViewController.swift */; };
01D3E43C23211B4C00E3BC02 /* RStudioServerAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D3E43B23211B4C00E3BC02 /* RStudioServerAction.swift */; };
@ -40,10 +47,36 @@
01FC5D02232874F600771CD7 /* ToolbarWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01FC5CFE232874F600771CD7 /* ToolbarWebViewController.swift */; };
01FC5D03232874F600771CD7 /* RStudioServerSessionWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01FC5CFF232874F600771CD7 /* RStudioServerSessionWebViewController.swift */; };
01FC5D04232874F600771CD7 /* PlotWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01FC5D00232874F600771CD7 /* PlotWebViewController.swift */; };
01FC6E97247B0AB60091AC87 /* exportPopupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01FC6E96247B0AB60091AC87 /* exportPopupViewController.swift */; };
01FC6E99247B0AF80091AC87 /* urls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01FC6E98247B0AF80091AC87 /* urls.swift */; };
01FC6E9B247B0B370091AC87 /* ExportWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01FC6E9A247B0B370091AC87 /* ExportWebViewController.swift */; };
01FC6E9D247B2FF80091AC87 /* DownloadFromRStudioServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01FC6E9C247B2FF80091AC87 /* DownloadFromRStudioServer.swift */; };
52B8A14237DA712A6A2ABDE0 /* Pods_RSwitch.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E2F8556B6C8EF8ED93F7E99 /* Pods_RSwitch.framework */; };
C4290DD6231F190F00AA5955 /* AppMenuActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4290DD5231F190E00AA5955 /* AppMenuActions.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
01575A3C24544613004A5715 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 01F3EF00230E635300DF5DF9 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 01575A33245443D7004A5715;
remoteInfo = "rswitch-cmd";
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
01575A32245443D7004A5715 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
01073F0E2311AE2E007162C9 /* String+Version.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Version.swift"; sourceTree = "<group>"; };
01073F122311E1CF007162C9 /* Globals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Globals.swift; sourceTree = "<group>"; };
@ -57,6 +90,8 @@
010A1C1323215B0900E32A9A /* SessionWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionWindowController.swift; sourceTree = "<group>"; };
0117C9DF232270F0004BC889 /* RStudioUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RStudioUtils.swift; sourceTree = "<group>"; };
011951B3231F00A000B62C3A /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
01575A34245443D7004A5715 /* rswitch-cmd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "rswitch-cmd"; sourceTree = BUILT_PRODUCTS_DIR; };
01575A36245443D7004A5715 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
016750FB2319A7A4009E2FD6 /* RSwitch.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RSwitch.entitlements; sourceTree = "<group>"; };
0178970C230ED25100F8F5BC /* AboutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = "<group>"; };
018A8C392312C7BC0006E87D /* procInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = procInfo.h; sourceTree = "<group>"; };
@ -69,7 +104,10 @@
0198B99D23196689003F7578 /* BrowseMenuAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowseMenuAction.swift; sourceTree = "<group>"; };
0198B99F231970ED003F7578 /* AppAlerts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAlerts.swift; sourceTree = "<group>"; };
0198B9A923197D3A003F7578 /* Running.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Running.swift; sourceTree = "<group>"; };
01A4F40923F3084E005B88C2 /* Reachable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Reachable.swift; sourceTree = "<group>"; };
01A4F40B23F30DB4005B88C2 /* Associations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Associations.swift; sourceTree = "<group>"; };
01B611EB232176A200432807 /* NewSessionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewSessionViewController.swift; sourceTree = "<group>"; };
01BDA1A5245482CD005DC733 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
01D3E439232119DD00E3BC02 /* WebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewController.swift; sourceTree = "<group>"; };
01D3E43B23211B4C00E3BC02 /* RStudioServerAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RStudioServerAction.swift; sourceTree = "<group>"; };
01D3E43E2321315900E3BC02 /* RStudioServerSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RStudioServerSession.swift; sourceTree = "<group>"; };
@ -84,6 +122,10 @@
01FC5CFE232874F600771CD7 /* ToolbarWebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToolbarWebViewController.swift; sourceTree = "<group>"; };
01FC5CFF232874F600771CD7 /* RStudioServerSessionWebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RStudioServerSessionWebViewController.swift; sourceTree = "<group>"; };
01FC5D00232874F600771CD7 /* PlotWebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlotWebViewController.swift; sourceTree = "<group>"; };
01FC6E96247B0AB60091AC87 /* exportPopupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = exportPopupViewController.swift; sourceTree = "<group>"; };
01FC6E98247B0AF80091AC87 /* urls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = urls.swift; sourceTree = "<group>"; };
01FC6E9A247B0B370091AC87 /* ExportWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExportWebViewController.swift; sourceTree = "<group>"; };
01FC6E9C247B2FF80091AC87 /* DownloadFromRStudioServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadFromRStudioServer.swift; sourceTree = "<group>"; };
0E2F8556B6C8EF8ED93F7E99 /* Pods_RSwitch.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RSwitch.framework; sourceTree = BUILT_PRODUCTS_DIR; };
53FF56D90FA7100C1726A4F7 /* Pods-RSwitch.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RSwitch.debug.xcconfig"; path = "Target Support Files/Pods-RSwitch/Pods-RSwitch.debug.xcconfig"; sourceTree = "<group>"; };
574911021B3B7938E36AB013 /* Pods-RSwitch.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RSwitch.release.xcconfig"; path = "Target Support Files/Pods-RSwitch/Pods-RSwitch.release.xcconfig"; sourceTree = "<group>"; };
@ -91,6 +133,14 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
01575A31245443D7004A5715 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
01575A4024544892004A5715 /* ArgumentParser in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
01F3EF05230E635300DF5DF9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -116,6 +166,8 @@
0178970C230ED25100F8F5BC /* AboutViewController.swift */,
01FC5CFD232874F500771CD7 /* plotPopupViewController.swift */,
01FC5D00232874F600771CD7 /* PlotWebViewController.swift */,
01FC6E96247B0AB60091AC87 /* exportPopupViewController.swift */,
01FC6E9A247B0B370091AC87 /* ExportWebViewController.swift */,
01FC5CFF232874F600771CD7 /* RStudioServerSessionWebViewController.swift */,
01FC5CFE232874F600771CD7 /* ToolbarWebViewController.swift */,
01073F202311E6BD007162C9 /* HandleRSwitch.swift */,
@ -131,6 +183,15 @@
path = Swift;
sourceTree = "<group>";
};
01575A35245443D7004A5715 /* rswitch-cmd */ = {
isa = PBXGroup;
children = (
01BDA1A5245482CD005DC733 /* Info.plist */,
01575A36245443D7004A5715 /* main.swift */,
);
path = "rswitch-cmd";
sourceTree = "<group>";
};
018A8C342312C6510006E87D /* ObjC */ = {
isa = PBXGroup;
children = (
@ -182,6 +243,7 @@
children = (
01073F1A2311E613007162C9 /* DownloadTarball.swift */,
01073F1C2311E64E007162C9 /* DownloadRStudio.swift */,
01FC6E9C247B2FF80091AC87 /* DownloadFromRStudioServer.swift */,
);
path = Downloaders;
sourceTree = "<group>";
@ -191,10 +253,13 @@
children = (
01073F182311E3B8007162C9 /* Bundle.swift */,
01073F122311E1CF007162C9 /* Globals.swift */,
01FC6E98247B0AF80091AC87 /* urls.swift */,
0117C9DF232270F0004BC889 /* RStudioUtils.swift */,
01975549231BD919003FAD7B /* RVersions.swift */,
0198B9A923197D3A003F7578 /* Running.swift */,
011951B3231F00A000B62C3A /* Preferences.swift */,
01A4F40923F3084E005B88C2 /* Reachable.swift */,
01A4F40B23F30DB4005B88C2 /* Associations.swift */,
);
path = Utils;
sourceTree = "<group>";
@ -212,16 +277,20 @@
isa = PBXGroup;
children = (
01F3EF0A230E635300DF5DF9 /* RSwitch */,
01575A35245443D7004A5715 /* rswitch-cmd */,
01F3EF09230E635300DF5DF9 /* Products */,
6E9DFB632C8DAEE9C1D64321 /* Pods */,
08E99D67B1A9A0A9D2CF3F66 /* Frameworks */,
);
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
};
01F3EF09230E635300DF5DF9 /* Products */ = {
isa = PBXGroup;
children = (
01F3EF08230E635300DF5DF9 /* RSwitch.app */,
01575A34245443D7004A5715 /* rswitch-cmd */,
);
name = Products;
sourceTree = "<group>";
@ -258,7 +327,38 @@
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
01BDA1A624548938005DC733 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
01575A33245443D7004A5715 /* rswitch-cmd */ = {
isa = PBXNativeTarget;
buildConfigurationList = 01575A38245443D7004A5715 /* Build configuration list for PBXNativeTarget "rswitch-cmd" */;
buildPhases = (
01BDA1A624548938005DC733 /* Headers */,
01575A30245443D7004A5715 /* Sources */,
01575A31245443D7004A5715 /* Frameworks */,
01575A32245443D7004A5715 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = "rswitch-cmd";
packageProductDependencies = (
01575A3F24544892004A5715 /* ArgumentParser */,
);
productName = "rswitch-cmd";
productReference = 01575A34245443D7004A5715 /* rswitch-cmd */;
productType = "com.apple.product-type.tool";
};
01F3EF07230E635300DF5DF9 /* RSwitch */ = {
isa = PBXNativeTarget;
buildConfigurationList = 01F3EF18230E635500DF5DF9 /* Build configuration list for PBXNativeTarget "RSwitch" */;
@ -272,6 +372,7 @@
buildRules = (
);
dependencies = (
01575A3D24544613004A5715 /* PBXTargetDependency */,
);
name = RSwitch;
productName = RSwitch;
@ -284,10 +385,13 @@
01F3EF00230E635300DF5DF9 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1100;
LastUpgradeCheck = 1100;
LastSwiftUpdateCheck = 1140;
LastUpgradeCheck = 1150;
ORGANIZATIONNAME = "Bob Rudis";
TargetAttributes = {
01575A33245443D7004A5715 = {
CreatedOnToolsVersion = 11.4;
};
01F3EF07230E635300DF5DF9 = {
CreatedOnToolsVersion = 11.0;
LastSwiftMigration = 1100;
@ -295,7 +399,7 @@
};
};
buildConfigurationList = 01F3EF03230E635300DF5DF9 /* Build configuration list for PBXProject "RSwitch" */;
compatibilityVersion = "Xcode 9.3";
compatibilityVersion = "Xcode 11.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
@ -303,11 +407,15 @@
Base,
);
mainGroup = 01F3EEFF230E635300DF5DF9;
packageReferences = (
01575A3E24544892004A5715 /* XCRemoteSwiftPackageReference "swift-argument-parser" */,
);
productRefGroup = 01F3EF09230E635300DF5DF9 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
01F3EF07230E635300DF5DF9 /* RSwitch */,
01575A33245443D7004A5715 /* rswitch-cmd */,
);
};
/* End PBXProject section */
@ -317,6 +425,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
01575A3B245445B2004A5715 /* rswitch-cmd in Resources */,
01F3EF10230E635500DF5DF9 /* Assets.xcassets in Resources */,
01F3EF13230E635500DF5DF9 /* Main.storyboard in Resources */,
);
@ -367,11 +476,22 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
01575A30245443D7004A5715 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
01575A4424544F49004A5715 /* AppAlerts.swift in Sources */,
01575A4324544DA6004A5715 /* RVersions.swift in Sources */,
01575A37245443D7004A5715 /* main.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
01F3EF04230E635300DF5DF9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
01073F212311E6BD007162C9 /* HandleRSwitch.swift in Sources */,
01A4F40A23F3084E005B88C2 /* Reachable.swift in Sources */,
0198B9A0231970ED003F7578 /* AppAlerts.swift in Sources */,
011951B4231F00A000B62C3A /* Preferences.swift in Sources */,
010A1C1423215B0900E32A9A /* SessionWindowController.swift in Sources */,
@ -390,15 +510,20 @@
01073F152311E370007162C9 /* Notify.swift in Sources */,
C4290DD6231F190F00AA5955 /* AppMenuActions.swift in Sources */,
01FC5D03232874F600771CD7 /* RStudioServerSessionWebViewController.swift in Sources */,
01FC6E9D247B2FF80091AC87 /* DownloadFromRStudioServer.swift in Sources */,
01073F1D2311E64E007162C9 /* DownloadRStudio.swift in Sources */,
01073F172311E397007162C9 /* Menu.swift in Sources */,
01F3EF0E230E635300DF5DF9 /* ViewController.swift in Sources */,
01FC6E97247B0AB60091AC87 /* exportPopupViewController.swift in Sources */,
01FC5D04232874F600771CD7 /* PlotWebViewController.swift in Sources */,
01A4F40C23F30DB4005B88C2 /* Associations.swift in Sources */,
01F3EF0C230E635300DF5DF9 /* AppDelegate.swift in Sources */,
01FC6E9B247B0B370091AC87 /* ExportWebViewController.swift in Sources */,
01FC5D01232874F600771CD7 /* plotPopupViewController.swift in Sources */,
01D3E441232131F300E3BC02 /* RStudioServerSessionManager.swift in Sources */,
01B611EC232176A200432807 /* NewSessionViewController.swift in Sources */,
01073F0F2311AE2E007162C9 /* String+Version.swift in Sources */,
01FC6E99247B0AF80091AC87 /* urls.swift in Sources */,
0198B99E23196689003F7578 /* BrowseMenuAction.swift in Sources */,
01FC5D02232874F600771CD7 /* ToolbarWebViewController.swift in Sources */,
01073F132311E1CF007162C9 /* Globals.swift in Sources */,
@ -407,6 +532,14 @@
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
01575A3D24544613004A5715 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 01575A33245443D7004A5715 /* rswitch-cmd */;
targetProxy = 01575A3C24544613004A5715 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
01F3EF11230E635500DF5DF9 /* Main.storyboard */ = {
isa = PBXVariantGroup;
@ -419,6 +552,50 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
01575A39245443D7004A5715 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "Developer ID Application";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = CBY22P58G8;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = "$(SRCROOT)/rswitch-cmd/Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = "is.rud.rswitch-cmd";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
STRIP_INSTALLED_PRODUCT = YES;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
01575A3A245443D7004A5715 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "Developer ID Application";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = CBY22P58G8;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = "$(SRCROOT)/rswitch-cmd/Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = "is.rud.rswitch-cmd";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
STRIP_INSTALLED_PRODUCT = YES;
SWIFT_VERSION = 5.0;
};
name = Release;
};
01F3EF16230E635500DF5DF9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -451,7 +628,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@ -470,11 +647,12 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INSTALL_PATH = /Users/hrbrmstr/Desktop;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
STRIP_INSTALLED_PRODUCT = NO;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
@ -512,7 +690,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@ -525,11 +703,12 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INSTALL_PATH = /Users/hrbrmstr/Desktop;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = NO;
SDKROOT = macosx;
STRIP_INSTALLED_PRODUCT = NO;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
@ -557,11 +736,13 @@
"$(PROJECT_DIR)/RSwitch/ObjC",
"$(PROJECT_DIR)/RSwitch/ObjC/ProcInfo",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 1.5.1;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 1.7.0;
PRODUCT_BUNDLE_IDENTIFIER = is.rud.bob.RSwitch;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "rswitch-1+";
SKIP_INSTALL = NO;
STRIP_INSTALLED_PRODUCT = YES;
SWIFT_OBJC_BRIDGING_HEADER = "RSwitch/ObjC/RSwitch-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
@ -590,11 +771,13 @@
"$(PROJECT_DIR)/RSwitch/ObjC",
"$(PROJECT_DIR)/RSwitch/ObjC/ProcInfo",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 1.5.1;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 1.7.0;
PRODUCT_BUNDLE_IDENTIFIER = is.rud.bob.RSwitch;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "rswitch-1+";
SKIP_INSTALL = NO;
STRIP_INSTALLED_PRODUCT = YES;
SWIFT_OBJC_BRIDGING_HEADER = "RSwitch/ObjC/RSwitch-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
@ -604,6 +787,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
01575A38245443D7004A5715 /* Build configuration list for PBXNativeTarget "rswitch-cmd" */ = {
isa = XCConfigurationList;
buildConfigurations = (
01575A39245443D7004A5715 /* Debug */,
01575A3A245443D7004A5715 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
01F3EF03230E635300DF5DF9 /* Build configuration list for PBXProject "RSwitch" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@ -623,6 +815,25 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
01575A3E24544892004A5715 /* XCRemoteSwiftPackageReference "swift-argument-parser" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "git@github.com:apple/swift-argument-parser.git";
requirement = {
branch = master;
kind = branch;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
01575A3F24544892004A5715 /* ArgumentParser */ = {
isa = XCSwiftPackageProductDependency;
package = 01575A3E24544892004A5715 /* XCRemoteSwiftPackageReference "swift-argument-parser" */;
productName = ArgumentParser;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 01F3EF00230E635300DF5DF9 /* Project object */;
}

78
RSwitch.xcodeproj/xcshareddata/xcschemes/RSwitch.xcscheme

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1150"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "01F3EF07230E635300DF5DF9"
BuildableName = "RSwitch.app"
BlueprintName = "RSwitch"
ReferencedContainer = "container:RSwitch.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "01F3EF07230E635300DF5DF9"
BuildableName = "RSwitch.app"
BlueprintName = "RSwitch"
ReferencedContainer = "container:RSwitch.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "01F3EF07230E635300DF5DF9"
BuildableName = "RSwitch.app"
BlueprintName = "RSwitch"
ReferencedContainer = "container:RSwitch.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

13
RSwitch.xcodeproj/xcuserdata/hrbrmstr.xcuserdatad/xcschemes/xcschememanagement.plist

@ -9,6 +9,19 @@
<key>orderHint</key>
<integer>2</integer>
</dict>
<key>rswitch-cmd.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>3</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>01F3EF07230E635300DF5DF9</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

16
RSwitch.xcworkspace/xcshareddata/swiftpm/Package.resolved

@ -0,0 +1,16 @@
{
"object": {
"pins": [
{
"package": "swift-argument-parser",
"repositoryURL": "git@github.com:apple/swift-argument-parser.git",
"state": {
"branch": "master",
"revision": "1081d08b1d716e6a68a9cbc258bb309359fbae1e",
"version": null
}
}
]
},
"version": 1
}

BIN
RSwitch.xcworkspace/xcuserdata/hrbrmstr.xcuserdatad/UserInterfaceState.xcuserstate

Binary file not shown.

60
RSwitch/Base.lproj/Main.storyboard

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097"/>
<capability name="System colors introduced in macOS 10.14" minToolsVersion="10.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -832,36 +832,36 @@ DQ
<scrollView appearanceType="aqua" fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rEB-nx-gFw">
<rect key="frame" x="9" y="11" width="463" height="247"/>
<autoresizingMask key="autoresizingMask"/>
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" copiesOnScroll="NO" id="iCP-uh-CRl">
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="iCP-uh-CRl">
<rect key="frame" x="0.0" y="0.0" width="463" height="247"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView ambiguous="YES" editable="NO" drawsBackground="NO" importsGraphics="NO" verticallyResizable="YES" smartInsertDelete="YES" id="kWH-Et-k6l">
<textView editable="NO" drawsBackground="NO" importsGraphics="NO" verticallyResizable="YES" smartInsertDelete="YES" id="kWH-Et-k6l">
<rect key="frame" x="0.0" y="0.0" width="463" height="247"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="systemBlueColor" catalog="System" colorSpace="catalog"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="alternatingContentBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="463" height="247"/>
<size key="maxSize" width="463" height="10000000"/>
<attributedString key="textStorage">
<fragment>
<string key="content">
RSwitch v1.5.1
RSwitch v1.7.0
Copyright © 2019 Bob Rudis
Copyright © 2020 Bob Rudis
MIT Licensed
</string>
<attributes>
<color key="NSColor" name="systemBlueColor" catalog="System" colorSpace="catalog"/>
<color key="NSColor" name="textColor" catalog="System" colorSpace="catalog"/>
<font key="NSFont" metaFont="label" size="17"/>
<paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
</attributes>
</fragment>
<fragment content="https://rud.is/rswitch/">
<attributes>
<color key="NSColor" name="systemBlueColor" catalog="System" colorSpace="catalog"/>
<color key="NSColor" name="textColor" catalog="System" colorSpace="catalog"/>
<font key="NSFont" metaFont="label" size="17"/>
<url key="NSLink" string="https://rud.is/rswitch/"/>
<paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
@ -872,7 +872,7 @@ MIT Licensed
Cgo
</string>
<attributes>
<color key="NSColor" name="systemBlueColor" catalog="System" colorSpace="catalog"/>
<color key="NSColor" name="textColor" catalog="System" colorSpace="catalog"/>
<font key="NSFont" metaFont="label" size="17"/>
<paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
</attributes>
@ -883,7 +883,7 @@ String+Version by DragonCherry
ProcInfo by Patrick Wardle
Just by Daniel Duan</string>
<attributes>
<color key="NSColor" name="systemBlueColor" catalog="System" colorSpace="catalog"/>
<color key="NSColor" name="textColor" catalog="System" colorSpace="catalog"/>
<font key="NSFont" size="11" name="HelveticaNeue"/>
<paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
</attributes>
@ -893,11 +893,11 @@ Just by Daniel Duan</string>
</textView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="1Xi-yD-fAs">
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="1Xi-yD-fAs">
<rect key="frame" x="-100" y="-100" width="225" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="S8X-5h-pQ6">
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="S8X-5h-pQ6">
<rect key="frame" x="-100" y="-100" width="15" height="223"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
@ -943,6 +943,40 @@ Just by Daniel Duan</string>
</objects>
<point key="canvasLocation" x="1543" y="1669"/>
</scene>
<!--Window Controller-->
<scene sceneID="EW7-BM-Jxb">
<objects>
<windowController storyboardIdentifier="exportPopupPanel" id="VkT-PO-mgW" customClass="ExportWebViewController" customModule="RSwitch" customModuleProvider="target" sceneMemberID="viewController">
<window key="window" title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="jld-Yw-4I9" customClass="NSPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="425" y="470" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1440"/>
<connections>
<outlet property="delegate" destination="VkT-PO-mgW" id="Kk8-u6-crK"/>
</connections>
</window>
<connections>
<segue destination="Emi-lu-BKC" kind="relationship" relationship="window.shadowedContentViewController" id="Zko-qD-0ow"/>
</connections>
</windowController>
<customObject id="ewW-uJ-OlL" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2423" y="406"/>
</scene>
<!--Export Popup View Controller-->
<scene sceneID="2dv-Ig-duI">
<objects>
<viewController id="Emi-lu-BKC" customClass="exportPopupViewController" customModule="RSwitch" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" id="ta8-41-7dT">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask"/>
</view>
</viewController>
<customObject id="RCl-OA-PEF" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2382" y="1492"/>
</scene>
<!--Rstudio Server Session Web View Controller-->
<scene sceneID="g2O-De-dmv">
<objects>

2
RSwitch/Info.plist

@ -25,7 +25,7 @@
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2019 Bob Rudis. All rights reserved. MIT Licensed</string>
<string>Copyright © 2020 Bob Rudis. All rights reserved. MIT Licensed</string>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>

17
RSwitch/Swift/AppDelegate.swift

@ -27,15 +27,18 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSToolbarDelegate {
}
@objc func performRStudioCheck(_ sender: NSObject) {
let v = RStudioUtils.latestVersionNumber()
if (!Preferences.lastVersionNotified.isVersion(equalTo: v)) {
Preferences.lastVersionNotified = v
notifyUser(title: "New RStudio Daily version available", text: ("Version: " + v))
if (currentReachabilityStatus != .notReachable) {
let v = RStudioUtils.latestVersionNumber()
if (!Preferences.lastVersionNotified.isVersion(equalTo: v)) {
Preferences.lastVersionNotified = v
notifyUserWithDL(title: "New RStudio Daily version available", text: ("Version: " + v))
}
}
}
@objc func performTimer(_ sender: Timer) {
if (Preferences.hourlyRStudioCheck) { performRStudioCheck(sender) }
if (Preferences.ensureFileHandlers) { FileAssociationUtils.setHandlers() }
}
var mainStoryboard: NSStoryboard!
@ -73,7 +76,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSToolbarDelegate {
}
DockIcon.standard.setVisibility(Preferences.showDockIcon)
}
func applicationDidFinishLaunching(_ aNotification: Notification) {
@ -89,7 +92,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSToolbarDelegate {
newSessController = (mainStoryboard.instantiateController(withIdentifier: "newSessPanel") as! NSWindowController)
sess = RStudioServerSessionManager()
if (Preferences.ensureFileHandlers) { FileAssociationUtils.setHandlers() }
timer = Timer.scheduledTimer(
timeInterval: 3600,
target: self,

57
RSwitch/Swift/Downloaders/DownloadFromRStudioServer.swift

@ -0,0 +1,57 @@
//
// DownloadFromRStudioServer.swift
// RSwitch
//
// Created by hrbrmstr on 8/24/19.
// Copyright © 2019 Bob Rudis. All rights reserved.
//
import Foundation
import Cocoa
func download_from_studio_server(fromRS : String, toFS : String) {
let rsURL = URL(string: fromRS)!
let fsURL = URL(string: toFS)!
URLSession.shared.configuration.timeoutIntervalForRequest = 300.0
let task = URLSession.shared.downloadTask(with: rsURL) {
localURL, urlResponse, error in
if (error != nil) {
NSLog("Error exporting from RStudio Server; \(String(describing: error))")
} else {
if let localURL = localURL {
if (FileManager.default.fileExists(atPath: fsURL.path)) {
do {
try FileManager.default.removeItem(at: fsURL)
} catch {
NSLog("Error removing file during RStudio Server export; \(error)")
}
}
do {
try FileManager.default.moveItem(at: localURL, to: fsURL)
NSWorkspace.shared.openFile(fsURL.deletingLastPathComponent().absoluteString, withApplication: "Finder")
NSWorkspace.shared.activateFileViewerSelecting([fsURL])
} catch {
NSLog("Error moving RStudio Server export file; \(error)")
}
}
}
}
task.resume()
}

2
RSwitch/Swift/Downloaders/DownloadRStudio.swift

@ -45,7 +45,7 @@ extension AppDelegate {
if (status < 300) {
guard let fileURL = tempURL else {
DispatchQueue.main.async { [weak self] in self?.rstudio_enabled = true }
DispatchQueue.main.async { [weak self] in self?.rstudio_enabled = true }
return
}

3
RSwitch/Swift/Downloaders/DownloadTarball.swift

@ -9,7 +9,8 @@
import Foundation
import Cocoa
let tarballURL = "https://mac.r-project.org/el-capitan/R-devel/R-devel-el-capitan-sa-x86_64.tar.gz"
let tarballURL = "https://mac.r-project.org/high-sierra/R-devel/x86_64/R-devel.tar.gz"
//let tarballURL = "https://mac.r-project.org/el-capitan/R-devel/R-devel-el-capitan-sa-x86_64.tar.gz"
let tarballFile = NSString(string: tarballURL).lastPathComponent as String
extension AppDelegate {

22
RSwitch/Swift/ExportWebViewController.swift

@ -0,0 +1,22 @@
//
// ExportWebViewController.swift
// RSwitch
//
// Created by hrbrmstr on 5/24/20.
// Copyright © 2020 Bob Rudis. All rights reserved.
//
import Cocoa
class ExportWebViewController: NSWindowController {
override func windowDidLoad() {
shouldCascadeWindows = false
window?.setFrameAutosaveName(window!.title)
super.windowDidLoad()
}
}

1
RSwitch/Swift/HandleRSwitch.swift

@ -33,6 +33,7 @@ extension AppDelegate {
withDestinationURL: NSURL(fileURLWithPath: title_link) as URL
)
self.notifyUser(title: "Success", text: "Current R version switched to " + title!)
// self.notifyUserWithDL(title: "Success", subtitle: "Subtitle", text: "Current R version switched to " + title!)
} catch {
self.notifyUser(title: "Action failed", text: "Failed to create alias for " + title_link + " (\(error))")
}

18
RSwitch/Swift/Menu.swift

@ -34,6 +34,18 @@ extension AppDelegate: NSMenuDelegate {
}
}
@objc func toggle_ensure_file_handlers(_ sender: NSMenuItem) {
Preferences.ensureFileHandlers = !Preferences.ensureFileHandlers
if (Preferences.ensureFileHandlers) { FileAssociationUtils.setHandlers() }
if let menu = statusItem.menu, let item = menu.item(withTag: 98) {
item.state = Preferences.ensureFileHandlers.stateValue
}
}
@objc func subscribeToMailingList(_ sender: NSMenuItem) {
NSWorkspace.shared.open(URL(string: "https://lists.sr.ht/~hrbrmstr/rswitch")!)
@ -115,6 +127,12 @@ extension AppDelegate: NSMenuDelegate {
rstudioCheckItem.state = Preferences.hourlyRStudioCheck.stateValue
prefSub.addItem(rstudioCheckItem)
let fileHandlersCheckItem = NSMenuItem(title: "Ensure RStudio opens R/Rmd files", action: #selector(toggle_ensure_file_handlers), keyEquivalent: "")
fileHandlersCheckItem.tag = 97
fileHandlersCheckItem.target = self
fileHandlersCheckItem.state = Preferences.ensureFileHandlers.stateValue
prefSub.addItem(fileHandlersCheckItem)
menu.addItem(NSMenuItem(title: "Check for update…", action: #selector(checkForUpdate), keyEquivalent: ""))
menu.addItem(NSMenuItem(title: "Subscribe to mailing list…", action: #selector(subscribeToMailingList), keyEquivalent: ""))
menu.addItem(NSMenuItem(title: "About RSwitch…", action: #selector(showAbout), keyEquivalent: ""))

25
RSwitch/Swift/MenuActions/BrowseMenuAction.swift

@ -30,18 +30,21 @@ class BrowseMenuAction {
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…", 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-Forge macOS Subversion…", url: "http://svn.rforge.net/osx/trunk/"),
BrowseMenuAction(title: "R-Project R GUI Subversion…", url: "https://svn.r-project.org/R-packages/trunk/Mac-GUI/"),
BrowseMenuAction(title: "Bioconductor…", url: "https://www.bioconductor.org/")
BrowseMenuAction(title: "Bioconductor…", url: "https://www.bioconductor.org/"),
BrowseMenuAction(title: "gfortran for macOS…", url: "https://github.com/fxcoudert/gfortran-for-macOS/releases"),
BrowseMenuAction(title: "macOS dependent static libs for building R…", url: "https://mac.r-project.org/libs-4/"),
BrowseMenuAction(title: "Sources for tools and libraries…", url: "https://mac.r-project.org/src/")
]
private static let webItemsExt = [
BrowseMenuAction(title: "R Package Documentation (rdrr.io)…", url: "https://rdrr.io/"),
BrowseMenuAction(title: "R Compiler Tools for RCpp on macOS…", url: "https://thecoatlessprofessor.com/programming/cpp/r-compiler-tools-for-rcpp-on-macos/"),
BrowseMenuAction(title: "R Compiler Tools for Rcpp on macOS…", url: "https://thecoatlessprofessor.com/programming/cpp/r-compiler-tools-for-rcpp-on-macos/"),
BrowseMenuAction(title: "Rseek…", url: "https://rseek.org"),
BrowseMenuAction(title: "R StackOverflow…", url: "https://stackoverflow.com/questions/tagged/r"),
BrowseMenuAction(title: "ROpenSci Discuss…", url: "https://discuss.ropensci.org/"),
@ -50,16 +53,18 @@ class BrowseMenuAction {
BrowseMenuAction(title: "Unofficial R-O GitHub CRAN Mirror…", url: "https://github.com/cran"),
BrowseMenuAction(title: "XQuartz (X11 for macOS)…", url: "https://www.xquartz.org/"),
BrowseMenuAction(title: "Homebrew (macOS Package Manager)…", url: "https://brew.sh/"),
BrowseMenuAction(title: "Apple Developer Portal…", url: "https://developer.apple.com/")
BrowseMenuAction(title: "OSGeo Homebrew tap…", url:"https://osgeo.github.io/homebrew-osgeo4mac/"),
BrowseMenuAction(title: "Apple Developer Portal…", url: "https://developer.apple.com/"),
BrowseMenuAction(title: "RStudio GitHub Issues…", url: "https://github.com/rstudio/rstudio/issues")
]
private static let webItemsMan = [
BrowseMenuAction(title: "An Introduction to R…", url: "file:///Library/Frameworks/R.framework/Versions/3.6/Resources/doc/manual/R-intro.html"),
BrowseMenuAction(title: "R Data Import/Export…", url: "file:///Library/Frameworks/R.framework/Versions/3.6/Resources/doc/manual/R-data.html"),
BrowseMenuAction(title: "R Installation and Administration…", url: "file:///Library/Frameworks/R.framework/Versions/3.6/Resources/doc/manual/R-admin.html"),
BrowseMenuAction(title: "Writing R Extensions…", url: "file:///Library/Frameworks/R.framework/Versions/3.6/Resources/doc/manual/"),
BrowseMenuAction(title: "The R language definition…", url: "file:///Library/Frameworks/R.framework/Versions/3.6/Resources/doc/manual/R-exts.html"),
BrowseMenuAction(title: "R Internals…", url: "file:///Library/Frameworks/R.framework/Versions/3.6/Resources/doc/manual/R-ints.html")
BrowseMenuAction(title: "An Introduction to R…", url: "file:///Library/Frameworks/R.framework/Resources/doc/manual/R-intro.html"),
BrowseMenuAction(title: "R Data Import/Export…", url: "file:///Library/Frameworks/R.framework/Resources/doc/manual/R-data.html"),
BrowseMenuAction(title: "R Installation and Administration…", url: "file:///Library/Frameworks/R.framework/Resources/doc/manual/R-admin.html"),
BrowseMenuAction(title: "Writing R Extensions…", url: "file:///Library/Frameworks/R.framework/Resources/doc/manual/"),
BrowseMenuAction(title: "The R language definition…", url: "file:///Library/Frameworks/R.framework/Resources/doc/manual/R-exts.html"),
BrowseMenuAction(title: "R Internals…", url: "file:///Library/Frameworks/R.framework/Resources/doc/manual/R-ints.html")
]
private static let webItemsBook = [

4
RSwitch/Swift/MenuActions/RStudioServerAction.swift

@ -36,14 +36,14 @@ class RStudioServerMenuAction {
menu.addItem(rsDropdown)
menu.setSubmenu(rsSub, for: rsDropdown)
let newRStudioSessItem = NSMenuItem(title: "New RStudio Server Connection…", action: Selector(("newRstudioServerSession:")), keyEquivalent: "")
let newRStudioSessItem = NSMenuItem(title: "New RStudio Server Connection…", action: #selector(AppDelegate.newRstudioServerSession(_:)), keyEquivalent: "")
rsSub.addItem(newRStudioSessItem)
rsSub.addItem(NSMenuItem.separator())
for sess in manager.sessions! {
let sessItem = NSMenuItem(title: sess.menuTitle, action: Selector(("activateServerSession:")), keyEquivalent: "")
let sessItem = NSMenuItem(title: sess.menuTitle, action: #selector(AppDelegate.activateServerSession(_:)), keyEquivalent: "")
sessItem.representedObject = sess
rsSub.addItem(sessItem)

27
RSwitch/Swift/Notify.swift

@ -10,11 +10,33 @@ import Foundation
import Cocoa
extension AppDelegate : NSUserNotificationCenterDelegate {
func notifyUser(title: String? = nil, subtitle: String? = nil, text: String? = nil) -> Void {
func notifyUserWithDL(title: String? = nil, subtitle: String? = nil, text: String? = nil) -> Void {
let notification = NSUserNotification()
// notification.identifier = "RSwitch"
notification.title = title
notification.subtitle = subtitle
notification.informativeText = text
notification.hasActionButton = true
notification.otherButtonTitle = "Dismiss"
notification.actionButtonTitle = "Download"
notification.soundName = NSUserNotificationDefaultSoundName
NSUserNotificationCenter.default.delegate = self
NSUserNotificationCenter.default.deliver(notification)
}
func notifyUser(title: String? = nil, subtitle: String? = nil, text: String? = nil) -> Void {
let notification = NSUserNotification()
// notification.identifier = "RSwitch"
notification.title = title
notification.subtitle = subtitle
notification.informativeText = text
@ -30,4 +52,7 @@ func notifyUser(title: String? = nil, subtitle: String? = nil, text: String? = n
return(true)
}
func userNotificationCenter(_ center: NSUserNotificationCenter, didActivate notification: NSUserNotification) {
}
}

83
RSwitch/Swift/RStudioServerSessionWebViewController.swift

@ -50,19 +50,86 @@ class RstudioServerSessionWebViewController: NSViewController, NSWindowDelegate
extension RstudioServerSessionWebViewController: WKUIDelegate {
func webView(_ webView: WKWebView, runOpenPanelWith parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping ([URL]?) -> Void) {
let openPanel = NSOpenPanel()
openPanel.canChooseFiles = true
openPanel.allowsMultipleSelection = false
openPanel.canChooseDirectories = false
openPanel.canCreateDirectories = false
openPanel.beginSheetModal(for:self.view.window!) { (response) in
if (response == NSApplication.ModalResponse.OK) {
completionHandler([openPanel.url!])
} else {
completionHandler(nil)
}
openPanel.close()
}
}
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if navigationAction.targetFrame == nil {
let plotWindowController = NSStoryboard(name: "Main", bundle: nil).instantiateController(withIdentifier: "plotPopupPanel") as! PlotWebViewController
let plotWV = (plotWindowController.contentViewController as! plotPopupViewController)
plotWV.view.window?.title = navigationAction.request.url!.absoluteString
plotWV.setupWebView(configuration: configuration)
plotWindowController.showWindow(self)
plotWV.loadWebView(urlIn: navigationAction.request.url!.absoluteString)
let u = URL(string: navigationAction.request.url!.absoluteString)!
return(plotWV.webView)
if ((u.urlComponents?.path.starts(with: "/export/")) != nil) {
let exportWindowController = NSStoryboard(name: "Main", bundle: nil).instantiateController(withIdentifier: "exportPopupPanel") as! ExportWebViewController
let exportWV = (exportWindowController.contentViewController as! exportPopupViewController)
exportWV.view.window?.title = navigationAction.request.url!.absoluteString
exportWV.setupWebView(configuration: configuration)
exportWV.loadWebView(urlIn: "")
let urlPath = navigationAction.request.url!.absoluteString
// 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()
}
}
}
return(exportWV.webView)
} else {
let plotWindowController = NSStoryboard(name: "Main", bundle: nil).instantiateController(withIdentifier: "plotPopupPanel") as! PlotWebViewController
let plotWV = (plotWindowController.contentViewController as! plotPopupViewController)
plotWV.view.window?.title = navigationAction.request.url!.absoluteString
plotWV.setupWebView(configuration: configuration)
plotWindowController.showWindow(self)
plotWV.loadWebView(urlIn: navigationAction.request.url!.absoluteString)
return(plotWV.webView)
}
}

41
RSwitch/Swift/Utils/Associations.swift

@ -0,0 +1,41 @@
//
// Associations.swift
// RSwitch
//
// Created by hrbrmstr on 2/11/20.
// Copyright © 2020 Bob Rudis. All rights reserved.
//
import Foundation
import AppKit
import ApplicationServices
class FileAssociationUtils {
// 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? ?? "";
LSSetDefaultRoleHandlerForContentType(setResR as CFString, LSRolesMask.all, "org.rstudio.RStudio" as CFString);
let setResRmd : String = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, "Rmd" as CFString, nil)?.takeRetainedValue() as String? ?? "";
LSSetDefaultRoleHandlerForContentType(setResRmd as CFString, LSRolesMask.all, "org.rstudio.RStudio" as CFString);
}
}

12
RSwitch/Swift/Utils/Preferences.swift

@ -21,6 +21,7 @@ extension UserDefaults {
enum Key: String {
case showDockIcon = "showDockIcon"
case hourlyRStudioCheck = "hourlyRStudioCheck"
case ensureFileHandlers = "ensureFileHandlers"
case firstRunGone = "firstRunGone"
case lastVersionNotified = ""
}
@ -86,10 +87,19 @@ struct Preferences {
defaults.synchronize()
}
}
static var ensureFileHandlers: Bool {
get { return(defaults.bool(forKey: .ensureFileHandlers)) }
set {
defaults.set(newValue, forKey: .ensureFileHandlers)
defaults.synchronize()
}
}
static func restore() {
Preferences.showDockIcon = false
Preferences.hourlyRStudioCheck = false
Preferences.ensureFileHandlers = false
Preferences.lastVersionNotified = ""
}

51
RSwitch/Swift/Utils/Reachable.swift

@ -0,0 +1,51 @@
//
// Reachable.swift
// RSwitch
//
// Created by hrbrmstr on 2/11/20.
// Copyright © 2020 Bob Rudis. All rights reserved.
//
import Foundation
import SystemConfiguration
protocol Utilities {}
extension NSObject: Utilities {
enum ReachabilityStatus {
case notReachable
case reachableViaWWAN
case reachableViaWiFi
}
var currentReachabilityStatus: ReachabilityStatus {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
return .notReachable
}
var flags: SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
return .notReachable
}
if flags.contains(.reachable) == false {
// The target host is not reachable.
return .notReachable
} else if flags.contains(.connectionRequired) == false {
// If the target host is reachable and no connection is required then we'll assume that you're on Wi-Fi...
return .reachableViaWiFi
} else if (flags.contains(.connectionOnDemand) == true || flags.contains(.connectionOnTraffic) == true) && flags.contains(.interventionRequired) == false {
// The connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs and no [user] intervention is needed
return .reachableViaWiFi
} else {
return .notReachable
}
}
}

25
RSwitch/Swift/Utils/urls.swift

@ -0,0 +1,25 @@
//
// urls.swift
// RSwitch
//
// Created by hrbrmstr on 5/24/20.
// Copyright © 2020 Bob Rudis. All rights reserved.
//
import Foundation
import Cocoa
import WebKit
extension URL {
var queryParameters: QueryParameters { return QueryParameters(url: self) }
}
class QueryParameters {
let queryItems: [URLQueryItem]
init(url: URL?) {
queryItems = URLComponents(string: url?.absoluteString ?? "")?.queryItems ?? []
}
subscript(name: String) -> String? {
return queryItems.first(where: { $0.name == name })?.value
}
}

84
RSwitch/Swift/exportPopupViewController.swift

@ -0,0 +1,84 @@
//
// exportPopupViewController.swift
// RSwitch
//
// Created by hrbrmstr on 5/24/20.
// Copyright © 2020 Bob Rudis. All rights reserved.
//
import Cocoa
import WebKit
// EXPORT
class exportPopupViewController: NSViewController {
var webView: WKWebView!
var urlPath: String = ""
open override func viewDidLoad() {
super.viewDidLoad()
}
func setupWebView(configuration: WKWebViewConfiguration) {
webView = WKWebView(frame: view.bounds, configuration: configuration)
webView.autoresizingMask = [.width, .height]
webView.uiDelegate = self
webView.navigationDelegate = self
view.addSubview(webView)
}
func loadWebView(urlIn: String) {
// 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()
// }
//
// }
//
// }
}
override func viewDidAppear() {
super.viewDidAppear()
}
}
extension exportPopupViewController: WKUIDelegate {
func webViewDidClose(_ webView: WKWebView) {
self.view.window?.close()
}
}
extension exportPopupViewController: WKNavigationDelegate {
open func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { }
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { }
}

29
RSwitch/Swift/plotPopupViewController.swift

@ -28,13 +28,23 @@ class plotPopupViewController: NSViewController {
view.addSubview(webView)
}
func loadWebView(urlIn: String) {
urlPath = urlIn
if let url = URL(string: urlPath) {
let urlRequest = URLRequest(url: url)
webView.load(urlRequest)
if (url.path.starts(with: "/export")) {
} else {
webView.load(urlRequest)
}
}
}
@ -50,12 +60,19 @@ extension plotPopupViewController: WKUIDelegate {
func webViewDidClose(_ webView: WKWebView) {
self.view.window?.close()
}
func webView(_ webView: WKWebView, runOpenPanelWith parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping ([URL]?) -> Void) {
}
}
extension plotPopupViewController: WKNavigationDelegate {
open func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
}
open func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {}
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>

BIN
guide/_site/r-macos-downloads.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 346 KiB

BIN
guide/_site/rswitch-prefs.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 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);

BIN
guide/_site/web-resources.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 KiB

68
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
@ -51,21 +52,20 @@ The `Resources` directory (and everything else in `/Library/Frameworks/R.framewo
- `Resources@ -> Versions/Current/Resources`
- `Versions/`
For the most control, you can install a coexisting version of R **oldrel**-1, **oldrel** (as of the date this document was created those would be R 3.4 and R 3.5), current **release** (R 3.6) and **devel** (3.7) by hand by going to the [R for macOS Developer's Page](https://mac.r-project.org/) and downloading the `tar.gz` version of those distributions:
For the most control, you can install a coexisting version of R **oldrel**-1, **oldrel** (as of the date this document was created those would be R 3.5 and R 3.6), current **release** (R 4.0) and **devel** (4.1) by hand by going to [R for macOS](https://mac.r-project.org/) and downloading the `tar.gz` version of those distributions:
![](r-macos-downloads.png)
Here are direct `https` links to the tarballs:
- [R 3.4](https://mac.r-project.org/mavericks/R-3.4-branch/R-3.4-branch-mavericks-sa-x86_64.tar.gz) (oldrel-1)
- [R 3.5](https://mac.r-project.org/el-capitan/R-3.5-branch/R-3.5-branch-el-capitan-sa-x86_64.tar.gz) (oldrel)
- [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 3.7](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
@ -101,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)
@ -139,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
@ -153,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:

BIN
guide/r-macos-downloads.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 346 KiB

BIN
guide/rswitch-1.5.0-prefs.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 KiB

BIN
guide/rswitch-1.5.0-resources-reorg.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 690 KiB

BIN
guide/rswitch-prefs.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

BIN
guide/web-resources.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 KiB

BIN
releases/RSwitch-1.7.0.app.zip

Binary file not shown.

22
rswitch-cmd/Info.plist

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>is.rud.rswitch-cmd</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>rswitch-cmd</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2020 Bob Rudis. All rights reserved. MIT Licensed</string>
</dict>
</plist>

91
rswitch-cmd/main.swift

@ -0,0 +1,91 @@
//
// main.swift
// rswitch-cmd
//
// Created by boB Rudis on 4/25/20.
// Copyright © 2020 Bob Rudis. All rights reserved.
//
import Foundation
import ArgumentParser
final class StandardErrorOutputStream: TextOutputStream {
func write(_ string: String) {
FileHandle.standardError.write(Data(string.utf8))
}
}
struct RSwitch: ParsableCommand {
static var configuration = CommandConfiguration(
abstract: "Switch R versions.",
version: "1.0.0"
)
@Flag(name: .shortAndLong, help: "List R versions.")
var list: Bool
@Argument(help: "The R version to switch to.")
var rversion: String?
func run() throws {
var outputStream = StandardErrorOutputStream()
let targetPath = RVersions.currentVersionTarget()
let versions = try RVersions.reloadVersions()
if (list || (rversion == nil)) {
for version in versions {
let complete = RVersions.hasRBinary(versionPath: version)
var v = version
if (version == targetPath) { v = v + " *" }
if (!complete) { v = version + " (incomplete)" }
print(v)
}
} else {
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)
} else {
let fm = FileManager.default
let rm_link = (RVersions.macos_r_framework as NSString).appendingPathComponent("Current")
let new_link = (RVersions.macos_r_framework as NSString).appendingPathComponent(rversion!)
do {
try fm.removeItem(atPath: rm_link)
} catch {
print("Failed to remove existing R version symlink. Check file/directory permissions.", to: &outputStream)
Darwin.exit(1)
}
do {
try fm.createSymbolicLink(
at: NSURL(fileURLWithPath: rm_link) as URL,
withDestinationURL: NSURL(fileURLWithPath: new_link) as URL
)
} catch {
print("Failed to create a symlink to the chosen R version. Check file/directory permissions.", to: &outputStream)
Darwin.exit(2)
}
Darwin.exit(0)
}
}
}
}
}
RSwitch.main()
Loading…
Cancel
Save