ntxt 1.0.0 → 1.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.
@@ -0,0 +1,63 @@
1
+
2
+ = About
3
+
4
+ Ntxt is a simple text format that defines hierarchical blocks of text
5
+ and tags on those blocks. The goal is to give the author an easy way
6
+ to search their text in a slightly more structured way than +grep+ 'ing.
7
+
8
+ Any tags found in a block are extracted and the block is _tagged_ with them.
9
+ All parent blocks also receive the tags of their child blocks. Thus, the
10
+ root block is tagged with all tags occuring in the document.
11
+
12
+ == Format Rules
13
+ === Headers
14
+
15
+ Header lines look like something you would see out of a wiki.
16
+
17
+ = Header 1 =
18
+ == Header 2 ==
19
+ = Another Header 1 =
20
+
21
+ Header 1 is the largest and highest header. All text after it, aside from
22
+ another 1-header, will be considered a sub-block. In the example
23
+ "Header 1" and "Another Header 1" are the two top-level blocks. "Header 2" is
24
+ a child of "Header 1".
25
+
26
+ === Indentation
27
+
28
+ Indentation also forms blocks.
29
+
30
+ = Header 1 =
31
+ == Header 2 ==
32
+ Sub block of header 2.
33
+ Sub block of the preceding line.
34
+ Another block below header 2.
35
+ = Another Header 1 =
36
+
37
+ In the above example Header 2 has 1 sub-block because there is an indentation
38
+ of 2-spaces with an intermediate indentation of 4-spaces. That 4-space line
39
+ is bundled into a subblock to the 2-space indented block of text.
40
+
41
+ The only ways to break out of this 2-indent text is to:
42
+
43
+ 1. Put in an empty line.
44
+ 2. Put in a header.
45
+ 3. Indent more shallowly, such as a 1-space line.
46
+
47
+ === Tags
48
+
49
+ Lines beginning with [tag1] [tag2] are considered to have tags
50
+ +tag1+ and +tag2+. For example:
51
+
52
+ Block1
53
+ [block 1 tag] [example]
54
+
55
+ [this is tag] Block2 [not a tag]
56
+ [block 2 tag] [example]
57
+
58
+ Notice, tag names may have spaces. Both blocks are tagged with +example+.
59
+ And finally, <code>not a tag</code> is, well, not a tag. It does not start a line.
60
+
61
+ Also note that you can't tag header blocks directly because the header line
62
+ must start with = and tag lines must begin with [. Blocks inherit all their
63
+ child blocks' tags, though, so finding header blocks by tags is still possible.
data/bin/ntxt CHANGED
@@ -27,7 +27,13 @@ OptionParser.new do |opt|
27
27
  $configs[:cmd] = 'tag'
28
28
  $configs[:tag_string] = v
29
29
  end
30
-
30
+
31
+ opt.on('-l', '--last=[Integer]',
32
+ 'Show the last n top-level blocks. Default is 1') do |v|
33
+ $configs[:cmd] = 'last'
34
+ $configs[:last] = (v.nil?)? 1 : v.to_i
35
+ end
36
+
31
37
  opt.on('-s','--search=String', 'Search the text for.' ) do |v|
32
38
  $configs[:cmd] = 'search'
33
39
  $configs[:search_string] = v
@@ -41,9 +47,10 @@ else
41
47
  exit 1
42
48
  end
43
49
 
50
+ # Remove empty lines from blocks and print. Guards against nils and empty lines.
44
51
  def printNonEmpty(txt)
45
52
  if txt
46
- txt = txt.strip
53
+ txt = txt.gsub(/^\s*$/m, '')
47
54
  print txt, "\n" if txt.length > 0
48
55
  end
49
56
  end
@@ -55,11 +62,11 @@ ntxt = File.open($configs[:filename]) { |io| Ntxt::Ntxt.new(io.read) }
55
62
  case $configs[:cmd]
56
63
  when 'print_tags'
57
64
  # Notice that we are re-wrapping the tags back into square brackets.
58
- puts "[#{ntxt.rootBlock.tags.sort.join('] [')}]"
65
+ puts "[#{ntxt.rootBlock.tags.keys.sort.join('] [')}]"
59
66
  when 'tag'
60
67
  ntxt.walkText(
61
68
  lambda { |txt, depth, block|
62
- printNonEmpty txt if block.tags.join(', ').index( $configs[:tag_string])},
69
+ printNonEmpty txt if block.tags.keys.sort.join(', ').index( $configs[:tag_string])},
63
70
  lambda { |depth, block| },
64
71
  lambda { |depth, block| } )
