nairda-ines 0.2.0 → 0.2.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/lib/ines/engine.rb +6 -0
- data/lib/ines/engine/text.rb +110 -0
- data/lib/ines/version.rb +1 -1
- data/spec/unit/engine/text_spec.rb +89 -0
- metadata +5 -2
data/lib/ines/engine.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
module INES
|
4
|
+
module Engine
|
5
|
+
# Basic engine using INES notation.
|
6
|
+
module Text
|
7
|
+
# Chars indicating each element in the text.
|
8
|
+
TAGS = {
|
9
|
+
'`' => :statement,
|
10
|
+
'$' => :shout,
|
11
|
+
'_' => :whisper,
|
12
|
+
'#' => :thought,
|
13
|
+
'*' => :action
|
14
|
+
}
|
15
|
+
|
16
|
+
class << self
|
17
|
+
# Parses given +text+ into Element Collection.
|
18
|
+
def load(text)
|
19
|
+
# Regular expression matching all available tags.
|
20
|
+
tag_regexp = Regexp.union(*TAGS.keys)
|
21
|
+
|
22
|
+
# Thankfully there's alternative to regular expressions.
|
23
|
+
scanner = StringScanner.new(text.to_s.strip)
|
24
|
+
|
25
|
+
# Initialize needed variables.
|
26
|
+
collection = Collection.new
|
27
|
+
position = 0
|
28
|
+
buffer = ''
|
29
|
+
|
30
|
+
# Try to extract all expressions marked by their tags. Additionally
|
31
|
+
# every not matched text will be added as Element of default type. In
|
32
|
+
# order of appearance, of course.
|
33
|
+
#
|
34
|
+
# FIXME: Most likely there are many ways to optimize and KISS this
|
35
|
+
# code, but currently it's enough to work fine :)
|
36
|
+
until scanner.eos?
|
37
|
+
if scanner.scan_until(tag_regexp)
|
38
|
+
# Add any not matched text to the buffer.
|
39
|
+
buffer << scanner.pre_match[position, scanner.pointer].strip
|
40
|
+
|
41
|
+
# Remember current position for later use.
|
42
|
+
position = scanner.pointer
|
43
|
+
|
44
|
+
# Remember found tag and make a regexp for it.
|
45
|
+
found = scanner[0]
|
46
|
+
match = Regexp.new(Regexp.escape(found))
|
47
|
+
|
48
|
+
if scanner.scan(match)
|
49
|
+
# Add any not matched text.
|
50
|
+
collection.add(Element.new(buffer)) unless buffer == ''
|
51
|
+
|
52
|
+
# Add everything after found tags as new Element.
|
53
|
+
content = scanner.post_match
|
54
|
+
collection.add(Element.new(content, TAGS[found]))
|
55
|
+
|
56
|
+
# End the scanning process.
|
57
|
+
scanner.terminate
|
58
|
+
elsif scanner.scan_until(match)
|
59
|
+
# Add any not matched text.
|
60
|
+
collection.add(Element.new(buffer)) unless buffer == ''
|
61
|
+
|
62
|
+
# Add everything between found tags as new Element.
|
63
|
+
content = scanner.pre_match[position, scanner.pointer]
|
64
|
+
collection.add(Element.new(content, TAGS[found]))
|
65
|
+
|
66
|
+
# Update remembered scanner position.
|
67
|
+
position = scanner.pointer
|
68
|
+
else
|
69
|
+
# Add any not matched text.
|
70
|
+
collection.add(Element.new(buffer + found))
|
71
|
+
end
|
72
|
+
|
73
|
+
# Clear the buffer.
|
74
|
+
buffer = ''
|
75
|
+
else
|
76
|
+
# No expressions left. Add rest of the text as default Element.
|
77
|
+
exp = scanner.scan_until(/\Z/)
|
78
|
+
collection.add(Element.new(exp))
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Return the collection, squeezing it first.
|
83
|
+
collection.squeeze!
|
84
|
+
end
|
85
|
+
|
86
|
+
# Converts given +collection+ to text notation. Raises ArgumentError
|
87
|
+
# if passed argument is not a Collection object.
|
88
|
+
def dump(collection)
|
89
|
+
raise ArgumentError, 'Argument must be an INES::Collection object.' unless collection.is_a?(Collection)
|
90
|
+
|
91
|
+
# Initialize the container.
|
92
|
+
text = ''
|
93
|
+
|
94
|
+
collection.squeeze!.stack.each do |e|
|
95
|
+
next unless TAGS.has_value?(e.expression)
|
96
|
+
tag = TAGS.invert[e.expression]
|
97
|
+
text << tag + e.content + tag + ' '
|
98
|
+
end
|
99
|
+
|
100
|
+
text.strip
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class Collection
|
107
|
+
# Cute alias for dumping Collection into string.
|
108
|
+
def to_s; Engine::Text.dump(self) end
|
109
|
+
end
|
110
|
+
end
|
data/lib/ines/version.rb
CHANGED
@@ -0,0 +1,89 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
2
|
+
|
3
|
+
include INES
|
4
|
+
include Engine
|
5
|
+
|
6
|
+
describe Text, 'loading' do
|
7
|
+
it 'should add and remove new tag' do
|
8
|
+
length = Text::TAGS.length
|
9
|
+
Text::TAGS['kitteh'] = :kitteh
|
10
|
+
Text::TAGS.length.should equal(length + 1)
|
11
|
+
Text::TAGS['kitteh'].should equal(:kitteh)
|
12
|
+
Text::TAGS.delete('kitteh')
|
13
|
+
Text::TAGS.length.should equal(length)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should parse simple text' do
|
17
|
+
c = Text.load('`Oh Hai!` *sez kitteh*')
|
18
|
+
c.should have(2).items
|
19
|
+
c.stack.first.content.should eql('Oh Hai!')
|
20
|
+
c.stack.last.content.should eql('sez kitteh')
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should parse text with line ending tag' do
|
24
|
+
c = Text.load('`Oh Hai!` **sez kitteh')
|
25
|
+
c.stack.should have(2).items
|
26
|
+
c.stack.first.content.should eql('Oh Hai!')
|
27
|
+
c.stack.last.content.should eql('sez kitteh')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should parse not tagged text' do
|
31
|
+
# Plain text only.
|
32
|
+
c = Text.load('Her kitteh kitteh kitteh!')
|
33
|
+
c.stack.should have(1).item
|
34
|
+
c.stack.first.content.should eql('Her kitteh kitteh kitteh!')
|
35
|
+
|
36
|
+
# Mixed with tagged text.
|
37
|
+
c = Text.load('Oh Hai! *sez kitteh*')
|
38
|
+
c.stack.should have(2).items
|
39
|
+
c.stack.first.content.should eql('Oh Hai!')
|
40
|
+
c.stack.last.content.should eql('sez kitteh')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should remove whitespace surrounding expressions only' do
|
44
|
+
# Spanned tags.
|
45
|
+
c = Text.load('! Oh Hai * sez kitteh * ')
|
46
|
+
c.stack.should have(2).items
|
47
|
+
c.stack.first.content.should eql('! Oh Hai')
|
48
|
+
c.stack.last.content.should eql('sez kitteh')
|
49
|
+
|
50
|
+
# Line ending tags.
|
51
|
+
c = Text.load(' Oh hai thar ! ** sez ` lil ` ** kitteh ! ')
|
52
|
+
c.stack.should have(2).items
|
53
|
+
c.stack.first.content.should eql('Oh hai thar !')
|
54
|
+
c.stack.last.content.should eql('sez ` lil ` ** kitteh !')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should not parse embedded tags' do
|
58
|
+
# Spanned tags.
|
59
|
+
c = Text.load('`*Hai!*` *kitteh `was` very happy*')
|
60
|
+
c.stack.should have(2).items
|
61
|
+
c.stack.first.content.should eql('*Hai!*')
|
62
|
+
c.stack.last.content.should eql('kitteh `was` very happy')
|
63
|
+
|
64
|
+
# Line ending tags.
|
65
|
+
c = Text.load('Hai! ** kitteh *was* `very` ``happy')
|
66
|
+
c.stack.should have(2).items
|
67
|
+
c.stack.first.content.should eql('Hai!')
|
68
|
+
c.stack.last.content.should eql('kitteh *was* `very` ``happy')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe Text, 'dumping' do
|
73
|
+
before(:each) do
|
74
|
+
@collection = Collection.new
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should dump collection' do
|
78
|
+
@collection << Element.new('Hai', :statement)
|
79
|
+
@collection << Element.new('thar!', :statement)
|
80
|
+
Text.dump(@collection).should eql(@collection.to_s)
|
81
|
+
Text.dump(@collection).should eql('`Hai thar!`')
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'it should dump collection with elements containing whitespace' do
|
85
|
+
@collection << Element.new(' Hai thar! ', :statement)
|
86
|
+
@collection << Element.new(' sez lil kitteh ', :action)
|
87
|
+
Text.dump(@collection).should eql('`Hai thar!` *sez lil kitteh*')
|
88
|
+
end
|
89
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nairda-ines
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Adrian Paca\xC5\x82a"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-05-
|
12
|
+
date: 2008-05-21 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -26,11 +26,14 @@ extra_rdoc_files:
|
|
26
26
|
files:
|
27
27
|
- README
|
28
28
|
- LICENSE
|
29
|
+
- lib/ines/engine/text.rb
|
29
30
|
- lib/ines/collection.rb
|
31
|
+
- lib/ines/engine.rb
|
30
32
|
- lib/ines/element.rb
|
31
33
|
- lib/ines/version.rb
|
32
34
|
- lib/ines.rb
|
33
35
|
- spec/unit/collection_spec.rb
|
36
|
+
- spec/unit/engine/text_spec.rb
|
34
37
|
- spec/unit/element_spec.rb
|
35
38
|
- spec/spec_helper.rb
|
36
39
|
- TODO
|