epic 0.0.2 → 0.0.3

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.
@@ -1,4 +1,8 @@
1
- == 0.0.1 2010-01-25
1
+ == 0.0.3 2010-01-25
2
+ * major enhancements
3
+ * added YUI compressor to compress JavaScript and CSS
4
+
5
+ == 0.0.2 2010-01-25
2
6
  * bug fixes
3
7
  * fixed path
4
8
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{epic}
8
- s.version = "0.0.2"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jeff Coleman"]
@@ -30,13 +30,17 @@ Gem::Specification.new do |s|
30
30
  "bin/epic",
31
31
  "epic.gemspec",
32
32
  "lib/epic.rb",
33
- "lib/file.rb",
33
+ "lib/epic/base.rb",
34
+ "lib/epic/compressor.rb",
35
+ "lib/epic/validator.rb",
36
+ "spec/compressor_spec.rb",
34
37
  "spec/epic_spec.rb",
35
38
  "spec/spec.opts",
36
39
  "spec/spec_helper.rb",
37
40
  "spec/stubs.rb",
38
41
  "vendor/ext/js.jar",
39
- "vendor/ext/jslint.js"
42
+ "vendor/ext/jslint.js",
43
+ "vendor/ext/yuicompressor-2.4.2.jar"
40
44
  ]