65
72
  when 'search'
@@ -73,11 +80,17 @@ when 'print'
73
80
  lambda { |txt, depth, block| print txt },
74
81
  lambda { |depth, block| },
75
82
  lambda { |depth, block| } )
83
+ when 'last'
84
+ ntxt.rootBlock.children[-$configs[:last].. -1].each do |blk|
85
+ puts blk.text
86
+ end
76
87
  when 'trace'
77
88
  ntxt.walkText(
78
89
  lambda { |txt, depth, block| print txt },
79
- lambda { |depth, block| puts "-----> #{depth} #{block.tags.join(',')}" },
80
- lambda { |depth, block| puts "<----- #{depth} " } )
90
+ lambda { |depth, block|
91
+ puts "-----> #{depth} #{block.tags.keys.sort.join(',')}" },
92
+ lambda { |depth, block|
93
+ puts "<----- #{depth} " } )
81
94
  when ''
82
95
  # nop
83
96
  when nil
@@ -1,3 +1,8 @@
1
1
  require 'ntxt/block'
2
2
  require 'ntxt/parser'
3
3
  require 'ntxt/ntxt'
4
+
5
+ # Ntxt module.
6
+ # See Ntxt::Parser and Ntxt::Block.
7
+ module Ntxt
8
+ end
@@ -10,21 +10,35 @@ module Ntxt
10
10
  # ONLY contain subblocks.
11
11
  class Block
12
12
 
13
- attr_accessor :children, :tags, :start, :offset, :ntxt, :parent
13
+ # A list of child Blcoks.
14
+ attr_accessor :children
15
+
16
+ # A hash of all tags of this block and its children.
17
+ attr_accessor :tags
18
+
19
+ # The +start+ index in the text string held in the Ntxt parent object.
20
+ # See the +ntxt+ field.
21
+ attr_accessor :start
22
+
23
+ # The offset from the +start+ field.
24
+ attr_accessor :offset
25
+
26
+ # The Ntxt object.
27
+ attr_accessor :ntxt
28
+
29
+ # The parent Block or nil if this is a root Block.
30
+ attr_accessor :parent
14
31
 
15
- if RUBY_VERSION =~ /^1.8/
16
- def self.blockReMatch(re, txt, offset)
17
- re.match(txt[offset..-1])
18
- end
19
- else
20
- def self.blockReMatch(re, txt, offset)
21
- re.match(text, offset)
22
- end
23
- end
24
-
32
+ # Create a new Block. Typically you will never need to do this.
33
+ # Blocks are created by Parser.
34
+ # [ntxtObj] The Ntxt object that this block belongs to.
35
+ # The Ntxt object holds the text this block will reference.
36
+ # [parentBlock] The parent block. Nil by default.
37
+ # [startTxt] The staring character in Ntxt.text.
38
+ # [stopTxt] The initial offset. If nil this is set to ntxtObj.text.length.
25
39
  def initialize(ntxtObj, parentBlock=nil, startTxt=0, stopTxt=0)
26
40
  @children = []
27
- @tags = []
41
+ @tags = Hash.new(0)
28
42
  @start = startTxt
29
43
  @offset = stopTxt || ntxtObj.text.length
30
44
  @ntxt = ntxtObj
@@ -45,31 +59,64 @@ module Ntxt
45
59
  end
46
60
  end
47
61
 
62
+ # Add a tag to this block and all ancestor blocks.
48
63
  def addTag(tag)
49
- @tags.push(tag)
64
+ @tags[tag] += 1
50
65
  @parent.addTag(tag) if @parent
51
66
  end
52
-
67
+
68
+ # Return the text slice that this block refers to.
69
+ # Note that parent blocks include their child blocks' text.
53
70
  def text
54
71
  @ntxt.text[@start, @offset]
55
72
  end
56
73
 
74
+ # Return true if the parent object is nil.
57
75
  def is_root?
58
- @parent
76
+ @parent.nil?
59
77
  end
60
78
 
79
+ # Given a block this will first call that block with this Block as
80
+ # the only argument. Then walk is recusively called on all child Blocks.
61
81
  def walk(&y)
62
82
  yield self
63
83
  @children.each { |c| c.walk(&y) }
64
84
  end
