simpleconsole 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,9 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2006 Hugh Bien
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
File without changes
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby -w
2
+ require File.dirname(__FILE__) + "/../lib/init.rb"
3
+
4
+ class TController < SimpleConsole::Controller
5
+ params :string => [:n => :name]
6
+ before_filter :check_for_invalid
7
+
8
+ def say_hi
9
+ puts "hi"
10
+ end
11
+
12
+ def show_id
13
+ @id = params[:id]
14
+ end
15
+
16
+ def show_name
17
+ @name = params[:name]
18
+ end
19
+
20
+ def show_title
21
+ @title = params[:title]
22
+ end
23
+
24
+ def method_missing(action)
25
+ puts "Unkown action: " + action.to_s
26
+ end
27
+
28
+ private
29
+ def check_for_invalid
30
+ if invalid_params?
31
+ print "Invalid param(s): "
32
+ puts invalid_params.join(", ")
33
+ exit
34
+ end
35
+ end
36
+
37
+ def finale
38
+ puts "finale!"
39
+ end
40
+ end
41
+
42
+ class TView < SimpleConsole::View
43
+
44
+ def show_id
45
+ puts "The value of id is #{@id}"
46
+ end
47
+
48
+ def show_name
49
+ puts "The value of name is #{@name}"
50
+ end
51
+
52
+ def show_title
53
+ puts "The value of title is #{@title}"
54
+ end
55
+
56
+ end
57
+
58
+ begin
59
+ SimpleConsole::Application.run(ARGV, TController, TView)
60
+ rescue Exception => error
61
+ puts error
62
+ end
@@ -0,0 +1,101 @@
1
+ require "rake/clean"
2
+ require "rubygems"
3
+ Gem::manage_gems
4
+ require "rake/gempackagetask"
5
+
6
+ CLEAN.include("doc")
7
+ SRC = FileList['lib/*']
8
+
9
+ desc "Creates documentation for the project"
10
+ task :doc do
11
+ sh "rdoc README MIT-LICENSE lib/* --main README"
12
+ end
13
+
14
+ desc "Runs all unit tests"
15
+ task :test do
16
+ Dir.glob("test/test_*.rb").each do |file|
17
+ require file
18
+ end
19
+ end
20
+
21
+ # needs some cleaning?
22
+ desc "Shows the total lines and LOC status"
23
+ task :stats do
24
+ total_lines = 0
25
+ total_codelines = 0
26
+ files = Hash.new
27
+
28
+ # Start with the library files
29
+ Dir.glob("lib/*").each do |file_name|
30
+ lines = 0; codelines = 0
31
+
32
+ next unless file_name =~ /.*rb/
33
+
34
+ file = File.open(file_name)
35
+
36
+ while line = file.gets
37
+ lines += 1
38
+ next if line =~ /^\s*$/
39
+ next if line =~ /^\s*#/
40
+ codelines += 1
41
+ end
42
+
43
+ files[File.basename(file_name)] = [lines, codelines]
44
+ total_lines += lines
45
+ total_codelines += codelines
46
+ end
47
+
48
+ puts "+-----------------------------------+--------+--------+"
49
+ puts "| Library File | Lines | LOC |"
50
+ puts "+-----------------------------------+--------+--------+"
51
+ files.each do |file_name, array|
52
+ print "| " + file_name + (" "*(34 - file_name.size)) + "|"
53
+ print " #{array[0]}" + (" "*(7 - array[0].to_s.size)) + "|"
54
+ puts " #{array[1]}" + (" "*(7 - array[1].to_s.size)) + "|"
55
+ end
56
+ puts "+-----------------------------------+--------+--------+"
57
+ print "| Total |"
58
+ print " #{total_lines}" + (" "*(7 - total_lines.to_s.size)) + "|"
59
+ puts " #{total_codelines}" + (" "*(7 - total_codelines.to_s.size)) + "|"
60
+ puts "+-----------------------------------+--------+--------+"
61
+
62
+ # Now do the test files
63
+ total_lines = 0; total_codelines = 0; files = Hash.new
64
+ Dir.glob("test/test_*").each do |file_name|
65
+ lines = 0; codelines = 0
66
+
67
+ next unless file_name =~ /.*rb/
68
+
69
+ file = File.open(file_name)
70
+
71
+ while line = file.gets
72
+ lines += 1
73
+ next if line =~ /^\s*$/
74
+ next if line =~ /^\s*#/
75
+ codelines += 1
76
+ end
77
+
78
+ files[File.basename(file_name)] = [lines, codelines]
79
+ total_lines += lines
80
+ total_codelines += codelines
81
+ end
82
+
83
+ puts "+-----------------------------------+--------+--------+"
84
+ puts "| Test File | Lines | LOC |"
85
+ puts "+-----------------------------------+--------+--------+"
86
+ files.each do |file_name, array|
87
+ print "| " + file_name + (" "*(34 - file_name.size)) + "|"
88
+ print " #{array[0]}" + (" "*(7 - array[0].to_s.size)) + "|"
89
+ puts " #{array[1]}" + (" "*(7 - array[1].to_s.size)) + "|"
90
+ end
91
+ puts "+-----------------------------------+--------+--------+"
92
+ print "| Total |"
93
+ print " #{total_lines}" + (" "*(7 - total_lines.to_s.size)) + "|"
94
+ puts " #{total_codelines}" + (" "*(7 - total_codelines.to_s.size)) + "|"
95
+ puts "+-----------------------------------+--------+--------+"
96
+ end
97
+
98
+ desc "Shows a quick coverage of tests."
99
+ task :rcov do
100
+ sh "rcov -T test/test_*.rb"
101
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby -w
2
+ require "rubygems"
3
+ require "simpleconsole"
4
+ # require File.dirname(__FILE__) + "/../"
5
+
6
+ SimpleConsole::Application.run(ARGV, _Controller_, _View_)
@@ -0,0 +1,5 @@
1
+ require "rubygems"
2
+ require "simpleconsole"
3
+
4
+ class _Controller_ < SimpleConsole::Controller
5
+ end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby -w
2
+ require "rubygems"
3
+ require "simpleconsole"
4
+ # require File.dirname(__FILE__) + "/../"
5
+
6
+ class _Controller_ < SimpleConsole::Controller
7
+ end
8
+
9
+ class _View_ < SimpleConsole::View
10
+ end
11
+
12
+ SimpleConsole::Application.run(ARGV, _Controller_, _View_)
@@ -0,0 +1,5 @@
1
+ require "rubygems"
2
+ require "simpleconsole"
3
+
4
+ class _View_ < SimpleConsole::View
5
+ end
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env ruby -w
2
+ # require File.dirname(__FILE__) + "/../lib/init.rb"
3
+ require "rubygems"
4
+ require "simpleconsole"
5
+
6
+ class Controller < SimpleConsole::Controller
7
+ params :string => {:c => :controller, :v => :view, :f => :file},
8
+ :bool => {:h => :help}
9
+ before_filter :check_params
10
+ before_filter :set_file, :only => [:application, :controller, :single, :view]
11
+ after_filter :put_file, :only => [:application, :controller, :single, :view]
12
+
13
+ def rakefile
14
+ @filename = "Rakefile"
15
+ read_file(@filename)
16
+ put_file(@filename)
17
+ end
18
+
19
+ def default
20
+ redirect_to :action => :help
21
+ end
22
+
23
+ def help
24
+ generators = [:application, :controller, :rakefile, :single, :view]
25
+ unless params[:id].nil?
26
+ redirect_to(:action => ("help_" + params[:id]).to_sym) if generators.include?(params[:id].to_sym)
27
+ render :action => :unknown_help
28
+ else
29
+ render :action => :help
30
+ end
31
+ end
32
+
33
+ def method_missing(method = "method_missing")
34
+ puts "Unknown action - #{method.to_s}."
35
+ puts "Try using 'simcon help' for usage info."
36
+ end
37
+
38
+ private
39
+ def set_file
40
+ if params.has_key?(:file)
41
+ @filename = params[:file]
42
+ else
43
+ @filename = nil
44
+ end
45
+
46
+ read_file
47
+ end
48
+
49
+ def read_file(filename = params[:action].to_s + ".rb")
50
+ begin
51
+ file = File.open(File.dirname(__FILE__) + "/files/" + filename)
52
+ @file_contents = file.read
53
+ file.close
54
+ rescue Exception => error
55
+ puts "Error when trying to open the file '#{filename}' for reading: "
56
+ + error.to_s
57
+ end
58
+
59
+ controller = params[:controller] || "Controller"
60
+ view = params[:view] || "View"
61
+ substitute_content(/_Controller_/ => controller, /_View_/ => view)
62
+ end
63
+
64
+ def put_file(filename = @filename)
65
+ if @filename
66
+ begin
67
+ File.open(filename, "w") do |file|
68
+ file.puts @file_contents
69
+ end
70
+ rescue Exception => error
71
+ puts "Error when trying to open the file '#{filename}' for writing: "
72
+ + error.to_s
73
+ end
74
+ else
75
+ puts @file_contents
76
+ end
77
+
78
+ render(:action => :file_generated)
79
+ end
80
+
81
+ def check_params
82
+ if params.has_key?(:help)
83
+ render :action => :help
84
+ end
85
+
86
+ if invalid_params?
87
+ puts "Unkown option(s): #{invalid_params.join(", ")}"
88
+ puts "Try using 'simcon help' for usage info."
89
+ exit
90
+ end
91
+ end
92
+
93
+ def substitute_content(rules)
94
+ rules.each do |regexp, replacement|
95
+ @file_contents.gsub!(regexp, replacement)
96
+ end
97
+ end
98
+ end
99
+
100
+ class View < SimpleConsole::View
101
+ def help
102
+ puts "Usage: simcon [generator] [--file output_file] [--options]"
103
+ puts ""
104
+ puts "Available generators and their usage:"
105
+ puts " application [--file output_file] [-c controller_name | -v view_name]"
106
+ puts " controller [--file output_file] [-c controller_name]"
107
+ puts " rakefile"
108
+ puts " single [--file output_file] [-c controller_name | -v view_name]"
109
+ puts " view [--file output_file] [-v view_name]"
110
+ puts ""
111
+ puts "The generators will create a new file given by the '-f output_file' argument. If no '--file' was given, it will output to STDOUT. Try 'gen help [generator]' for more info about each generator."
112
+ puts ""
113
+ puts "Available options:"
114
+ puts " -f | --file FILENAME"
115
+ puts " -c | --controller CONTROLLER"
116
+ puts " -v | --view VIEW"
117
+ end
118
+
119
+ def file_generated
120
+ puts "The file '#{@filename}' was generated." if @filename
121
+ end
122
+
123
+ def help_application
124
+ puts "Usage simcon application [-f output_file] [-c controller_name | -v view_name]"
125
+ puts ""
126
+ puts "Generates the script that will run an application. The Controller/View class names should be replaced and any files should be required within the script."
127
+ end
128
+
129
+ def help_controller
130
+ puts "Usage simcon controller [-f output_file] [-c controller_name]"
131
+ puts ""
132
+ puts "Generates the Controller class for an application."
133
+ end
134
+
135
+ def help_single
136
+ puts "Usage simcon single [-f output_file] [-c controller_name | -v view_name]"
137
+ puts ""
138
+ puts "Generates an entire application within a single script, including the Controller/View classes and the Application.run statement."
139
+ end
140
+
141
+ def help_view
142
+ puts "Usage simcon view [-f output_file] [-v view_name]"
143
+ puts ""
144
+ puts "Generates the View class for an application."
145
+ end
146
+
147
+ def help_rakefile
148
+ puts "Usage: simcon rakefile"
149
+ puts ""
150
+ puts "Will generate a default Rakefile in the current directory."
151
+ puts "Some tasks include: rdoc, rcov, tests, stats, package, and install."
152
+ end
153
+
154
+ def unknown_help
155
+ puts "Unknown action - #{params[:id]}."
156
+ help
157
+ end
158
+ end
159
+
160
+ SimpleConsole::Application.run(ARGV, Controller, View)
@@ -0,0 +1,59 @@
1
+ # Runs the application with the given controller and view.
2
+ #
3
+ # == Sample Usage
4
+ # Inside the script myapp:
5
+ #
6
+ # #!/usr/bin/env ruby -w
7
+ # require "rubygems"
8
+ # require "simpleconsole"
9
+ # require "your_files_with_controller_and_view.rb"
10
+ #
11
+ # Application.run(ARGV, ControllerClassConstant, ViewClassConstant)
12
+ # # .. the ViewClassConstant is optional, so run(ARGV, ControllerClassConstant) is valid
13
+ #
14
+ # From the command line:
15
+ #
16
+ # myapp [action] [id] [options]
17
+ # myapp action id --key value
18
+ #
19
+ # * action - this will be implemented as a method in the controller and/or view
20
+ # * id - this is accessible in the controller/view as params[:id]
21
+ # * options - will become available through the params hash. So "--key value" will be params[:key] = value.
22
+ #
23
+ # == Routing Rules
24
+ # * Usually, ARGV is passed to argv for parsing and execution.
25
+ # * ARGV[0] is taken to be the _action_ to execute
26
+ # * In the case that ARGV[0] does not exist, then the controller and view are called with the method 'default'.
27
+ # * If controller_klass implements _action_ as a method, it is executed.
28
+ # * If view_klass implements _action_ as a method, it is executed after the controller.
29
+ # * If there is no view_klass, no _action_ is taken for the view.
30
+ # * If the _action_ only exists in the controller_klass or view_klass, only that single _action_ is executed and no errors are raised.
31
+ # * If no _action_ exists in the controller_klass or view_klass, controller_klass's _method_missing_ is called and the view is ignored.
32
+ class SimpleConsole::Application
33
+
34
+ # This is the method to call to run your program from the top-level script.
35
+ # Check out the rdoc on SimpleConsole::Application for usage.
36
+ def self.run(argv, controller_klass, view_klass = nil)
37
+ @@control = controller_klass.new
38
+ @@view = view_klass ? view_klass.new(@@control) : nil
39
+ @@control.set_params(argv)
40
+ @@control.set_action(argv[0] || :default)
41
+
42
+ @@control.execute_action
43
+ @@view.render_action unless @@view.nil?
44
+
45
+ @@control.method_missing(@@control.params[:action]) if !control_implements? && !view_implements?
46
+ end
47
+
48
+ private
49
+ # Does the controller implement this action?
50
+ def self.control_implements?
51
+ return @@control.respond_to?(@@control.params[:action])
52
+ end
53
+
54
+ # Does the view implement this action?
55
+ def self.view_implements?
56
+ return !@@view.nil? && @@view.respond_to?(@@control.params[:action])
57
+ end
58
+
59
+ end
@@ -0,0 +1,222 @@
1
+ require File.dirname(__FILE__) + "/filter.rb"
2
+
3
+ # The Controller defines _actions_ for the application. Each _action_ can be
4
+ # implemented as an instance method.
5
+ #
6
+ # == Sample Usage
7
+ # # .. inside controller.rb
8
+ # class MyController < SimpleConsole::Controller
9
+ # def say_hello
10
+ # puts "hello!"
11
+ # end
12
+ # end
13
+ #
14
+ # # .. inside myapp
15
+ # # ..
16
+ # Application.run(ARGV, MyController)
17
+ #
18
+ # == What it did
19
+ # The above example defines the action "say_hello". So in the console:
20
+ #
21
+ # % myapp say_hello
22
+ # hello!
23
+ #
24
+ # == Related Methods
25
+ # Check out the "before_filter" and "after_filter" methods, similar to the
26
+ # methods implemented in Rails.
27
+ class SimpleConsole::Controller
28
+ attr_accessor :params
29
+
30
+ # Filter for methods to call previous to an action
31
+ @@before_chain = SimpleConsole::Filter.new
32
+
33
+ # Filter for methods to call after an action occurs
34
+ @@after_chain = SimpleConsole::Filter.new
35
+
36
+ # Keeps track of param types
37
+ @@params_parser = SimpleConsole::ParamsParser.new
38
+
39
+ # Initializes the "params" hash and creates a new Controller. Not needed when
40
+ # developing an application with SimpleConsole.
41
+ def initialize()
42
+ @params = Hash.new
43
+ end
44
+
45
+ # Returns true if the controller defines the action given, otherwise returns
46
+ # false (returns false on private methods, also).
47
+ def respond_to?(action)
48
+ if @@block_action.include?(action.to_s)
49
+ return false
50
+ elsif private_methods.include?(action.to_s)
51
+ return false
52
+ else
53
+ super
54
+ end
55
+ end
56
+
57
+ # Sets the controller's params hash when given ARGV.
58
+ def set_params(argv)
59
+ # Set params[:id]
60
+ id = argv[1] if argv[1] && argv[1] !~ /^-/
61
+ if id.to_i == 0 && id != "0"
62
+ params[:id] = id
63
+ else
64
+ params[:id] = id.to_i
65
+ end
66
+ params.update(@@params_parser.argv_to_params(argv))
67
+ end
68
+
69
+ # Sets the current action to the new action parameter.
70
+ def set_action(action)
71
+ params[:action] = action
72
+ end
73
+
74
+ # Executes in order:
75
+ # before_filter_for action
76
+ # actual action
77
+ # after_filter_for action
78
+ def execute_action
79
+ begin
80
+ params[:action] ||= :default
81
+ call_before_filter_for(params[:action])
82
+ send(params[:action]) if respond_to?(params[:action])
83
+ call_after_filter_for(params[:action])
84
+ rescue RuntimeError => error
85
+ raise error unless error.message == "Simple::Console Redirection"
86
+ end
87
+ end
88
+
89
+ protected
90
+ # When the view is rendered, this action is used instead
91
+ # == Example Usage
92
+ # render(:action => :new_view)
93
+ def render(parameters)
94
+ params.update(parameters)
95
+ end
96
+
97
+ # A redirect will discontinue the current action and redirect to the new one
98
+ # with the updated params.
99
+ # == Example Usage
100
+ # redirect_to(:action => :new_action)
101
+ def redirect_to(parameters)
102
+ params.update(parameters)
103
+ execute_action
104
+ raise RuntimeError, "Simple::Console Redirection"
105
+ end
106
+
107
+ # Returns an array of options that weren't specified by the params call.
108
+ # == Example Usage
109
+ # params :string => {:f => :first, :s => :second},
110
+ # :int => {:t => :third}
111
+ # before_filter :check_params
112
+ # # ...
113
+ # def check_params
114
+ # puts "Invalid option(s): " + invalid_params.join(", ")
115
+ # end
116
+ # == On the command line
117
+ # myapp --first one -t 3 --fourth oops --fifth huh?
118
+ # Invalid option(s): --fourth, --fifth
119
+ def invalid_params
120
+ return @@params_parser.invalid_params
121
+ end
122
+
123
+ # Returns true if the user gave any invalid options. To retrieve the list of
124
+ # invalid options use the method invalid_params.
125
+ def invalid_params?
126
+ return true if @@params_parser.invalid_params.size > 0
127
+ return false
128
+ end
129
+
130
+ private
131
+ # Calls all methods from "before_filter" for the given method.
132
+ # controller.call_before_filter_for(:method)
133
+ # This will look for all "before_filter" :actions that are hooked onto
134
+ # :method and execute them right before :method is called.
135
+ def call_before_filter_for(method_name)
136
+ @@before_chain.filter_for(method_name).each do |method|
137
+ self.send(method)
138
+ end
139
+ end
140
+
141
+ # Similar to "call_before_filter_for" except for the "after_filter".
142
+ def call_after_filter_for(method_name)
143
+ @@after_chain.filter_for(method_name).each do |method|
144
+ self.send(method)
145
+ end
146
+ end
147
+
148
+ protected
149
+ # Executes a method before certain actions.
150
+ # before_filter :method
151
+ # before_filter :method, :only => [:only_before_this_method]
152
+ # before_filter :method, :except => [:not_for_this_method!]
153
+ #
154
+ # == Sample Usage
155
+ # class MyController < SimpleConsole::Controller
156
+ # before_filter :say_hello, :only => [:say_bye]
157
+ #
158
+ # def say_bye
159
+ # puts "bye!"
160
+ # end
161
+ #
162
+ # private
163
+ # def say_hello
164
+ # puts "hello!"
165
+ # end
166
+ # end
167
+ #
168
+ # Now whenever the action "say_bye" is executed, "say_hello" is executed right
169
+ # before it:
170
+ #
171
+ # % myapp say_bye
172
+ # hello!
173
+ # bye!
174
+ def self.before_filter(method_to_call, options = nil)
175
+ @@before_chain.add_filter(method_to_call, options)
176
+ end
177
+
178
+ # Similar to "before_filter", except these methods are executed _AFTER_
179
+ # certain actions.
180
+ def self.after_filter(method_to_call, options = nil)
181
+ @@after_chain.add_filter(method_to_call, options)
182
+ end
183
+
184
+ # Sets the params that are accepted in a controller.
185
+ # params :string => { :l => :long_name }
186
+ #
187
+ # Now, for your application:
188
+ # % myapp action -l this_is_a_parameter
189
+ #
190
+ # This will result in 'params[:long_name] = "this_is_a_parameter"'
191
+ # Types include :string, :int, :text, and :bool.
192
+ #
193
+ # == Sample Usage
194
+ # class MyController < SimpleConsole::Controller
195
+ # params :int => { :i => :integer },
196
+ # :string => { :n => :name, :t => :title },
197
+ # :text => { :d => :description },
198
+ # :bool => { :o => :open, :c => :closed}
199
+ #
200
+ # # ...
201
+ # end
202
+ #
203
+ # On the command line:
204
+ # % myapp action -i 1 --name Hugh -t Mr --description programmer --open
205
+ #
206
+ # In the controller, the params hash is set for each key using the long name:
207
+ # params[:integer] = 1
208
+ # params[:name] = "Hugh"
209
+ # params[:title] = "Mr"
210
+ # params[:description] = "programmer"
211
+ # params[:open] = true
212
+ # params[:closed] = nil # because the -c or --closed switch wasn't set
213
+ def self.params(list)
214
+ @@params_parser.int_params(list[:int])
215
+ @@params_parser.string_params(list[:string])
216
+ @@params_parser.bool_params(list[:bool])
217
+ @@params_parser.text_params(list[:text])
218
+ end
219
+
220
+ # block all of these methods from being controller actions
221
+ @@block_action = self.new.methods
222
+ end
@@ -0,0 +1,69 @@
1
+ # This class keeps track of filters - much like Rails filters for
2
+ # ActionController.
3
+ #
4
+ # == Sample Usage
5
+ #
6
+ # before_filter = Filter.new
7
+ # before_filter.add_filter :first
8
+ # before_filter.add_filter :second, :only => [:use_me]
9
+ # before_filter.add_filter :third, :except => [:use_me]
10
+ #
11
+ # before_filter.filter_for(:use_me)
12
+ # # => Returns [:first, :second]
13
+ class SimpleConsole::Filter
14
+
15
+ # Initializes the filter
16
+ def initialize
17
+ @filter_chain = Hash.new
18
+ end
19
+
20
+ # Adds a method call to the current filter. Options include:
21
+ # * :except => Array
22
+ # * :only => Array
23
+ #
24
+ # == Sample Usage
25
+ #
26
+ # chain = Filter.new
27
+ # chain.add_filter(:first)
28
+ # chain.add_filter(:second, :only => [:use_me])
29
+ # chain.add_filter(:third, :except => [:dont_use_me])
30
+ # # => Adds :first to all, :second only to :use_me, and :third to all except :dont_use_me
31
+ def add_filter(method_to_call, options = nil)
32
+ if options == nil
33
+ @filter_chain[method_to_call.to_sym] = true
34
+ elsif options.has_key?(:only)
35
+ @filter_chain[method_to_call.to_sym] = Hash.new
36
+ @filter_chain[method_to_call.to_sym][:only] = options[:only]
37
+ elsif options.has_key?(:except)
38
+ @filter_chain[method_to_call.to_sym] = Hash.new
39
+ @filter_chain[method_to_call.to_sym][:except] = options[:except]
40
+ end
41
+ end
42
+
43
+ # Returns a list of the methods in the filter for method_name.
44
+ #
45
+ # == Example Usage
46
+ #
47
+ # chain = Filter.new
48
+ # chain.add_filter(:first, :second)
49
+ # chain.add_filter(:third, :fourth, :only => [:call_me])
50
+ # chain.add_filter(:fifth, :sixth, :except => [:call_me])
51
+ #
52
+ # filter_for(:call_me)
53
+ # # => [:first, :second, :third, :fourth, :fifth]
54
+ def filter_for(method_name)
55
+ methods = Array.new
56
+
57
+ @filter_chain.each do |method_to_call, option|
58
+ if option == true
59
+ methods << method_to_call
60
+ elsif option.has_key?(:only) && option[:only].include?(method_name.to_sym)
61
+ methods << method_to_call
62
+ elsif option.has_key?(:except) && !option[:except].include?(method_name.to_sym)
63
+ methods << method_to_call
64
+ end
65
+ end
66
+
67
+ return methods.uniq
68
+ end
69
+ end
@@ -0,0 +1,22 @@
1
+ # Handles the initialization of SimpleConsole by requiring all files and putting
2
+ # the classes under the SimpleConsole module.
3
+
4
+ # SimpleConsole is a module used for building command-line applications.
5
+ # The three most important methods are SimpleConsole::Controller,
6
+ # SimpleConsole::View, and SimpleConsole::Application.
7
+ module SimpleConsole
8
+ class Filter
9
+ end
10
+ class ParamsParser
11
+ end
12
+ class Controller
13
+ end
14
+ class View
15
+ end
16
+ class Application
17
+ end
18
+ end
19
+
20
+ Dir.glob(File.dirname(__FILE__) + "/*.rb").uniq.each do |file|
21
+ require file
22
+ end
@@ -0,0 +1,89 @@
1
+ class SimpleConsole::ParamsParser
2
+ def initialize
3
+ @letter_to_key ||= Hash.new
4
+ @key_types ||= Hash.new
5
+ @letter_types ||= Hash.new
6
+ @error_list ||= Array.new
7
+ end
8
+
9
+ def int_params(list)
10
+ set_key(list, :int)
11
+ end
12
+
13
+ def text_params(list)
14
+ set_key(list, :text)
15
+ end
16
+
17
+ def string_params(list)
18
+ set_key(list, :string)
19
+ end
20
+
21
+ def bool_params(list)
22
+ set_key(list, :bool)
23
+ end
24
+
25
+ def argv_to_params(argv)
26
+ params = Hash.new
27
+ @letter_to_key ||= Hash.new
28
+ argv.each do |arg|
29
+ if arg =~ /^--(.*)$/
30
+ argument = $1
31
+ value = argv[argv.index(arg) + 1]
32
+ if @letter_to_key.has_value?(argument.to_sym)
33
+ params[argument.to_sym] = get_value_of(value, argument.to_sym)
34
+ else
35
+ add_error(arg)
36
+ end
37
+ elsif arg =~ /^-(.)/
38
+ argument = $1
39
+ value = argv[argv.index(arg) + 1]
40
+ if @letter_to_key.has_key?(argument.to_sym)
41
+ argument = @letter_to_key[argument.to_sym]
42
+ params[argument.to_sym] = get_value_of(value, argument.to_sym)
43
+ else
44
+ add_error(arg)
45
+ end
46
+ end
47
+ end
48
+
49
+ return params
50
+ end
51
+
52
+ def invalid_params
53
+ @error_list ||= Array.new
54
+ return @error_list
55
+ end
56
+
57
+ private
58
+ def set_key(list, type)
59
+ return if !list
60
+ @letter_to_key ||= Hash.new
61
+ @key_types ||= Hash.new
62
+ @letter_types ||= Hash.new
63
+ @letter_to_key.update(list)
64
+ list.each do |letter, key|
65
+ @key_types[key] = type
66
+ @letter_types[letter] = type
67
+ end
68
+ end
69
+
70
+ def add_error(error)
71
+ @error_list ||= Array.new
72
+ @error_list << error
73
+ end
74
+
75
+ def get_value_of(value, key)
76
+ type = @key_types[key] if @key_types.has_key?(key)
77
+ type = @letter_types[key] if @letter_types.has_key?(key)
78
+
79
+ if type == :int
80
+ return value.to_i
81
+ elsif type == :text
82
+ return value.to_s
83
+ elsif type == :string
84
+ return value.to_s
85
+ elsif type == :bool
86
+ return true
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,22 @@
1
+ # Handles the initialization of SimpleConsole by requiring all files and putting
2
+ # the classes under the SimpleConsole module.
3
+
4
+ # SimpleConsole is a module used for building command-line applications.
5
+ # The three most important methods are SimpleConsole::Controller,
6
+ # SimpleConsole::View, and SimpleConsole::Application.
7
+ module SimpleConsole
8
+ class Filter
9
+ end
10
+ class ParamsParser
11
+ end
12
+ class Controller
13
+ end
14
+ class View
15
+ end
16
+ class Application
17
+ end
18
+ end
19
+
20
+ Dir.glob(File.dirname(__FILE__) + "/*.rb").uniq.each do |file|
21
+ require file
22
+ end
@@ -0,0 +1,56 @@
1
+ # The View is meant to render the output for each action in the Controller.
2
+ # Each 'view template' is just another method definition, usually with a lot of
3
+ # 'puts' method calls. The instance variables of the Controller is injected
4
+ # into the View, so if @var is set in the controller, you can access it in the
5
+ # view.
6
+ #
7
+ # == Sample Usage
8
+ # class MyController < SimpleConsole::Controller
9
+ # def say_hello
10
+ # @word = "Hello!"
11
+ # end
12
+ # end
13
+ #
14
+ # class MyView < SimpleConsole::View
15
+ # def say_hello
16
+ # puts @word
17
+ # end
18
+ # end
19
+ #
20
+ # SimpleConsole::Application.run(ARGV, MyController, MyView)
21
+ #
22
+ # == What it did
23
+ # The above example defines the action "say_hello". So in the console:
24
+ #
25
+ # % myapp say_hello
26
+ # Hello!
27
+ #
28
+ # == Related Methods
29
+ # Check out SimpleConsole::Controller's render method, which can change which
30
+ # view template is rendered.
31
+ class SimpleConsole::View
32
+ attr_accessor :params
33
+
34
+ # Llinks the view to the controller
35
+ def initialize(controller) #:nodoc
36
+ @control = controller
37
+ end
38
+
39
+ # Renders the current action, the default being @control's params[:action]
40
+ def render_action(action = @control.params[:action]) #:nodoc
41
+ set_variables
42
+ begin
43
+ send(action) if respond_to?(action)
44
+ rescue TypeError => error
45
+ raise TypeError, "params[:action] should be set to :default if no action is given"
46
+ end
47
+ end
48
+
49
+ private
50
+ # Sets the instance variables of this view to be the same as it's @control.
51
+ def set_variables #:nodoc
52
+ @control.instance_variables.each do |var|
53
+ instance_variable_set(var, @control.instance_variable_get(var))
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,61 @@
1
+ require "test/unit"
2
+ require "rubygems"
3
+ require "mocha"
4
+ require "stubba"
5
+ require File.dirname(__FILE__) + "/../lib/init.rb"
6
+
7
+ class AppControl < SimpleConsole::Controller
8
+ def method_missing(method_name)
9
+ end
10
+ end
11
+
12
+ class TwoAppControl < SimpleConsole::Controller
13
+ end
14
+
15
+ class TestApplication < Test::Unit::TestCase
16
+ include SimpleConsole
17
+
18
+ def setup
19
+ @call_chain = [:call_before_filter_for, :call_after_filter_for]
20
+ end
21
+
22
+ def teardown
23
+ end
24
+
25
+ # Sets a controller object to pass into Application.run
26
+ def set_control(method_call = nil)
27
+ control = mock
28
+ control.expects(:new).at_least_once.returns(control)
29
+ control.expects(:execute_action).at_least_once
30
+ control.expects(:params).at_least_once.returns({:action => method_call})
31
+ control.expects(:set_action).at_least_once
32
+ control.expects(:set_params).at_least_once
33
+
34
+ control.expects(method_call).at_least_once if method_call
35
+
36
+ return control
37
+ end
38
+
39
+ # Sets a view object to pass into Application.run
40
+ def set_view
41
+ view = mock
42
+ view.expects(:new).at_least_once.returns(view)
43
+ view.expects(:render_action).at_least_once
44
+
45
+ return view
46
+ end
47
+
48
+ def test_basic_control_run
49
+ Application.stubs(:control_implements?).returns(false)
50
+
51
+ # Run with default action, only controller no view
52
+ Application.run(Array.new, set_control(:default))
53
+ end
54
+
55
+ # Run tests where the controller and view don't implement action
56
+ def test_control_view_no_action_run
57
+ # Run with method_missing because neither controller or view has action
58
+ Application.run([:action], AppControl, set_view)
59
+ end
60
+ end
61
+
@@ -0,0 +1,56 @@
1
+ require "test/unit"
2
+ require "rubygems"
3
+ require "stubba"
4
+ require File.dirname(__FILE__) + "/../lib/init.rb"
5
+
6
+ # SampleController for tests usage.
7
+ # :say_hi should be followed by a :say_bye
8
+ # :bye should be prepended with a :hello
9
+ class SampleController < SimpleConsole::Controller
10
+ before_filter :say_hi, :only => [:say_bye]
11
+ after_filter :bye, :except => [:say_bye]
12
+
13
+ def say_bye; "bye"; end
14
+
15
+ def hello; "hello"; end
16
+
17
+ def default; redirect_to :action => :say_bye; raise "I shouldn't raise"; end
18
+
19
+ def say_hi; "hi"; end
20
+
21
+ def bye; "goodbye"; end
22
+ end
23
+
24
+ class TestController < Test::Unit::TestCase
25
+ def setup
26
+ @control = SampleController.new
27
+ end
28
+
29
+ def teardown
30
+ end
31
+
32
+ def test_filters_for_execute_action
33
+ @control.expects(:say_hi).at_least_once
34
+ @control.expects(:say_bye).at_least_once
35
+ @control.set_action(:say_bye)
36
+ @control.execute_action
37
+
38
+ @control.expects(:hello).times(1)
39
+ @control.expects(:bye).times(1)
40
+ @control.set_action(:hello)
41
+ @control.execute_action
42
+ end
43
+
44
+ def test_no_filters
45
+ control = SimpleConsole::Controller.new
46
+
47
+ assert_raise(NoMethodError) { control.execute_action }
48
+ end
49
+
50
+ def test_execute_action_with_redirect
51
+ control = SampleController.new
52
+ control.expects(:say_bye).at_least_once
53
+ assert_nothing_raised(RuntimeError) { control.execute_action }
54
+ end
55
+
56
+ end
@@ -0,0 +1,77 @@
1
+ require "test/unit"
2
+ require File.dirname(__FILE__) + "/../lib/init.rb"
3
+
4
+ class TestFilter < Test::Unit::TestCase
5
+ def setup
6
+ @filter = SimpleConsole::Filter.new
7
+ end
8
+
9
+ def teardown
10
+ end
11
+
12
+ def filter_chain
13
+ return @filter.instance_variable_get(:@filter_chain)
14
+ end
15
+
16
+ def assert_similar_arrays(expected, actual)
17
+ expected.each do |item|
18
+ assert(actual.include?(item))
19
+ end
20
+
21
+ actual.each do |item|
22
+ assert(expected.include?(item))
23
+ end
24
+ end
25
+
26
+ def test_add_filter_without_arguments
27
+ assert_raise(ArgumentError) { @filter.add_filter }
28
+ end
29
+
30
+ def test_filter_all
31
+ filters = Array.new
32
+ methods = [:one, :two, :three, :four, :five]
33
+
34
+ methods.each do |method|
35
+ filters << method
36
+ @filter.add_filter method
37
+
38
+ assert_similar_arrays(filters, @filter.filter_for(:random))
39
+ end
40
+ end
41
+
42
+ def test_filter_only
43
+ filters = Hash.new
44
+ filters[:one] = [:method_one, :method1, :one_method]
45
+ filters[:two] = [:method_two, :method2, :two_method]
46
+ filters[:three] = [:method_three, :method3, :three_method]
47
+ filters[:all] = filters[:one] + filters[:two] + filters[:three]
48
+
49
+ filters.each do |filter, methods|
50
+ methods.each { |method| @filter.add_filter method, :only => [filter, :all] } unless filter == :all
51
+ end
52
+
53
+ filters.each do |filter, methods|
54
+ assert_similar_arrays(methods, @filter.filter_for(filter))
55
+ end
56
+ end
57
+
58
+ def test_filter_except
59
+ filters = Hash.new
60
+
61
+ ones = [:method_one, :method1, :one_method]
62
+ twos = [:method_two, :method2, :two_method]
63
+ threes = [:method_three, :method3, :three_method]
64
+
65
+ filters[:one] = twos + threes
66
+ filters[:two] = ones + threes
67
+ filters[:three] = ones + twos
68
+
69
+ ones.each { |m| @filter.add_filter m, :except => [:one] }
70
+ twos.each { |m| @filter.add_filter m, :except => [:two] }
71
+ threes.each { |m| @filter.add_filter m, :except => [:three] }
72
+
73
+ filters.each do |filter, methods|
74
+ assert_similar_arrays(methods, @filter.filter_for(filter))
75
+ end
76
+ end
77
+ end
File without changes
@@ -0,0 +1,51 @@
1
+ require "test/unit"
2
+ require File.dirname(__FILE__) + "/../lib/init.rb"
3
+
4
+ class TestParamsParser < Test::Unit::TestCase
5
+ def setup
6
+ @parser = SimpleConsole::ParamsParser.new
7
+ end
8
+
9
+ def teardown
10
+ end
11
+
12
+ def assert_same_hash(expected, result)
13
+ expected.each do |key, value|
14
+ assert(result.has_key?(key) && result.has_value?(value))
15
+ assert_equal(value, result[key])
16
+ end
17
+
18
+ result.each do |key, value|
19
+ assert(expected.has_key?(key) && expected.has_value?(value))
20
+ assert_equal(value, expected[key])
21
+ end
22
+ end
23
+
24
+ def test_int
25
+ @parser.int_params(:i => :id, :f => :float)
26
+ argv = ["-i", "1", "--float", "2"]
27
+
28
+ assert_same_hash({:id => 1, :float => 2}, @parser.argv_to_params(argv))
29
+ end
30
+
31
+ def test_bool
32
+ @parser.bool_params(:o => :open, :c => :close)
33
+ argv = ["-o", "doesn't matter", "--close", "--open"]
34
+
35
+ assert_same_hash({:open => true, :close => true}, @parser.argv_to_params(argv))
36
+ end
37
+
38
+ def test_text
39
+ @parser.text_params(:d => :description, :t => :text)
40
+ argv = ["-d", "a description", "--text", "the text"]
41
+
42
+ assert_same_hash({:description => "a description", :text => "the text"}, @parser.argv_to_params(argv))
43
+ end
44
+
45
+ def test_string
46
+ @parser.string_params(:s => :string, :t => :title)
47
+ argv = ["-s", "a string", "--title", "the title"]
48
+
49
+ assert_same_hash({:string => "a string", :title => "the title"}, @parser.argv_to_params(argv))
50
+ end
51
+ end
@@ -0,0 +1,32 @@
1
+ require "test/unit"
2
+ require "rubygems"
3
+ require "mocha"
4
+ require File.dirname(__FILE__) + "/../lib/init.rb"
5
+
6
+ class TestView < Test::Unit::TestCase
7
+ include SimpleConsole
8
+
9
+ def setup
10
+ end
11
+
12
+ def teardown
13
+ end
14
+
15
+ def test_render_action
16
+ controller = Controller.new
17
+ controller.set_action(:default)
18
+
19
+ view = View.new(controller)
20
+ view.render_action
21
+
22
+ assert_equal(controller.params[:action], view.params[:action])
23
+ end
24
+
25
+ def test_render_non_existant_action
26
+ controller = Controller.new
27
+ view = nil
28
+
29
+ assert_nothing_raised { view = View.new(controller) }
30
+ assert_raise (TypeError) { view.render_action }
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: simpleconsole
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2006-09-18 00:00:00 -07:00
8
+ summary: Microframework for developing console apps quickly.
9
+ require_paths:
10
+ - lib
11
+ email: bienhd@gmail.com
12
+ homepage: http://simpleconsole.rubyforge.org
13
+ rubyforge_project:
14
+ description:
15
+ autorequire:
16
+ default_executable: simcon
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - Hugh Bien
30
+ files:
31
+ - bin/execute
32
+ - bin/files
33
+ - bin/simcon
34
+ - bin/files/application.rb
35
+ - bin/files/controller.rb
36
+ - bin/files/Rakefile
37
+ - bin/files/single.rb
38
+ - bin/files/view.rb
39
+ - test/test_application.rb
40
+ - test/test_controller.rb
41
+ - test/test_filter.rb
42
+ - test/test_init.rb
43
+ - test/test_params_parser.rb
44
+ - test/test_view.rb
45
+ - lib/application.rb
46
+ - lib/controller.rb
47
+ - lib/filter.rb
48
+ - lib/init.rb
49
+ - lib/params_parser.rb
50
+ - lib/simpleconsole.rb
51
+ - lib/view.rb
52
+ - README
53
+ - MIT-LICENSE
54
+ test_files:
55
+ - test/test_application.rb
56
+ - test/test_controller.rb
57
+ - test/test_filter.rb
58
+ - test/test_init.rb
59
+ - test/test_params_parser.rb
60
+ - test/test_view.rb
61
+ rdoc_options: []
62
+
63
+ extra_rdoc_files:
64
+ - README
65
+ - MIT-LICENSE
66
+ executables:
67
+ - simcon
68
+ extensions: []
69
+
70
+ requirements: []
71
+
72
+ dependencies: []
73
+