kcomp 0.1.1 → 0.1.2

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.
@@ -2,10 +2,14 @@
2
2
 
3
3
  This is a simple command-line compiler for CodeKit .kit files for those of us who don't have it, aren't on Macs, or simply prefer the command line Usage is pretty simple:
4
4
 
5
- kcomp SRC-DIR DEST-DIR
5
+ kcomp [-s SOURCEDIR] [-d DESTDIR] [-f]
6
6
 
7
7
  if the arguemnts are omitted, they will both be assumed to be the CWD. Documentation on the .kit file format can be found at http://incident57.com/codekit/kit.php.
8
8
 
9
+ == WARNING!
10
+
11
+ This thing is hacky as hell. I started with the spec, and basically iterated until diff showed no difference between those files compiled by codekit and those compiled by this tool. I reserve every possible right to have screwed up fantastically.
12
+
9
13
  == Contributing to kcomp
10
14
 
11
15
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
data/bin/kcomp CHANGED
@@ -1,4 +1,24 @@
1
1
  #!/usr/bin/env ruby
2
2
  require File.dirname(__FILE__) + "/../lib/kcomp"
3
+ require 'optparse'
3
4
 
4
- KComp.compile! ARGV[0] || ".", ARGV[1] || "."
5
+ options = {:src => '.', :dest => '.'}
6
+
7
+ OptionParser.new do |opts|
8
+ opts.banner = "Usage: kcomp [options]"
9
+ opts.on("-s", "--source SOURCE", "The source parent directory for all .kit files") do |src|
10
+ options[:src] = src
11
+ end
12
+ opts.on("-d", "--destination DESTINATION", "The output directory") do |dest|
13
+ options[:dest] = dest
14
+ end
15
+ opts.on("-f", "--flatten", "Flatten all output in destination directory") do
16
+ options[:flatten] = true
17
+ end
18
+ opts.on_tail("-h", "--help", "Print this help message") do
19
+ puts opts
20
+ exit
21
+ end
22
+ end.parse!
23
+
24
+ KComp.compile! options[:src], options[:dest], options
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "kcomp"
8
- s.version = "0.1.1"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jeremy Holland"]
@@ -43,17 +43,13 @@ Gem::Specification.new do |s|
43
43
  "spec/support/test-src/_partial1.kit",
44
44
  "spec/support/test-src/_partial2.kit",
45
45
  "spec/support/test-src/_partial3.kit",
46
- "spec/support/test-src/inc1.kit",
47
46
  "spec/support/test-src/inc10.kit",
48
47
  "spec/support/test-src/inc11.kit",
49
48
  "spec/support/test-src/inc12.kit",
50
- "spec/support/test-src/inc2.kit",
51
- "spec/support/test-src/inc4.kit",
52
49
  "spec/support/test-src/inc5.kit",
53
50
  "spec/support/test-src/inc7.kit",
54
51
  "spec/support/test-src/inc8.kit",
55
52
  "spec/support/test-src/inc9.kit",
56
- "spec/support/test-src/somedir/inc3.kit",
57
53
  "spec/support/test-src/somedir/inc6.kit",
58
54
  "spec/support/test-src/test-inclusion.kit"
59
55
  ]
@@ -1,24 +1,30 @@
1
1
  require 'rgl/adjacency'
2
2
  require 'rgl/topsort'
3
3
  require 'fileutils'
4
+ require 'pry'
4
5
  require File.dirname(__FILE__) + "/errors"
5
6
 
6
7
  class KComp
7
- def initialize(src, dest)
8
+ def initialize(src, dest, opts={})
9
+ @options = opts
8
10
  @depdg = RGL::DirectedAdjacencyGraph.new
9
11
  @texts = {}
10
- @ctexts = {}
11
- @vars = {}
12
+ @compiled = []
12
13
  @src = src = src =~ /\/$/ ? src : src + "/"
14
+ if @src !~ /^[.\/]/
15
+ @src = "./" + @src
16
+ end
13
17
  @dest = dest = dest =~ /\/$/ ? dest : dest + "/"
