shift 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+
2
+ .rvmrc
3
+ .yardoc
4
+ doc
5
+ *.swp
6
+ *.gem
data/.yardopts ADDED
@@ -0,0 +1,7 @@
1
+ --hide-void-return
2
+ -m markdown
3
+ -M rdiscount
4
+ --title "Shift - State and logic-less compiler and compressor interface"
5
+ lib/**/*.rb
6
+ --no-private
7
+ --main README.md
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Jostein Berre Eliassen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,100 @@
1
+
2
+ Shift (draft)
3
+ =====
4
+
5
+ **State and logic-less compiler and compressor interface**
6
+
7
+ ---
8
+
9
+ Shift is a generic Ruby interface to different compilers, compressors, transformers and so on. What the [Tilt](https://github.com/rtomayko/tilt) gem does for template languages, Shift does for stuff that compiles in one step, without stateful template logic.
10
+
11
+ * [Documentation](http://rubydoc.info/github/jbe/shift/master/frames)
12
+ * [File type mappings](http://rubydoc.info/github/jbe/shift/master/Shift)
13
+
14
+ ### Installation
15
+
16
+ gem install tilt
17
+
18
+
19
+ ### Usage
20
+
21
+ To read and process a file, using the preferred available default component for that filetype:
22
+
23
+ ```ruby
24
+
25
+ Shift.read('thefile.js') # => minified js string
26
+
27
+ ```
28
+
29
+ Or to read, process, and then write:
30
+
31
+ ```ruby
32
+
33
+ Shift.read('canopy.sass').write('canopy.css')
34
+
35
+ ```
36
+
37
+ The components can also be used directly:
38
+
39
+ ```ruby
40
+
41
+ cc = Shift::ClosureCompiler.new(:compilation_level => 'ADVANCED_OPTIMIZATIONS')
42
+ minified_js_string = cc.read(path)
43
+
44
+ ```
45
+
46
+ To simply process a string, or to process and save a string:
47
+
48
+ ```ruby
49
+
50
+ md = Shift::RDiscount.new
51
+ md.process("hello *there*") # => "<p>hello <em>there</em></p>"
52
+ md.process("hello *there*").write('message.html')
53
+
54
+ ```
55
+ To see if a component is available (check if the gem is installed and so on):
56
+
57
+ ```ruby
58
+
59
+ Shift::YUICompressor.available?.
60
+
61
+ ```
62
+
63
+ To get the first available preferred default component class for a file:
64
+
65
+ ```ruby
66
+
67
+ Shift['somefile.js'] # => Shift::UglifyJS
68
+
69
+ ```
70
+
71
+ You can also do:
72
+
73
+ ```ruby
74
+
75
+ Shift[:md] # => Shift::RDiscount
76
+
77
+ ```
78
+
79
+ ### Available engines
80
+
81
+ * UglifyJS
82
+ * ClosureCompiler
83
+ * YUICompressor
84
+ * CoffeeScript
85
+ * Sass
86
+ * RDiscount
87
+ * Redcarpet
88
+
89
+
90
+ ### Why not use or extend Tilt instead?
91
+
92
+ I am making a separate library for this rather than extending Tilt, because i would usually only need one of the two in a given context. One and two step compilation are somewhat different things. Shift is more on the build side. Tilt is more on the dynamic side.
93
+
94
+ ### Bye
95
+
96
+ Bye Bye, see you. There are proper [docs](http://rubydoc.info/github/jbe/shift/master/frames) if you want more. And once again, [the mappings are there too](http://rubydoc.info/github/jbe/shift/master/Shift). Contributions and feedback is welcome, of course.
97
+
98
+ ---
99
+
100
+ © 2011 Jostein Berre Eliassen. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+
2
+ task :test do
3
+ $LOAD_PATH.unshift './lib'
4
+ require 'shift'
5
+ require 'minitest/autorun'
6
+ begin; require 'turn'; rescue LoadError; end
7
+ Dir.glob("test/**/*_test.rb").each { |test| require "./#{test}" }
8
+ end
9
+
10
+ task :shell do
11
+ system 'pry -I lib -r shift'
12
+ end
13
+
14
+ task :default => :test
15
+
16
+
17
+
@@ -0,0 +1,19 @@
1
+
2
+
3
+ module Shift
4
+ class ClosureCompiler < Identity
5
+
6
+ def self.gem_dependencies
7
+ %w{closure-compiler}
8
+ end
9
+
10
+ def self.compiler_class
11
+ Closure::Compiler
12
+ end
13
+
14
+ def process_plain(str)
15
+ @engine.compile(str)
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+
2
+ module Shift
3
+ class CoffeeScript < Identity
4
+
5
+ def self.gem_dependencies
6
+ %w{coffee-script}
7
+ end
8
+
9
+ def self.require_libs
10
+ %w{coffee-script}
11
+ end
12
+
13
+ def initialize(opts={})
14
+ @opts = opts
15
+ end
16
+
17
+
18
+ def process_plain(str)
19
+ ::CoffeeScript.compile(str, @opts)
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,116 @@
1
+
2
+
3
+ module Shift
4
+
5
+ # Returns the input unaltered. The purpose is mainly to inherit
6
+ # from this when defining other, more useful compilers.
7
+ #
8
+ class Identity
9
+
10
+ # Mixed into the resulting strings to make them easy to save.
11
+ #
12
+ module StringExtension
13
+
14
+ # Write the string to a sepcified path.
15
+ #
16
+ def write(path)
17
+ File.open(path, 'w') do |file|
18
+ file.write(self)
19
+ end
20
+ self
21
+ end
22
+ end
23
+
24
+
25
+ # One-liner on what the user must have/do to make it available.
26
+ # Used in DependencyError.
27
+ #
28
+ def self.instructions
29
+ if gem_dependencies.any?
30
+ 'gem install ' + gem_dependencies.join(' ')
31
+ else
32
+ 'Google it :)'
33
+ end
34
+ end
35
+
36
+ # Wether the requirements are met in the current environment.
37
+ # Typically checks if the required gems and/or command line
38
+ # stuff is available.
39
+ #
40
+ def self.available?
41
+ gem_dependencies.all? {|d| Gem.available?(d) }
42
+ end
43
+
44
+ # A list of Rubygems needed for the component to work.
45
+ #
46
+ def self.gem_dependencies
47
+ []
48
+ end
49
+
50
+ # A list of things to be required on initialization.
51
+ #
52
+ def self.require_libs
53
+ gem_dependencies
54
+ end
55
+
56
+ # The class of the wrapped compiler, or false if none
57
+ # is used.
58
+ #
59
+ def self.compiler_class
60
+ false
61
+ end
62
+
63
+ # A default instance without options.
64
+ #
65
+ def self.default
66
+ @default ||= new
67
+ end
68
+
69
+ def self.new(*prms)
70
+ unless available?
71
+ raise Shift::DependencyError, "#{self} not available. " +
72
+ "Possible fix: #{instructions}"
73
+ end
74
+ @req ||= require_libs.each {|str| require str }
75
+ super
76
+ end
77
+
78
+ # Create a new instance. Ignores the given options.
79
+ #
80
+ def initialize(*prms)
81
+ if self.class.compiler_class
82
+ @engine = self.class.compiler_class.new(*prms)
83
+ end
84
+ end
85
+
86
+ # Process the supplied string, returning the resulting `String` (with a #write method attached to it).
87
+ #
88
+ def process(str)
89
+ process_plain(str).extend(StringExtension)
90
+ end
91
+ alias :compress :process
92
+ alias :compile :process
93
+ alias :transform :process
94
+
95
+ # Process the supplied string, returning the resulting `String`.
96
+ #
97
+ def process_plain(str)
98
+ str.dup
99
+ end
100
+
101
+ # Read and process a file.
102
+ #
103
+ # @raise [DependencyError] when none of the mapped
104
+ # implementations are available.
105
+ #
106
+ # @return [String] The processed `String`
107
+ #
108
+ def read(path)
109
+ process(File.read(path)).extend(StringExtension)
110
+ end
111
+
112
+ end
113
+ Echo = Identity
114
+ end
115
+
116
+
@@ -0,0 +1,18 @@
1
+
2
+ module Shift
3
+ class RDiscount < Identity
4
+
5
+ def self.gem_dependencies
6
+ %w{rdiscount}
7
+ end
8
+
9
+ def initialize(*switches)
10
+ @switches = switches
11
+ end
12
+
13
+ def process_plain(str)
14
+ ::RDiscount.new(str, *@switches).to_html
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Shift
2
+ class Redcarpet < Identity
3
+
4
+ def self.gem_dependencies
5
+ %w{redcarpet}
6
+ end
7
+
8
+ def initialize(*switches)
9
+ @switches = switches
10
+ end
11
+
12
+ def process_plain(str)
13
+ ::Redcarpet.new(str, *@switches).to_html
14
+ end
15
+
16
+ end
17
+ RedCarpet = Redcarpet
18
+ end
@@ -0,0 +1,17 @@
1
+ module Shift
2
+ class Sass < Identity
3
+
4
+ def self.gem_dependencies
5
+ %w{sass}
6
+ end
7
+
8
+ def initialize(opts={})
9
+ @opts = opts
10
+ end
11
+
12
+ def process_plain(str)
13
+ ::Sass::Engine.new(str, @opts).render
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+
2
+
3
+ module Shift
4
+ class UglifyJS < Identity
5
+
6
+ def self.gem_dependencies
7
+ %w{uglifier}
8
+ end
9
+
10
+ def self.compiler_class
11
+ Uglifier
12
+ end
13
+
14
+ def process_plain(str)
15
+ @engine.compile(str)
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+
2
+ module Shift
3
+ class YUICompressor < Identity
4
+
5
+ def self.gem_dependencies
6
+ %w{yui-compressor}
7
+ end
8
+
9
+ def self.require_libs
10
+ %w{yui/compressor}
11
+ end
12
+
13
+ def self.compiler_class
14
+ YUI::JavaScriptCompressor
15
+ end
16
+
17
+ def process_plain(str)
18
+ @engine.compress(str)
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+
2
+
3
+ module Shift
4
+
5
+ # Shift base error, from which other errors inherit.
6
+ #
7
+ class Error < StandardError; end
8
+
9
+ # Raised when the environment needed to perform a given
10
+ # action is not available. Typically, you will need to
11
+ # install another gem or some library/software.
12
+ #
13
+ class DependencyError < Error; end
14
+
15
+ # Raised when you try to read a file for which there are
16
+ # no mappings without specifying its type.
17
+ #
18
+ class UnknownFormatError < Error; end
19
+
20
+ end
@@ -0,0 +1,32 @@
1
+
2
+ module Shift
3
+
4
+ # Mappings from file names to implementation classes. The
5
+ # classes are listed in order of preference per type.
6
+ #
7
+ MAPPINGS = {
8
+ 'echo' => %w{ Identity },
9
+ 'js' => %w{ UglifyJS ClosureCompiler YUICompressor },
10
+ 'coffee' => %w{ CoffeeScript },
11
+ 'sass' => %w{ Sass },
12
+ 'md' => %w{ RDiscount Redcarpet }
13
+ }
14
+
15
+ # @raise [DependencyError] when none of the mapped
16
+ # implementations are available.
17
+ #
18
+ # @return [Class] The preferred available class associated
19
+ # with the file or extension.
20
+ #
21
+ def self.best_available_mapping_for(key)
22
+ MAPPINGS[key].each do |kls_name|
23
+ kls = const_get(kls_name)
24
+ return kls if kls.available?
25
+ end
26
+ help = const_get(MAPPINGS[key].first)::INSTRUCTIONS
27
+ raise DependencyError, "no implementation available for " +
28
+ "#{key.inspect}. Possible solution: #{help}"
29
+ end
30
+ end
31
+
32
+
data/lib/shift.rb ADDED
@@ -0,0 +1,60 @@
1
+
2
+
3
+ # SHIFT
4
+ #
5
+ # State and logic-less compiler and compressor interface
6
+ #
7
+ # (c) 2011 Jostein Berre Eliassen - MIT licence
8
+
9
+
10
+ module Shift
11
+
12
+ VERSION = '0.1.0'
13
+
14
+ require 'shift/errors'
15
+ require 'shift/mappings'
16
+
17
+
18
+ # components
19
+
20
+ autoload :Identity, 'shift/c/identity'
21
+ autoload :UglifyJS, 'shift/c/uglify_js'
22
+ autoload :ClosureCompiler, 'shift/c/closure_compiler'
23
+ autoload :YUICompressor, 'shift/c/yui_compressor'
24
+ autoload :CoffeeScript, 'shift/c/coffee_script'
25
+ autoload :Sass, 'shift/c/sass'
26
+ autoload :RDiscount, 'shift/c/rdiscount'
27
+ autoload :Redcarpet, 'shift/c/redcarpet'
28
+ autoload :RedCarpet, 'shift/c/redcarpet'
29
+
30
+
31
+ # Read and process a file with the mapped component.
32
+ #
33
+ # @see Shift.[]
34
+ #
35
+ # (see Identity#read)
36
+ #
37
+ def self.read(path, opts={})
38
+ self[path].new(opts).read(path)
39
+ end
40
+
41
+ # Get the preferred available class mapped to match the
42
+ # given filename or extension.
43
+ #
44
+ # @raise [UnknownFormatError] when none of the mappings match.
45
+ #
46
+ # (see Shift.best_available_mapping_for)
47
+ #
48
+ def self.[](file)
49
+ pattern = File.basename(file.to_s.downcase)
50
+ until pattern.empty?
51
+ if MAPPINGS[pattern]
52
+ return best_available_mapping_for(pattern)
53
+ end
54
+ pattern.sub!(/^[^.]*\.?/, '')
55
+ end
56
+ raise UnknownFormatError, "no mapping matches #{file}"
57
+ end
58
+
59
+ end
60
+
data/shift.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+ require 'shift'
3
+
4
+ Gem::Specification.new do |s|
5
+
6
+ s.name = 'shift'
7
+
8
+ s.author = 'Jostein Berre Eliassen'
9
+ s.email = 'josteinpost@gmail.com'
10
+ s.homepage = "http://github.com/jbe/shift"
11
+ s.license = "MIT"
12
+
13
+ s.version = Shift::VERSION
14
+ s.platform = Gem::Platform::RUBY
15
+
16
+ s.summary = 'Shift is a generic interface to different compilers, compressors, etc.'
17
+ s.description = 'Shift is a generic interface to different compilers, compressors, etc. What the Tilt gem does for template languages, Shift does for compilers and compressors.'
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- spec/*`.split("\n")
21
+ s.require_path = 'lib'
22
+ s.bindir = 'bin'
23
+ end
@@ -0,0 +1,33 @@
1
+ require File.join(File.dirname(__FILE__), 'identity_test')
2
+
3
+
4
+ class ClosureCompilerTest < IdentityTest
5
+
6
+ FUNCTION = <<-eos
7
+ function hello(name) {
8
+ alert('Hello, ' + name);
9
+ }
10
+ eos
11
+
12
+ INVOCATION = <<-eos
13
+ hello('New user');
14
+ eos
15
+
16
+ def subject
17
+ Shift::ClosureCompiler
18
+ end
19
+
20
+ def options
21
+ {:compilation_level => 'ADVANCED_OPTIMIZATIONS'}
22
+ end
23
+
24
+ def transformations
25
+ {
26
+ [FUNCTION, INVOCATION].join("\n") =>
27
+ "alert(\"Hello, New user\");\n",
28
+ FUNCTION => "\n",
29
+ INVOCATION => "hello(\"New user\");\n"
30
+ }
31
+ end
32
+
33
+ end
@@ -0,0 +1,23 @@
1
+ require File.join(File.dirname(__FILE__), 'identity_test')
2
+
3
+
4
+ class CoffeeScriptTest < IdentityTest
5
+
6
+ def subject
7
+ Shift::CoffeeScript
8
+ end
9
+
10
+ def options
11
+ {:bare => true}
12
+ end
13
+
14
+ def transformations
15
+ {
16
+ 'hello' => 'hello;',
17
+ 'x = 23' => "var x;\nx = 23;",
18
+ 'frog -> "croak"' =>
19
+ "frog(function() {\n return \"croak\";\n});"
20
+ }
21
+ end
22
+
23
+ end
@@ -0,0 +1,79 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'helper')
2
+
3
+ # Test Shift::Identity.
4
+ class IdentityTest < TestCase
5
+
6
+ def subject
7
+ Shift::Identity
8
+ end
9
+
10
+ def instance
11
+ @instance ||= subject.new(options)
12
+ end
13
+
14
+ def options
15
+ {}
16
+ end
17
+
18
+ def transformations
19
+ {
20
+ 'echo' => 'echo',
21
+ '' => ''
22
+ }
23
+ end
24
+
25
+ test 'instructions' do
26
+ unless subject == Shift::Identity
27
+ refute_same subject.instructions,
28
+ subject.superclass.instructions,
29
+ 'gives instructions'
30
+ end
31
+ end
32
+
33
+ test 'has_default_instance' do
34
+ assert_instance_of subject, subject.default
35
+ end
36
+
37
+ test 'process' do
38
+ transformations.each do |a, b|
39
+ assert_equal b, instance.process(a)
40
+ end
41
+ end
42
+
43
+ # the usual ruby system file errors will just pass through,
44
+ # no use in testing for them.
45
+
46
+ test 'read' do
47
+ transformations.each do |a, b|
48
+ with_tempfile(a) do |path|
49
+ assert_equal b, instance.read(path)
50
+ end
51
+ end
52
+ end
53
+
54
+ test 'read and write' do
55
+ transformations.each do |a, b|
56
+ with_tempfile(a) do |src_path|
57
+ with_tempfile do |trg_path|
58
+ instance.read(src_path).write(trg_path)
59
+ assert_equal b, IO.read(trg_path)
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ test 'process and write' do
66
+ transformations.each do |a, b|
67
+ with_tempfile do |path|
68
+ instance.process(a).write(path)
69
+ assert_equal b, IO.read(path)
70
+ end
71
+ end
72
+ end
73
+
74
+ test 'initialize when unavailable' do
75
+ wrap = Class.new(subject).extend(Unavabelizer)
76
+ assert_raises(Shift::DependencyError) { wrap.new }
77
+ end
78
+
79
+ end
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), 'identity_test')
2
+
3
+
4
+ class RDiscountTest < IdentityTest
5
+
6
+ def subject
7
+ Shift::RDiscount
8
+ end
9
+
10
+ def instance
11
+ subject.new
12
+ end
13
+
14
+ def transformations
15
+ { 'hello' => "<p>hello</p>\n" }
16
+ end
17
+
18
+ end
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), 'identity_test')
2
+
3
+
4
+ class RedCarpetTest < IdentityTest
5
+
6
+ def subject
7
+ Shift::Redcarpet
8
+ end
9
+
10
+ def instance
11
+ subject.new
12
+ end
13
+
14
+ def transformations
15
+ { 'hello' => "<p>hello</p>\n" }
16
+ end
17
+
18
+ end
@@ -0,0 +1,14 @@
1
+ require File.join(File.dirname(__FILE__), 'identity_test')
2
+
3
+
4
+ class SassTest < IdentityTest
5
+
6
+ def subject
7
+ Shift::Sass
8
+ end
9
+
10
+ def transformations
11
+ {"#footer\n :height 200px" => "#footer {\n height: 200px; }\n"}
12
+ end
13
+
14
+ end
@@ -0,0 +1,33 @@
1
+ require File.join(File.dirname(__FILE__), 'identity_test')
2
+
3
+
4
+ class UglifyJSTest < IdentityTest
5
+
6
+ FUNCTION = <<-eos
7
+ function hello(name) {
8
+ alert('Hello, ' + name);
9
+ }
10
+ eos
11
+
12
+ INVOCATION = <<-eos
13
+ hello('New user');
14
+ eos
15
+
16
+ def subject
17
+ Shift::UglifyJS
18
+ end
19
+
20
+ def options
21
+ {}
22
+ end
23
+
24
+ def transformations
25
+ {
26
+ [FUNCTION, INVOCATION].join("\n") =>
27
+ "function hello(a){alert(\"Hello, \"+a)}hello(\"New user\")",
28
+ FUNCTION => "function hello(a){alert(\"Hello, \"+a)}",
29
+ INVOCATION => "hello(\"New user\")"
30
+ }
31
+ end
32
+
33
+ end
@@ -0,0 +1,33 @@
1
+ require File.join(File.dirname(__FILE__), 'identity_test')
2
+
3
+
4
+ class YUICompressorTest < IdentityTest
5
+
6
+ FUNCTION = <<-eos
7
+ function hello(name) {
8
+ alert('Hello, ' + name);
9
+ }
10
+ eos
11
+
12
+ INVOCATION = <<-eos
13
+ hello('New user');
14
+ eos
15
+
16
+ def subject
17
+ Shift::YUICompressor
18
+ end
19
+
20
+ def options
21
+ {}
22
+ end
23
+
24
+ def transformations
25
+ {
26
+ [FUNCTION, INVOCATION].join("\n") =>
27
+ "function hello(name){alert(\"Hello, \"+name)}hello(\"New user\");",
28
+ FUNCTION => "function hello(name){alert(\"Hello, \"+name)};",
29
+ INVOCATION => "hello(\"New user\");"
30
+ }
31
+ end
32
+
33
+ end
@@ -0,0 +1,6 @@
1
+
2
+ Hello dear.
3
+
4
+ Could you please bring with you my electric power drill, a cup of baking soda, three rolls of duct tape and The Brothers Karamazov when you come back from the apartment? I'm going on a mission again.
5
+
6
+ Thanks.
@@ -0,0 +1,5 @@
1
+
2
+
3
+ piglet = -> 'grunt grunt'
4
+
5
+ piglet()
data/test/helper.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'tempfile'
2
+
3
+ class TestCase < MiniTest::Unit::TestCase
4
+ def self.test(name, &block)
5
+ test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym
6
+ defined = instance_method(test_name) rescue false
7
+ raise "#{test_name} already defined in #{self}" if defined
8
+
9
+ block ||= proc { skip }
10
+ define_method(test_name, &block)
11
+ end
12
+
13
+ def with_tempfile(data=nil)
14
+ file = Tempfile.new('shift_test')
15
+ file.write(data) if data
16
+ file.close
17
+ yield(file.path)
18
+ file.unlink
19
+ end
20
+
21
+ def file(name)
22
+ File.join(File.dirname(__FILE__), 'data', name)
23
+ end
24
+
25
+ end
26
+
27
+
28
+
29
+
30
+
31
+ module Unavabelizer
32
+ def available?
33
+ false
34
+ end
35
+ end
36
+
37
+
@@ -0,0 +1,65 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+ require File.join(File.dirname(__FILE__), 'support')
3
+
4
+
5
+
6
+
7
+ # Test Shift base module methods
8
+ class ShiftTest < TestCase
9
+
10
+ test 'read nonexistant file' do
11
+ assert_raises(Errno::ENOENT) do
12
+ Shift.read('/ubongobaluba-hepp-piglets/seriously.echo')
13
+ end
14
+ end
15
+
16
+ test 'read file' do
17
+ assert_match Shift.read(file 'letter.echo'),
18
+ /electric power drill/
19
+ end
20
+
21
+ test 'reads existing file and writes result' do
22
+ with_tempfile do |path|
23
+ Shift.read(file('letter.echo')).write(path)
24
+ assert_equal(IO.read(file 'letter.echo'), IO.read(path))
25
+ end
26
+ end
27
+
28
+
29
+ # mappings
30
+
31
+ test 'has mappings' do
32
+ assert_kind_of Hash, Shift::MAPPINGS
33
+ end
34
+
35
+ test 'reads unmapped file' do
36
+ assert_raises(Shift::UnknownFormatError) do
37
+ Shift.read('oy-oy-oy.noformatforthis')
38
+ end
39
+ end
40
+
41
+ test 'gets available mapping' do
42
+ assert_equal Shift[:echo], Shift::Identity, 'given type'
43
+ assert_equal Shift['treaty.null'], NullComponent, 'given path'
44
+ assert_equal Shift['some/path/hey.bingo.bongo'],
45
+ NullComponent, 'with detailed mapping'
46
+ end
47
+
48
+ test 'prioritizes' do
49
+ assert_equal Shift['file.null'], NullComponent,
50
+ 'first when available'
51
+ assert_equal Shift['file.prioritized'], NullComponent,
52
+ 'second when available but not first'
53
+ end
54
+
55
+ test 'raises DependencyError' do
56
+ begin
57
+ Shift[:unavailable] # defined in test/support.rb
58
+ assert false, 'when no components available'
59
+ rescue Shift::DependencyError => err
60
+ assert_match /meditate/, err.message, 'with helpful message'
61
+ end
62
+ end
63
+
64
+ end
65
+
data/test/support.rb ADDED
@@ -0,0 +1,37 @@
1
+
2
+ class UnavailableComponent < Shift::Identity
3
+
4
+ INSTRUCTIONS = 'meditate.'
5
+
6
+ def self.available?
7
+ false
8
+ end
9
+
10
+ end
11
+
12
+ class NullComponent < Shift::Identity
13
+
14
+ def self.available?
15
+ true
16
+ end
17
+
18
+ def process(str)
19
+ ''
20
+ end
21
+
22
+ end
23
+
24
+ Shift::MAPPINGS['unavailable'] = ['UnavailableComponent'] * 10
25
+
26
+ Shift::MAPPINGS['null'] = %w{NullComponent}
27
+ Shift::MAPPINGS['bingo.bongo'] = %w{NullComponent}
28
+
29
+ Shift::MAPPINGS['prioritized'] = %w{UnavailableComponent
30
+ NullComponent Identity}
31
+
32
+
33
+
34
+
35
+
36
+
37
+
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shift
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Jostein Berre Eliassen
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-05-09 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Shift is a generic interface to different compilers, compressors, etc. What the Tilt gem does for template languages, Shift does for compilers and compressors.
22
+ email: josteinpost@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - .gitignore
31
+ - .yardopts
32
+ - LICENSE
33
+ - README.md
34
+ - Rakefile
35
+ - lib/shift.rb
36
+ - lib/shift/c/closure_compiler.rb
37
+ - lib/shift/c/coffee_script.rb
38
+ - lib/shift/c/identity.rb
39
+ - lib/shift/c/rdiscount.rb
40
+ - lib/shift/c/redcarpet.rb
41
+ - lib/shift/c/sass.rb
42
+ - lib/shift/c/uglify_js.rb
43
+ - lib/shift/c/yui_compressor.rb
44
+ - lib/shift/errors.rb
45
+ - lib/shift/mappings.rb
46
+ - shift.gemspec
47
+ - test/c/closure_compiler_test.rb
48
+ - test/c/coffee_script_test.rb
49
+ - test/c/identity_test.rb
50
+ - test/c/rdiscount_test.rb
51
+ - test/c/redcarpet_test.rb
52
+ - test/c/sass_test.rb
53
+ - test/c/uglify_js_test.rb
54
+ - test/c/yui_compressor_test.rb
55
+ - test/data/letter.echo
56
+ - test/data/piglet.coffee
57
+ - test/helper.rb
58
+ - test/shift_test.rb
59
+ - test/support.rb
60
+ has_rdoc: true
61
+ homepage: http://github.com/jbe/shift
62
+ licenses:
63
+ - MIT
64
+ post_install_message:
65
+ rdoc_options: []
66
+
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ requirements: []
86
+
87
+ rubyforge_project:
88
+ rubygems_version: 1.3.7
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Shift is a generic interface to different compilers, compressors, etc.
92
+ test_files: []
93
+