creamerscript-sweeteners 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.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +97 -0
- data/Rakefile +1 -0
- data/creamerscript-sweeteners.gemspec +26 -0
- data/lib/creamerscript/sweeteners.rb +21 -0
- data/lib/creamerscript/sweeteners/array.rb +9 -0
- data/lib/creamerscript/sweeteners/base.rb +37 -0
- data/lib/creamerscript/sweeteners/default.rb +17 -0
- data/lib/creamerscript/sweeteners/js_argument_list.rb +13 -0
- data/lib/creamerscript/sweeteners/method_definition.rb +59 -0
- data/lib/creamerscript/sweeteners/method_invocation.rb +55 -0
- data/lib/creamerscript/sweeteners/object.rb +9 -0
- data/lib/creamerscript/sweeteners/property_invocation.rb +27 -0
- data/lib/creamerscript/sweeteners/string.rb +9 -0
- data/lib/creamerscript/sweeteners/version.rb +5 -0
- data/spec/creamerscript/sweeteners/array_spec.rb +33 -0
- data/spec/creamerscript/sweeteners/base_spec.rb +0 -0
- data/spec/creamerscript/sweeteners/js_argument_list_spec.rb +13 -0
- data/spec/creamerscript/sweeteners/method_definition_spec.rb +39 -0
- data/spec/creamerscript/sweeteners/method_invocation_spec.rb +66 -0
- data/spec/creamerscript/sweeteners/object_spec.rb +22 -0
- data/spec/creamerscript/sweeteners/property_invocation_spec.rb +27 -0
- data/spec/creamerscript/sweeteners/string_spec.rb +31 -0
- data/spec/spec_helper.rb +10 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NzM2NjM0ZTM3YzliZmM1YTQ3ZjM5MzZjMjEyYmZkOGU3MzFhMzYwYg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MzM4OTcxNzRlYTUwZjMwZTM2MmVkOGQyZTg3NTI3Njk2NDhhMWY3YQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MzQ4MGUwYzEyNDM5YmUxNTdhZWMxM2E4ZTRlN2YyODY1MjVkZjE2YjYzMmQ3
|
10
|
+
NWE4NDE0N2RmMmI4ODRjY2MzM2VjMDE3YmNmMWRmOGFkMjEzNmE1NmZlZmJi
|
11
|
+
YmJkMjY4NzJkNzBhM2RiNDc5MTQxODA3NDk2NTA3ZmNiZDA1NDE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
Y2Y2Mjc4MzQ3NjI4NWE0OWExNmM5NThjOGM5NDY5ZDk4ZmYwZTdhMDRkNzZm
|
14
|
+
NTI0OGYzN2Y1ZWNlZWUyNGY5MjE0ZDZjYWYxNmFlZTRiMWJjNTE1ZGQ0MDlm
|
15
|
+
YzEzNjQxYzQ4ZWIzNGM2MTI3N2IzNmQ1NDEzYzY3MThhZWE0ZmI=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Matte Noble
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# CreamerScript::Sweeteners
|
2
|
+
|
3
|
+
Sweeteners are the components that take CreamerScript code and
|
4
|
+
transforms it into Coffeescript.
|
5
|
+
|
6
|
+
## Overview
|
7
|
+
|
8
|
+
In the end, CreamerScript is just a syntactic sugar framework on
|
9
|
+
top of Coffeescript. Sweeteners are the work horses of the framework;
|
10
|
+
they are responsible for first parsing out any code that looks like
|
11
|
+
something they want to transform and then subsequently transforming it.
|
12
|
+
|
13
|
+
## Sweetener Interface
|
14
|
+
|
15
|
+
Sweeteners need to implement a specific interface in order to work with
|
16
|
+
CreamerScript.
|
17
|
+
|
18
|
+
### `pattern` <small>**Required**</small>
|
19
|
+
|
20
|
+
Must match the simplest form of the thing it cares about. Don't try to
|
21
|
+
match recursive things like arrays inside of an array. Just match an
|
22
|
+
array with no brackets inside it. CreamerScript will works its way out
|
23
|
+
hitting all levels of nesting.
|
24
|
+
|
25
|
+
### `type` <small>Optional</small>
|
26
|
+
|
27
|
+
<small>*Default:* class name, lowercased and underscored.</small>
|
28
|
+
|
29
|
+
A name for the Sweetener. This is used to generate tokens and then later
|
30
|
+
to determine which Sweetener should handle transforming which chunks of
|
31
|
+
code.
|
32
|
+
|
33
|
+
### `substitute` <small>Optional</small>
|
34
|
+
|
35
|
+
<small>*Default:* Replaces the entire matched pattern with a token.</small>
|
36
|
+
|
37
|
+
You should override this if you need to do something special with the
|
38
|
+
matched code like only replace a portion of it.
|
39
|
+
|
40
|
+
### `to_coffee` <small>Optional</small>
|
41
|
+
|
42
|
+
<small>*Default:* The original code that was replaced.</small>
|
43
|
+
|
44
|
+
This is what turns CreamerScript into Coffeescript. When `to_coffee` is
|
45
|
+
called, you have access to a `source` instance variable that contains
|
46
|
+
the original code that was replaced. You should transform `source` into
|
47
|
+
Coffeescript.
|
48
|
+
|
49
|
+
`source` may contain other tokens that have not been transformed yet.
|
50
|
+
That's fine; treat them like you would a variable or any other entity.
|
51
|
+
|
52
|
+
## Writing Sweeteners
|
53
|
+
|
54
|
+
Implement at least `pattern`. Usually you'll need `to_coffee` as well.
|
55
|
+
To tell CreamerScript to use your Sweetener, just register it.
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
Creamerscript::Sweeteners.register(MyCustomSweetener)
|
59
|
+
```
|
60
|
+
|
61
|
+
Only one Sweetener will be used, per type. It's generally a good idea to
|
62
|
+
use a somewhat broad type, like `:method_definition` or `:string`.
|
63
|
+
|
64
|
+
## Default Sweeteners
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
require "creamerscript/sweeteners/default"
|
68
|
+
```
|
69
|
+
|
70
|
+
1\. Smalltalk/Obj-C inspired method invocations (for methods defined in
|
71
|
+
CreamerScript):
|
72
|
+
|
73
|
+
```coffeescript
|
74
|
+
(this say:words to:person)
|
75
|
+
(this start:)
|
76
|
+
```
|
77
|
+
|
78
|
+
2\. Smalltalk/Obj-C inspired method invocations (for methods defined in
|
79
|
+
Coffeescript/JavaScript)
|
80
|
+
|
81
|
+
```coffeescript
|
82
|
+
($ get: "/people", success, "json")
|
83
|
+
```
|
84
|
+
|
85
|
+
3\. Expression based property invocations:
|
86
|
+
|
87
|
+
```smalltalk
|
88
|
+
(person name)
|
89
|
+
```
|
90
|
+
|
91
|
+
4\. Smalltalk inspired method definitions (with `def` thrown in for good
|
92
|
+
measure)
|
93
|
+
|
94
|
+
```smalltalk
|
95
|
+
def send_async:request on_queue:queue with_options:options
|
96
|
+
...
|
97
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'creamerscript/sweeteners/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "creamerscript-sweeteners"
|
8
|
+
spec.version = Creamerscript::Sweeteners::VERSION
|
9
|
+
spec.authors = ["Matte Noble"]
|
10
|
+
spec.email = ["me@mattenoble.com"]
|
11
|
+
spec.description = %q{Sweeteners transform Creamerscript code.}
|
12
|
+
spec.summary = %q{Sweeteners are what takes Creamerscript code and transforms it into Coffeescript.}
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "active_support"
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "rspec"
|
25
|
+
spec.add_development_dependency "debugger"
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "active_support/inflector"
|
2
|
+
|
3
|
+
module Creamerscript
|
4
|
+
module Sweeteners
|
5
|
+
def self.register(sweetener)
|
6
|
+
sweetener.new.tap { |s| sweeteners[s.type] = s }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.each
|
10
|
+
sweeteners.each { |type, sweetener| yield sweetener }
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.for(type)
|
14
|
+
sweeteners[type]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.sweeteners
|
18
|
+
@sweeteners ||= {}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Creamerscript
|
2
|
+
module Sweeteners
|
3
|
+
class Base
|
4
|
+
SYMBOL = /[A-Za-z0-9$_@]+/
|
5
|
+
|
6
|
+
attr_accessor :substitutions, :source
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@substitutions = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(id)
|
13
|
+
@source = substitutions[id]
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_coffee
|
17
|
+
source
|
18
|
+
end
|
19
|
+
|
20
|
+
def substitute(source)
|
21
|
+
source.gsub!(pattern) { |match| tokenize(match) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def tokenize(substitution)
|
25
|
+
token.tap { substitutions[substitutions.size] = substitution }
|
26
|
+
end
|
27
|
+
|
28
|
+
def token
|
29
|
+
"_____CREAMER_#{type.upcase}_#{substitutions.size}_____"
|
30
|
+
end
|
31
|
+
|
32
|
+
def type
|
33
|
+
self.class.name.split("::").last.underscore.to_sym
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "creamerscript/sweeteners"
|
2
|
+
require "creamerscript/sweeteners/base"
|
3
|
+
require "creamerscript/sweeteners/array"
|
4
|
+
require "creamerscript/sweeteners/js_argument_list"
|
5
|
+
require "creamerscript/sweeteners/method_definition"
|
6
|
+
require "creamerscript/sweeteners/method_invocation"
|
7
|
+
require "creamerscript/sweeteners/object"
|
8
|
+
require "creamerscript/sweeteners/property_invocation"
|
9
|
+
require "creamerscript/sweeteners/string"
|
10
|
+
|
11
|
+
Creamerscript::Sweeteners.register(Creamerscript::Sweeteners::String)
|
12
|
+
Creamerscript::Sweeteners.register(Creamerscript::Sweeteners::Object)
|
13
|
+
Creamerscript::Sweeteners.register(Creamerscript::Sweeteners::Array)
|
14
|
+
Creamerscript::Sweeteners.register(Creamerscript::Sweeteners::PropertyInvocation)
|
15
|
+
Creamerscript::Sweeteners.register(Creamerscript::Sweeteners::JSArgumentList)
|
16
|
+
Creamerscript::Sweeteners.register(Creamerscript::Sweeteners::MethodInvocation)
|
17
|
+
Creamerscript::Sweeteners.register(Creamerscript::Sweeteners::MethodDefinition)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Creamerscript
|
2
|
+
module Sweeteners
|
3
|
+
class JSArgumentList < Base
|
4
|
+
def substitute(source)
|
5
|
+
source.gsub!(pattern) { |match| match.gsub($1, tokenize($1)) }
|
6
|
+
end
|
7
|
+
|
8
|
+
def pattern
|
9
|
+
/\(#{SYMBOL} #{SYMBOL}:(#{SYMBOL},\s*[#{SYMBOL},\s]*)\)/
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Creamerscript
|
2
|
+
module Sweeteners
|
3
|
+
class MethodDefinition < Base
|
4
|
+
def pattern
|
5
|
+
/def #{SYMBOL}(?::#{SYMBOL})?(?:\s+#{SYMBOL}:#{SYMBOL})*/
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_coffee
|
9
|
+
if method_name =~ /^constructor/
|
10
|
+
constructor
|
11
|
+
else
|
12
|
+
arguments.empty? ? definition_without_arguments : definition_with_arguments
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def constructor
|
17
|
+
"constructor: (#{arguments}) ->"
|
18
|
+
end
|
19
|
+
|
20
|
+
def definition_without_arguments
|
21
|
+
"#{method_name}: =>"
|
22
|
+
end
|
23
|
+
|
24
|
+
def definition_with_arguments
|
25
|
+
"#{method_name}: (#{arguments}) =>"
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_name
|
29
|
+
signature_keys.join("_")
|
30
|
+
end
|
31
|
+
|
32
|
+
def arguments
|
33
|
+
parameter_names.join(", ")
|
34
|
+
end
|
35
|
+
|
36
|
+
def type
|
37
|
+
:method_definition
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def signature_keys
|
43
|
+
argument_list.flatten.each_with_index.map { |arg, index| arg if index.even? }.compact
|
44
|
+
end
|
45
|
+
|
46
|
+
def parameter_names
|
47
|
+
argument_list.flatten.each_with_index.map { |arg, index| arg.gsub(",", "") if index.odd? }.compact
|
48
|
+
end
|
49
|
+
|
50
|
+
def argument_list
|
51
|
+
body.split.map { |arg| arg.split(":") }
|
52
|
+
end
|
53
|
+
|
54
|
+
def body
|
55
|
+
source.split("def ").last
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Creamerscript
|
2
|
+
module Sweeteners
|
3
|
+
class MethodInvocation < Base
|
4
|
+
def pattern
|
5
|
+
/\(#{SYMBOL} #{SYMBOL}[^\(\)]+\)/m
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_coffee
|
9
|
+
method_name =~ /^new/ ? initializer : normal_method_call
|
10
|
+
end
|
11
|
+
|
12
|
+
def initializer
|
13
|
+
"new #{subject}(#{arguments})"
|
14
|
+
end
|
15
|
+
|
16
|
+
def normal_method_call
|
17
|
+
"#{subject}.#{method_name}(#{arguments})"
|
18
|
+
end
|
19
|
+
|
20
|
+
def subject
|
21
|
+
body.split.first
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_name
|
25
|
+
signature_keys.join("_")
|
26
|
+
end
|
27
|
+
|
28
|
+
def arguments
|
29
|
+
parameter_values.join(", ")
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def signature_keys
|
35
|
+
argument_list.flatten.each_with_index.map { |arg, index| arg if index.even? }.compact
|
36
|
+
end
|
37
|
+
|
38
|
+
def parameter_values
|
39
|
+
argument_list.flatten.each_with_index.map { |arg, index| arg.gsub(",", "") if index.odd? }.compact
|
40
|
+
end
|
41
|
+
|
42
|
+
def argument_list
|
43
|
+
body_without_subject.map { |arg| arg.split(":") }
|
44
|
+
end
|
45
|
+
|
46
|
+
def body_without_subject
|
47
|
+
body.split[1..-1]
|
48
|
+
end
|
49
|
+
|
50
|
+
def body
|
51
|
+
source[1..-2]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Creamerscript
|
2
|
+
module Sweeteners
|
3
|
+
class PropertyInvocation < Base
|
4
|
+
def pattern
|
5
|
+
/\(#{SYMBOL} #{SYMBOL}\)/
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_coffee
|
9
|
+
"#{subject}.#{property_name}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def subject
|
13
|
+
body.split.first
|
14
|
+
end
|
15
|
+
|
16
|
+
def property_name
|
17
|
+
body.split.last
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def body
|
23
|
+
source[1..-2]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Creamerscript::Sweeteners::Array do
|
4
|
+
let!(:sweetener) { described_class.new }
|
5
|
+
|
6
|
+
def substitution(source)
|
7
|
+
source.tap { sweetener.substitute(source) }
|
8
|
+
end
|
9
|
+
|
10
|
+
it "substitutes an array" do
|
11
|
+
substitution("[1, 2, 3]").should == "_____CREAMER_ARRAY_0_____"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "substitutes a nested array" do
|
15
|
+
sweetener.substitute("[1, [2, 3], 4]")
|
16
|
+
sweetener.substitutions[0].should == "[2, 3]"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "substitutes many arrays" do
|
20
|
+
substitution("[1, 2, 3] [4, 5] [6, 7, 8]").should == "_____CREAMER_ARRAY_0_____ _____CREAMER_ARRAY_1_____ _____CREAMER_ARRAY_2_____"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "stores the content of each array" do
|
24
|
+
sweetener.substitute("[1, 2, 3] [4, 5] [6, 7, 8]")
|
25
|
+
sweetener.substitutions[2].should == "[6, 7, 8]"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "stores the content of nested arrays" do
|
29
|
+
sweetener.substitute(sweetener.substitute("[1, [2, 3], 4]"))
|
30
|
+
sweetener.substitutions[0].should == "[2, 3]"
|
31
|
+
sweetener.substitutions[1].should == "[1, _____CREAMER_ARRAY_0_____, 4]"
|
32
|
+
end
|
33
|
+
end
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Creamerscript::Sweeteners::JSArgumentList do
|
4
|
+
let!(:sweetener) { described_class.new }
|
5
|
+
|
6
|
+
def substitution(source)
|
7
|
+
source.tap { sweetener.substitute(source) }
|
8
|
+
end
|
9
|
+
|
10
|
+
it "substitutes a normal comma seperated list of arguments" do
|
11
|
+
substitution("(this foo:arg1, arg2, arg3)").should == "(this foo:_____CREAMER_JS_ARGUMENT_LIST_0_____)"
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Creamerscript::Sweeteners::MethodDefinition do
|
4
|
+
let!(:sweetener) { described_class.new }
|
5
|
+
|
6
|
+
def definition(source)
|
7
|
+
sweetener.stub(:substitutions).and_return({ 0 => source })
|
8
|
+
sweetener.call(0)
|
9
|
+
sweetener
|
10
|
+
end
|
11
|
+
|
12
|
+
def substitution(source)
|
13
|
+
source.tap { sweetener.substitute(source) }
|
14
|
+
end
|
15
|
+
|
16
|
+
it "substitutes method definitions" do
|
17
|
+
substitution("def foo:bar").should == "_____CREAMER_METHOD_DEFINITION_0_____"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "parses out the method name" do
|
21
|
+
definition("def do:stuff for:ever and:then report:back").method_name.should == "do_for_and_report"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "parses out the arguments" do
|
25
|
+
definition("def do:stuff for:ever and:then report:back").arguments.should == "stuff, ever, then, back"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "converts to CoffeeScript" do
|
29
|
+
definition("def do:stuff for:ever").to_coffee.should == "do_for: (stuff, ever) =>"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "converts a method with no arguments to CoffeeScript" do
|
33
|
+
definition("def zap").to_coffee.should == "zap: =>"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "converts a constructor to CoffeeScript" do
|
37
|
+
definition("def constructor:stuff with:things").to_coffee.should == "constructor: (stuff, things) ->"
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Creamerscript::Sweeteners::MethodInvocation do
|
4
|
+
let!(:sweetener) { described_class.new }
|
5
|
+
|
6
|
+
def invocation(source)
|
7
|
+
sweetener.substitutions = { 0 => source }
|
8
|
+
sweetener.call(0)
|
9
|
+
sweetener
|
10
|
+
end
|
11
|
+
|
12
|
+
def substitution(source)
|
13
|
+
source.tap { sweetener.substitute(source) }
|
14
|
+
end
|
15
|
+
|
16
|
+
it "substitutes nested invocations depth-first" do
|
17
|
+
sweetener.substitute("(this foo:(bar baz:))")
|
18
|
+
sweetener.substitutions[0].should == "(bar baz:)"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "substitutes deeply nested invocations depth-first" do
|
22
|
+
sweetener.substitute("(this foo:(bar baz:(beep boop:)))")
|
23
|
+
sweetener.substitutions[0].should == "(beep boop:)"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "substitutes deeply nested, multi-line, invocations depth-first" do
|
27
|
+
source = %{
|
28
|
+
(this foo:bar
|
29
|
+
baz:(beep boop:ping
|
30
|
+
ding:(dong ditch:)))
|
31
|
+
|
32
|
+
(this spark:(mark bark:(tark lark:))) }
|
33
|
+
|
34
|
+
sweetener.substitute(source)
|
35
|
+
sweetener.substitutions[0].should == "(dong ditch:)"
|
36
|
+
sweetener.substitutions[1].should == "(tark lark:)"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "parses out the subject" do
|
40
|
+
invocation("(this foo:bar)").subject.should == "this"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "parses out the method name based on Signature Keys" do
|
44
|
+
invocation("(this foo:bar and:baz with:barf)").method_name.should == "foo_and_with"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "parses out the arguments based on Parameter Names" do
|
48
|
+
invocation("(this foo:bar and:baz with:barf)").arguments.should == "bar, baz, barf"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "parses out the argument list when it's a normal JavaScript list" do
|
52
|
+
invocation("(this foo:_____CREAMER_JS_ARGUMENT_LIST_0_____)").arguments.should == "_____CREAMER_JS_ARGUMENT_LIST_0_____"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "transforms itself to Coffeescript" do
|
56
|
+
invocation("(this foo:bar and:baz with:barf)").to_coffee.should == "this.foo_and_with(bar, baz, barf)"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "transforms constructor calls" do
|
60
|
+
invocation("(Date new:)").to_coffee.should == "new Date()"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "transforms constructor calls with multiple parameters" do
|
64
|
+
invocation("(Date new:stuff with:thing)").to_coffee.should == "new Date(stuff, thing)"
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Creamerscript::Sweeteners::Object do
|
4
|
+
let!(:sweetener) { described_class.new }
|
5
|
+
|
6
|
+
def substitution(source)
|
7
|
+
source.tap { sweetener.substitute(source) }
|
8
|
+
end
|
9
|
+
|
10
|
+
it "substitutes an object" do
|
11
|
+
substitution("{a:1, b:2}").should == "_____CREAMER_OBJECT_0_____"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "substitutes a nested object" do
|
15
|
+
sweetener.substitute("{a:1, b:{c:2, d:3}}")
|
16
|
+
sweetener.substitutions[0].should == "{c:2, d:3}"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "substitutes many objects" do
|
20
|
+
substitution("{a:1} {b:2} {c:3}").should == "_____CREAMER_OBJECT_0_____ _____CREAMER_OBJECT_1_____ _____CREAMER_OBJECT_2_____"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Creamerscript::Sweeteners::PropertyInvocation do
|
4
|
+
let!(:sweetener) { described_class.new }
|
5
|
+
|
6
|
+
def invocation(source)
|
7
|
+
sweetener.stub(:substitutions).and_return({ 0 => source })
|
8
|
+
sweetener.call(0)
|
9
|
+
sweetener
|
10
|
+
end
|
11
|
+
|
12
|
+
def substitution(source)
|
13
|
+
source.tap { sweetener.substitute(source) }
|
14
|
+
end
|
15
|
+
|
16
|
+
it "substitutes property invocations" do
|
17
|
+
substitution("(this selector)").should == "_____CREAMER_PROPERTY_INVOCATION_0_____"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "parses out the subject" do
|
21
|
+
invocation("(this foo)").subject.should == "this"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "parses out the property name" do
|
25
|
+
invocation("(this foo)").property_name.should == "foo"
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Creamerscript::Sweeteners::String do
|
4
|
+
let!(:sweetener) { described_class.new }
|
5
|
+
|
6
|
+
def substitution(source)
|
7
|
+
source.tap { sweetener.substitute(source) }
|
8
|
+
end
|
9
|
+
|
10
|
+
it "substitutes a string" do
|
11
|
+
substitution('"hello"').should == "_____CREAMER_STRING_0_____"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "substitutes a string containing an escaped quote" do
|
15
|
+
substitution('"MOG \"Its you!\""').should == "_____CREAMER_STRING_0_____"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "substitutes many strings" do
|
19
|
+
substitution('"hey" "there guy" "whats up"').should == "_____CREAMER_STRING_0_____ _____CREAMER_STRING_1_____ _____CREAMER_STRING_2_____"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "stores the content of each string" do
|
23
|
+
sweetener.substitute('"hey" "there guy" "whats up"')
|
24
|
+
sweetener.substitutions[1].should == '"there guy"'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "stores the content of each string containing escaped quotes" do
|
28
|
+
sweetener.substitute('"hey" "there \"guy\"" "whats up"')
|
29
|
+
sweetener.substitutions[1].should == '"there \"guy\""'
|
30
|
+
end
|
31
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require "debugger"
|
2
|
+
require "creamerscript/sweeteners"
|
3
|
+
require "creamerscript/sweeteners/default"
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
7
|
+
config.run_all_when_everything_filtered = true
|
8
|
+
config.filter_run :focus
|
9
|
+
config.order = 'random'
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: creamerscript-sweeteners
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matte Noble
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-03-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: active_support
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: debugger
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Sweeteners transform Creamerscript code.
|
84
|
+
email:
|
85
|
+
- me@mattenoble.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- Gemfile
|
92
|
+
- LICENSE.txt
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- creamerscript-sweeteners.gemspec
|
96
|
+
- lib/creamerscript/sweeteners.rb
|
97
|
+
- lib/creamerscript/sweeteners/array.rb
|
98
|
+
- lib/creamerscript/sweeteners/base.rb
|
99
|
+
- lib/creamerscript/sweeteners/default.rb
|
100
|
+
- lib/creamerscript/sweeteners/js_argument_list.rb
|
101
|
+
- lib/creamerscript/sweeteners/method_definition.rb
|
102
|
+
- lib/creamerscript/sweeteners/method_invocation.rb
|
103
|
+
- lib/creamerscript/sweeteners/object.rb
|
104
|
+
- lib/creamerscript/sweeteners/property_invocation.rb
|
105
|
+
- lib/creamerscript/sweeteners/string.rb
|
106
|
+
- lib/creamerscript/sweeteners/version.rb
|
107
|
+
- spec/creamerscript/sweeteners/array_spec.rb
|
108
|
+
- spec/creamerscript/sweeteners/base_spec.rb
|
109
|
+
- spec/creamerscript/sweeteners/js_argument_list_spec.rb
|
110
|
+
- spec/creamerscript/sweeteners/method_definition_spec.rb
|
111
|
+
- spec/creamerscript/sweeteners/method_invocation_spec.rb
|
112
|
+
- spec/creamerscript/sweeteners/object_spec.rb
|
113
|
+
- spec/creamerscript/sweeteners/property_invocation_spec.rb
|
114
|
+
- spec/creamerscript/sweeteners/string_spec.rb
|
115
|
+
- spec/spec_helper.rb
|
116
|
+
homepage:
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ! '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.0.0
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: Sweeteners are what takes Creamerscript code and transforms it into Coffeescript.
|
140
|
+
test_files:
|
141
|
+
- spec/creamerscript/sweeteners/array_spec.rb
|
142
|
+
- spec/creamerscript/sweeteners/base_spec.rb
|
143
|
+
- spec/creamerscript/sweeteners/js_argument_list_spec.rb
|
144
|
+
- spec/creamerscript/sweeteners/method_definition_spec.rb
|
145
|
+
- spec/creamerscript/sweeteners/method_invocation_spec.rb
|
146
|
+
- spec/creamerscript/sweeteners/object_spec.rb
|
147
|
+
- spec/creamerscript/sweeteners/property_invocation_spec.rb
|
148
|
+
- spec/creamerscript/sweeteners/string_spec.rb
|
149
|
+
- spec/spec_helper.rb
|