climax 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -162,3 +162,51 @@ debugger will not begin until the current iteration of `main` has completed.
162
162
  This is excellent for stopping a long running process without interrupting its work. By sending an
163
163
  :exit or :quit event, whether through the Control DRb or from your application itself, your
164
164
  application will be allowed to finish processing its current unit of work before exiting.
165
+
166
+ Generating a New Application
167
+ ============================
168
+
169
+ To help you get started quickly, you can easily generate a new application using climax by running
170
+ the following command:
171
+
172
+ climax create <project-name>
173
+
174
+ Climax will then create a new project for you that is ready to rock and roll. Here is the file
175
+ structure generated for a new project named "my_project":
176
+
177
+ my_project/
178
+ Gemfile
179
+ LICENSE.txt
180
+ README.md
181
+ Rakefile
182
+ bin/
183
+ my_project*
184
+ features/
185
+ step_definitions/
186
+ support/
187
+ io.rb
188
+ env.rb
189
+ lib/
190
+ my_project.rb
191
+ my_project/
192
+ version.rb
193
+ my_project.gemspec
194
+ pkg
195
+
196
+ Your new application has the boilerplate code necessary to start running your application immediately:
197
+
198
+ cd my_project
199
+ ./bin/my_project --help
200
+ Usage: my_project [options]
201
+ -d, --daemon Fork application and run in background
202
+ --log_level Set to debug, info, warn, error, or fatal. Default: info.
203
+ --log_file File to log output to. By default logs to stdout.
204
+ --control_port Override the port for the control DRb to listen on. Default is 7249
205
+ -h, --help Display this help message.
206
+
207
+ Running the application will simply print `"Hello World"` until you hit `Ctrl-C`.
208
+
209
+ The three files you will want to modify are `README.md` (with info about your application),
210
+ `<project-name>.gemspec` and `lib/<project-name>.rb`.
211
+
212
+ You can bundle your application with `gem bundle *.gemspec`.
data/bin/climax ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
3
+ require 'rubygems' rescue nil
4
+ require 'climax/cli'
5
+ Climax::CLI::Application.new(ARGV)
data/lib/climax.rb CHANGED
@@ -1,218 +1 @@
1
- require "pry"
2
- require "slop"
3
- require "logger"
4
- require "pry-remote"
5
- require "climax/version"
6
- require "climax/control_drb"
7
-
8
- module Climax
9
- module Application
10
-
11
- def initialize(args=[])
12
- @args = args.dup
13
- options do
14
- on :d, :daemon, "Fork application and run in background"
15
- on :log_level=, "Set to debug, info, warn, error, or fatal. Default: info.", :default => "info"
16
- on :log_file=, "File to log output to. By default logs to stdout.", :default => nil
17
- on :control_port=, "Override the port for the control DRb to listen on. Default is 7249", :as => :int, :default => 7249
18
- end
19
- configure
20
- _parse_options
21
- end
22
-
23
- def _pre_main
24
- if daemonize?
25
- exit 0 if !Process.fork.nil?
26
- log.debug "Running in background (#{$$})"
27
- end
28
-
29
- log.debug "Starting Control DRb on port #{control_port}"
30
- @control_drb = Climax::ControlDRb.new(self, control_port)
31
- end
32
-
33
- def _post_main
34
- log.debug "Stopping Control DRb"
35
- @control_drb.stop_service
36
- end
37
-
38
- def _parse_options
39
- slop.parse!
40
- @opts = slop
41
- exit 0 if opts.help?
42
- rescue => e
43
- abort("#{e.message}\n#{slop.to_s}")
44
- end
45
-
46
- def daemonize?
47
- @daemonize = opts[:daemon]
48
- end
49
-
50
- def log
51
- if @log.nil?
52
- @log = Logger.new(log_file || $stdout, "daily")
53
- @log.level = log_level
54
- if log_file
55
- @log.formatter = proc do |severity, datetime, progname, msg|
56
- datetime = datetime.strftime("%Y-%m-%d %H:%M:%S")
57
- "[#{datetime}] #{$$} #{severity} -- #{msg}\n"
58
- end
59
- else
60
- # Give a more concise format when logging to STDOUT
61
- @log.formatter = proc do |severity, datetime, progname, msg|
62
- "#{severity}: #{msg}\n"
63
- end
64
- end
65
- end
66
- @log
67
- end
68
-
69
- def control_port
70
- @control_port ||= opts[:control_port]
71
- end
72
-
73
- def control_port= (port)
74
- raise "Cannot set control port to #{port}: ControlDRb is already running!" if @control_drb
75
- @control_port = port
76
- end
77
-
78
- def log_file
79
- @log_file ||= opts[:log_file]
80
- end
81
-
82
- def log_file= (path)
83
- if !@log.nil?
84
- warning = "Changing log path to #{path}!"
85
- $stderr.write(warning)
86
- log.warn(warning)
87
- @log = nil
88
- end
89
- @log_file = path
90
- end
91
-
92
- # Return current log_level
93
- def log_level
94
- @log_level ||= string_to_log_level opts[:log_level]
95
- end
96
-
97
- # Set log level to "debug", "warn", "info", etc. or use Logger::DEBUG, etc.
98
- def log_level= (level)
99
- log.level = @log_level = string_to_log_level(level)
100
- log.warn("Changed log level to #{level}")
101
- end
102
-
103
- # Example: "debug" => Logger::DEBUG
104
- def string_to_log_level (string)
105
- return string if string.is_a? Fixnum
106
- Logger.const_get(string.upcase)
107
- end
108
-
109
- # Raw command line arguments passed to application
110
- def args
111
- @args
112
- end
113
-
114
- # Return instance of Slop
115
- def slop
116
- @slop ||= Slop.new(:strict => true, :help => true)
117
- end
118
-
119
- # Method for wrapping calls to on() and banner(). Simply for readability.
120
- # Example:
121
- # options do
122
- # on 'v', 'verbose', 'More output'
123
- # end
124
- def options (&block)
125
- yield
126
- end
127
-
128
- # Run the application
129
- def run
130
- _pre_main
131
- pre_main
132
- @exit_status = _event_loop
133
- _post_main
134
- post_main
135
-
136
- exit exit_status if exit_status.is_a? Fixnum
137
- abort(exit_status.to_s)
138
- end
139
-
140
- def exit_status
141
- @exit_status
142
- end
143
-
144
- # Return current options. nil until ClimaxApplication::new has finished running
145
- def opts
146
- @opts
147
- end
148
-
149
- # Set a command line option ala Slop
150
- def on (*args)
151
- slop.on(*args)
152
- end
153
-
154
- # Set help banner output ala Slop
155
- def banner (*args)
156
- slop.banner(*args)
157
- end
158
-
159
- def command (cmd, &block)
160
- slop.command(cmd, block)
161
- end
162
-
163
- def _event_loop
164
- while true
165
-
166
- begin
167
- event = _next_event
168
-
169
- unless event.nil?
170
- case event.type
171
- when :set_log_level then log_level = event.payload
172
- when :stop_control_drb then @control_drb && @control_drb.stop_service
173
- when :start_remote_debugger then binding.remote_pry
174
- when :quit, :exit then return 0
175
- end
176
- end
177
- end while !event.nil?
178
-
179
- result = main
180
- return result if !result.nil?
181
- end
182
- end
183
-
184
- def send_event (type, payload=nil)
185
- events_mutex.synchronize {
186
- events.unshift OpenStruct.new(:type => type, :payload => payload)
187
- }
188
- end
189
-
190
- def events
191
- @events ||= []
192
- end
193
-
194
- def _next_event
195
- events_mutex.synchronize {
196
- events.pop
197
- }
198
- end
199
-
200
- def events_mutex
201
- @events_mutex ||= Mutex.new
202
- end
203
-
204
- def configure
205
- end
206
-
207
- def main
208
- raise "Please implement a main() method for your application."
209
- end
210
-
211
- def pre_main
212
- end
213
-
214
- def post_main
215
- end
216
-
217
- end
218
- end
1
+ require 'climax/application'
@@ -0,0 +1,218 @@
1
+ require "pry"
2
+ require "slop"
3
+ require "logger"
4
+ require "pry-remote"
5
+ require "climax/version"
6
+ require "climax/control_drb"
7
+
8
+ module Climax
9
+ module Application
10
+
11
+ def initialize(args=[])
12
+ @args = args.dup
13
+ options do
14
+ on :d, :daemon, "Fork application and run in background"
15
+ on :log_level=, "Set to debug, info, warn, error, or fatal. Default: info.", :default => "info"
16
+ on :log_file=, "File to log output to. By default logs to stdout.", :default => nil
17
+ on :control_port=, "Override the port for the control DRb to listen on. Default is 7249", :as => :int, :default => 7249
18
+ end
19
+ configure
20
+ _parse_options
21
+ end
22
+
23
+ def _pre_main
24
+ if daemonize?
25
+ exit 0 if !Process.fork.nil?
26
+ log.debug "Running in background (#{$$})"
27
+ end
28
+
29
+ log.debug "Starting Control DRb on port #{control_port}"
30
+ @control_drb = Climax::ControlDRb.new(self, control_port)
31
+ end
32
+
33
+ def _post_main
34
+ log.debug "Stopping Control DRb"
35
+ @control_drb.stop_service
36
+ end
37
+
38
+ def _parse_options
39
+ slop.parse!
40
+ @opts = slop
41
+ exit 0 if opts.help?
42
+ rescue => e
43
+ abort("#{e.message}\n#{slop.to_s}")
44
+ end
45
+
46
+ def daemonize?
47
+ @daemonize = opts[:daemon]
48
+ end
49
+
50
+ def log
51
+ if @log.nil?
52
+ @log = Logger.new(log_file || $stdout, "daily")
53
+ @log.level = log_level
54
+ if log_file
55
+ @log.formatter = proc do |severity, datetime, progname, msg|
56
+ datetime = datetime.strftime("%Y-%m-%d %H:%M:%S")
57
+ "[#{datetime}] #{$$} #{severity} -- #{msg}\n"
58
+ end
59
+ else
60
+ # Give a more concise format when logging to STDOUT
61
+ @log.formatter = proc do |severity, datetime, progname, msg|
62
+ "#{severity}: #{msg}\n"
63
+ end
64
+ end
65
+ end
66
+ @log
67
+ end
68
+
69
+ def control_port
70
+ @control_port ||= opts[:control_port]
71
+ end
72
+
73
+ def control_port= (port)
74
+ raise "Cannot set control port to #{port}: ControlDRb is already running!" if @control_drb
75
+ @control_port = port
76
+ end
77
+
78
+ def log_file
79
+ @log_file ||= opts[:log_file]
80
+ end
81
+
82
+ def log_file= (path)
83
+ if !@log.nil?
84
+ warning = "Changing log path to #{path}!"
85
+ $stderr.write(warning)
86
+ log.warn(warning)
87
+ @log = nil
88
+ end
89
+ @log_file = path
90
+ end
91
+
92
+ # Return current log_level
93
+ def log_level
94
+ @log_level ||= string_to_log_level opts[:log_level]
95
+ end
96
+
97
+ # Set log level to "debug", "warn", "info", etc. or use Logger::DEBUG, etc.
98
+ def log_level= (level)
99
+ log.level = @log_level = string_to_log_level(level)
100
+ log.warn("Changed log level to #{level}")
101
+ end
102
+
103
+ # Example: "debug" => Logger::DEBUG
104
+ def string_to_log_level (string)
105
+ return string if string.is_a? Fixnum
106
+ Logger.const_get(string.upcase)
107
+ end
108
+
109
+ # Raw command line arguments passed to application
110
+ def args
111
+ @args
112
+ end
113
+
114
+ # Return instance of Slop
115
+ def slop
116
+ @slop ||= Slop.new(:strict => true, :help => true)
117
+ end
118
+
119
+ # Method for wrapping calls to on() and banner(). Simply for readability.
120
+ # Example:
121
+ # options do
122
+ # on 'v', 'verbose', 'More output'
123
+ # end
124
+ def options (&block)
125
+ yield
126
+ end
127
+
128
+ # Run the application
129
+ def run
130
+ _pre_main
131
+ pre_main
132
+ @exit_status = _event_loop
133
+ _post_main
134
+ post_main
135
+
136
+ exit exit_status if exit_status.is_a? Fixnum
137
+ abort(exit_status.to_s)
138
+ end
139
+
140
+ def exit_status
141
+ @exit_status
142
+ end
143
+
144
+ # Return current options. nil until ClimaxApplication::new has finished running
145
+ def opts
146
+ @opts
147
+ end
148
+
149
+ # Set a command line option ala Slop
150
+ def on (*args)
151
+ slop.on(*args)
152
+ end
153
+
154
+ # Set help banner output ala Slop
155
+ def banner (*args)
156
+ slop.banner(*args)
157
+ end
158
+
159
+ def command (cmd, &block)
160
+ slop.command(cmd, block)
161
+ end
162
+
163
+ def _event_loop
164
+ while true
165
+
166
+ begin
167
+ event = _next_event
168
+
169
+ unless event.nil?
170
+ case event.type
171
+ when :set_log_level then log_level = event.payload
172
+ when :stop_control_drb then @control_drb && @control_drb.stop_service
173
+ when :start_remote_debugger then binding.remote_pry
174
+ when :quit, :exit then return 0
175
+ end
176
+ end
177
+ end while !event.nil?
178
+
179
+ result = main
180
+ return result if !result.nil?
181
+ end
182
+ end
183
+
184
+ def send_event (type, payload=nil)
185
+ _events_mutex.synchronize {
186
+ _events.unshift OpenStruct.new(:type => type, :payload => payload)
187
+ }
188
+ end
189
+
190
+ def _events
191
+ @_events ||= []
192
+ end
193
+
194
+ def _next_event
195
+ _events_mutex.synchronize {
196
+ _events.pop
197
+ }
198
+ end
199
+
200
+ def _events_mutex
201
+ @_events_mutex ||= Mutex.new
202
+ end
203
+
204
+ def configure
205
+ end
206
+
207
+ def main
208
+ raise "Please implement a main() method for your application."
209
+ end
210
+
211
+ def pre_main
212
+ end
213
+
214
+ def post_main
215
+ end
216
+
217
+ end
218
+ end
data/lib/climax/cli.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'slop'
2
+
3
+ require 'climax/commands/create'
4
+ require 'climax/commands/control'
5
+
6
+ module Climax
7
+ module CLI
8
+ class Application
9
+
10
+ def initialize (args)
11
+ @args = args.dup
12
+ @opts = Slop.parse(:strict => true, :help => true) do
13
+ command 'create' do
14
+ run do |options, args|
15
+ Climax::CLI::Command::Create.new(options, args).run
16
+ end
17
+ end
18
+
19
+ command 'control' do
20
+ on 'p', 'port=', 'Port of control drb to connect to. Default: 7249', :default => 7249, :as => :int
21
+ run do |options, args|
22
+ Climax::CLI::Command::Control.new(options, args).run
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def opts
29
+ @opts
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,77 @@
1
+ require 'fileutils'
2
+ require 'erb'
3
+
4
+ module Climax
5
+ module CLI
6
+ module Command
7
+ class Create
8
+
9
+ def initialize (options, args)
10
+ @opts = options.dup
11
+ @args = args.dup
12
+ end
13
+
14
+ def run
15
+ raise "Too many arguments. Just pass name of new climax application" if args.length > 1
16
+ raise "Not enough arguments. Please pass name of new climax application" if args.length < 1
17
+ @full_path = args[0]
18
+ @name = File.basename(@full_path)
19
+ @dir = File.dirname(@full_path)
20
+
21
+ create_directory_structure @name, @dir
22
+ end
23
+
24
+ def in_directory (dir, &block)
25
+ cwd = FileUtils.pwd
26
+ FileUtils.mkpath(dir)
27
+ FileUtils.cd(dir)
28
+ begin
29
+ yield
30
+ ensure
31
+ FileUtils.cd(cwd)
32
+ end
33
+ end
34
+
35
+ def create_directory_structure (name, dir)
36
+ in_directory(dir) do
37
+ # Create standard bundler gem layout
38
+ %x[bundle gem #{name}]
39
+ # Add a couple extra directories
40
+ FileUtils.mkpath(["#{name}/bin", "#{name}/features", "#{name}/pkg"])
41
+
42
+ # Get bundler generated module path
43
+ gemspec = File.read("#{name}/#{name}.gemspec")
44
+ module_string = /gem.version\s+=\s+(.*)::VERSION/.match(gemspec)[1]
45
+ module_path = module_string.split("::")
46
+
47
+ template_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "templates")
48
+
49
+ File.open("#{name}/bin/#{name}", "w") do |file|
50
+ file.write(ERB.new(File.read(File.join(template_dir, "application_wrapper.erb")), 0, '<>').result(binding))
51
+ end
52
+
53
+ FileUtils.chmod "+x", "#{name}/bin/#{name}"
54
+
55
+ File.open("#{name}/lib/#{name}.rb", "w") do |file|
56
+ file.write(ERB.new(File.read(File.join(template_dir, "application.rb.erb")), 0, '<>').result(binding))
57
+ end
58
+
59
+ gemspec.gsub!(/^end$/, " gem.add_development_dependency \"cucumber\"\n gem.add_runtime_dependency \"climax\"\nend")
60
+ File.open("#{name}/#{name}.gemspec", "w") do |file|
61
+ file.write(gemspec)
62
+ end
63
+
64
+ end
65
+ end
66
+
67
+ def opts
68
+ @opts
69
+ end
70
+
71
+ def args
72
+ @args
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,3 +1,3 @@
1
1
  module Climax
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,37 @@
1
+ require "climax"
2
+ require "<%= name %>/version"
3
+
4
+ <% indent = 0 %>
5
+ <% module_path.each do |m| %>
6
+ <%= (" "*indent) + "module #{m}\n" %>
7
+ <% indent = indent + 2 %>
8
+ <% end %>
9
+
10
+ class Application
11
+ include Climax::Application
12
+
13
+ def configure
14
+ # options do
15
+ # on 'v', 'verbose', 'More verbose'
16
+ # end
17
+ end
18
+
19
+ def pre_main
20
+ # log.debug "Application has is about to run"
21
+ end
22
+
23
+ def main
24
+ log.info "Hello World!"
25
+ sleep 1
26
+ return nil
27
+ end
28
+
29
+ def post_main
30
+ # log.debug "Application is shutting down."
31
+ end
32
+ end
33
+
34
+ <% module_path.each do |_| %>
35
+ <% indent = indent - 2 %>
36
+ <%= (" "*indent) + "end\n" %>
37
+ <% end %>
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+ $:.unshift File.expand_path("../../lib", __FILE__)
4
+ require "rubygems" rescue nil
5
+ require "<%= name %>"
6
+ <%= module_string %>::Application.new(ARGV).run
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: climax
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-21 00:00:00.000000000 Z
12
+ date: 2013-02-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pry
@@ -96,7 +96,8 @@ description: Opinionated framework for Ruby CLI applications that provides loggi
96
96
  of long running processes
97
97
  email:
98
98
  - alfred.fazio@gmail.com
99
- executables: []
99
+ executables:
100
+ - climax
100
101
  extensions: []
101
102
  extra_rdoc_files: []
102
103
  files:
@@ -104,10 +105,17 @@ files:
104
105
  - Gemfile
105
106
  - README.markdown
106
107
  - Rakefile
108
+ - bin/climax
107
109
  - climax.gemspec
108
110
  - lib/climax.rb
111
+ - lib/climax/application.rb
112
+ - lib/climax/cli.rb
113
+ - lib/climax/commands/control.rb
114
+ - lib/climax/commands/create.rb
109
115
  - lib/climax/control_drb.rb
110
116
  - lib/climax/version.rb
117
+ - templates/application.rb.erb
118
+ - templates/application_wrapper.erb
111
119
  - test/bin/hello_world
112
120
  - test/lib/hello_world.rb
113
121
  homepage: https://github.com/appriss/climax