motion-osx-cli 1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +112 -0
- data/lib/motion-osx-cli.rb +21 -0
- data/lib/project/motion-osx-cli.rb +110 -0
- metadata +65 -0
data/README.md
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# motion-osx-cli
|
2
|
+
|
3
|
+
This gem helps you create command line tools for OSX using RubyMotion.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'motion-osx-cli'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install motion-osx-cli
|
18
|
+
|
19
|
+
And add this line to your Rakefile:
|
20
|
+
|
21
|
+
require 'motion-osx-cli'
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Define a `main` method in your AppDelegate class which will be the main entry point for your application.
|
26
|
+
|
27
|
+
```Ruby
|
28
|
+
class AppDelegate
|
29
|
+
def main(argc, argv)
|
30
|
+
# your code
|
31
|
+
end
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
You can pass arguments to your app when executing it on the command line. `argc` is an integer repesenting the number of arguments passed to your application, and `argv` is an array containing each of these arguments. Let's see an example:
|
36
|
+
|
37
|
+
```Ruby
|
38
|
+
class AppDelegate
|
39
|
+
def main(argc, argv)
|
40
|
+
puts "Number of arguments:"
|
41
|
+
p argc
|
42
|
+
puts "Arguments:"
|
43
|
+
p argv
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
```
|
49
|
+
$ /Users/me/Desktop/my-app hello world
|
50
|
+
Number of arguments:
|
51
|
+
3
|
52
|
+
Arguments:
|
53
|
+
["/Users/me/Desktop/my-app", "hello", "world"]
|
54
|
+
```
|
55
|
+
|
56
|
+
As you can see, even if we don't pass any arguments, the first argument will always be the full path of the file we're executing. This is a standard behaviour for any command line application.
|
57
|
+
|
58
|
+
## Frameworks
|
59
|
+
|
60
|
+
By default, your app will only require the `Foundation` framework, which is required by the Rubymotion runtime. If you want to include other frameworks you can do so in your Rakefile:
|
61
|
+
|
62
|
+
```Ruby
|
63
|
+
Motion::Project::App.setup do |app|
|
64
|
+
app.frameworks << 'AppKit'
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
If you want to add some UI to your application, you will need to create a NSApplication:
|
69
|
+
|
70
|
+
```Ruby
|
71
|
+
class AppDelegate
|
72
|
+
def main(argc, argv)
|
73
|
+
app = NSApplication.sharedApplication
|
74
|
+
app.delegate = self
|
75
|
+
NSApp.run
|
76
|
+
end
|
77
|
+
|
78
|
+
def applicationDidFinishLaunching(notification)
|
79
|
+
# This will be executed after NSApp.run
|
80
|
+
end
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
## Distribution
|
85
|
+
|
86
|
+
When the Rubymotion toolchain builds your application, it will generate a .app file. However in the case of a command line application we are only interested in the executable. To retrieve it, right click in the .app file and click `Show Package Contents`. The executable will be located in a path similar to this, inside your `build` directory:
|
87
|
+
|
88
|
+
build/MacOSX-10.9-Release/my-app.app/Contents/MacOS/my-app
|
89
|
+
|
90
|
+
You can now copy it somewhere else and execute it on your terminal.
|
91
|
+
|
92
|
+
## Testing
|
93
|
+
|
94
|
+
If your app does does not require require the AppKit framework and doesn't call `NSApp.run` at any point, `rake spec` will fail. Currently, Rubymotion's test framework expects a run loop to be created by a NSApplication.
|
95
|
+
|
96
|
+
## TODO
|
97
|
+
|
98
|
+
- Find a way to make tests work.
|
99
|
+
- Create a Rubymotion template.
|
100
|
+
- Patch the toolchain to only create the executable and not the .app
|
101
|
+
|
102
|
+
## Thanks
|
103
|
+
|
104
|
+
Thanks to [Jack Chen](http://twitter.com/chendo) for his article [Building a Command Line OS X app with RubyMotion](http://chen.do/blog/2013/10/04/building-a-command-line-os-x-app-with-rubymotion/) which saved me a lot of detective work.
|
105
|
+
|
106
|
+
## Contributing
|
107
|
+
|
108
|
+
1. Fork it
|
109
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
110
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
111
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
112
|
+
5. Create new Pull Request
|
@@ -0,0 +1,21 @@
|
|
1
|
+
unless defined?(Motion::Project::Config)
|
2
|
+
raise "This file must be required within a RubyMotion project Rakefile."
|
3
|
+
end
|
4
|
+
|
5
|
+
require_relative 'project/motion-osx-cli'
|
6
|
+
|
7
|
+
lib_dir_path = File.dirname(File.expand_path(__FILE__))
|
8
|
+
Motion::Project::App.setup do |app|
|
9
|
+
app.frameworks = ['Foundation']
|
10
|
+
|
11
|
+
platform = app.respond_to?(:template) ? app.template : :ios
|
12
|
+
if platform != :osx
|
13
|
+
raise <<EOS
|
14
|
+
motion-osx-cli helps you create command line apps for OSX and does not work on iOS.
|
15
|
+
Make sure you are requiring the OSX template in your Rakefile:
|
16
|
+
|
17
|
+
require 'motion/project/template/osx'
|
18
|
+
|
19
|
+
EOS
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (c) 2012, HipByte SPRL and contributors
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
10
|
+
# list of conditions and the following disclaimer.
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
16
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
17
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
18
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
19
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
20
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
21
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
22
|
+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
23
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
24
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
25
|
+
|
26
|
+
module Motion; module Project;
|
27
|
+
class OSXConfig < XcodeConfig
|
28
|
+
def main_cpp_file_txt(spec_objs)
|
29
|
+
main_txt = ""
|
30
|
+
if frameworks.include?('AppKit')
|
31
|
+
main_txt << "#import <AppKit/AppKit.h>"
|
32
|
+
else
|
33
|
+
main_txt << "#import <Foundation/Foundation.h>"
|
34
|
+
end
|
35
|
+
main_txt << <<EOS
|
36
|
+
|
37
|
+
|
38
|
+
extern "C" {
|
39
|
+
void rb_define_global_const(const char *, void *);
|
40
|
+
void rb_rb2oc_exc_handler(void);
|
41
|
+
void rb_exit(int);
|
42
|
+
void RubyMotionInit(int argc, char **argv);
|
43
|
+
EOS
|
44
|
+
if spec_mode
|
45
|
+
spec_objs.each do |_, init_func|
|
46
|
+
main_txt << "void #{init_func}(void *, void *);\n"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
main_txt << <<EOS
|
50
|
+
}
|
51
|
+
EOS
|
52
|
+
if spec_mode
|
53
|
+
main_txt << <<EOS
|
54
|
+
@interface SpecLauncher : NSObject
|
55
|
+
@end
|
56
|
+
|
57
|
+
@implementation SpecLauncher
|
58
|
+
|
59
|
+
- (void)runSpecs
|
60
|
+
{
|
61
|
+
EOS
|
62
|
+
spec_objs.each do |_, init_func|
|
63
|
+
main_txt << "#{init_func}(self, 0);\n"
|
64
|
+
end
|
65
|
+
main_txt << <<EOS
|
66
|
+
[NSClassFromString(@\"Bacon\") performSelector:@selector(run)];
|
67
|
+
}
|
68
|
+
|
69
|
+
- (void)appLaunched:(NSNotification *)notification
|
70
|
+
{
|
71
|
+
[self runSpecs];
|
72
|
+
}
|
73
|
+
|
74
|
+
@end
|
75
|
+
EOS
|
76
|
+
end
|
77
|
+
|
78
|
+
main_txt << <<EOS
|
79
|
+
int
|
80
|
+
main(int argc, char **argv)
|
81
|
+
{
|
82
|
+
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
83
|
+
EOS
|
84
|
+
if ENV['ARR_CYCLES_DISABLE']
|
85
|
+
main_txt << <<EOS
|
86
|
+
setenv("ARR_CYCLES_DISABLE", "1", true);
|
87
|
+
EOS
|
88
|
+
end
|
89
|
+
main_txt << <<EOS
|
90
|
+
RubyMotionInit(argc, argv);
|
91
|
+
EOS
|
92
|
+
if spec_mode && frameworks.include?('AppKit')
|
93
|
+
main_txt << "SpecLauncher *specLauncher = [[SpecLauncher alloc] init];\n"
|
94
|
+
main_txt << "[[NSNotificationCenter defaultCenter] addObserver:specLauncher selector:@selector(appLaunched:) name:NSApplicationDidFinishLaunchingNotification object:nil];\n"
|
95
|
+
end
|
96
|
+
main_txt << <<EOS
|
97
|
+
NSMutableArray * arguments = [[NSMutableArray alloc] initWithCapacity: argc];
|
98
|
+
for (int i = 0; i < argc; i++)
|
99
|
+
{
|
100
|
+
[arguments addObject: [NSString stringWithUTF8String: argv[i]]];
|
101
|
+
}
|
102
|
+
[[NSClassFromString(@"#{delegate_class}") new] performSelector:NSSelectorFromString(@"main:") withObject:[NSNumber numberWithInt:argc] withObject:arguments];
|
103
|
+
[pool release];
|
104
|
+
rb_exit(0);
|
105
|
+
return 0;
|
106
|
+
}
|
107
|
+
EOS
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end; end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: motion-osx-cli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.0'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mark Villacampa
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-12-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: ! ' Easily create command line utilities for OSX with Rubymotion '
|
31
|
+
email:
|
32
|
+
- m@markvillacampa.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- README.md
|
38
|
+
- lib/motion-osx-cli.rb
|
39
|
+
- lib/project/motion-osx-cli.rb
|
40
|
+
homepage: ''
|
41
|
+
licenses:
|
42
|
+
- ''
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
requirements: []
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.8.25
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Easily create command line utilities for OSX with Rubymotion
|
65
|
+
test_files: []
|