65
85
 
66
- # printFunc is a lambda that takes the text, depth, and the node.
67
- # enterChild is a lambda that takes depth and the node.
68
- # exitChild is a lambda that takes depth and the node.
86
+ # This method handles the complexity of handing the user
87
+ # the text immediately handled by each block.
88
+ #
89
+ # If you call Block.text you will get a contiguous block of text
90
+ # that covers this Block and all its children. Essentially the +start+
91
+ # to the +offset+ substring of Ntxt.text.
92
+ #
93
+ # What this method does is pass each text that belongs only to
94
+ # the particular Block in question and the children. The text
95
+ # is passed to the user in order, so concatinating it would
96
+ # result in equivalent output to Block.text.
97
+ #
98
+ # This method is useful for visualizing the text structure
99
+ # or filtering out blocks that aren't interesting to the user.
100
+ #
101
+ # [printFunc] A lambda that takes the text, depth, and the Block.
102
+ # [enterChild] A lambda that takes depth and the Block.
103
+ # [exitChild] A lambda that takes depth and the Block.
104
+ # For example:
105
+ #
106
+ # printBlock = lambda { |text, depth, block| ... }
107
+ # enterBlock = lambda { |depth, block| ... }
108
+ # exitBlock = lambda { |depth, block| ... }
109
+ #
110
+ # block.walkText( printBlock, enterBlock, exitBlock )
111
+ #
69
112
  def walkText(printFunc, enterChild, exitChild)
70
113
  walkTextHelper(printFunc, enterChild, exitChild, 0)
71
114
  end
72
115
 
116
+ protected
117
+
118
+ # Helper function for walkText. Takes the same arguments
119
+ # with the depth set to 0.
73
120
  def walkTextHelper(printFunc, enterChild, exitChild, depth)
74
121
  enterChild.call(depth, self)
75
122
 
@@ -95,5 +142,25 @@ module Ntxt
95
142
 
96
143
  exitChild.call(depth, self)
97
144
  end
145
+
146
+ private
147
+
148
+ if RUBY_VERSION =~ /^1.8/
149
+
150
+ # Regular expression matcher with an offset.
151
+ # The implementation of this is descided at runtime depending on
152
+ # if Ruby 1.9's new RE match method is found.
153
+ def self.blockReMatch(re, txt, offset)
154
+ re.match(txt[offset..-1])
155
+ end
156
+ else
157
+
158
+ # Regular expression matcher with an offset.
159
+ # The implementation of this is descided at runtime depending on
160
+ # if Ruby 1.9's new RE match method is found.
161
+ def self.blockReMatch(re, txt, offset)
162
+ re.match(txt, offset)
163
+ end
164
+ end
98
165
  end
99
166
  end
@@ -1,24 +1,25 @@
1
1
 
2
2
  module Ntxt
3
3
 
4
- # Root class that contains the text array that Blocks reference
5
- # and the root block.
4
+ # Root class that contains the text array that Block objects reference.
6
5
  class Ntxt
7
- attr_accessor :text, :rootBlock
8
6
 
7
+ # The raw text file. This is a String.
8
+ attr_accessor :text
9
+
10
+ # The root Block. It will contain all tags in the document
11
+ # and has a Block.start of 0 and a Block.offset of #text.length.
12
+ attr_accessor :rootBlock
13
+
14
+ # Create a new Ntxt object. This requires a String that is the text
15
+ # of the object.
16
+ # ntxt = Ntxt::Ntxt.new( File.open('n.txt'){ |io| io.read } )
9
17
  def initialize(text)
10
18
  @text = text
11
19
  @rootBlock = (Parser.new).parse(self)
12
20
  end
13
21
 
14
- # walkText(print, enter, exit)
15
- # Walk the ntxt tree with 3 callbacks, print, enter, and exit.
16
- # Print is a lambda that takes the text, the depth, and a copy of
17
- # the Ntxt::Block it is in.
18
- # Enter is the same, but is called with no text argument and is called
19
- # when a block is entered (that is, the depth has increased by 1).
20
- # Exit is the same, but is called with no text argument and is called
21
- # when a block is exited (that is, the depth has decreated by 1).
22
+ # Calls Block#walkText.
22
23
  def walkText(print, enter, exit)
23
24
  @rootBlock.walkText(print, enter, exit)
24
25
  end
@@ -1,98 +1,126 @@
1
1
  require 'ntxt/block'
