md_inc 0.2.9 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- md_inc (0.2.6)
4
+ md_inc (0.2.9)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -16,6 +16,11 @@ Or install it yourself as:
16
16
 
17
17
  $ gem install md_inc
18
18
 
19
+ **Note that with version 0.3.0 the API for adding
20
+ new commands has changed. You command methodss
21
+ should be ordinary methods, not module methods
22
+ as before.**
23
+
19
24
  ## Usage
20
25
 
21
26
  MdInc is a simple text inclusion filter intended for use
@@ -61,7 +66,22 @@ And you can exclude lines based on a regular expression:
61
66
  lines that contain DONTWANT
62
67
  .skip(/DONTWANT/, inc('file1'))
63
68
 
64
- As you can probably guess from this last example,
69
+ Along with .commands there are also ..commands. The
70
+ difference is that ..command can handle inline text.
71
+ Here's an example that makes all the lines uppercase:
72
+
73
+ ..upcase_content
74
+ some text
75
+ that will
76
+ become uppercase
77
+ ..end
78
+
79
+ If your command starts with an .., md\_inc will gather up
80
+ all of the following lines until it hits a ..end and
81
+ makes those lines available to the command via the
82
+ `content` method.
83
+
84
+ As you can probably guess from the examples,
65
85
  the MdInc dot commands are really just inline Ruby
66
86
  code that gets executed during file processing.
67
87
  Because of this it's easy to extend MdInc with
@@ -1,6 +1,5 @@
1
1
  module MdInc
2
2
  module Commands
3
- class << self
4
3
  def root(path)
5
4
  @root = path
6
5
  end
@@ -9,15 +8,64 @@ module MdInc
9
8
  @root ? File.join(@root, path) : path
10
9
  end
11
10
 
11
+ def content
12
+ @content
13
+ end
14
+
15
+ def process_file(file_name)
16
+ process(File.read(file_name))
17
+ end
18
+
12
19
  def process(content)
13
20
  output = process_lines(content.split("\n"))
14
21
  output.flatten.join("\n")
15
22
  end
16
23
 
17
24
  def process_lines(lines)
18
- lines.map do |line|
19
- (line.length > 1 && line[0] == '.') ? instance_eval(line[1..-1]) : line
25
+ result = []
26
+ until lines.empty?
27
+ line = lines.shift
28
+ ltype = line_type(line)
29
+
30
+ if ltype == :multi_line_cmd
31
+ result +=process_multiline_cmd(line, lines)
32
+ elsif ltype == :single_line_cmd
33
+ result << process_single_line_cmd(line)
34
+ else
35
+ result << line
36
+ end
20
37
  end
38
+ result
39
+ end
40
+
41
+ def line_type(line)
42
+ if %{. ..}.include?(line)
43
+ :text
44
+ elsif line[0,2] == '..'
45
+ :multi_line_cmd
46
+ elsif line[0,1] == '.'
47
+ :single_line_cmd
48
+ else
49
+ :text
50
+ end
51
+ end
52
+
53
+ def process_single_line_cmd(line)
54
+ #puts "single line cmd: #{line}"
55
+ instance_eval(line[1..-1])
56
+ end
57
+
58
+ def process_multiline_cmd(line, lines)
59
+ content_lines = []
60
+ until lines.empty? || (lines.first =~ /^..end/)
61
+ content_lines << lines.shift
62
+ end
63
+ lines.shift unless lines.empty?
64
+ save_content = @content
65
+ @content = content_lines
66
+ result = instance_eval(line[2..-1])
67
+ @content = @save_content
68
+ result
21
69
  end
22
70
 
23
71
  def x(*args)
@@ -42,7 +90,7 @@ module MdInc
42
90
  if language.nil?
43
91
  lines.map {|l| l.rstrip.prepend(' ')}
44
92
  else
45
- ["```#{language}"] + lines + ["```"]
93
+ ["```#{language}"] + lines + ["```"]
46
94
  end
47
95
  end
48
96
 
@@ -75,6 +123,10 @@ module MdInc
75
123
  lines.map {|l| l[min_indent..-1]}
