epic 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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