2
+ require 'ntxt/ntxt'
2
3
 
3
4
  module Ntxt
5
+
6
+ # The parser for Ntxt. Most of this a typical user will not find useful
7
+ # with the exception of Parser.parse.
4
8
  class Parser
5
9
 
6
- ###########################################################################
10
+ # An internal class that contains the current parse position
11
+ # and current limits on that parse, such as an artificial end-of-file
12
+ # marker to terminate a sub-parsing of a sub-block.
7
13
  class State
8
14
 
9
- attr_accessor :lines, :block, :lineStart, :lineEnd, :line, :start, :offset
15
+ # Array of lines. The result of Ntxt.text being split on '\n'
16
+ attr_accessor :lines
17
+
18
+ # The current Block being built up.
19
+ attr_accessor :block
20
+
21
+ # The index into #lines to start parsing at
22
+ # and before which #prevLine should return nil.
23
+ attr_accessor :lineStart
24
+
25
+ # The index into #lines at which #nextLine should return nil.
26
+ # This defaults to #lines.length
27
+ attr_accessor :lineEnd
28
+
29
+ # The current line this State points at.
30
+ attr_accessor :line
31
+
32
+ # The index into Ntxt.text that corresponds to the first
33
+ # character of the #currLine.
34
+ attr_accessor :start
35
+
36
+ # The offset from #start. The substring of Ntxt.text
37
+ # starting at #start and of length #offset will produce the
38
+ # text being considered by this State.
39
+ attr_accessor :offset
10
40
 
11
41
  def initialize(lines, block, lineStart, start, lineEnd)
12
- @lines = lines
13
- @block = block
14
- @lineStart = lineStart
15
- @lineEnd = lineEnd
16
- @line = lineStart
17
- @start = start
18
- @offset = 0
42
+ @lines = lines # The array of lines to parse.
43
+ @block = block # The block this state is operating on.
44
+ @lineStart = lineStart # The starting line in this state.
45
+ @line = lineStart # The current line this state points at.
46
+ @lineEnd = lineEnd # The last line. @lineEnd <= @lines.length.
47
+ @start = start # Start index in text.
48
+ @offset = 0 # Offset from @start.
19
49
  end
20
50
 
21
- # Return the current line.
51
+ # Return the current line. If #prevLine or #nextLine has
52
+ # walked outside of the #lineStart or #lineEnd limits this will
53
+ # return nil.
22
54
  def currLine
23
- @lines[@line]
55
+ if @line < @lineEnd && @line >= @lineStart
56
+ @lines[@line]
57
+ else
58
+ nil
59
+ end
24
60
  end
25
61
 
26
- # Shift the state to the next line and return that line.
27
- # If this goes out of bounds of the text nil is returned.
62
+ # Return the next line (#line + 1) unless we step beyond #lineEnd.
63
+ # If we exceed #lineEnd, nil is returned.
64
+ # Notice that this also updates #offset.
28
65
  def nextLine
29
- nextLine = @line+1
30
- if nextLine < @lineEnd
31
- nextOffset = @offset + @lines[@line].length + 1
32
- @offset = nextOffset
33
- @line = nextLine
34
- @lines[nextLine]
35
- else
66
+
67
+ # If we are already past the end, return nil, do nothing.
68
+ if @line >= @lineEnd
36
69
  nil
37
- end
70
+
71
+ # Otherwise we are updating some state.
72
+ else
73
+ @offset = @offset + @lines[@line].length + 1
74
+ @line = @line + 1
75
+
76
+ # Recheck if we are inside the array and return nil if we are not.
77
+ (@line < @lineEnd) ? @lines[@line] : nil
78
+ end
38
79
  end # nextLine
39
80
 
40
- # Shift the state to the previous line and return that line.
41
- # If this goes out of bounds of the text nil is returned.
81
+ # Return the previous line (#line - 1) unless we step before #lineStart.
82
+ # If we exceed #lineStart, nil is returned.
83
+ # Notice that this also updates #offset.
42
84
  def prevLine
43
- nextLine = @line - 1
44
- if nextLine >= @lineStart
45
- nextOffset = @offset - @lines[nextLine].length - 1
46
- @offset = nextOffset
47
- @line = nextLine
48
- @lines[nextLine]
49
- else
85
+ if @line < @lineStart
50
86
  nil
