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.
@@ -0,0 +1,6 @@
1
+ require INES_ROOT + 'engine/text'
2
+
3
+ module INES #:nodoc: all
4
+ module Engine
5
+ end
6
+ end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module INES
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.1'
3
3
  end
@@ -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.0
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-20 00:00:00 -07:00
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