14
- build_vertices src
18
+ if @dest !~ /^[.\/]/
19
+ @dest = "./" + @dest
20
+ end
21
+ build_vertices @src
15
22
  @vertices = @depdg.to_a
16
- build_edges src
23
+ build_edges @src
17
24
  check_for_cycles
18
25
  @tsort = @depdg.topsort_iterator
19
26
  @reversedg = @depdg.reverse
20
27
  @rtsort = @reversedg.topsort_iterator
21
- define_variables
22
28
  end
23
29
 
24
30
  def dependency_digraph
@@ -39,51 +45,60 @@ class KComp
39
45
  end
40
46
 
41
47
  private
42
- def define_variables
43
- @tsort.each do |v|
44
- rf = f = @texts[v]
45
- vars = {}
46
- f.scan(/(<!-- ?[$@]([A-Za-z_][A-Za-z0-9_\-]*) ?[ :=] *(.+) *-->)/).each do |var|
47
- vars[var[1]] = var.last.strip
48
- rf.gsub! var.first, ""
49
- end
50
- define_variables_for_vertex v, vars
51
- end
52
- end
53
48
 
54
- def define_variables_for_vertex(v, vars)
55
- @vars[v] ||= {}
56
- @vars[v].merge! vars
57
- @depdg.adjacent_vertices(v).each do |dep|
58
- define_variables_for_vertex dep, vars
59
- end
60
- end
61
-
62
- def compile_files(dest)
63
- @rtsort.each do |v|
64
- rf = f = @texts[v]
65
- f.scan(/(<!--!!! (.+) !!!-->)/).each do |import|
66
- rf.gsub! import.first, @ctexts[import.last]
67
- end
68
- f.scan(/(<!-- ?[$@]([A-Za-z_][A-Za-z0-9_\-]*) ?-->)/).each do |import|
69
- if @vars[v][import.last].nil?
70
- raise UndefinedVariableError, "Variable #{import.last} not defined."
49
+ def compile_inclusion(vertex, dest, ovars={}, inclusion=false)
50
+ vars = ovars.dup
51
+ f = @texts[vertex].dup
52
+ rf = f.dup
53
+ if (vertex !~ /_[^\/]+\.kit$/ || inclusion)
54
+ f.scan(/(<!-- *[$@]([A-Za-z0-9_][A-Za-z0-9_]*) *-->)|(<!-- ?[$@]([A-Za-z0-9_][A-Za-z0-9_]*) ?[ :=] *(.+) *-->)|(<!--!!! (.+) !!!-->)/).each do |import|
55
+ begin
56
+ if (import[0].nil? && import[2].nil?)
57
+ rf.gsub! import[5], compile_inclusion(import[6], dest, vars, true).rstrip
58
+ elsif (import[5].nil? && import[2].nil?)
59
+ rf.gsub! import[0], vars[import[1]]
60
+ else
61
+ vars[import[3]] = import[4].strip
62
+ rf.gsub!(import[2] + "\n", "")
63
+ rf.gsub!(import[2], "")
64
+ end
71
65
  end
72
- rf.gsub! import.first, @vars[v][import.last]
73
66
  end
74
- @ctexts[v] = rf.gsub(/\n+/, "\n")
75
- if (v !~ /_[^\/]+\.kit$/)
76
- filename = dest + v.gsub(@src, "").gsub(/\.kit$/, ".html")
77
- dirname = filename.gsub(/\/[^\/]+$/, "")
67
+ if (vertex !~ /_[^\/]+\.kit$/)
68
+ unless @options[:flatten]
69
+ filename = dest + vertex.gsub(@src, "").gsub(/\.kit$/, detect_format(rf))
70
+ dirname = filename.gsub(/\/[^\/]+$/, "")
71
+ else
72
+ filename = dest + vertex.gsub(/([^\/]+\/)+/, "").gsub(/\.kit$/, detect_format(rf))
73
+ dirname = filename.gsub(/\/[^\/]+$/, "")
74
+ end
78
75
  puts "Compiling #{filename}"