87
+ else
88
+ nLine = @line - 1
89
+ @offset = @offset - @lines[nLine].length - 1
90
+ @line = nLine
91
+ @lines[nLine]
51
92
  end
52
93
  end # prevLine
53
94
 
54
95
  # Shift the state starting points to the current position of
55
96
  # what has been read in this state, effecitvely consuming that input.
97
+ #
98
+ # The #start field is moved to #start+offset. The #offset is set to 0.
99
+ # Finally the #lineStart is set to #line.
56
100
  def consume
57
101
  @start = @start + @offset
58
102
  @offset = 0
59
103
  @lineStart = @line
60
104
  end
61
105
 
62
- # Create a new state that is framed from the lineStart+1 of this state
63
- # and ends at the current line of the given state.
64
- def lowerSubState
65
- endOfFrame = @line+1
66
-
67
- endOfFrame = @lineEnd if endOfFrame > @lineEnd
68
-
69
- State.new(@lines,
70
- @block,
71
- @lineStart+1,
72
- @start + @lines[@lineStart].length + 1,
73
- endOfFrame)
74
- end # lowerSubState
75
-
76
- # Create a new state that is framed with the remaining contents of
77
- # this state
78
- def upperSubState
79
- State.new(@lines, @block, @line, @start + @offset, @lineEnd)
80
- end
81
-
106
+ # Print as a string.
82
107
  def to_s
83
108
  "lineStart: %s, lineEnd: %s, line: %s, start: %s, offset: %s"%[
84
109
  @lineStart, @lineEnd, @line, @start, @offset
85
110
  ]
86
111
  end
87
112
 
88
- # Seek this state's position to the tiven state's position.
113
+ # Seek this state's position forward to the given state's position.
114
+ # If a state with a position behind the current state's position is
115
+ # passed in as an argument the behavior is undefined.
89
116
  def seek(state)
90
117
  @line = state.line
91
118
  @offset = (state.start + state.offset - @start).abs()
92
119
  end # seek
93
120
 
94
121
  end # Parser::State
95
- ###########################################################################
122
+
123
+
96
124
 
97
125
  # Return an array in which the first element is the indent length and
98
126
  # the second element is the contained text. Nil otherwise.
@@ -115,6 +143,17 @@ module Ntxt
115
143
  end
116
144
  end # self.hlevel
117
145
 
146
+ # Extract all the tags from the given line.
147
+ # [block] The block to which all tags will be added with Block#addTag.
148
+ # All parent blocks recieve copies of the child block's tag.
149
+ # [line] The line to extract all tags from. Tags are
150
+ # square-bracket-enclosed strings found in sequence at the
151
+ # beginning of a line. If the sequence is broken, extraction stops.
152
+ # Some tag examples:
153
+ # [a tag] [another tag]
154
+ # [a tag] [another tag] Not a tag. [not a tag]
155
+ # No tag on this line.
156
+ # No tag on this line either. [not a tag]
118
157
  def self.extractTags(block, line)
