keyword_params 0.0.1
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/.gitignore +4 -0
- data/.rvmrc +7 -0
- data/Gemfile +4 -0
- data/README +1 -0
- data/Rakefile +42 -0
- data/example.rb +77 -0
- data/keyword_params.gemspec +23 -0
- data/lib/keyword_params.rb +42 -0
- data/lib/keyword_params/version.rb +3 -0
- metadata +75 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
|
2
|
+
if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
|
3
|
+
&& -s "${rvm_path:-$HOME/.rvm}/environments/ruby-1.9.2-p0@keyword_params" ]] ; then
|
4
|
+
\. "${rvm_path:-$HOME/.rvm}/environments/ruby-1.9.2-p0@keyword_params"
|
5
|
+
else
|
6
|
+
rvm --create "ruby-1.9.2-p0@keyword_params"
|
7
|
+
fi
|
data/Gemfile
ADDED
data/README
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Please see example.rb!
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
LIB_PATH = File.expand_path("lib", File.dirname(__FILE__))
|
5
|
+
EXAMPLE_FILE = File.expand_path("example.rb", File.dirname(__FILE__))
|
6
|
+
|
7
|
+
Bundler::GemHelper.install_tasks
|
8
|
+
|
9
|
+
task "load_path" do
|
10
|
+
$LOAD_PATH.unshift(File.expand_path("lib", File.dirname(__FILE__)))
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Run the tests"
|
14
|
+
task "test" => %w[load_path] do
|
15
|
+
require 'rcodetools/xmpfilter'
|
16
|
+
require 'rcodetools/options'
|
17
|
+
include Rcodetools
|
18
|
+
example_file = EXAMPLE_FILE
|
19
|
+
example_code = File.read(example_file)
|
20
|
+
xmp_options = {
|
21
|
+
include_paths: [LIB_PATH]
|
22
|
+
}
|
23
|
+
output = ::XMPFilter.run(example_code,xmp_options)
|
24
|
+
diff = IO.popen("diff #{example_file} -", "r+")
|
25
|
+
diff.write(output)
|
26
|
+
diff.close_write
|
27
|
+
results = diff.read
|
28
|
+
diff.close_read
|
29
|
+
if $CHILD_STATUS.success?
|
30
|
+
puts "Green!"
|
31
|
+
exit 0
|
32
|
+
else
|
33
|
+
puts results
|
34
|
+
exit 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Run the examples"
|
39
|
+
task "example" do
|
40
|
+
$LOAD_PATH.unshift(LIB_PATH)
|
41
|
+
load EXAMPLE_FILE
|
42
|
+
end
|
data/example.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Ruby doesn't have keyword arguments, but it fakes them pretty well.
|
2
|
+
|
3
|
+
def explain(options={})
|
4
|
+
"the #{options[:the]} says #{options[:says]}"
|
5
|
+
end
|
6
|
+
|
7
|
+
explain the: "pig", says: "oink" # => "the pig says oink"
|
8
|
+
explain the: "frog", says: "ribbit" # => "the frog says ribbit"
|
9
|
+
|
10
|
+
# Which is fine, but it isn't as declarative (and therefore not as
|
11
|
+
# self-documenting) as proper keyword arguments.
|
12
|
+
|
13
|
+
# Also, when using keywords to construct English-like DSLs, as we are
|
14
|
+
# above, we often would like to assign different names to the
|
15
|
+
# parameters which are passed by keyword.
|
16
|
+
|
17
|
+
def explain2(options={})
|
18
|
+
animal = options[:the]
|
19
|
+
sound = options[:says]
|
20
|
+
"the #{animal} says #{sound}"
|
21
|
+
end
|
22
|
+
|
23
|
+
# And then there's defaulting for missing paramters...
|
24
|
+
|
25
|
+
def explain3(options={})
|
26
|
+
animal = options.fetch(:the) { "cow" }
|
27
|
+
sound = options.fetch(:says){ "moo" }
|
28
|
+
"the #{animal} says #{sound}"
|
29
|
+
end
|
30
|
+
|
31
|
+
explain3 # => "the cow says moo"
|
32
|
+
|
33
|
+
# Of course, it might be nice to offer a positional-argument version
|
34
|
+
# as well.
|
35
|
+
|
36
|
+
def explain4(*args)
|
37
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
38
|
+
animal = args[0] || options.fetch(:the) { "cow" }
|
39
|
+
sound = args[1] || options.fetch(:says){ "moo" }
|
40
|
+
"the #{animal} says #{sound}"
|
41
|
+
end
|
42
|
+
|
43
|
+
explain4 "horse", "neigh" # => "the horse says neigh"
|
44
|
+
explain4 "duck", says: "quack" # => "the duck says quack"
|
45
|
+
explain4 the: "donkey", :says => "hee-haw" # => "the donkey says hee-haw"
|
46
|
+
|
47
|
+
# Once we've written all this parameter-munging machinery, we then
|
48
|
+
# repeat it in the method's documentation. (Assuming we document it at
|
49
|
+
# all). This seems a bit un-DRY.
|
50
|
+
|
51
|
+
# Let's see if we can improve on the situation.
|
52
|
+
|
53
|
+
require 'keyword_params'
|
54
|
+
|
55
|
+
class BarnYard
|
56
|
+
extend KeywordParams
|
57
|
+
|
58
|
+
keyword(:the) { "cow" }
|
59
|
+
keyword(:says) { "moo" }
|
60
|
+
def explain(animal, sound)
|
61
|
+
"the #{animal} says #{sound}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
b = BarnYard.new
|
66
|
+
|
67
|
+
b.explain "horse", "neigh" # => "the horse says neigh"
|
68
|
+
b.explain "duck", says: "quack" # => "the duck says quack"
|
69
|
+
b.explain the: "donkey", :says => "hee-haw" # => "the donkey says hee-haw"
|
70
|
+
b.explain the: "cat" # => "the cat says moo"
|
71
|
+
b.explain # => "the cow says moo"
|
72
|
+
|
73
|
+
# Improvement? Well, I'll leave that for you to judge. Certainly
|
74
|
+
# specifying part of the method's signature above the method
|
75
|
+
# definition proper has a nasty "old-style C" feel to it. But I feel
|
76
|
+
# like it's a lot more self-documenting than doing the keyword
|
77
|
+
# processing inside the method.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "keyword_params/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "keyword_params"
|
7
|
+
s.version = KeywordParams::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Avdi Grimm"]
|
10
|
+
s.email = ["avdi@avdi.org"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{Declarative keyword arguments for methods}
|
13
|
+
s.description = %q{Declarative keyword arguments for methods}
|
14
|
+
|
15
|
+
s.rubyforge_project = "keyword_params"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_development_dependency 'rcodetools'
|
23
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
module KeywordParams
|
3
|
+
class KeywordList
|
4
|
+
def initialize
|
5
|
+
@keywords = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_keyword(name, default_block)
|
9
|
+
@keywords << OpenStruct.new(name: name, default_block: default_block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def values(options={})
|
13
|
+
@keywords.map {|keyword|
|
14
|
+
options.fetch(keyword.name, &keyword.default_block)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def keyword(name, &default_block)
|
20
|
+
@keyword_list ||= KeywordList.new
|
21
|
+
@keyword_list.add_keyword(name, default_block)
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_added(name)
|
25
|
+
# Avoid crazy stack recursion
|
26
|
+
return if Thread.current[:in_keyword_params_method_added]
|
27
|
+
Thread.current[:in_keyword_params_method_added] = true
|
28
|
+
original_method = instance_method(name)
|
29
|
+
keyword_list = @keyword_list
|
30
|
+
@keyword_list = nil
|
31
|
+
define_method(name) do |*args|
|
32
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
33
|
+
keyword_args = keyword_list.values(options)
|
34
|
+
# We only need keyword arg values for as many positional args
|
35
|
+
# as are NOT supplied.
|
36
|
+
needed_keyword_args = keyword_args[(args.size..-1)]
|
37
|
+
original_method.bind(self).call(*(args + needed_keyword_args))
|
38
|
+
end
|
39
|
+
super
|
40
|
+
Thread.current[:in_keyword_params_method_added] = false
|
41
|
+
end
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: keyword_params
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Avdi Grimm
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-09-29 00:00:00 -04:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rcodetools
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
type: :development
|
26
|
+
version_requirements: *id001
|
27
|
+
description: Declarative keyword arguments for methods
|
28
|
+
email:
|
29
|
+
- avdi@avdi.org
|
30
|
+
executables: []
|
31
|
+
|
32
|
+
extensions: []
|
33
|
+
|
34
|
+
extra_rdoc_files: []
|
35
|
+
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- .rvmrc
|
39
|
+
- Gemfile
|
40
|
+
- README
|
41
|
+
- Rakefile
|
42
|
+
- example.rb
|
43
|
+
- keyword_params.gemspec
|
44
|
+
- lib/keyword_params.rb
|
45
|
+
- lib/keyword_params/version.rb
|
46
|
+
has_rdoc: true
|
47
|
+
homepage: ""
|
48
|
+
licenses: []
|
49
|
+
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
rubyforge_project: keyword_params
|
70
|
+
rubygems_version: 1.5.2
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: Declarative keyword arguments for methods
|
74
|
+
test_files: []
|
75
|
+
|