collin-fold 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.
- data/README +0 -0
- data/Rakefile.rb +18 -0
- data/lib/fold.rb +8 -0
- data/lib/fold/abstract_fold.rb +26 -0
- data/lib/fold/engine.rb +25 -0
- data/lib/fold/fold_factory.rb +52 -0
- data/lib/fold/precompiler.rb +52 -0
- data/rspec/fixtures/fold/fixture.target.fold +9 -0
- data/rspec/fold/abstract_fold_spec.rb +58 -0
- data/rspec/fold/engine_spec.rb +52 -0
- data/rspec/fold/fold_factory_spec.rb +66 -0
- data/rspec/fold/precompiler_spec.rb +108 -0
- data/rspec/fold_spec.rb +15 -0
- data/rspec/fold_spec_helper.rb +4 -0
- metadata +87 -0
data/README
ADDED
File without changes
|
data/Rakefile.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
|
4
|
+
namespace :spec do
|
5
|
+
task :prepare do
|
6
|
+
path = File.dirname(__FILE__)
|
7
|
+
p path
|
8
|
+
@specs= Dir.glob("#{path}/rspec/**/*.rb").join(' ')
|
9
|
+
end
|
10
|
+
|
11
|
+
task :all => :prepare do
|
12
|
+
system "spec #{@specs}"
|
13
|
+
end
|
14
|
+
|
15
|
+
task :doc => :prepare do
|
16
|
+
system "spec #{@specs} --format specdoc"
|
17
|
+
end
|
18
|
+
end
|
data/lib/fold.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Fold
|
4
|
+
class AbstractFold < OpenStruct
|
5
|
+
Regex= //
|
6
|
+
def initialize source={}
|
7
|
+
attrs= {
|
8
|
+
:text => '',
|
9
|
+
:children => [],
|
10
|
+
:tabs => -1
|
11
|
+
}.merge(source)
|
12
|
+
|
13
|
+
attrs[:text].gsub! self.class::Regex, ''
|
14
|
+
|
15
|
+
super attrs
|
16
|
+
end
|
17
|
+
|
18
|
+
def render
|
19
|
+
text
|
20
|
+
end
|
21
|
+
|
22
|
+
def render_children
|
23
|
+
children.map{|child| child.render}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/fold/engine.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Fold
|
2
|
+
class Engine
|
3
|
+
def initialize source
|
4
|
+
@source= source
|
5
|
+
prepare_source
|
6
|
+
end
|
7
|
+
|
8
|
+
def prepare_source
|
9
|
+
@prepared_source= true
|
10
|
+
end
|
11
|
+
|
12
|
+
def lines
|
13
|
+
@source.split(/\n/).reject{|line| line.blank?}
|
14
|
+
end
|
15
|
+
|
16
|
+
def render fold= precompiler.new.fold(lines)
|
17
|
+
fold.children.map{|child| child.render}
|
18
|
+
end
|
19
|
+
|
20
|
+
# *** me hard
|
21
|
+
def precompiler
|
22
|
+
@precompiler||= instance_eval "#{self.class.to_s.split(/::/).first}::Precompiler"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Fold
|
2
|
+
module FoldFactory
|
3
|
+
Indent= 2
|
4
|
+
class IndentationError < StandardError; end
|
5
|
+
|
6
|
+
def self.included klass
|
7
|
+
klass.extend ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
def produce line=''
|
11
|
+
tabs = count_soft_tabs(line)
|
12
|
+
line = line.sub(/^[ ]+/, '')
|
13
|
+
attrs= {
|
14
|
+
:text => line,
|
15
|
+
:tabs => tabs
|
16
|
+
}
|
17
|
+
|
18
|
+
if klass= detect_class(line)
|
19
|
+
klass.new attrs
|
20
|
+
else
|
21
|
+
AbstractFold.new attrs.merge(:tabs => -1)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def detect_class line
|
26
|
+
return nil if line.blank?
|
27
|
+
self.class.defined_folds.reverse.detect {|fold| fold::Regex and fold::Regex.match(line)}
|
28
|
+
end
|
29
|
+
|
30
|
+
def count_soft_tabs line
|
31
|
+
spaces= line.index(/([^ ]|$)/)
|
32
|
+
raise IndentationError if spaces.odd?
|
33
|
+
spaces / Indent
|
34
|
+
end
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
def folds id, regex=AbstractFold::Regex, &block
|
38
|
+
fold= Class.new(AbstractFold)
|
39
|
+
fold.const_set :Regex, regex
|
40
|
+
|
41
|
+
fold.send :define_method, :render, &block if block_given?
|
42
|
+
|
43
|
+
const_set id, fold
|
44
|
+
defined_folds << fold
|
45
|
+
end
|
46
|
+
|
47
|
+
def defined_folds
|
48
|
+
@folds||= []
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Fold
|
2
|
+
class Precompiler
|
3
|
+
include Fold::FoldFactory
|
4
|
+
|
5
|
+
def fold lines
|
6
|
+
last_line= produce
|
7
|
+
|
8
|
+
parent_line= nil
|
9
|
+
|
10
|
+
parent_stack= []
|
11
|
+
|
12
|
+
lines.each do |text|
|
13
|
+
line = produce text
|
14
|
+
|
15
|
+
indent = line.tabs - last_line.tabs
|
16
|
+
|
17
|
+
raise IndentationError if indent > 1
|
18
|
+
|
19
|
+
if step_in? indent
|
20
|
+
parent_line = last_line
|
21
|
+
parent_line.children << line
|
22
|
+
parent_stack << parent_line
|
23
|
+
end
|
24
|
+
|
25
|
+
if step_aside? indent
|
26
|
+
parent_line.children << line
|
27
|
+
end
|
28
|
+
|
29
|
+
if step_out? indent
|
30
|
+
parent_stack= parent_stack.slice 0, parent_stack.length + indent
|
31
|
+
parent_line = parent_stack.last
|
32
|
+
parent_line.children << line
|
33
|
+
end
|
34
|
+
|
35
|
+
last_line= line
|
36
|
+
end
|
37
|
+
parent_stack.first
|
38
|
+
end
|
39
|
+
|
40
|
+
def step_in? indent
|
41
|
+
indent == 1
|
42
|
+
end
|
43
|
+
|
44
|
+
def step_out? indent
|
45
|
+
indent < 0
|
46
|
+
end
|
47
|
+
|
48
|
+
def step_aside? indent
|
49
|
+
indent == 0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
require 'rspec/fold_spec_helper'
|
3
|
+
|
4
|
+
describe Fold::AbstractFold do
|
5
|
+
it "inherits OpenStruct" do
|
6
|
+
Fold::AbstractFold.superclass.should == OpenStruct
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Fold::AbstractFold, ".initialize" do
|
11
|
+
it "and sets the regex" do
|
12
|
+
Fold::Precompiler.folds :What, /what/
|
13
|
+
Fold::Precompiler::What::Regex.should == /what/
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Fold::AbstractFold, ".render" do
|
18
|
+
it "renders cleanly" do
|
19
|
+
fold= Fold::AbstractFold.new(:text=>"LINE")
|
20
|
+
fold.render.should == "LINE"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "renders from block" do
|
24
|
+
Fold::Precompiler.folds :What, /what/ do
|
25
|
+
"#{text}?"
|
26
|
+
end
|
27
|
+
|
28
|
+
what= Fold::Precompiler::What.new(:text=>'whatever')
|
29
|
+
what.render.should== "ever?"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "renders children" do
|
33
|
+
Fold::Precompiler.folds :Parent, /^parent / do
|
34
|
+
"Hey, #{text} here, my children are: #{render_children.join(', ')}"
|
35
|
+
end
|
36
|
+
|
37
|
+
Fold::Precompiler.folds :Child, /^child /
|
38
|
+
|
39
|
+
will= Fold::Precompiler::Parent.new(:text=>"Will")
|
40
|
+
will.children << Fold::Precompiler::Child.new(:text=>"Tony")
|
41
|
+
will.children << Fold::Precompiler::Child.new(:text=>"Ace")
|
42
|
+
|
43
|
+
will.render.should == "Hey, Will here, my children are: Tony, Ace"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe Fold::AbstractFold, ".render_children" do
|
48
|
+
it "renders cleanly" do
|
49
|
+
Fold::Precompiler.folds :Parent, /^parent /
|
50
|
+
Fold::Precompiler.folds :Child, /^child /
|
51
|
+
|
52
|
+
will= Fold::Precompiler::Parent.new(:text=>"Will")
|
53
|
+
will.children << Fold::Precompiler::Child.new(:text=>"Tony")
|
54
|
+
will.children << Fold::Precompiler::Child.new(:text=>"Ace")
|
55
|
+
|
56
|
+
will.render_children.should == ["Tony", "Ace"]
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rspec/fold_spec_helper'
|
2
|
+
|
3
|
+
describe Fold::Engine do
|
4
|
+
it "inherits Module" do
|
5
|
+
Fold::Engine.class.should == Class
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#initialize" do
|
9
|
+
before(:each) do
|
10
|
+
@path= "#{FoldFixtureRoot}/fixture.target.fold"
|
11
|
+
@engine= Fold::Engine.new File.read(@path)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "sets fold content" do
|
15
|
+
@engine.instance_variable_get(:@source).should == File.read(@path)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#prepare_fold" do
|
20
|
+
before(:each) do
|
21
|
+
@path= "#{FoldFixtureRoot}/fixture.target.fold"
|
22
|
+
@engine= Fold::Engine.new File.read(@path)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "prepares fold content" do
|
26
|
+
@engine.instance_variable_get(:@prepared_source).should_not be_nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#lines" do
|
31
|
+
it "splits on line breaks" do
|
32
|
+
lines= 10
|
33
|
+
src= "LINE\n" * lines
|
34
|
+
en= Fold::Engine.new src
|
35
|
+
en.lines.length.should == lines
|
36
|
+
end
|
37
|
+
|
38
|
+
it "rejects whitespace only lines" do
|
39
|
+
src= "LINE\n \nLINE\n\t\n\t\nwhatup?"
|
40
|
+
en= Fold::Engine.new src
|
41
|
+
en.lines.length.should == 3
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#render" do
|
46
|
+
it "renders spec" do
|
47
|
+
Fold::Precompiler.folds :Line, //
|
48
|
+
source= File.read "#{FoldFixtureRoot}/fixture.target.fold"
|
49
|
+
en= Fold::Engine.new source
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'rspec/fold_spec_helper'
|
2
|
+
|
3
|
+
class Included; include Fold::FoldFactory end
|
4
|
+
|
5
|
+
describe Fold::FoldFactory do
|
6
|
+
it "inherits module" do
|
7
|
+
Fold::FoldFactory.class.should == Module
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Fold::FoldFactory, ".count_soft_tabs" do
|
12
|
+
before(:each) {@it= Included.new}
|
13
|
+
|
14
|
+
it "counts one soft tabs" do
|
15
|
+
@it.count_soft_tabs(" LINE").should == 1
|
16
|
+
end
|
17
|
+
|
18
|
+
it "counts tree soft tabs" do
|
19
|
+
@it.count_soft_tabs(" " * 3 + "LINE").should == 3
|
20
|
+
end
|
21
|
+
|
22
|
+
it "raises IndentationError on odd spaced indentation" do
|
23
|
+
lambda {
|
24
|
+
@it.count_soft_tabs(" LINE")
|
25
|
+
}.should raise_error(Fold::Precompiler::IndentationError)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe Fold::FoldFactory, ".produce" do
|
30
|
+
before(:each) {@it= Included.new}
|
31
|
+
|
32
|
+
it "folds abstractly" do
|
33
|
+
@it.produce.is_a?(Fold::AbstractFold).should == true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "folds other folds" do
|
37
|
+
Included.folds :Location, /^\@/
|
38
|
+
@it.produce('@LINE').is_a?(Included::Location).should == true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
#describe Fold::Precompiler::Action::Regex do
|
45
|
+
# it "matches !LINE" do
|
46
|
+
# Fold::Precompiler::Action::Regex.should match("!LINE")
|
47
|
+
# end
|
48
|
+
#end
|
49
|
+
#
|
50
|
+
#describe Fold::Precompiler::Selector::Regex do
|
51
|
+
# it "matches ?LINE" do
|
52
|
+
# Fold::Precompiler::Selector::Regex.should match("?LINE")
|
53
|
+
# end
|
54
|
+
#end
|
55
|
+
#
|
56
|
+
#describe Fold::Precompiler::Group::Regex do
|
57
|
+
# it "matches describe LINE" do
|
58
|
+
# Fold::Precompiler::Group::Regex.should match("describe LINE")
|
59
|
+
# end
|
60
|
+
#end
|
61
|
+
#
|
62
|
+
#describe Fold::Precompiler::Example::Regex do
|
63
|
+
# it "matches it LINE" do
|
64
|
+
# Fold::Precompiler::Example::Regex.should match("it LINE")
|
65
|
+
# end
|
66
|
+
#end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'rspec/fold_spec_helper'
|
2
|
+
|
3
|
+
describe Fold::Precompiler do
|
4
|
+
it "inherits module" do
|
5
|
+
Fold::Precompiler.class.should == Class
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Confused < Fold::Precompiler
|
10
|
+
folds :Line, //
|
11
|
+
folds :What, /what/
|
12
|
+
end
|
13
|
+
|
14
|
+
describe Fold::Precompiler, ".folds" do
|
15
|
+
it "generates AbstractFold subclasses" do
|
16
|
+
Confused::What.superclass.should == Fold::AbstractFold
|
17
|
+
end
|
18
|
+
|
19
|
+
it "in the appropriate namespace" do
|
20
|
+
Confused::What.should_not be_nil
|
21
|
+
end
|
22
|
+
|
23
|
+
it "pushes to defined_folds" do
|
24
|
+
Confused.defined_folds.should include(Confused::What)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Fold::Precompiler, ".fold" do
|
29
|
+
before(:each) do
|
30
|
+
@it= Confused.new
|
31
|
+
end
|
32
|
+
|
33
|
+
it "has notion of top level" do
|
34
|
+
en= Fold::Engine.new %{
|
35
|
+
LINE 1
|
36
|
+
LINE 2
|
37
|
+
LINE 3
|
38
|
+
LINE 4
|
39
|
+
LINE 5
|
40
|
+
LINE 6
|
41
|
+
|
42
|
+
LINE 7
|
43
|
+
LINE 8
|
44
|
+
LINE 9
|
45
|
+
}
|
46
|
+
@it.fold(en.lines).children.length.should == 3
|
47
|
+
end
|
48
|
+
|
49
|
+
it "barfs on innappropriate indentation" do
|
50
|
+
en= Fold::Engine.new %{
|
51
|
+
LINE 1
|
52
|
+
LINE 2
|
53
|
+
}
|
54
|
+
lambda {
|
55
|
+
@it.fold(en.lines)
|
56
|
+
}.should raise_error(Confused::IndentationError)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe Fold::Precompiler, ".step_in?" do
|
61
|
+
before(:each) do
|
62
|
+
@it= Confused.new
|
63
|
+
end
|
64
|
+
|
65
|
+
it "must indent 1" do
|
66
|
+
@it.step_in?(1).should == true
|
67
|
+
end
|
68
|
+
|
69
|
+
it "no more" do
|
70
|
+
@it.step_in?(2).should == false
|
71
|
+
end
|
72
|
+
|
73
|
+
it "no less" do
|
74
|
+
@it.step_in?(0).should == false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe Fold::Precompiler, ".step_out?" do
|
79
|
+
before(:each) do
|
80
|
+
@it= Confused.new
|
81
|
+
end
|
82
|
+
|
83
|
+
it "must indent < 0" do
|
84
|
+
@it.step_out?(-1).should == true
|
85
|
+
end
|
86
|
+
|
87
|
+
it "cannot indent > 0" do
|
88
|
+
@it.step_out?(0).should == false
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe Fold::Precompiler, ".step_aside?" do
|
93
|
+
before(:each) do
|
94
|
+
@it= Confused.new
|
95
|
+
end
|
96
|
+
|
97
|
+
it "must indent 0" do
|
98
|
+
@it.step_aside?(0).should == true
|
99
|
+
end
|
100
|
+
|
101
|
+
it "no more" do
|
102
|
+
@it.step_aside?(1).should == false
|
103
|
+
end
|
104
|
+
|
105
|
+
it "no less" do
|
106
|
+
@it.step_aside?(-1).should == false
|
107
|
+
end
|
108
|
+
end
|
data/rspec/fold_spec.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rspec/fold_spec_helper'
|
2
|
+
|
3
|
+
describe Fold do
|
4
|
+
it "inherits Module" do
|
5
|
+
Fold.class.should == Module
|
6
|
+
end
|
7
|
+
|
8
|
+
it "has an Engine Class" do
|
9
|
+
Fold.constants.should include("Engine")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "has a precompiler class" do
|
13
|
+
Fold.constants.should include("Precompiler")
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: collin-fold
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Collin Miller
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-06-25 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: rspec
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: "0"
|
32
|
+
version:
|
33
|
+
description: A toolkit for creating whitespace active mini-languages. Inspired by Haml, light on features.
|
34
|
+
email: collintmiller@gmail.com
|
35
|
+
executables: []
|
36
|
+
|
37
|
+
extensions: []
|
38
|
+
|
39
|
+
extra_rdoc_files: []
|
40
|
+
|
41
|
+
files:
|
42
|
+
- README
|
43
|
+
- Rakefile.rb
|
44
|
+
- lib/fold
|
45
|
+
- lib/fold/fold_factory.rb
|
46
|
+
- lib/fold/precompiler.rb
|
47
|
+
- lib/fold/engine.rb
|
48
|
+
- lib/fold/abstract_fold.rb
|
49
|
+
- lib/fold.rb
|
50
|
+
- rspec/fold
|
51
|
+
- rspec/fold/precompiler_spec.rb
|
52
|
+
- rspec/fold/abstract_fold_spec.rb
|
53
|
+
- rspec/fold/engine_spec.rb
|
54
|
+
- rspec/fold/fold_factory_spec.rb
|
55
|
+
- rspec/fixtures
|
56
|
+
- rspec/fixtures/fold
|
57
|
+
- rspec/fixtures/fold/fixture.target.fold
|
58
|
+
- rspec/fold_spec.rb
|
59
|
+
- rspec/fold_spec_helper.rb
|
60
|
+
has_rdoc: false
|
61
|
+
homepage: http://github.com/collin/fold
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
requirements: []
|
80
|
+
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 1.2.0
|
83
|
+
signing_key:
|
84
|
+
specification_version: 2
|
85
|
+
summary: A toolkit for creating whitespace active mini-languages. Inspired by Haml, light on features.
|
86
|
+
test_files: []
|
87
|
+
|