vorax 0.4.2 → 5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -29
- data/vorax.gemspec +3 -11
- metadata +4 -92
- data/.rspec +0 -1
- data/Rakefile +0 -30
- data/lib/vorax.rb +0 -60
- data/lib/vorax/base_funnel.rb +0 -30
- data/lib/vorax/output/html_convertor.rb +0 -120
- data/lib/vorax/output/html_funnel.rb +0 -79
- data/lib/vorax/output/pagezip_convertor.rb +0 -20
- data/lib/vorax/output/tablezip_convertor.rb +0 -22
- data/lib/vorax/output/vertical_convertor.rb +0 -53
- data/lib/vorax/output/zip_convertor.rb +0 -117
- data/lib/vorax/parser/argument.rb~ +0 -125
- data/lib/vorax/parser/conn_string.rb +0 -104
- data/lib/vorax/parser/grammars/alias.rb +0 -904
- data/lib/vorax/parser/grammars/alias.rl +0 -138
- data/lib/vorax/parser/grammars/column.rb +0 -454
- data/lib/vorax/parser/grammars/column.rl +0 -64
- data/lib/vorax/parser/grammars/common.rl +0 -107
- data/lib/vorax/parser/grammars/declare.rb +0 -9606
- data/lib/vorax/parser/grammars/declare.rl +0 -160
- data/lib/vorax/parser/grammars/for_block.rb +0 -440
- data/lib/vorax/parser/grammars/for_block.rl +0 -73
- data/lib/vorax/parser/grammars/plsql_def.rb +0 -539
- data/lib/vorax/parser/grammars/plsql_def.rl +0 -73
- data/lib/vorax/parser/grammars/statement.rb +0 -925
- data/lib/vorax/parser/grammars/statement.rl +0 -83
- data/lib/vorax/parser/parser.rb +0 -344
- data/lib/vorax/parser/plsql_structure.rb +0 -222
- data/lib/vorax/parser/plsql_walker.rb +0 -143
- data/lib/vorax/parser/statement_inspector.rb~ +0 -52
- data/lib/vorax/parser/stmt_inspector.rb +0 -78
- data/lib/vorax/parser/target_ref.rb +0 -110
- data/lib/vorax/sqlplus.rb +0 -273
- data/lib/vorax/version.rb +0 -7
- data/lib/vorax/vorax_io.rb +0 -70
- data/spec/column_spec.rb +0 -40
- data/spec/conn_string_spec.rb +0 -53
- data/spec/declare_spec.rb +0 -281
- data/spec/pagezip_spec.rb +0 -153
- data/spec/parser_spec.rb +0 -352
- data/spec/plsql_structure_spec.rb +0 -68
- data/spec/spec_helper.rb +0 -13
- data/spec/sql/create_objects.sql +0 -69
- data/spec/sql/dbms_crypto.spc +0 -339
- data/spec/sql/dbms_stats.spc +0 -4097
- data/spec/sql/drop_user.sql +0 -10
- data/spec/sql/muci.spc +0 -26
- data/spec/sql/setup_user.sql +0 -22
- data/spec/sql/test.fnc +0 -12
- data/spec/sql/test.pkg +0 -83
- data/spec/sqlplus_spec.rb +0 -52
- data/spec/stmt_inspector_spec.rb +0 -96
- data/spec/tablezip_spec.rb +0 -111
- data/spec/vertical_spec.rb +0 -150
data/README.md
CHANGED
@@ -1,38 +1,13 @@
|
|
1
1
|
# Ruby::Vorax
|
2
2
|
|
3
|
-
|
4
|
-
the
|
5
|
-
|
6
|
-
SQL/PLSQL code.
|
3
|
+
This is just a helper gem for VoraX, an Oracle IDE for geeks. It just defines
|
4
|
+
the other gems VoraX is depending on, as a convenient method to install all the
|
5
|
+
required gems in one step.
|
7
6
|
|
8
7
|
## Installation
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
gem 'vorax'
|
13
|
-
|
14
|
-
And then execute:
|
15
|
-
|
16
|
-
$ bundle
|
17
|
-
|
18
|
-
Or install it yourself as:
|
9
|
+
Just a matter of:
|
19
10
|
|
20
11
|
$ gem install vorax
|
21
12
|
|
22
|
-
## Usage
|
23
|
-
|
24
|
-
To create a SqlPLUS connection and execute something:
|
25
|
-
|
26
|
-
sp = Sqlplus.new('sqlplus')
|
27
|
-
sp.exec('select table_name from all_tables;')
|
28
|
-
print sp.read_output(32767) while sp.busy?
|
29
|
-
sp.terminate
|
30
|
-
|
31
|
-
To get the structure of a PLSQL code:
|
32
|
-
|
33
|
-
text = File.open('spec/sql/test.pkg', 'rb') { |file| file.read }
|
34
|
-
structure = Parser::PlsqlStructure.new(text)
|
35
|
-
structure.print_tree
|
36
|
-
|
37
|
-
See the "YARD" generated documentation for additional info.
|
38
13
|
|
data/vorax.gemspec
CHANGED
@@ -1,25 +1,17 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'vorax/version'
|
5
|
-
|
6
1
|
Gem::Specification.new do |gem|
|
2
|
+
|
7
3
|
gem.name = "vorax"
|
8
|
-
gem.version =
|
4
|
+
gem.version = "5.0"
|
9
5
|
gem.authors = ["Alexandru Tica"]
|
10
6
|
gem.email = ["alexandru.tica@gmail.com"]
|
11
7
|
gem.description = %q{Provides the logic required by Vorax, an Oracle IDE for geeks. Even the main goal of this gem is to support Vorax, it can also be used as it is to interact with a hidden SqlPLUS process or to parse SQL/PLSQL code.}
|
12
8
|
gem.summary = %q{Vorax ruby code companion.}
|
13
|
-
gem.homepage = ""
|
9
|
+
gem.homepage = "https://github.com/talek/vorax-rb"
|
14
10
|
|
15
11
|
gem.files = `git ls-files`.split($/)
|
16
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
-
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
-
gem.require_paths = ["lib"]
|
19
12
|
|
20
13
|
gem.add_runtime_dependency "nokogiri"
|
21
14
|
gem.add_runtime_dependency "childprocess"
|
22
15
|
gem.add_runtime_dependency "rubytree"
|
23
16
|
|
24
|
-
gem.add_development_dependency "rspec", "~> 2.6"
|
25
17
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vorax
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0
|
4
|
+
version: '5.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-
|
12
|
+
date: 2013-05-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -59,22 +59,6 @@ dependencies:
|
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: rspec
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ~>
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '2.6'
|
70
|
-
type: :development
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '2.6'
|
78
62
|
description: Provides the logic required by Vorax, an Oracle IDE for geeks. Even the
|
79
63
|
main goal of this gem is to support Vorax, it can also be used as it is to interact
|
80
64
|
with a hidden SqlPLUS process or to parse SQL/PLSQL code.
|
@@ -85,63 +69,10 @@ extensions: []
|
|
85
69
|
extra_rdoc_files: []
|
86
70
|
files:
|
87
71
|
- .gitignore
|
88
|
-
- .rspec
|
89
72
|
- LICENSE.txt
|
90
73
|
- README.md
|
91
|
-
- Rakefile
|
92
|
-
- lib/vorax.rb
|
93
|
-
- lib/vorax/base_funnel.rb
|
94
|
-
- lib/vorax/output/html_convertor.rb
|
95
|
-
- lib/vorax/output/html_funnel.rb
|
96
|
-
- lib/vorax/output/pagezip_convertor.rb
|
97
|
-
- lib/vorax/output/tablezip_convertor.rb
|
98
|
-
- lib/vorax/output/vertical_convertor.rb
|
99
|
-
- lib/vorax/output/zip_convertor.rb
|
100
|
-
- lib/vorax/parser/argument.rb~
|
101
|
-
- lib/vorax/parser/conn_string.rb
|
102
|
-
- lib/vorax/parser/grammars/alias.rb
|
103
|
-
- lib/vorax/parser/grammars/alias.rl
|
104
|
-
- lib/vorax/parser/grammars/column.rb
|
105
|
-
- lib/vorax/parser/grammars/column.rl
|
106
|
-
- lib/vorax/parser/grammars/common.rl
|
107
|
-
- lib/vorax/parser/grammars/declare.rb
|
108
|
-
- lib/vorax/parser/grammars/declare.rl
|
109
|
-
- lib/vorax/parser/grammars/for_block.rb
|
110
|
-
- lib/vorax/parser/grammars/for_block.rl
|
111
|
-
- lib/vorax/parser/grammars/plsql_def.rb
|
112
|
-
- lib/vorax/parser/grammars/plsql_def.rl
|
113
|
-
- lib/vorax/parser/grammars/statement.rb
|
114
|
-
- lib/vorax/parser/grammars/statement.rl
|
115
|
-
- lib/vorax/parser/parser.rb
|
116
|
-
- lib/vorax/parser/plsql_structure.rb
|
117
|
-
- lib/vorax/parser/plsql_walker.rb
|
118
|
-
- lib/vorax/parser/statement_inspector.rb~
|
119
|
-
- lib/vorax/parser/stmt_inspector.rb
|
120
|
-
- lib/vorax/parser/target_ref.rb
|
121
|
-
- lib/vorax/sqlplus.rb
|
122
|
-
- lib/vorax/version.rb
|
123
|
-
- lib/vorax/vorax_io.rb
|
124
|
-
- spec/column_spec.rb
|
125
|
-
- spec/conn_string_spec.rb
|
126
|
-
- spec/declare_spec.rb
|
127
|
-
- spec/pagezip_spec.rb
|
128
|
-
- spec/parser_spec.rb
|
129
|
-
- spec/plsql_structure_spec.rb
|
130
|
-
- spec/spec_helper.rb
|
131
|
-
- spec/sql/create_objects.sql
|
132
|
-
- spec/sql/dbms_crypto.spc
|
133
|
-
- spec/sql/dbms_stats.spc
|
134
|
-
- spec/sql/drop_user.sql
|
135
|
-
- spec/sql/muci.spc
|
136
|
-
- spec/sql/setup_user.sql
|
137
|
-
- spec/sql/test.fnc
|
138
|
-
- spec/sql/test.pkg
|
139
|
-
- spec/sqlplus_spec.rb
|
140
|
-
- spec/stmt_inspector_spec.rb
|
141
|
-
- spec/tablezip_spec.rb
|
142
|
-
- spec/vertical_spec.rb
|
143
74
|
- vorax.gemspec
|
144
|
-
homepage:
|
75
|
+
homepage: https://github.com/talek/vorax-rb
|
145
76
|
licenses: []
|
146
77
|
post_install_message:
|
147
78
|
rdoc_options: []
|
@@ -165,24 +96,5 @@ rubygems_version: 1.8.24
|
|
165
96
|
signing_key:
|
166
97
|
specification_version: 3
|
167
98
|
summary: Vorax ruby code companion.
|
168
|
-
test_files:
|
169
|
-
- spec/column_spec.rb
|
170
|
-
- spec/conn_string_spec.rb
|
171
|
-
- spec/declare_spec.rb
|
172
|
-
- spec/pagezip_spec.rb
|
173
|
-
- spec/parser_spec.rb
|
174
|
-
- spec/plsql_structure_spec.rb
|
175
|
-
- spec/spec_helper.rb
|
176
|
-
- spec/sql/create_objects.sql
|
177
|
-
- spec/sql/dbms_crypto.spc
|
178
|
-
- spec/sql/dbms_stats.spc
|
179
|
-
- spec/sql/drop_user.sql
|
180
|
-
- spec/sql/muci.spc
|
181
|
-
- spec/sql/setup_user.sql
|
182
|
-
- spec/sql/test.fnc
|
183
|
-
- spec/sql/test.pkg
|
184
|
-
- spec/sqlplus_spec.rb
|
185
|
-
- spec/stmt_inspector_spec.rb
|
186
|
-
- spec/tablezip_spec.rb
|
187
|
-
- spec/vertical_spec.rb
|
99
|
+
test_files: []
|
188
100
|
has_rdoc:
|
data/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--require spec_helper
|
data/Rakefile
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require_relative 'spec/spec_helper.rb'
|
2
|
-
require 'rspec/core/rake_task'
|
3
|
-
require 'yard'
|
4
|
-
|
5
|
-
desc 'Default: run specs.'
|
6
|
-
task :default => :spec
|
7
|
-
|
8
|
-
desc "Run specs"
|
9
|
-
RSpec::Core::RakeTask.new
|
10
|
-
|
11
|
-
desc "Generate documentation"
|
12
|
-
YARD::Rake::YardocTask.new
|
13
|
-
|
14
|
-
desc 'Builds the gem'
|
15
|
-
task :build do
|
16
|
-
sh "gem build vorax.gemspec"
|
17
|
-
end
|
18
|
-
|
19
|
-
desc 'Builds and installs the gem'
|
20
|
-
task :install => :build do
|
21
|
-
sh "gem install vorax-#{Vorax::VERSION} --no-rdoc --no-ri"
|
22
|
-
end
|
23
|
-
|
24
|
-
desc 'Tags version, pushes to remote, and pushes gem'
|
25
|
-
task :release => :build do
|
26
|
-
sh "git tag v#{Vorax::VERSION}"
|
27
|
-
sh "git push origin master"
|
28
|
-
sh "git push origin v#{Vorax::VERSION}"
|
29
|
-
sh "gem push vorax-#{Vorax::VERSION}.gem"
|
30
|
-
end
|
data/lib/vorax.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require 'rubygems' unless defined? Gem
|
4
|
-
require 'logger'
|
5
|
-
require 'childprocess'
|
6
|
-
require 'antlr3'
|
7
|
-
|
8
|
-
# The main Vorax namespace. Everything related to VoraX is part
|
9
|
-
# of this module.
|
10
|
-
module Vorax
|
11
|
-
|
12
|
-
# Sets the logger to be used for debug purposes.
|
13
|
-
# @param logger [Logger] the logger object.
|
14
|
-
def self.logger=(logger)
|
15
|
-
@logger = logger
|
16
|
-
end
|
17
|
-
|
18
|
-
# Get the current logger.
|
19
|
-
def self.logger
|
20
|
-
@logger
|
21
|
-
end
|
22
|
-
|
23
|
-
# Log a debug entry.
|
24
|
-
# @param message [String] the message to be logged.
|
25
|
-
def self.debug(message)
|
26
|
-
if @logger
|
27
|
-
@logger.add(Logger::DEBUG, nil, 'rby') { message }
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# Raised when another SqlPlus is already executing.
|
32
|
-
class AnotherExecRunning < StandardError; end
|
33
|
-
|
34
|
-
# Raised when the platform is not supported (see cancel)
|
35
|
-
class PlatformNotSupported < StandardError; end
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
require 'vorax/version.rb'
|
40
|
-
require 'vorax/vorax_io.rb'
|
41
|
-
require 'vorax/sqlplus.rb'
|
42
|
-
require 'vorax/base_funnel.rb'
|
43
|
-
require 'vorax/output/html_funnel.rb'
|
44
|
-
require 'vorax/output/html_convertor.rb'
|
45
|
-
require 'vorax/output/vertical_convertor.rb'
|
46
|
-
require 'vorax/output/zip_convertor.rb'
|
47
|
-
require 'vorax/output/pagezip_convertor.rb'
|
48
|
-
require 'vorax/output/tablezip_convertor.rb'
|
49
|
-
require 'vorax/parser/parser.rb'
|
50
|
-
require 'vorax/parser/conn_string.rb'
|
51
|
-
require 'vorax/parser/target_ref.rb'
|
52
|
-
require 'vorax/parser/stmt_inspector.rb'
|
53
|
-
require 'vorax/parser/plsql_walker.rb'
|
54
|
-
require 'vorax/parser/plsql_structure.rb'
|
55
|
-
require 'vorax/parser/grammars/statement.rb'
|
56
|
-
require 'vorax/parser/grammars/alias.rb'
|
57
|
-
require 'vorax/parser/grammars/column.rb'
|
58
|
-
require 'vorax/parser/grammars/declare.rb'
|
59
|
-
require 'vorax/parser/grammars/plsql_def.rb'
|
60
|
-
require 'vorax/parser/grammars/for_block.rb'
|
data/lib/vorax/base_funnel.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require 'nokogiri'
|
4
|
-
|
5
|
-
module Vorax
|
6
|
-
|
7
|
-
# A funnel is an abstraction for the idea of formatting text. You
|
8
|
-
# write some text into the funnel and then you read it formatted. It's
|
9
|
-
# up to every subclass to implement the transformation logic.
|
10
|
-
class BaseFunnel
|
11
|
-
|
12
|
-
# Write the text to be converted into the funnel. By default, this
|
13
|
-
# method does nothing, since it is intended to be overwritten by
|
14
|
-
# subclasses.
|
15
|
-
#
|
16
|
-
# @param text [String] the text to be formatted.
|
17
|
-
def write(text)
|
18
|
-
# do nothing: subclass responsability
|
19
|
-
end
|
20
|
-
|
21
|
-
# Read the converted text. By default, this method does nothing. It is
|
22
|
-
# intended to be overridden in subclasses.
|
23
|
-
def read
|
24
|
-
# do nothing: subclass responsability
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
@@ -1,120 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
module Vorax
|
4
|
-
module Output
|
5
|
-
|
6
|
-
# An abstraction for converting an XML/HTML to something else. The idea is that
|
7
|
-
# sqlplus may be configured to spit HTML output so that we can easily parse
|
8
|
-
# it and transform it to something else. The io attribute is the pipe used to
|
9
|
-
# push HTML content and fetch the formatted text.
|
10
|
-
class HTMLConvertor < Nokogiri::XML::SAX::Document
|
11
|
-
|
12
|
-
attr_reader :io, :text
|
13
|
-
|
14
|
-
# Creates a new convertor.
|
15
|
-
def initialize()
|
16
|
-
super()
|
17
|
-
@io = StringIO.new("")
|
18
|
-
@tags_chain = []
|
19
|
-
@text = ''
|
20
|
-
end
|
21
|
-
|
22
|
-
# This callback must be defined in every subclass. It is
|
23
|
-
# invoked as soon as a new tag is detected.
|
24
|
-
#
|
25
|
-
# @param name [String] the detected tag name
|
26
|
-
# @param attrs [Array] an array with all defined attributes for
|
27
|
-
# the detected tag.
|
28
|
-
def start_hook name, attrs = []
|
29
|
-
# this should be implemented in sub-classes
|
30
|
-
end
|
31
|
-
|
32
|
-
# This callback must be defined in every subclass. It is
|
33
|
-
# invoked as soon as a end tag definition is detected.
|
34
|
-
#
|
35
|
-
# @param name [String] the name of the endding tag
|
36
|
-
def end_hook name
|
37
|
-
# this should be implemented in sub-classes
|
38
|
-
end
|
39
|
-
|
40
|
-
# Indent every line from the provided text with the given pad
|
41
|
-
# size.
|
42
|
-
#
|
43
|
-
# @param text [String] the multiline text to be indented
|
44
|
-
# @param pad_size [int] the padding size
|
45
|
-
#
|
46
|
-
# @return the indented text
|
47
|
-
def self.ml_indent(text, pad_size)
|
48
|
-
text.gsub(/\r?\n/, "\n#{' '*pad_size}")
|
49
|
-
end
|
50
|
-
|
51
|
-
# Get the N-th line from the provided multiline text.
|
52
|
-
#
|
53
|
-
# @param text [String] the multiline text
|
54
|
-
# @param lineno [int] the line number
|
55
|
-
# @return the N-th line
|
56
|
-
def self.ml_segment(text, lineno)
|
57
|
-
text.split(/\r?\n/)[lineno] || ""
|
58
|
-
end
|
59
|
-
|
60
|
-
# Get the size of the largest line from a multiline text.
|
61
|
-
#
|
62
|
-
# @param text [String] the multiline text.
|
63
|
-
# @return the size of the largest line
|
64
|
-
def self.ml_width(text)
|
65
|
-
text.split(/\r?\n/).inject(0) { |counter, elem| [elem.length, counter].max }
|
66
|
-
end
|
67
|
-
|
68
|
-
# Get the number of lines from a multiline text.
|
69
|
-
#
|
70
|
-
# @param text [String] the multiline text.
|
71
|
-
# @return the number of lines
|
72
|
-
def self.ml_count(text)
|
73
|
-
text.scan(/\r?\n/).size
|
74
|
-
end
|
75
|
-
|
76
|
-
# Get the HTML tag to be used to ping the Nokogiri parser.
|
77
|
-
# @return the ping tag
|
78
|
-
def self.ping_tag
|
79
|
-
"s"
|
80
|
-
end
|
81
|
-
|
82
|
-
# Whenever or not the convertor should spit plain text which is directly
|
83
|
-
# under <body> tag.
|
84
|
-
def should_spit_text?
|
85
|
-
@tags_chain.size > 0 &&
|
86
|
-
#(not @text.empty?) &&
|
87
|
-
["body", "p", "br", HTMLConvertor.ping_tag].include?(@tags_chain.last[:name])
|
88
|
-
end
|
89
|
-
|
90
|
-
# The text accumulated within the current tag. This is automatically
|
91
|
-
# called from the Nokogiri engine.
|
92
|
-
def characters(str)
|
93
|
-
@text << str if str && !str.empty?
|
94
|
-
end
|
95
|
-
|
96
|
-
private
|
97
|
-
|
98
|
-
def start_element name, attrs = []
|
99
|
-
@tags_chain.push({:name => name.downcase, :attrs => attrs})
|
100
|
-
if should_spit_text?
|
101
|
-
chunk = @text
|
102
|
-
chunk.strip! unless @tags_chain.last[:name] == 'pre'
|
103
|
-
@io << chunk unless chunk.empty?
|
104
|
-
@text.clear
|
105
|
-
end
|
106
|
-
start_hook(name, attrs)
|
107
|
-
end
|
108
|
-
|
109
|
-
def end_element name
|
110
|
-
if name == 'pre'
|
111
|
-
@io << @text
|
112
|
-
end
|
113
|
-
end_hook(name.downcase)
|
114
|
-
@tags_chain.pop
|
115
|
-
end
|
116
|
-
|
117
|
-
end
|
118
|
-
|
119
|
-
end
|
120
|
-
end
|