79
76
  unless Dir.exists?(dirname)
80
77
  FileUtils.mkdir_p dirname
81
78
  end
82
79
  File.open(filename, 'w+') do |file|
83
- file.write @ctexts[v]
80
+ file.write rf
84
81
  end
85
82
  end
86
83
  end
84
+ rf
85
+ end
86
+
87
+ def compile_files(dest)
88
+ @tsort.each do |v|
89
+ compile_inclusion(v, dest)
90
+ end
91
+ end
92
+
93
+ def detect_format(text)
94
+ case text
95
+ when /<\?php/
96
+ ".php"
97
+ when /<%=?/
98
+ ".erb"
99
+ else
100
+ ".html"
101
+ end
87
102
  end
88
103
 
89
104
  def check_for_cycles
@@ -108,11 +123,11 @@ class KComp
108
123
 
109
124
  def build_edges(src)
110
125
  @depdg.vertices.each do |v|
111
- add_edges(src, v)
126
+ add_edges(src, v, v.gsub(src, "").gsub(/\/[^\/]+$/, "") + "/")
112
127
  end
113
128
  end
114
129
 
115
- def add_edges(src, vertex)
130
+ def add_edges(src, vertex, subdir="")
116
131
  rf = f = File.read(vertex)
117
132
  f.scan(/(<!-- ?@(?:import|include) ['"]?((?:[A-Za-z0-9_\/\-.]+(?:, *)?)+)['"]? ?-->)/).each do |import|
118
133
  repl = []
@@ -121,14 +136,14 @@ class KComp
121
136
  if incl !~ /\.\w+$/
122
137
  incl = "#{incl}.kit"
123
138
  end
124
- if @vertices.include?(src + incl)
125
- match = src + incl
126
- elsif @vertices.include?(src + "_" + incl)
127
- match = src + "_" + incl
139
+ if @vertices.include?(src + subdir + incl)
140
+ match = src + subdir + incl
141
+ elsif @vertices.include?(src + subdir + incl.gsub(/\/([^\/]+)$/, "/_#{$1}"))
142
+ match = src + subdir + "_" + incl
128
143
  else
129
144
  match = @vertices.select { |v| v =~ /#{incl}$/ }.first
130
145
  if match.nil?
131
- match = @vertices.select { |v| v =~ /_#{incl}$/ }.first
146
+ match = @vertices.select { |v| v =~ /#{incl.gsub(/([^\/]+\/)+/, "")}$/ }.first
132
147
  end
133
148
  end
134
149
  if match.nil?
@@ -142,8 +157,8 @@ class KComp
142
157
  @texts[vertex] = rf
143
158
  end
144
159
 
145
- def self.compile!(src, dest)
146
- kc = KComp.new src, dest
160
+ def self.compile!(src, dest, opts={})
161
+ kc = KComp.new src, dest, opts
147
162
  kc.compile!
148
163
  end
149
164
  end
@@ -16,135 +16,20 @@ describe KComp do
16
16
  let(:comp) { KComp.new GOOD_SRC, DEST }
17
17
  let(:undef) { KComp.new UNDEFINED_VAR_SRC, DEST }
18
18
 
19
- describe "dependency_digraph" do
20
- let(:dg) { comp.dependency_digraph }
21
- let(:adjv) { dg.adjacent_vertices(GOOD_SRC + "/test-inclusion.kit") }
22
- it "should contain a node for each .kit file in the directory" do
23
- dg.should include(GOOD_SRC + "/_partial1.kit")
24
- dg.should include(GOOD_SRC + "/_partial2.kit")
25
- dg.should include(GOOD_SRC + "/_partial3.kit")
26
- dg.should include(GOOD_SRC + "/inc1.kit")
27
- dg.should include(GOOD_SRC + "/inc2.kit")
28
- dg.should include(GOOD_SRC + "/somedir/inc3.kit")
29
- dg.should include(GOOD_SRC + "/inc4.kit")
30
- dg.should include(GOOD_SRC + "/inc5.kit")
31
- dg.should include(GOOD_SRC + "/somedir/inc6.kit")
32
- dg.should include(GOOD_SRC + "/inc7.kit")
33
- dg.should include(GOOD_SRC + "/inc8.kit")
34
- dg.should include(GOOD_SRC + "/inc9.kit")
35
- dg.should include(GOOD_SRC + "/inc10.kit")
36
- dg.should include(GOOD_SRC + "/inc11.kit")
37
- dg.should include(GOOD_SRC + "/inc12.kit")
38
- dg.should include(GOOD_SRC + "/test-inclusion.kit")
39
- end
40
-
41
- it "should have directed edges indicating dependency relations" do
42
- adjv.should include(GOOD_SRC + "/_partial1.kit")
43
- adjv.should include(GOOD_SRC + "/_partial2.kit")
44
- adjv.should include(GOOD_SRC + "/inc1.kit")
45
- adjv.should include(GOOD_SRC + "/inc2.kit")
46
- adjv.should include(GOOD_SRC + "/somedir/inc3.kit")
47
- adjv.should include(GOOD_SRC + "/inc4.kit")
48
- adjv.should include(GOOD_SRC + "/inc5.kit")
49
- adjv.should include(GOOD_SRC + "/somedir/inc6.kit")
50
- adjv.should include(GOOD_SRC + "/inc7.kit")
51
- adjv.should include(GOOD_SRC + "/inc8.kit")
52
- adjv.should include(GOOD_SRC + "/inc9.kit")
53
- adjv.should include(GOOD_SRC + "/inc10.kit")
54
- end
55
-
56
- it "should not have any directed edges for undependent or indirectly dependent files" do
57
- adjv = dg.adjacent_vertices(GOOD_SRC + "/test-inclusion.kit")
58
- adjv.should_not include(GOOD_SRC + "/test-inclusion.kit")
59
- adjv.should_not include(GOOD_SRC + "/inc11.kit")
60
- adjv.should_not include(GOOD_SRC + "/inc12.kit")
61
- adjv.should_not include(GOOD_SRC + "/_partial3.kit")
62
- end
63
- end
64
-
65
- describe "reverse_dependency_digraph" do
66
- let(:dg) { comp.reverse_dependency_digraph }
67
- let(:adjv1) { dg.adjacent_vertices(GOOD_SRC + "/inc4.kit") }
68
- let(:adjv2) { dg.adjacent_vertices(GOOD_SRC + "/inc11.kit") }
69
- let(:adjv3) { dg.adjacent_vertices(GOOD_SRC + "/_partial3.kit") }
70
-
71
- it "should contain a node for each .kit file in the directory" do
72
- dg.should include(GOOD_SRC + "/_partial1.kit")
73
- dg.should include(GOOD_SRC + "/_partial2.kit")
74
- dg.should include(GOOD_SRC + "/_partial3.kit")
75
- dg.should include(GOOD_SRC + "/inc1.kit")
76
- dg.should include(GOOD_SRC + "/inc2.kit")
77
- dg.should include(GOOD_SRC + "/somedir/inc3.kit")
78
- dg.should include(GOOD_SRC + "/inc4.kit")
79
- dg.should include(GOOD_SRC + "/inc5.kit")
80
- dg.should include(GOOD_SRC + "/somedir/inc6.kit")
81
- dg.should include(GOOD_SRC + "/inc7.kit")
82
- dg.should include(GOOD_SRC + "/inc8.kit")
83
- dg.should include(GOOD_SRC + "/inc9.kit")
84
- dg.should include(GOOD_SRC + "/inc10.kit")
85
- dg.should include(GOOD_SRC + "/inc11.kit")
86
- dg.should include(GOOD_SRC + "/inc12.kit")
87
- dg.should include(GOOD_SRC + "/test-inclusion.kit")
88
- end
89
-
90
- it "should have directed edges indicating dependent relations" do
91
- adjv1.should include(GOOD_SRC + "/test-inclusion.kit")
92
- adjv2.should include(GOOD_SRC + "/inc10.kit")
93
- adjv3.should include(GOOD_SRC + "/inc10.kit")
94
- end
95
-
96
- it "should not have any directed edges for undependent or indirectly dependent files" do
97
- adjv1.should_not include(GOOD_SRC + "/inc10.kit")
98
- adjv2.should_not include(GOOD_SRC + "/test-inclusion.kit")
99
- adjv3.should_not include(GOOD_SRC + "/test-inclusion.kit")
100
- end
101
- end
102
-
103
- describe "files" do
104
- let(:files) { comp.files }
105
-
106
- it "should return an array of all .kit files" do
107
- files.should include(GOOD_SRC + "/_partial1.kit")
108
- files.should include(GOOD_SRC + "/_partial2.kit")
109
- files.should include(GOOD_SRC + "/_partial3.kit")
110
- files.should include(GOOD_SRC + "/inc1.kit")
111
- files.should include(GOOD_SRC + "/inc2.kit")
112
- files.should include(GOOD_SRC + "/somedir/inc3.kit")
113
- files.should include(GOOD_SRC + "/inc4.kit")
114
- files.should include(GOOD_SRC + "/inc5.kit")
115
- files.should include(GOOD_SRC + "/somedir/inc6.kit")
116
- files.should include(GOOD_SRC + "/inc7.kit")
117
- files.should include(GOOD_SRC + "/inc8.kit")
118
- files.should include(GOOD_SRC + "/inc9.kit")
119
- files.should include(GOOD_SRC + "/inc10.kit")
120
- files.should include(GOOD_SRC + "/inc11.kit")
121
- files.should include(GOOD_SRC + "/inc12.kit")
122
- files.should include(GOOD_SRC + "/test-inclusion.kit")
123
- end
124
-
125
- it "should order the files topologically by dependency" do
126
- files.index(GOOD_SRC + "/_partial3.kit").should > files.index(GOOD_SRC + "/inc10.kit")
127
- files.index(GOOD_SRC + "/inc11.kit").should > files.index(GOOD_SRC + "/inc10.kit")
128
- files.index(GOOD_SRC + "/_partial1.kit").should > files.index(GOOD_SRC + "/test-inclusion.kit")
129
- files.index(GOOD_SRC + "/inc10.kit").should > files.index(GOOD_SRC + "/test-inclusion.kit")
130
- end
131
- end
132
-
133
19
  describe "compile!" do
134
20
 
135
21
  it "should create any destination directories it needs (as dictated by the source directory structure)" do
136
22
  FileUtils.rm_rf DEST + "/*"
137
- capture_stdout do
138
- comp.compile!
139
- end
23
+ comp.compile!
140
24
  Dir.exists?(DEST + "/somedir").should be_true
141
25
  end
142
26
 
143
27
  it "should create a single html file for each regular kit file" do
144
- File.exists?(DEST + "/inc1.html").should be_true
145
- File.exists?(DEST + "/inc2.html").should be_true
146
- File.exists?(DEST + "/somedir/inc3.html").should be_true
147
- File.exists?(DEST + "/inc4.html").should be_true
28
+ comp.compile!
29
+ File.exists?(DEST + "/inc1.html").should be_false
30
+ File.exists?(DEST + "/inc2.html").should be_false
31
+ File.exists?(DEST + "/somedir/inc3.html").should be_false
32
+ File.exists?(DEST + "/inc4.html").should be_false
148
33
  File.exists?(DEST + "/inc5.html").should be_true
149
34
  File.exists?(DEST + "/somedir/inc6.html").should be_true
150
35
  File.exists?(DEST + "/inc7.html").should be_true
@@ -157,6 +42,7 @@ describe KComp do
157
42
  end
158
43
 
159
44
  it "should not create an html file for partials" do
45
+ comp.compile!
160
46
  File.exists?(DEST + "/partial1.html").should be_false
161
47
  File.exists?(DEST + "/partial2.html").should be_false
162
48
  File.exists?(DEST + "/partial3.html").should be_false
@@ -164,10 +50,7 @@ describe KComp do
164
50
 
165
51
  describe "generated files" do
166
52
  it "should contain any valid variable references" do
167
- File.read(DEST + "/inc1.html").should =~ /VAR 1/
168
- File.read(DEST + "/inc2.html").should =~ /VAR 2/
169
- File.read(DEST + "/somedir/inc3.html").should =~ /VAR 3/
170
- File.read(DEST + "/inc4.html").should =~ /VAR 4/
53
+ comp.compile!
171
54
  f = File.read(DEST + "/test-inclusion.html")
172
55
  f.should =~ /VAR 1/
173
56
  f.should =~ /VAR 2/
@@ -184,6 +67,7 @@ describe KComp do
184
67
  end
185
68
 
186
69
  it "should contain any inclusions" do
70
+ comp.compile!
187
71
  f = File.read(DEST + "/inc10.html")
188
72
  f.scan(/INCLUSION 11/).length.should == 1
189
73
  f.scan(/PARTIAL 3/).length.should == 1
@@ -216,11 +100,6 @@ describe KComp do
216
100
  f.scan(/VAR 12/).length.should == 1
217
101
  end
218
102
  end
219
-
220
- it "should strip out any repeated newlines" do
221
- f = File.read(DEST + "/test-inclusion.html")
222
- f.should_not =~ /\n\n+/
223
- end
224
103
  end
225
104
 
226
105
  end
@@ -229,7 +108,7 @@ describe KComp do
229
108
  describe "compile!" do
230
109
  it "should create a new KComp instance with the provided source and destination directories and delegate compilation thereto" do
231
110
  kcomp = mock('KComp')
232
- KComp.should_receive(:new).with('blah', 'hat').and_return kcomp
111
+ KComp.should_receive(:new).with('blah', 'hat', {}).and_return kcomp
233
112
  kcomp.should_receive(:compile!)
234
113
  KComp.compile!('blah', 'hat')
235
114
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kcomp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -157,17 +157,13 @@ files:
157
157
  - spec/support/test-src/_partial1.kit
158
158
  - spec/support/test-src/_partial2.kit
159
159
  - spec/support/test-src/_partial3.kit
160
- - spec/support/test-src/inc1.kit
161
160
  - spec/support/test-src/inc10.kit
162
161
  - spec/support/test-src/inc11.kit
163
162
  - spec/support/test-src/inc12.kit
164
- - spec/support/test-src/inc2.kit
165
- - spec/support/test-src/inc4.kit
166
163
  - spec/support/test-src/inc5.kit
167
164
  - spec/support/test-src/inc7.kit
168
165
  - spec/support/test-src/inc8.kit
169
166
  - spec/support/test-src/inc9.kit
170
- - spec/support/test-src/somedir/inc3.kit
171
167
  - spec/support/test-src/somedir/inc6.kit
172
168
  - spec/support/test-src/test-inclusion.kit
173
169
  homepage: http://github.com/awebneck/kcomp
@@ -185,7 +181,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
185
181
  version: '0'
186
182
  segments:
187
183
  - 0
188
- hash: 785217893617116794
184
+ hash: 2103192968802245187
189
185
  required_rubygems_version: !ruby/object:Gem::Requirement
190
186
  none: false
191
187
  requirements:
@@ -1,3 +0,0 @@
1
- INCLUSION 1
2
-
3
- <!-- @var1 -->
@@ -1,3 +0,0 @@
1
- INCLUSION 2
2
-
3
- <!--@var2-->
@@ -1,3 +0,0 @@
1
- INCLUSION 4
2
-
3
- <!--$var4-->
@@ -1,3 +0,0 @@
1
- INCLUSION 3
2
-
3
- <!-- $var3 -->