76
124
  end
77
125
 
126
+ def upcase_content
127
+ content.map {|l| l.upcase}
128
+ end
129
+
78
130
  private
79
131
 
80
132
  def min_indent(lines)
@@ -85,6 +137,6 @@ module MdInc
85
137
  def indent_depth(s)
86
138
  /^ */.match(s).end(0)
87
139
  end
140
+
88
141
  end
89
- end
90
142
  end
@@ -1,3 +1,3 @@
1
1
  module MdInc
2
- VERSION = "0.2.9"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/md_inc.rb CHANGED
@@ -1,22 +1,32 @@
1
1
  require 'md_inc/version'
2
2
  require 'md_inc/md_inc_commands'
3
+ require 'ostruct'
3
4
 
4
5
  module MdInc
5
6
  class TextProcessor
6
- def root(path)
7
- Commands.root(path)
7
+ attr_accessor :root
8
+
9
+ def initialize(options={})
10
+ @options = options
8
11
  end
9
12
 
10
13
  def process(string)
11
- Commands.process(string)
14
+ context = OpenStruct.new(@options)
15
+ context.root = root
16
+ context.options = @options
17
+ context.extend Commands
18
+ if @options[:modules]
19
+ @options[:modules].each {|m| context.extend m}
20
+ end
21
+ context.process(string)
12
22
  end
13
23
 
14
24
  def process_stream(stream)
15
- Commands.process(stream.read)
25
+ process(stream.read)
16
26
  end
17
27
 
18
28
  def process_file(path)
19
- Commands.process(File.read(path))
29
+ process(File.read(path))
20
30
  end
21
31
  end
22
32
  end
data/spec/md_inc_spec.rb CHANGED
@@ -2,14 +2,20 @@ require 'md_inc'
2
2
  require 'fileutils'
3
3
 
4
4
  describe MdInc::Commands do
5
+ let(:context) do
6
+ o = Object.new
7
+ o.extend MdInc::Commands
8
+ o
9
+ end
10
+
5
11
  context '#code' do
6
12
  it 'uses git style tagging if a language is supplied' do
7
- output = MdInc::Commands.code("java", %w{foo})
13
+ output = context.code("java", %w{foo})
8
14
  output.should == [ "```java", "foo", "```"]
9
15
  end
10
16
 
11
17
  it 'uses traditional code indenting if a language is not supplied' do
12
- output = MdInc::Commands.code(nil, %w{foo})
18
+ output = context.code(nil, %w{foo})
13
19
  output.should == [ " foo"]
14
20
  end
15
21
  end
@@ -18,12 +24,12 @@ describe MdInc::Commands do
18
24
  let(:lines) { %w{foo skip1 skip2 bar skip3 baz skip4 skip5} }
19
25
 
20
26
  it 'skips the lines that match the regular expression' do
21
- output = MdInc::Commands.skip(/skip/, lines)
27
+ output = context.skip(/skip/, lines)
22
28
  output.should == %w{foo bar baz}
23
29
  end
24
30
 
25
31
  it 'doesnt skip the lines that down match the regular expression' do
26
- output = MdInc::Commands.skip(/no match/, lines)
32
+ output = context.skip(/no match/, lines)
27
33
  output.should == lines
28
34
  end
29
35
  end
@@ -32,12 +38,12 @@ describe MdInc::Commands do
32
38
  let(:lines) { %w{aaa bbb ccc ddd eee} }
33
39
 
34
40
  it 'returns the lines between the patterns, exclusive' do
35
- output = MdInc::Commands.between(/aaa/, /ddd/, lines)
41
+ output = context.between(/aaa/, /ddd/, lines)
36
42
  output.should == %w{bbb ccc}
37
43
  end
38
44
 
39
45
  it 'will skip the whole output if first re doesnt match' do
40
- output = MdInc::Commands.between(/no match/, /ccc/, lines)
46
+ output = context.between(/no match/, /ccc/, lines)
41
47
  output.should == []
42
48
  end