41
45
  s.homepage = %q{http://github.com/progressions/epic}
42
46
  s.rdoc_options = ["--charset=UTF-8"]
@@ -44,7 +48,8 @@ Gem::Specification.new do |s|
44
48
  s.rubygems_version = %q{1.3.5}
45
49
  s.summary = %q{Epic validation of HTML, JavaScript and CSS}
46
50
  s.test_files = [
47
- "spec/epic_spec.rb",
51
+ "spec/compressor_spec.rb",
52
+ "spec/epic_spec.rb",
48
53
  "spec/spec_helper.rb",
49
54
  "spec/stubs.rb"
50
55
  ]
@@ -2,160 +2,11 @@ dir = File.dirname(__FILE__)
2
2
  $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
3
3
 
4
4
  require 'rubygems'
5
- require 'file'
5
+ require 'f'
6
6
  require 'g'
7
7
  require 'active_support'
8
8
  require 'w3c_validators'
9
9
 
10
- module Epic
11
- module Validator
12
- class Configuration
13
- attr_accessor :base_path, :tmp_path, :doctype, :jslint_settings
14
- end
15
-
16
- class Base
17
- class << self
18
- def configuration
19
- @@configuration ||= Epic::Validator::Configuration.new
20
- end
21
-
22
- def configure
23
- yield configuration
24
- end
25
- end
26
-
27
- def configuration
28
- self.class.configuration
29
- end
30
-
31
- # Parses out the <tt>base_path</tt> setting from a path to display it in a
32
- # less verbose way.
33
- #
34
- def display_path(path)
35
- path = File.expand_path(path)
36
- path.gsub(base_path.to_s, "")
37
- end
38
-
39
- def base_path
40
- configuration.base_path || ""
41
- end
42
-
43
- def tmp_path
44
- configuration.tmp_path || ""
45
- end
46
- end
47
-
48
- class HTML < Base
49
- def validator
50
- @validator ||= W3CValidators::MarkupValidator.new
51
- end
52
-
53
- def validate(path)
54
- $stdout.print " #{path} validating . . . "
55
-
56
- doctype = configuration.doctype || "HTML 4.01 Transitional"
57
- validator.set_doctype!(doctype)
58
-
59
- results = validator.validate_file(path)
60
-
61
- valid = results.errors.length <= 0
62
-
63
- if valid
64
- $stdout.puts "OK"
65
- else
66
- $stdout.puts "validation errors"
67
- results.errors.each do |err|
68
- $stdout.puts
69
- $stdout.puts err.to_s
70
- end
71
- end
72
-
73
- valid
74
- end
75
- end
76
-
77
- class JavaScript < Base
78
- def use_jslint_settings?
79
- !jslint_settings.blank?
80
- end
81
-
82
- def jslint_settings
83
- configuration.jslint_settings
84
- end
85
-
86
- def jslint_settings_count
87
- jslint_settings.to_s.split("\n").size
88
- end
89
-
90
- def pre_process(content)
91
- content
92
- end
93
-
94
- def validate(path)
95
- display = display_path(path)
96
- $stdout.print " #{display} validating . . . "
97
- output = ""
98
-
99
- File.open(path) do |f|
100
- output = f.read
101
- end
102
-
103
- output = pre_process(output)
104
-
105
- FileUtils.mkdir_p(tmp_path)
106
-
107
- js_fragment_path = File.expand_path("#{tmp_path}/#{File.basename(path)}_fragment")
108
- fragment_display_path = display_path(js_fragment_path)
109
-
110
- if File.exists?(js_fragment_path)
111
- puts "That already exists?"
112
- else
113
- File.open(js_fragment_path,'w') do |f|
114
- f.puts jslint_settings if use_jslint_settings?
115
- f.puts output
116
- end
117
-
118
- jslint_path = File.expand_path("#{File.dirname(__FILE__)}/../vendor/ext/jslint.js")
119
- raise "#{jslint_path} does not exist" unless File.exists?(jslint_path)
120
- rhino_path = File.expand_path("#{File.dirname(__FILE__)}/../vendor/ext/js.jar")
121
- raise "#{rhino_path} does not exist" unless File.exists?(rhino_path)
122
-
123
- results = F.execute("java -jar #{rhino_path} #{jslint_path} #{js_fragment_path}", :return => true)
124
-
125
- if results =~ /jslint: No problems found/
126
- $stdout.puts "OK"
127
- else
128
- $stdout.puts "errors found!"
129
- results.split("\n").each do |result|
130
- if result =~ /line (\d+) character (\d+): (.*)/
131
- line_number = $1.to_i
132
- error = "Error at #{fragment_display_path} line #{line_number-jslint_settings_count} character #{$2}: #{$3}"
133
- error += F.get_line_from_file(js_fragment_path, line_number)
134
-
135
- $stdout.puts error
136
- end
137
- end
138
- message = "JavaScript Errors embedded in #{display}"
139
- g(message)
140
- raise message
141
- end
142
- end
143
- end
144
- end
145
-
146
- class JSON < JavaScript
147
- def pre_process(output)
148
- output
149
- end
150
-
151
- def jslint_settings
152
- end
153
- end
154
-
155
- class Stylesheet < Base
156
- def validate(filename)
157
- true
158
- end
159
- end
160
- end
161
- end
10
+ require 'epic/base'
11
+ require 'epic/validator'
12
+ require 'epic/compressor'
@@ -0,0 +1,49 @@
1
+ module Epic #:nodoc
2
+ class Configuration
3
+ attr_accessor :base_path, :tmp_path, :doctype, :jslint_settings
4
+ end
5
+
6
+ class Base
7
+ class << self
8
+ def configuration
9
+ @@configuration ||= Epic::Configuration.new
10
+ end
11
+
12
+ def configure
13
+ yield configuration
14
+ end
15
+
16
+ # Parses out the <tt>base_path</tt> setting from a path to display it in a
17
+ # less verbose way.
18
+ #
19
+ def display_path(path)
20
+ path = File.expand_path(path)
21
+ path.gsub(base_path.to_s, "")
22
+ end
23
+
24
+ def base_path
25
+ configuration.base_path
26
+ end
27
+ end
28
+
29
+ def configuration
30
+ self.class.configuration
31
+ end
32
+
33
+ # Parses out the <tt>base_path</tt> setting from a path to display it in a
34
+ # less verbose way.
35
+ #
36
+ def display_path(path)
37
+ path = File.expand_path(path)
38
+ path.gsub(base_path.to_s, "")
39
+ end
40
+
41
+ def base_path
42
+ configuration.base_path || ""
43
+ end
44
+
45
+ def tmp_path
46
+ configuration.tmp_path || ""
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,126 @@
1
+ module Epic #:nodoc:
2
+ module Compressor #:nodoc:
3
+ # Compresses a file using the specified compressor/minifier (currently YUI Compressor 2.4.2).
4
+ #
5
+ # === Usage
6
+ #
7
+ # Epic::Compressor::Base.compress("filename.js", "type" => "js")
8
+ #
9
+ # Epic::Compressor::Base.compress("filename.css", "type" => "css")
10
+ #
11
+ # Outputs the compressed file to <tt>_path_.min.</tt>
12
+ #
13
+ # === Options
14
+ #
15
+ # "type":: "js" or "css". Identifies the file type.
16
+ #
17
+ # "obfuscate":: true or false. Change internal variable names within the code.
18
+ #
19
+ # "verbose":: true or false. Output warnings about code quality.
20
+ #
21
+ # "preserve_semi":: true or false. Preserve unnecessary semicolons.
22
+ #
23
+ # TODO: Make it support multiple compressors.
24
+ #
25
+ # TODO: Convert it to an object, so you instantiate the Compressor class and then call it
26
+ # on a file or a string.
27
+ #
28
+ # TODO: Get some stringify_keys! action going so you can send in symbols or strings.
29
+ #
30
+ class Base < Epic::Base
31
+ def self.compress(path, options={})
32
+ options.stringify_keys!
33
+ compressed_display_path = display_path(path)
34
+ compressed_path = "#{path}.min"
35
+
36
+ options["type"] ||= "js"
37
+ options["type"] = options["type"].to_s
38
+
39
+ # if the compressed_file exists, don't create it again
40
+ #
41
+ unless File.exists?(compressed_path)
42
+ $stdout.print " #{compressed_display_path} compressing . . . "
43
+ compressed = ''
44
+
45
+ # set options and defaults
46
+ #
47
+ if options.delete("obfuscate")
48
+ options["nomunge"] = ""
49
+ end
50
+ if options.delete("verbose")
51
+ options["verbose"] = ""
52
+ end
53
+ options["charset"] = "utf-8"
54
+
55
+ if options["type"].to_s == "js" && !options["preserve_semi"]
56
+ options["preserve-semi"] = ""
57
+ end
58
+
59
+ # join the options together for appending to the command line
60
+ #
61
+ options_string = options.map {|k,v| "--#{k} #{v}"}.join(" ")
62
+
63
+ # call the compressor
64
+ #
65
+ compressor_path = File.expand_path("#{File.dirname(__FILE__)}/../../vendor/ext/yuicompressor-2.4.2.jar")
66
+ raise "#{compressor_path} does not exist" unless File.exists?(compressor_path)
67
+
68
+ command = "java -jar #{compressor_path} #{options_string} #{path} -o #{compressed_path} 2>&1"
69
+ result = F.execute(command, :return => true)
70
+
71
+ result.split("\n").each do |line|
72
+ if line =~ /\[ERROR\] (\d+):(\d+):(.*)/
73
+ line_number = $1.to_i
74
+ error = "Error at #{compressed_display_path} line #{line_number} character #{$2}: #{$3}"
75
+ error += F.get_line_from_file(path, line_number)
76
+
77
+ $stdout.puts error
78
+ g(error)
79
+ end
80
+ end
81
+
82
+ if result =~ /ERROR/
83
+ raise "JavaScript errors in #{compressed_display_path}"
84
+ else
85
+ $stdout.puts "OK"
86
+ end
87
+ end
88
+
89
+ # The compressed file should exist now. If it does, use it. If not, raise an error.
90
+ #
91
+ if File.exists?(compressed_path)
92
+ compressed = File.read(compressed_path)
93
+ else
94
+ raise "File does not exist: #{compressed_display_path}"
95
+ end
96
+
97
+ compressed
98
+ end
99
+ end
100
+
101
+ # Compresses a CSS file using the specified compressor/minifier (currently YUI Compressor 2.4.2).
102
+ #
103
+ # === Usage
104
+ #
105
+ # Epic::Compressor::Stylesheet.compress("filename.css")
106
+ #
107
+ class Stylesheet < Base
108
+ def self.compress(path)
109
+ super(path, "type" => "css")
110
+ end
111
+ end
112
+
113
+ # Compresses a JavaScript file using the specified compressor/minifier (currently YUI Compressor 2.4.2).
114
+ #
115
+ # === Usage
116
+ #
117
+ # Epic::Compressor::JavaScript.compress("filename.js")
118
+ #
119
+ class JavaScript < Base
120
+ # TODO: Add options hash
121
+ def self.compress(filename)
122
+ super(filename, "type" => "js")
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,118 @@
1
+ require 'epic/base'
2
+
3
+ module Epic
4
+ module Validator
5
+ class HTML < Epic::Base
6
+ def validator
7
+ @validator ||= W3CValidators::MarkupValidator.new
8
+ end
9
+
10
+ def validate(path)
11
+ $stdout.print " #{path} validating . . . "
12
+
13
+ doctype = configuration.doctype || "HTML 4.01 Transitional"
14
+ validator.set_doctype!(doctype)
15
+
16
+ results = validator.validate_file(path)
17
+
18
+ valid = results.errors.length <= 0
19
+
20
+ if valid
21
+ $stdout.puts "OK"
22
+ else
23
+ $stdout.puts "validation errors"
24
+ results.errors.each do |err|
25
+ $stdout.puts
26
+ $stdout.puts err.to_s
27
+ end
28
+ end
29
+
30
+ valid
31
+ end
32
+ end
33
+
34
+ class JavaScript < Base
35
+ def use_jslint_settings?
36
+ !jslint_settings.blank?
37
+ end
38
+
39
+ def jslint_settings
40
+ configuration.jslint_settings
41
+ end
42
+
43
+ def jslint_settings_count
44
+ jslint_settings.to_s.split("\n").size
45
+ end
46
+
47
+ def pre_process(content)
48
+ content
49
+ end
50
+
51
+ def validate(path)
52
+ display = display_path(path)
53
+ $stdout.print " #{display} validating . . . "
54
+ output = ""
55
+
56
+ File.open(path) do |f|
57
+ output = f.read
58
+ end
59
+
60
+ output = pre_process(output)
61
+
62
+ FileUtils.mkdir_p(tmp_path)
63
+
64
+ js_fragment_path = File.expand_path("#{tmp_path}/#{File.basename(path)}_fragment")
65
+ fragment_display_path = display_path(js_fragment_path)
66
+
67
+ if File.exists?(js_fragment_path)
68
+ puts "That already exists?"
69
+ else
70
+ File.open(js_fragment_path,'w') do |f|
71
+ f.puts jslint_settings if use_jslint_settings?
72
+ f.puts output
73
+ end
74
+
75
+ jslint_path = File.expand_path("#{File.dirname(__FILE__)}/../../vendor/ext/jslint.js")
76
+ raise "#{jslint_path} does not exist" unless File.exists?(jslint_path)
77
+ rhino_path = File.expand_path("#{File.dirname(__FILE__)}/../../vendor/ext/js.jar")
78
+ raise "#{rhino_path} does not exist" unless File.exists?(rhino_path)
79
+
80
+ results = F.execute("java -jar #{rhino_path} #{jslint_path} #{js_fragment_path}", :return => true)
81
+
82
+ if results =~ /jslint: No problems found/
83
+ $stdout.puts "OK"
84
+ else
85
+ $stdout.puts "errors found!"
86
+ results.split("\n").each do |result|
87
+ if result =~ /line (\d+) character (\d+): (.*)/
88
+ line_number = $1.to_i
89
+ error = "Error at #{fragment_display_path} line #{line_number-jslint_settings_count} character #{$2}: #{$3}"
90
+ error += F.get_line_from_file(js_fragment_path, line_number)
91
+
92
+ $stdout.puts error
93
+ end
94
+ end
95
+ message = "JavaScript Errors embedded in #{display}"
96
+ g(message)
97
+ raise message
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ class JSON < JavaScript
104
+ def pre_process(output)
105
+ output
106
+ end
107
+
108
+ def jslint_settings
109
+ end
110
+ end
111
+
112
+ class Stylesheet < Base
113
+ def validate(filename)
114
+ true
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,127 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Compressor" do
4
+ before(:each) do
5
+ stub_io
6
+ File.stub!(:exists?).with(/yuicompressor/).and_return(true)
7
+ end
8
+
9
+ describe "Base" do
10
+ it "should use the compressed file if it already exists" do
11
+ File.stub!(:exists?).with(/file.js/).and_return(true)
12
+ @file = "compressed file"
13
+ File.stub(:read).and_return(@file)
14
+ Epic::Compressor::Base.compress("file.js", "type" => "js").should == @file
15
+ end
16
+
17
+ describe "generate a compressed file if one doesn't exist" do
18
+ before(:each) do
19
+ File.stub!(:exists?).with(/file.js/).and_return(false, true)
20
+ File.stub!(:exists?).with(/file.css/).and_return(false, true)
21
+ end
22
+
23
+ it "should log what it's doing" do
24
+ $stdout.should_receive(:print).with(/file.js compressing . . ./)
25
+ Epic::Compressor::Base.compress("file.js", "type" => "js")
26
+ end
27
+
28
+ it "should run the compressor" do
29
+ F.should_receive(:execute).with(/yuicompressor/, :return => true).and_return("")
30
+ Epic::Compressor::Base.compress("file.js", "type" => "js")
31
+ end
32
+
33
+ describe "options" do
34
+ it "should set nomunge" do
35
+ F.should_receive(:execute).with(/nomunge/, :return => true).and_return("")
36
+ Epic::Compressor::Base.compress("file.js", "type" => "js", "obfuscate" => true)
37
+ end
38
+
39
+ it "should not set nomunge" do
40
+ F.stub!(:execute).with(/yuicompressor/, :return => true).and_return("")
41
+ F.should_not_receive(:execute).with(/nomunge/, :return => true).and_return("")
42
+ Epic::Compressor::Base.compress("file.js", "type" => "js", "obfuscate" => false)
43
+ end
44
+
45
+ it "should set verbose" do
46
+ F.should_receive(:execute).with(/verbose/, :return => true).and_return("")
47
+ Epic::Compressor::Base.compress("file.js", "type" => "js", "verbose" => true)
48
+ end
49
+
50
+ it "should not set verbose" do
51
+ F.stub!(:execute).with(/yuicompressor/, :return => true).and_return("")
52
+ F.should_not_receive(:execute).with(/verbose/, :return => true).and_return("")
53
+ Epic::Compressor::Base.compress("file.js", "type" => "js", "verbose" => false)
54
+ end
55
+
56
+ it "should set preserve-semi on javascript" do
57
+ F.should_receive(:execute).with(/preserve-semi/, :return => true).and_return("")
58
+ Epic::Compressor::Base.compress("file.js", "type" => "js")
59
+ end
60
+
61
+ it "should not set preserve-semi on css" do
62
+ File.stub!(:exists?).with(/file.css/).and_return(true)
63
+ F.stub!(:execute).with(/yuicompressor/, :return => true).and_return("")
64
+ F.should_not_receive(:execute).with(/preserve-semi/, :return => true).and_return("")
65
+ Epic::Compressor::Base.compress("file.css", "type" => "css")
66
+ end
67
+ end
68
+
69
+ describe "on errors" do
70
+ before(:each) do
71
+ F.stub!(:execute).with(/yuicompressor/, :return => true).and_return("[ERROR] 12:13: Too much fruzzlegump")
72
+ end
73
+
74
+ it "should raise an exception" do
75
+ lambda {
76
+ Epic::Compressor::Base.compress("file.js", "type" => "js")
77
+ }.should raise_error(/JavaScript errors/)
78
+ end
79
+
80
+ it "should growl" do
81
+ @g.should_receive(:notify)
82
+ lambda {
83
+ Epic::Compressor::Base.compress("file.js", "type" => "js")
84
+ }.should raise_error(/JavaScript errors/)
85
+ end
86
+
87
+ it "should show the source code" do
88
+ F.should_receive(:get_line_from_file).with("file.js", 12).and_return("")
89
+ lambda {
90
+ Epic::Compressor::Base.compress("file.js", "type" => "js")
91
+ }.should raise_error(/JavaScript errors/)
92
+ end
93
+ end
94
+
95
+ it "should report OK" do
96
+ $stdout.should_receive(:puts).with("OK")
97
+ Epic::Compressor::Base.compress("file.js", "type" => "js")
98
+ end
99
+
100
+ it "should raise an error if the compressed file doesn't exist" do
101
+ # File.stub!(:exists?).with(/file.js/).and_return(true)
102
+ # File.stub!(:exists?).with(/file.js.min/).and_return(false)
103
+ # lambda {
104
+ Epic::Compressor::Base.compress("file.js", "type" => "js")
105
+ # }.should raise_error(/File does not exist/)
106
+ end
107
+ end
108
+ end
109
+
110
+ describe "JavaScript" do
111
+ it "should call Base with type js" do
112
+ File.stub(:exists?).with(/file.js/).and_return(true)
113
+ @file = "compressed file"
114
+ File.stub(:read).and_return(@file)
115
+ Epic::Compressor::JavaScript.compress("file.js").should == @file
116
+ end
117
+ end
118
+
119
+ describe "Stylesheet" do
120
+ it "should call Base with type css" do
121
+ File.stub(:exists?).with(/file.css/).and_return(true)
122
+ @file = "compressed file"
123
+ File.stub(:read).and_return(@file)
124
+ Epic::Compressor::Stylesheet.compress("file.css").should == @file
125
+ end
126
+ end
127
+ end
@@ -81,7 +81,7 @@ describe "Validator" do
81
81
  end
82
82
 
83
83
  it "should set jslint settings" do
84
- Epic::Validator::JavaScript.configure do |config|
84
+ Epic::Base.configure do |config|
85
85
  config.jslint_settings = @jslint_settings
86
86
  end
87
87
  Epic::Validator::JavaScript.new.jslint_settings.should == @jslint_settings
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: epic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Coleman
@@ -63,13 +63,17 @@ files:
63
63
  - bin/epic
64
64
  - epic.gemspec
65
65
  - lib/epic.rb
66
- - lib/file.rb
66
+ - lib/epic/base.rb
67
+ - lib/epic/compressor.rb
68
+ - lib/epic/validator.rb
69
+ - spec/compressor_spec.rb
67
70
  - spec/epic_spec.rb
68
71
  - spec/spec.opts
69
72
  - spec/spec_helper.rb
70
73
  - spec/stubs.rb
71
74
  - vendor/ext/js.jar
72
75
  - vendor/ext/jslint.js
76
+ - vendor/ext/yuicompressor-2.4.2.jar
73
77
  has_rdoc: true
74
78
  homepage: http://github.com/progressions/epic
75
79
  licenses: []
@@ -99,6 +103,7 @@ signing_key:
99
103
  specification_version: 3
100
104
  summary: Epic validation of HTML, JavaScript and CSS
101
105
  test_files:
106
+ - spec/compressor_spec.rb
102
107
  - spec/epic_spec.rb
103
108
  - spec/spec_helper.rb
104
109
  - spec/stubs.rb
@@ -1,63 +0,0 @@
1
- # Provides a wrapper around common calls that interact with the file system.
2
- #
3
- module F
4
-
5
- module_function
6
-
7
- # Concatenates together the contents of all the files in the <tt>source_path</tt>
8
- # into the <tt>destination_path</tt>.
9
- #
10
- def concat_files(source_path, destination_path)
11
- File.open(destination_path, "a") do |output|
12
- Dir[source_path].each do |path|
13
- output.puts File.read(path)
14
- end
15
- end
16
- end
17
-
18
- # Saves the <tt>output</tt> string to the <tt>destination_path</tt> given.
19
- #
20
- # Returns <tt>true</tt> if the destination file was newly created, <tt>false</tt> if
21
- # it already existed.
22
- #
23
- def save_to_file(output, destination_path)
24
- if File.exists?(destination_path)
25
- false
26
- else
27
- File.open(destination_path, "w") do |w|
28
- w.write(output)
29
- end
30
- true
31
- end
32
- end
33
-
34
- # Given a <tt>path</tt> and <tt>line_number</tt>, returns the line and two lines previous
35
- #
36
- # Used for displaying validation errors.
37
- #
38
- def get_line_from_file(path, line_number)
39
- line_number = line_number.to_i
40
- output = "\n"
41
- lines = File.readlines(path)
42
-
43
- 3.times do |i|
44
- line = lines[line_number-(3-i)]
45
- output += line if line
46
- end
47
-
48
- output += "\n"
49
- output
50
- end
51
-
52
- # Execute a system command. If the parameter <tt>:return</tt> is true, execute the command
53
- # with the backtick (`) command and return the results. Otherwise, just execute the command
54
- # and let the output go to the screen.
55
- #
56
- def execute(command, params={})
57
- if params[:return]
58
- `#{command}`
59
- else
60
- Kernel.system command
61
- end
62
- end
63
- end