├── LICENSE ├── README.md ├── Ruby ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── bin │ ├── _terminal-share │ └── terminal-share ├── lib │ ├── terminal-share.rb │ └── terminal-share │ │ ├── share.rb │ │ └── version.rb └── terminal-share.gemspec ├── Terminal Share.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata └── Terminal Share ├── AppDelegate.h ├── AppDelegate.m ├── Info.plist ├── Prefix.pch ├── en.lproj └── InfoPlist.strings └── main.m /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 – 2021 Mattt (https://mat.tt/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > This library is no longer being maintained. 2 | 3 | # terminal-share 4 | 5 | **macOS Sharing Services... as a Service** 6 | 7 | Mac OS X 10.8 Mountain Lion introduced built-in sharing as a system-level feature 8 | with programmatic access provided via the 9 | [`NSSharingService` APIs](https://developer.apple.com/documentation/appkit/nssharingservice). 10 | 11 | `terminal-share` extends access to these APIs 12 | by proxying through a simple command-line application. 13 | 14 | ## Installation 15 | 16 | Install `terminal-share` by running the following command from Terminal: 17 | 18 | ``` 19 | $ gem install terminal-share 20 | ``` 21 | 22 | This will also install the `terminal-share` executable. 23 | 24 | ```ruby 25 | require 'terminal-share' 26 | 27 | TerminalShare.share(:twitter, text: "This was shared from the command-line, courtesy of terminal-share, by @mattt", url: "https://github.com/mattt/terminal-share") 28 | ``` 29 | 30 | ![Screenshot](https://raw.github.com/mattt/terminal-share/screenshots/terminal-share-screenshot.png) 31 | 32 | ## Command Line 33 | 34 | ``` 35 | $ terminal-share -service NAME \ 36 | [-text text] \ 37 | [-image /path/to/image] \ 38 | [-video /path/to/video] \ 39 | [-url "http://example.com"] 40 | ``` 41 | 42 | ### Arguments 43 | 44 | - `service`: (**Required**) A short string corresponding to the name of a particular `NSSharingService` to be used. Available values: 45 | - `twitter` - `NSSharingServiceNamePostOnTwitter` 46 | - `sinaweibo` - `NSSharingServiceNamePostOnSinaWeibo` 47 | - `email` - `NSSharingServiceNameComposeEmail` 48 | - `message` - `NSSharingServiceNameComposeMessage` 49 | - `airdrop` - `NSSharingServiceNameSendViaAirDrop` 50 | - `readinglist` - `NSSharingServiceNameAddToSafariReadingList` 51 | - `iphoto` - `NSSharingServiceNameAddToIPhoto` 52 | - `aperture` - `NSSharingServiceNameAddToAperture` 53 | - `facebook` - `NSSharingServiceNamePostOnFacebook` 54 | - `flickr` - `NSSharingServiceNamePostImageOnFlickr` 55 | - `vimeo` - `NSSharingServiceNamePostVideoOnVimeo` 56 | - `youku` - `NSSharingServiceNamePostVideoOnYouku` 57 | - `tudou` - `NSSharingServiceNamePostVideoOnTudou` 58 | - `text`: (_optional_) Text to be shared. 59 | - `image`: (_optional_) File path to an image to be shared. 60 | - `video`: (_optional_) File path to a video to be shared. 61 | - `url`: (_optional_) URL to be shared. 62 | 63 | > Not all services support sharing of all types of content. See the [NSSharingService Documentation](http://developer.apple.com/library/Mac/#documentation/AppKit/Reference/NSSharingService_Class/Reference/Reference.html) for additional guidelines. 64 | 65 | ### Example 66 | 67 | ``` 68 | $ terminal-share -service twitter \ 69 | -text "This was shared from the command-line, \ 70 | courtesy of terminal-share, by @mattt" \ 71 | -url "https://github.com/mattt/terminal-share" 72 | ``` 73 | 74 | ## Creator 75 | 76 | Mattt ([@mattt](https://twitter.com/mattt)) 77 | 78 | ## Credit 79 | 80 | Thanks to [Eloy Durán](https://github.com/alloy) for his work on 81 | [`terminal-notifier`](https://github.com/alloy/terminal-notifier), 82 | which provides a great example of how to use the Script Bridge APIs. 83 | 84 | ## License 85 | 86 | terminal-share is available under the MIT license. 87 | See the LICENSE file for more info. 88 | -------------------------------------------------------------------------------- /Ruby/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | gemspec 6 | -------------------------------------------------------------------------------- /Ruby/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | terminal-share (1.0.0) 5 | 6 | GEM 7 | remote: https://rubygems.org/ 8 | specs: 9 | rake (13.0.3) 10 | 11 | PLATFORMS 12 | ruby 13 | 14 | DEPENDENCIES 15 | rake (~> 13.0.1) 16 | terminal-share! 17 | 18 | BUNDLED WITH 19 | 2.1.4 20 | -------------------------------------------------------------------------------- /Ruby/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler' 4 | Bundler.setup 5 | 6 | require 'bundler/gem_tasks' 7 | 8 | task :default do 9 | system 'rake -T' 10 | end 11 | -------------------------------------------------------------------------------- /Ruby/bin/_terminal-share: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattt/terminal-share/bfa8456822078147d337bab46faaf5a81031f3d1/Ruby/bin/_terminal-share -------------------------------------------------------------------------------- /Ruby/bin/terminal-share: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | system "#{Gem.bin_path('terminal-share', '_terminal-share')} #{ARGV.join(' ')}" 5 | -------------------------------------------------------------------------------- /Ruby/lib/terminal-share.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'terminal-share/version' 4 | require 'terminal-share/share' 5 | -------------------------------------------------------------------------------- /Ruby/lib/terminal-share/share.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'shellwords' 4 | 5 | module TerminalShare 6 | class UnavailableException < RuntimeError 7 | end 8 | 9 | class << self 10 | def share(service, items = {}) 11 | raise UnavailableException unless available? 12 | 13 | arguments = ["-service #{service}"] 14 | %i[text image video url].each do |type| 15 | arguments << %(-#{type} "#{items[type]}") if items[type] 16 | end 17 | 18 | command = "terminal-share #{Shellwords.shelljoin(arguments)}" 19 | 20 | system command 21 | end 22 | 23 | private 24 | 25 | def available? 26 | @available ||= `uname`.strip == 'Darwin' && `sw_vers -productVersion`.strip >= '10.8' && !`which terminal-share`.empty? 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /Ruby/lib/terminal-share/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module TerminalShare 4 | VERSION = '1.0.0' 5 | end 6 | -------------------------------------------------------------------------------- /Ruby/terminal-share.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.push File.expand_path('lib', __dir__) 4 | require 'terminal-share' 5 | 6 | Gem::Specification.new do |s| 7 | s.name = 'terminal-share' 8 | s.authors = ['Mattt'] 9 | s.email = 'mattt@me.com' 10 | s.license = 'MIT' 11 | s.homepage = 'https://mat.tt' 12 | s.version = TerminalShare::VERSION 13 | s.platform = Gem::Platform::RUBY 14 | s.summary = 'terminal-share' 15 | s.description = 'A command-line interface to the macOS Sharing Services' 16 | 17 | s.add_development_dependency "rake", "~> 13.0.1" 18 | 19 | s.files = Dir['./**/*'].reject { |file| file =~ %r{\./(bin|log|pkg|script|spec|test|vendor)} } 20 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 21 | s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } 22 | s.require_paths = ['lib'] 23 | end 24 | -------------------------------------------------------------------------------- /Terminal Share.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | F82D7D811633D86400F553DC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F82D7D7D1633D84A00F553DC /* AppDelegate.m */; }; 11 | F82D7D821633D86700F553DC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F82D7D7E1633D84A00F553DC /* main.m */; }; 12 | F82D7D891633D95200F553DC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F82D7D791633D84A00F553DC /* InfoPlist.strings */; }; 13 | F8DB9E661633B53F009D6470 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8DB9E651633B53F009D6470 /* Cocoa.framework */; }; 14 | F8DB9E831633B550009D6470 /* ScriptingBridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8DB9E821633B550009D6470 /* ScriptingBridge.framework */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | F82D7D761633D84A00F553DC /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = "Terminal Share/AppDelegate.h"; sourceTree = SOURCE_ROOT; }; 19 | F82D7D771633D84A00F553DC /* Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Prefix.pch; path = "Terminal Share/Prefix.pch"; sourceTree = SOURCE_ROOT; }; 20 | F82D7D7A1633D84A00F553DC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; 21 | F82D7D7D1633D84A00F553DC /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = "Terminal Share/AppDelegate.m"; sourceTree = SOURCE_ROOT; }; 22 | F82D7D7E1633D84A00F553DC /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = main.m; path = "Terminal Share/main.m"; sourceTree = SOURCE_ROOT; }; 23 | F82D7D7F1633D84A00F553DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = "Terminal Share/Info.plist"; sourceTree = SOURCE_ROOT; }; 24 | F8DB9E611633B53F009D6470 /* terminal-share.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "terminal-share.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | F8DB9E651633B53F009D6470 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 26 | F8DB9E681633B53F009D6470 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 27 | F8DB9E691633B53F009D6470 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 28 | F8DB9E6A1633B53F009D6470 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 29 | F8DB9E821633B550009D6470 /* ScriptingBridge.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ScriptingBridge.framework; path = System/Library/Frameworks/ScriptingBridge.framework; sourceTree = SDKROOT; }; 30 | /* End PBXFileReference section */ 31 | 32 | /* Begin PBXFrameworksBuildPhase section */ 33 | F8DB9E5E1633B53F009D6470 /* Frameworks */ = { 34 | isa = PBXFrameworksBuildPhase; 35 | buildActionMask = 2147483647; 36 | files = ( 37 | F8DB9E831633B550009D6470 /* ScriptingBridge.framework in Frameworks */, 38 | F8DB9E661633B53F009D6470 /* Cocoa.framework in Frameworks */, 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | F82D7D781633D84A00F553DC /* en.lproj */ = { 46 | isa = PBXGroup; 47 | children = ( 48 | F82D7D791633D84A00F553DC /* InfoPlist.strings */, 49 | ); 50 | name = en.lproj; 51 | path = "Terminal Share/en.lproj"; 52 | sourceTree = SOURCE_ROOT; 53 | }; 54 | F82D7D801633D85400F553DC /* Supporting Files */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | F82D7D771633D84A00F553DC /* Prefix.pch */, 58 | F82D7D781633D84A00F553DC /* en.lproj */, 59 | F82D7D7E1633D84A00F553DC /* main.m */, 60 | F82D7D7F1633D84A00F553DC /* Info.plist */, 61 | ); 62 | name = "Supporting Files"; 63 | sourceTree = ""; 64 | }; 65 | F8DB9E561633B53F009D6470 = { 66 | isa = PBXGroup; 67 | children = ( 68 | F8DB9E6B1633B53F009D6470 /* Terminal Share */, 69 | F8DB9E641633B53F009D6470 /* Frameworks */, 70 | F8DB9E621633B53F009D6470 /* Products */, 71 | ); 72 | sourceTree = ""; 73 | }; 74 | F8DB9E621633B53F009D6470 /* Products */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | F8DB9E611633B53F009D6470 /* terminal-share.app */, 78 | ); 79 | name = Products; 80 | sourceTree = ""; 81 | }; 82 | F8DB9E641633B53F009D6470 /* Frameworks */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | F8DB9E821633B550009D6470 /* ScriptingBridge.framework */, 86 | F8DB9E651633B53F009D6470 /* Cocoa.framework */, 87 | F8DB9E671633B53F009D6470 /* Other Frameworks */, 88 | ); 89 | name = Frameworks; 90 | sourceTree = ""; 91 | }; 92 | F8DB9E671633B53F009D6470 /* Other Frameworks */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | F8DB9E681633B53F009D6470 /* AppKit.framework */, 96 | F8DB9E691633B53F009D6470 /* CoreData.framework */, 97 | F8DB9E6A1633B53F009D6470 /* Foundation.framework */, 98 | ); 99 | name = "Other Frameworks"; 100 | sourceTree = ""; 101 | }; 102 | F8DB9E6B1633B53F009D6470 /* Terminal Share */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | F82D7D761633D84A00F553DC /* AppDelegate.h */, 106 | F82D7D7D1633D84A00F553DC /* AppDelegate.m */, 107 | F82D7D801633D85400F553DC /* Supporting Files */, 108 | ); 109 | path = "Terminal Share"; 110 | sourceTree = ""; 111 | }; 112 | /* End PBXGroup section */ 113 | 114 | /* Begin PBXNativeTarget section */ 115 | F8DB9E601633B53F009D6470 /* terminal-share */ = { 116 | isa = PBXNativeTarget; 117 | buildConfigurationList = F8DB9E7F1633B540009D6470 /* Build configuration list for PBXNativeTarget "terminal-share" */; 118 | buildPhases = ( 119 | F8DB9E5D1633B53F009D6470 /* Sources */, 120 | F8DB9E5E1633B53F009D6470 /* Frameworks */, 121 | F8DB9E5F1633B53F009D6470 /* Resources */, 122 | ); 123 | buildRules = ( 124 | ); 125 | dependencies = ( 126 | ); 127 | name = "terminal-share"; 128 | productName = "Terminal Share"; 129 | productReference = F8DB9E611633B53F009D6470 /* terminal-share.app */; 130 | productType = "com.apple.product-type.application"; 131 | }; 132 | /* End PBXNativeTarget section */ 133 | 134 | /* Begin PBXProject section */ 135 | F8DB9E581633B53F009D6470 /* Project object */ = { 136 | isa = PBXProject; 137 | attributes = { 138 | LastUpgradeCheck = 0450; 139 | ORGANIZATIONNAME = "Mattt Thompson"; 140 | }; 141 | buildConfigurationList = F8DB9E5B1633B53F009D6470 /* Build configuration list for PBXProject "Terminal Share" */; 142 | compatibilityVersion = "Xcode 3.2"; 143 | developmentRegion = English; 144 | hasScannedForEncodings = 0; 145 | knownRegions = ( 146 | en, 147 | ); 148 | mainGroup = F8DB9E561633B53F009D6470; 149 | productRefGroup = F8DB9E621633B53F009D6470 /* Products */; 150 | projectDirPath = ""; 151 | projectRoot = ""; 152 | targets = ( 153 | F8DB9E601633B53F009D6470 /* terminal-share */, 154 | ); 155 | }; 156 | /* End PBXProject section */ 157 | 158 | /* Begin PBXResourcesBuildPhase section */ 159 | F8DB9E5F1633B53F009D6470 /* Resources */ = { 160 | isa = PBXResourcesBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | F82D7D891633D95200F553DC /* InfoPlist.strings in Resources */, 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | /* End PBXResourcesBuildPhase section */ 168 | 169 | /* Begin PBXSourcesBuildPhase section */ 170 | F8DB9E5D1633B53F009D6470 /* Sources */ = { 171 | isa = PBXSourcesBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | F82D7D821633D86700F553DC /* main.m in Sources */, 175 | F82D7D811633D86400F553DC /* AppDelegate.m in Sources */, 176 | ); 177 | runOnlyForDeploymentPostprocessing = 0; 178 | }; 179 | /* End PBXSourcesBuildPhase section */ 180 | 181 | /* Begin PBXVariantGroup section */ 182 | F82D7D791633D84A00F553DC /* InfoPlist.strings */ = { 183 | isa = PBXVariantGroup; 184 | children = ( 185 | F82D7D7A1633D84A00F553DC /* en */, 186 | ); 187 | name = InfoPlist.strings; 188 | sourceTree = ""; 189 | }; 190 | /* End PBXVariantGroup section */ 191 | 192 | /* Begin XCBuildConfiguration section */ 193 | F8DB9E7D1633B540009D6470 /* Debug */ = { 194 | isa = XCBuildConfiguration; 195 | buildSettings = { 196 | ALWAYS_SEARCH_USER_PATHS = NO; 197 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 198 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 199 | CLANG_CXX_LIBRARY = "libc++"; 200 | CLANG_ENABLE_OBJC_ARC = YES; 201 | CLANG_WARN_EMPTY_BODY = YES; 202 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 203 | COPY_PHASE_STRIP = NO; 204 | GCC_C_LANGUAGE_STANDARD = gnu99; 205 | GCC_DYNAMIC_NO_PIC = NO; 206 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 207 | GCC_OPTIMIZATION_LEVEL = 0; 208 | GCC_PREPROCESSOR_DEFINITIONS = ( 209 | "DEBUG=1", 210 | "$(inherited)", 211 | ); 212 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 213 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 214 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 215 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 216 | GCC_WARN_UNUSED_VARIABLE = YES; 217 | INFOPLIST_PREPROCESS = NO; 218 | MACOSX_DEPLOYMENT_TARGET = 10.8; 219 | ONLY_ACTIVE_ARCH = YES; 220 | SDKROOT = macosx; 221 | }; 222 | name = Debug; 223 | }; 224 | F8DB9E7E1633B540009D6470 /* Release */ = { 225 | isa = XCBuildConfiguration; 226 | buildSettings = { 227 | ALWAYS_SEARCH_USER_PATHS = NO; 228 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 229 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 230 | CLANG_CXX_LIBRARY = "libc++"; 231 | CLANG_ENABLE_OBJC_ARC = YES; 232 | CLANG_WARN_EMPTY_BODY = YES; 233 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 234 | COPY_PHASE_STRIP = YES; 235 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 236 | GCC_C_LANGUAGE_STANDARD = gnu99; 237 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 238 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 239 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 240 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 241 | GCC_WARN_UNUSED_VARIABLE = YES; 242 | INFOPLIST_PREPROCESS = NO; 243 | MACOSX_DEPLOYMENT_TARGET = 10.8; 244 | SDKROOT = macosx; 245 | }; 246 | name = Release; 247 | }; 248 | F8DB9E801633B540009D6470 /* Debug */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | CODE_SIGN_IDENTITY = "Mac Developer"; 252 | COMBINE_HIDPI_IMAGES = YES; 253 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 254 | GCC_PREFIX_HEADER = "Terminal Share/Prefix.pch"; 255 | INFOPLIST_FILE = "Terminal Share/Info.plist"; 256 | MACOSX_DEPLOYMENT_TARGET = 10.8; 257 | OTHER_LDFLAGS = ( 258 | "-sectcreate", 259 | __TEXT, 260 | __info_plist, 261 | "\"$(INFOPLIST_FILE)\"", 262 | ); 263 | PRODUCT_NAME = "$(TARGET_NAME)"; 264 | WRAPPER_EXTENSION = app; 265 | }; 266 | name = Debug; 267 | }; 268 | F8DB9E811633B540009D6470 /* Release */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | CODE_SIGN_IDENTITY = "Mac Developer"; 272 | COMBINE_HIDPI_IMAGES = YES; 273 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 274 | GCC_PREFIX_HEADER = "Terminal Share/Prefix.pch"; 275 | INFOPLIST_FILE = "Terminal Share/Info.plist"; 276 | MACOSX_DEPLOYMENT_TARGET = 10.8; 277 | OTHER_LDFLAGS = ( 278 | "-sectcreate", 279 | __TEXT, 280 | __info_plist, 281 | "\"$(INFOPLIST_FILE)\"", 282 | ); 283 | PRODUCT_NAME = "$(TARGET_NAME)"; 284 | WRAPPER_EXTENSION = app; 285 | }; 286 | name = Release; 287 | }; 288 | /* End XCBuildConfiguration section */ 289 | 290 | /* Begin XCConfigurationList section */ 291 | F8DB9E5B1633B53F009D6470 /* Build configuration list for PBXProject "Terminal Share" */ = { 292 | isa = XCConfigurationList; 293 | buildConfigurations = ( 294 | F8DB9E7D1633B540009D6470 /* Debug */, 295 | F8DB9E7E1633B540009D6470 /* Release */, 296 | ); 297 | defaultConfigurationIsVisible = 0; 298 | defaultConfigurationName = Release; 299 | }; 300 | F8DB9E7F1633B540009D6470 /* Build configuration list for PBXNativeTarget "terminal-share" */ = { 301 | isa = XCConfigurationList; 302 | buildConfigurations = ( 303 | F8DB9E801633B540009D6470 /* Debug */, 304 | F8DB9E811633B540009D6470 /* Release */, 305 | ); 306 | defaultConfigurationIsVisible = 0; 307 | defaultConfigurationName = Release; 308 | }; 309 | /* End XCConfigurationList section */ 310 | }; 311 | rootObject = F8DB9E581633B53F009D6470 /* Project object */; 312 | } 313 | -------------------------------------------------------------------------------- /Terminal Share.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Terminal Share/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // AppDelegate.h 2 | // 3 | // Copyright (c) 2012 Mattt Thompson (http://mattt.me/) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | @interface AppDelegate : NSObject 26 | @end 27 | -------------------------------------------------------------------------------- /Terminal Share/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // AppDelegate.m 2 | // 3 | // Copyright (c) 2012 Mattt Thompson (http://mattt.me/) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import "AppDelegate.h" 26 | 27 | static void PrintHelpBanner() { 28 | NSMutableArray *mutableLines = [NSMutableArray array]; 29 | NSMutableDictionary *mutableArguments = [NSMutableDictionary dictionary]; 30 | mutableArguments[@"service"] = @"A short string corresponding to the name of a particular NSSharingService to be used. Available values:\n\t\t\t\ttwitter, sinaweibo, email, message, airdrop, iphoto, aperture, facebook, flickr, vimeo, youku, tudou\n"; 31 | mutableArguments[@"text"] = @"Text to be shared (optional)"; 32 | mutableArguments[@"image"] = @"Image to be shared (optional)"; 33 | mutableArguments[@"video"] = @"Video to be shared (optional)"; 34 | mutableArguments[@"url"] = @"URL to be shared (optional)"; 35 | mutableArguments[@"file"] = @"File to be shared (optional)"; 36 | 37 | [mutableLines addObjectsFromArray:@[@"terminal-share", @"", @"A command-line interface to the Mac OS X Sharing Services", @""]]; 38 | 39 | [mutableLines addObjectsFromArray:@[@"Usage:", @"\t$ terminal-share -service NAME [-text text] [-image /path/to/image] [-video /path/to/video] [-url \"http://example.com\"] [-file /path/to/file]", @""]]; 40 | 41 | [mutableLines addObjectsFromArray:@[@"Example:", @"\t$terminal-share -service twitter -text \"This was shared from the command-line, courtesy of terminal-share, by @mattt\" -url \"https://github.com/mattt/terminal-share\"", @""]]; 42 | 43 | 44 | [mutableLines addObject:@"Arguments:"]; 45 | [@[@"service", @"text", @"image", @"video", @"url", @"file"] enumerateObjectsUsingBlock:^(id key, NSUInteger idx, BOOL *stop) { 46 | NSString *argument = [key stringByPaddingToLength:8 withString:@" " startingAtIndex:0]; 47 | NSString *description = [mutableArguments objectForKey:key]; 48 | [mutableLines addObject:[NSString stringWithFormat:@"\t-%@\t\t%@", argument, description]]; 49 | }]; 50 | [mutableLines addObject:@""]; 51 | 52 | [mutableLines addObjectsFromArray:@[@"Author:", @"\tMattt Thompson ", @""]]; 53 | [mutableLines addObjectsFromArray:@[@"Website:", @"\thttps://github.com/mattt", @""]]; 54 | 55 | [mutableLines enumerateObjectsUsingBlock:^(id line, NSUInteger idx, BOOL *stop) { 56 | printf("%s\n", [line UTF8String]); 57 | }]; 58 | } 59 | 60 | static NSString * NSSharingServiceNameFromDefaults(NSUserDefaults *defaults) { 61 | NSString *service = [[defaults objectForKey:@"service"] lowercaseString]; 62 | 63 | if ([service isEqualToString:@"twitter"]) { 64 | return NSSharingServiceNamePostOnTwitter; 65 | } else if ([service isEqualToString:@"sinaweibo"]) { 66 | return NSSharingServiceNamePostOnSinaWeibo; 67 | } else if ([service isEqualToString:@"email"]) { 68 | return NSSharingServiceNameComposeEmail; 69 | } else if ([service isEqualToString:@"message"]) { 70 | return NSSharingServiceNameComposeMessage; 71 | } else if ([service isEqualToString:@"airdrop"]) { 72 | return NSSharingServiceNameSendViaAirDrop; 73 | } else if ([service isEqualToString:@"readinglist"]) { 74 | return NSSharingServiceNameAddToSafariReadingList; 75 | } else if ([service isEqualToString:@"iphoto"]) { 76 | return NSSharingServiceNameAddToIPhoto; 77 | } else if ([service isEqualToString:@"aperture"]) { 78 | return NSSharingServiceNameAddToAperture; 79 | } else if ([service isEqualToString:@"facebook"]) { 80 | return NSSharingServiceNamePostOnFacebook; 81 | } else if ([service isEqualToString:@"flickr"]) { 82 | return NSSharingServiceNamePostImageOnFlickr; 83 | } else if ([service isEqualToString:@"vimeo"]) { 84 | return NSSharingServiceNamePostVideoOnVimeo; 85 | } else if ([service isEqualToString:@"youku"]) { 86 | return NSSharingServiceNamePostVideoOnYouku; 87 | } else if ([service isEqualToString:@"tudou"]) { 88 | return NSSharingServiceNamePostVideoOnTudou; 89 | } 90 | 91 | return nil; 92 | } 93 | 94 | static NSArray * NSSharingServiceItemsFromDefaults(NSUserDefaults *defaults) { 95 | NSMutableArray *mutableItems = [NSMutableArray array]; 96 | if ([defaults objectForKey:@"text"]) { 97 | [mutableItems addObject:[defaults objectForKey:@"text"]]; 98 | } 99 | 100 | if ([defaults objectForKey:@"image"]) { 101 | NSImage *image = [[NSImage alloc] initWithContentsOfFile:[defaults objectForKey:@"image"]]; 102 | if (image) { 103 | [mutableItems addObject:image]; 104 | } 105 | } 106 | 107 | if ([defaults objectForKey:@"url"]) { 108 | NSURL *url = [NSURL URLWithString:[defaults objectForKey:@"url"]]; 109 | if (url) { 110 | [mutableItems addObject:url]; 111 | } 112 | } 113 | 114 | if ([defaults objectForKey:@"video"]) { 115 | NSURL *videoURL = [NSURL fileURLWithPath:[defaults objectForKey:@"video"]]; 116 | if (videoURL) { 117 | [mutableItems addObject:videoURL]; 118 | } 119 | } 120 | 121 | if ([defaults objectForKey:@"file"]) { 122 | NSURL *fileURL = [NSURL fileURLWithPath:[defaults objectForKey:@"file"]]; 123 | if (fileURL) { 124 | [mutableItems addObject:fileURL]; 125 | } 126 | } 127 | 128 | return mutableItems; 129 | } 130 | 131 | @interface AppDelegate () 132 | @end 133 | 134 | @implementation AppDelegate 135 | 136 | - (void)applicationDidFinishLaunching:(NSNotification *)notification { 137 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 138 | 139 | NSString *sharingServiceName = NSSharingServiceNameFromDefaults(defaults); 140 | if (!sharingServiceName) { 141 | PrintHelpBanner(); 142 | exit(EXIT_FAILURE); 143 | } 144 | 145 | NSSharingService *sharingService = [NSSharingService sharingServiceNamed:sharingServiceName]; 146 | sharingService.delegate = self; 147 | [sharingService performWithItems:NSSharingServiceItemsFromDefaults(defaults)]; 148 | } 149 | 150 | #pragma mark - ScriptingBridge 151 | 152 | - (BOOL)activateAppWithBundleID:(NSString *)bundleID { 153 | id app = [SBApplication applicationWithBundleIdentifier:bundleID]; 154 | if (app) { 155 | [app activate]; 156 | 157 | return YES; 158 | } else { 159 | NSLog(@"Unable to find an application with the specified bundle indentifier."); 160 | 161 | return NO; 162 | } 163 | } 164 | 165 | #pragma mark - NSSharingServiceDelegate 166 | 167 | - (void)sharingService:(NSSharingService *)sharingService 168 | didShareItems:(NSArray *)items 169 | { 170 | exit(EXIT_SUCCESS); 171 | } 172 | 173 | - (void)sharingService:(NSSharingService *)sharingService 174 | didFailToShareItems:(NSArray *)items 175 | error:(NSError *)error 176 | { 177 | exit(EXIT_FAILURE); 178 | } 179 | 180 | @end 181 | -------------------------------------------------------------------------------- /Terminal Share/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.mattt.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | LSUIElement 28 | 29 | NSHumanReadableCopyright 30 | Copyright © 2012 Mattt Thompson. All rights reserved. 31 | NSMainNibFile 32 | MainMenu 33 | NSPrincipalClass 34 | NSApplication 35 | 36 | 37 | -------------------------------------------------------------------------------- /Terminal Share/Prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | -------------------------------------------------------------------------------- /Terminal Share/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Terminal Share/main.m: -------------------------------------------------------------------------------- 1 | // main.m 2 | // 3 | // Copyright (c) 2012 Mattt Thompson (http://mattt.me/) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "AppDelegate.h" 25 | 26 | int main(int argc, char *argv[]) { 27 | @autoreleasepool { 28 | NSApplication *application = [NSApplication sharedApplication]; 29 | AppDelegate *appDelegate = [[AppDelegate alloc] init]; 30 | [application setDelegate:appDelegate]; 31 | [application run]; 32 | } 33 | 34 | return EXIT_SUCCESS; 35 | } 36 | --------------------------------------------------------------------------------