119
158
  while line =~ /^\s*\[([^\[]+)\]/m
120
159
  block.addTag($~[1])
@@ -123,6 +162,10 @@ module Ntxt
123
162
  end
124
163
  end # self.extractTags
125
164
 
165
+ # Parse the given Ntxt 's Ntxt#text.
166
+ # [ntxtObj] If this is an Ntxt object, Ntxt#text is parsed.
167
+ # If +ntxtObj+ is not an Ntxt object, it is assumed to be
168
+ # a valid argument for Ntxt.new and a new Ntxt is constructed.
126
169
  def parse(ntxtObj)
127
170
 
128
171
  # If ntxtObj isn't an Ntxt, create it as one.
@@ -144,60 +187,87 @@ module Ntxt
144
187
  nil
145
188
  end
146
189
  end # parse(ntxtObj)
147
-
190
+
191
+ # Take the state off the top of the #stack and attempt to parse
192
+ # an Hlevel block. An HLevel block is a wiki-like header block of text.
193
+ # For example:
194
+ # = Header 1 =
195
+ # == Header 2 ==
196
+ # [level] an integer from 1 to 6.
197
+ # [title] a string of the text found between the equal signs.
148
198
  def parseHlevel(level, title)
149
199
  state = @stack[-1]
150
200
 
151
- begin
152
- line = state.nextLine
201
+ # If in parseHlevel, don't get the current line. That is contained
202
+ # in the title argument. Instead, get the next line and proceed.
203
+ line = state.nextLine
204
+
205
+ while line
206
+ # Check if we have discovered another block in the form of an hlevel.
207
+ hl = Parser::hlevel(line)
153
208
 
154
- if line
155
- hl = Parser::hlevel(line)
156
-
157
- if hl && hl[0].to_i <= level
158
- state.prevLine # Rewind. We steped onto another h block.
159
- break
160
- end
209
+ if hl && hl[0].to_i <= level
210
+ break
161
211
  end
162
- end while line
212
+
213
+ line = state.nextLine
214
+ end
215
+
216
+ block = Block.new(
217
+ state.block.ntxt,
218
+ state.block,
219
+ state.start,
220
+ state.offset)
221
+
222
+ subState = State.new(
223
+ state.lines,
224
+ block,
225
+ state.lineStart+1,
226
+ state.start + state.lines[state.lineStart].length + 1,
227
+ state.line)
163
228
 
164
- block = Block.new(state.block.ntxt,
165
- state.block,
166
- state.start,
167
- state.offset)
168
- subState = state.lowerSubState
169
- subState.block = block
170
229
  @stack.push subState
171
230
  parseLines
172
231
  @stack.pop
173
232
  state.consume
174
233
  end # parseHlevel(leve, title)
175
234
 
235
+ # Parse blocks of text that are indented at the given level or greater.
236
+ # [indentLevel] an integer denoteing the number of characters this line is
237
+ # indented at.
238
+ # [text] the content of the line that was indented.
176
239
  def parseIndent(indentLevel, text)
177
240
  state = @stack[-1]
178
241
  line = state.currLine
179
242
 
180
- # BUild the block. Update the offset.
243
+ # Build the block. Update the offset.
181
244
  block = Block.new(state.block.ntxt,
182
245
  state.block,
183
246
  state.start,
184
247
  state.offset)
185
-
248
+
249
+ id = rand(100)
250
+
186
251
  # Position state at the ed of the block.
187
252
  # Blocks are ended by empty lines or lines with the = starting them.
188
253
  while line
189
-
254
+
190
255
  break unless line =~ /^(\s*)([^=\s].*)$/
191
256
 
192
257
  nextIndentLevel = $~[1].length
193
258
  nextLine = $~[2]
194
259
 
195
260
  break if nextIndentLevel < indentLevel
196
-
261
+
197
262
  if nextIndentLevel > indentLevel
198
263
  # Advance to the next line after parsing a subblock.
199
- subState = state.upperSubState()
200
- subState.block = block
264
+ subState = State.new(
265
+ state.lines,
266
+ block,
267
+ state.line,
268
+ state.start + state.offset,
269
+ state.lineEnd)
270
+
201
271
  @stack.push subState
202
272
  parseIndent(nextIndentLevel, nextLine)
203
273
  @stack.pop
@@ -209,28 +279,35 @@ module Ntxt
209
279
  end # if nextIndentLevel > indentLevel
210
280
 
211
281
  end # while line
212
-
213
282
  block.offset = state.offset
214
283
  state.consume
215
284
  end # parseIndent(indentLevel, text)
216
285
 
286
+ # This is the root of the parser's call tree after #parse sets up
287
+ # the parse. This plucks the State off the Parser.stack, obtains the
288
+ # State.currLine.
289
+ #
290
+ # When an indented line is found, #parseIndent is called.
291
+ # When a header line is found, #parseHlevel is caled.
292
+ # Otherwise, we move to the next line.
217
293
  def parseLines
218
294
  state = @stack[-1]
219
- state.block.children = []
220
295
  line = state.currLine
221
296
 
222
297
  while line
223
298
  tmp = Parser::hlevel(line)
224
-
299
+
225
300
  if tmp
226
301
  state.consume
227
302
  parseHlevel(tmp[0].to_i, tmp[1])
303
+ line = state.currLine
228
304
  elsif line =~ /^(\s*)(\S.*)$/
229
305
  state.consume
230
306
  parseIndent($~[1].length, $~[2])
307
+ line = state.currLine
308
+ else
309
+ line = state.nextLine
231
310
  end # if tmp
232
-
233
- line = state.nextLine
234
311
  end # while line
235
312
  end # parseLines
236
313
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 0
8
- - 0
9
- version: 1.0.0
8
+ - 1
9
+ version: 1.0.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Sam Baskinger
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-10-30 00:00:00 -05:00
17
+ date: 2011-11-01 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies: []
20
20