43
49
  end
@@ -45,24 +51,33 @@ describe MdInc::Commands do
45
51
  context '#normalize_indent' do
46
52
  it 'does nothing to non-indented lines' do
47
53
  lines = %w{aaa, bbb, ccc}
48
- output = MdInc::Commands.normalize_indent(lines)
54
+ output = context.normalize_indent(lines)
49
55
  output.should == lines
50
56
  end
51
57
 
52
58
  it 'does nothing to lines with at least one non-indented line' do
53
59
  lines = [' aaa', 'bbb', ' ccc']
54
- output = MdInc::Commands.normalize_indent(lines)
60
+ output = context.normalize_indent(lines)
55
61
  output.should == lines
56
62
  end
57
63
 
58
64
  it 'unindents so that the least indented line has no indent' do
59
65
  lines = [' aaa', ' bbb', ' ccc']
60
- output = MdInc::Commands.normalize_indent(lines)
66
+ output = context.normalize_indent(lines)
61
67
  output.should == ['aaa', ' bbb', ' ccc']
62
68
  end
63
69
 
64
70
  end
71
+ end
72
+
73
+ module TestModule
74
+ def test_cmd
75
+ ['line 1 from module', 'line 2 from module']
76
+ end
65
77
 
78
+ def return_option(name)
79
+ [options[name]]
80
+ end
66
81
  end
67
82
 
68
83
  describe MdInc::TextProcessor do
@@ -141,7 +156,39 @@ describe MdInc::TextProcessor do
141
156
  it 'can do recursive inclusion' do
142
157
  text = "first\n.inc 'temp3'\nlast"
143
158
  output = mdi.process(text)
144
- output.should == "first\ntemp3 line1\naaa\nbbb\ntemp3 line3\nlast"
159
+ output.should == "first\ntemp3 line1\naaa\nbbb\ntemp3 line3\nlast"
160
+ end
161
+
162
+ it 'can optionally include other modules for commands' do
163
+ processor = MdInc::TextProcessor.new :modules => [TestModule]
164
+ text = "first\n.test_cmd\nlast"
165
+ output = processor.process(text)
166
+ output.should == "first\nline 1 from module\nline 2 from module\nlast"
167
+ end
168
+
169
+ it 'can asscess the options hash from inside of a command' do
170
+ processor = MdInc::TextProcessor.new :modules => [TestModule], :color => "GREEN"
171
+ text = "first\n.return_option :color\nlast"
172
+ output = processor.process(text)
173
+ output.should == "first\nGREEN\nlast"
174
+ end
175
+
176
+ it 'has a working multiline example command in upcase_content' do
177
+ text = "first\n..upcase_content\naaa\nbbb\nccc\n..end\nlast"
178
+ output = mdi.process(text)
179
+ output.should == "first\nAAA\nBBB\nCCC\nlast"
180
+ end
181
+
182
+ it 'handles multiline commands correctly' do
183
+ text = ".x require 'new_commands'\nfirst\n..multi_up\naaa\nbbb\n..end\nccc"
184
+ output = mdi.process(text)
185
+ output.should == "first\nAAA\nBBB\nccc"
186
+ end
187
+
188
+ it 'handles .. as text, not as a multiline command' do
189
+ text = "\nfirst\n..\nlast"
190
+ output = mdi.process(text)
191
+ output.should == text
145
192
  end
146
193
  end
147
194
  end
data/spec/new_commands.rb CHANGED
@@ -4,8 +4,12 @@
4
4
  # module and off you go.
5
5
  module MdInc
6
6
  module Commands
7
- def self.inc_up(path)
7
+ def inc_up(path)
8
8
  inc(path).map {|s| s.upcase!}
9
9
  end
10
+
11
+ def multi_up
12
+ content.map {|l| l.upcase}
13
+ end
10
14
  end
11
15
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: md_inc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.9
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-11 00:00:00.000000000 Z
12
+ date: 2013-03-16 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: MdInc is a simple text inclusion utility (it sucks in files) intended
15
15
  for use with markdown and similar utilities.