txprails 0.1.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/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +50 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/VERSION_NAME +1 -0
- data/bin/txprails +9 -0
- data/ext/txparse/Makefile +157 -0
- data/ext/txparse/extconf.rb +8 -0
- data/ext/txparse/test_txp.rb +65 -0
- data/ext/txparse/txparse.cpp +139 -0
- data/ext/txparse/txparse.h +15 -0
- data/ext/txparse/txparse_lib.cpp +191 -0
- data/ext/txparse/txparse_lib.h +17 -0
- data/ext/txparse/txparse_tag.cpp +109 -0
- data/ext/txparse/txparse_tag.h +7 -0
- data/lib/init_rails.rb +16 -0
- data/lib/txprails/commands.rb +88 -0
- data/lib/txprails/template.rb +29 -0
- data/lib/txprails/util.rb +44 -0
- data/lib/txprails/version.rb +64 -0
- data/lib/txprails.rb +44 -0
- data/test/helper.rb +10 -0
- data/test/test_txprails.rb +7 -0
- data/txprails.gemspec +73 -0
- metadata +91 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Jose Miguel Perez
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
= TXPRrails
|
2
|
+
|
3
|
+
*DISCLAIMER:*
|
4
|
+
|
5
|
+
TXPRails born kind of a experiment. Please be aware that this is a work in
|
6
|
+
progress.
|
7
|
+
|
8
|
+
= TXPRails = TextPattern Rails
|
9
|
+
|
10
|
+
This gem is a experiment for using TextPattern like templates in a Rails
|
11
|
+
environment. Rails have many template engines available, from ERB thru Haml,
|
12
|
+
etc. However, for many of us from a more traditional PHP/like environment,
|
13
|
+
XML-style templates seems more natural. Moreover, Txp style templates differ
|
14
|
+
from Haml or ERB in one thing: the templates are not "compiled" in the sense
|
15
|
+
of making 1 pre-compile pass (Haml) or more-or-less-directly ruby-executed
|
16
|
+
(ERB). Txp templates are executed while parsing, using different techniques
|
17
|
+
explained below.
|
18
|
+
|
19
|
+
I think Haml is kind of awesome, and I'm slowly getting used to it. However,
|
20
|
+
I'm still fascinated of the elegance and simplicity of TXP XML'ish templates.
|
21
|
+
|
22
|
+
So, in essence, I started this project solely for this pourposes:
|
23
|
+
|
24
|
+
* Try to make my first publicy available Ruby Gem.
|
25
|
+
* Test and experience the C/C++ binding of Ruby. (TXPRails is more or less
|
26
|
+
80% written in C++).
|
27
|
+
* Learn and practice myself some advanced Rails techniques.
|
28
|
+
* Just for fun... :-)
|
29
|
+
|
30
|
+
*This project and some of the code (namely the Rails plugin bootstrap) is
|
31
|
+
heavily inspired by Haml itself.*
|
32
|
+
|
33
|
+
Please, PLEASE, if you find this gem useful, comment and make suggestions to make it better. I think you may also benefit and learn from TXPRails.
|
34
|
+
|
35
|
+
|
36
|
+
== Note on Patches/Pull Requests
|
37
|
+
|
38
|
+
* Fork the project.
|
39
|
+
* Make your feature addition or bug fix.
|
40
|
+
* Add tests for it. This is important so I don't break it in a
|
41
|
+
future version unintentionally.
|
42
|
+
* Commit, do not mess with rakefile, version, or history.
|
43
|
+
(if you want to have your own version, that is fine but bump version in a
|
44
|
+
commit by itself I can ignore when I pull)
|
45
|
+
* Send me a pull request. Bonus points for topic branches.
|
46
|
+
|
47
|
+
== Copyright
|
48
|
+
|
49
|
+
Copyleft (c) 2010 Jose Miguel Perez. Do not see LICENSE for no details.
|
50
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "txprails"
|
8
|
+
gem.summary = %Q{TextPattern-like template engine for Rails}
|
9
|
+
gem.description = %Q{TXPRails is a template engine based on TextPattern for Rails.}
|
10
|
+
gem.email = "josemiguel@perezruiz.com"
|
11
|
+
gem.homepage = "http://github.com/twoixter/txprails"
|
12
|
+
gem.authors = ["Jose Miguel Pérez Ruiz"]
|
13
|
+
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/test_*.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'rcov/rcovtask'
|
30
|
+
Rcov::RcovTask.new do |test|
|
31
|
+
test.libs << 'test'
|
32
|
+
test.pattern = 'test/**/test_*.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
task :rcov do
|
37
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
task :test => :check_dependencies
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "txprails #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
54
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/VERSION_NAME
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Domestikal Example
|
data/bin/txprails
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
|
2
|
+
SHELL = /bin/sh
|
3
|
+
|
4
|
+
#### Start of system configuration section. ####
|
5
|
+
|
6
|
+
srcdir = .
|
7
|
+
topdir = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0
|
8
|
+
hdrdir = $(topdir)
|
9
|
+
VPATH = $(srcdir):$(topdir):$(hdrdir)
|
10
|
+
exec_prefix = $(prefix)
|
11
|
+
prefix = $(DESTDIR)/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr
|
12
|
+
sharedstatedir = $(prefix)/com
|
13
|
+
mandir = $(DESTDIR)/usr/share/man
|
14
|
+
psdir = $(docdir)
|
15
|
+
oldincludedir = $(DESTDIR)/usr/include
|
16
|
+
localedir = $(datarootdir)/locale
|
17
|
+
bindir = $(exec_prefix)/bin
|
18
|
+
libexecdir = $(exec_prefix)/libexec
|
19
|
+
sitedir = $(DESTDIR)/Library/Ruby/Site
|
20
|
+
htmldir = $(docdir)
|
21
|
+
vendorarchdir = $(vendorlibdir)/$(sitearch)
|
22
|
+
includedir = $(prefix)/include
|
23
|
+
infodir = $(DESTDIR)/usr/share/info
|
24
|
+
vendorlibdir = $(vendordir)/$(ruby_version)
|
25
|
+
sysconfdir = $(prefix)/etc
|
26
|
+
libdir = $(exec_prefix)/lib
|
27
|
+
sbindir = $(exec_prefix)/sbin
|
28
|
+
rubylibdir = $(libdir)/ruby/$(ruby_version)
|
29
|
+
docdir = $(datarootdir)/doc/$(PACKAGE)
|
30
|
+
dvidir = $(docdir)
|
31
|
+
vendordir = $(libdir)/ruby/vendor_ruby
|
32
|
+
datarootdir = $(prefix)/share
|
33
|
+
pdfdir = $(docdir)
|
34
|
+
archdir = $(rubylibdir)/$(arch)
|
35
|
+
sitearchdir = $(sitelibdir)/$(sitearch)
|
36
|
+
datadir = $(datarootdir)
|
37
|
+
localstatedir = $(prefix)/var
|
38
|
+
sitelibdir = $(sitedir)/$(ruby_version)
|
39
|
+
|
40
|
+
CC = gcc
|
41
|
+
LIBRUBY = $(LIBRUBY_SO)
|
42
|
+
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
43
|
+
LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
|
44
|
+
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)
|
45
|
+
|
46
|
+
RUBY_EXTCONF_H =
|
47
|
+
CFLAGS = -fno-common -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common $(cflags)
|
48
|
+
INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
|
49
|
+
DEFS =
|
50
|
+
CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
|
51
|
+
CXXFLAGS = $(CFLAGS)
|
52
|
+
ldflags = -L. -arch i386 -arch x86_64
|
53
|
+
dldflags =
|
54
|
+
archflag =
|
55
|
+
DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
|
56
|
+
LDSHARED = $(CXX) -arch i386 -arch x86_64 -pipe -bundle -undefined dynamic_lookup
|
57
|
+
AR = ar
|
58
|
+
EXEEXT =
|
59
|
+
|
60
|
+
RUBY_INSTALL_NAME = ruby
|
61
|
+
RUBY_SO_NAME = ruby
|
62
|
+
arch = universal-darwin10.0
|
63
|
+
sitearch = universal-darwin10.0
|
64
|
+
ruby_version = 1.8
|
65
|
+
ruby = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
|
66
|
+
RUBY = $(ruby)
|
67
|
+
RM = rm -f
|
68
|
+
MAKEDIRS = mkdir -p
|
69
|
+
INSTALL = /usr/bin/install -c
|
70
|
+
INSTALL_PROG = $(INSTALL) -m 0755
|
71
|
+
INSTALL_DATA = $(INSTALL) -m 644
|
72
|
+
COPY = cp
|
73
|
+
|
74
|
+
#### End of system configuration section. ####
|
75
|
+
|
76
|
+
preload =
|
77
|
+
|
78
|
+
libpath = . $(libdir)
|
79
|
+
LIBPATH = -L. -L$(libdir)
|
80
|
+
DEFFILE =
|
81
|
+
|
82
|
+
CLEANFILES = mkmf.log
|
83
|
+
DISTCLEANFILES =
|
84
|
+
|
85
|
+
extout =
|
86
|
+
extout_prefix =
|
87
|
+
target_prefix = /txprails
|
88
|
+
LOCAL_LIBS =
|
89
|
+
LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl
|
90
|
+
SRCS = txparse.cpp txparse_lib.cpp txparse_tag.cpp
|
91
|
+
OBJS = txparse.o txparse_lib.o txparse_tag.o
|
92
|
+
TARGET = txparse
|
93
|
+
DLLIB = $(TARGET).bundle
|
94
|
+
EXTSTATIC =
|
95
|
+
STATIC_LIB =
|
96
|
+
|
97
|
+
BINDIR = $(bindir)
|
98
|
+
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
|
99
|
+
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
|
100
|
+
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
|
101
|
+
|
102
|
+
TARGET_SO = $(DLLIB)
|
103
|
+
CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
|
104
|
+
CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
|
105
|
+
|
106
|
+
all: $(DLLIB)
|
107
|
+
static: $(STATIC_LIB)
|
108
|
+
|
109
|
+
clean:
|
110
|
+
@-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
|
111
|
+
|
112
|
+
distclean: clean
|
113
|
+
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
|
114
|
+
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
|
115
|
+
|
116
|
+
realclean: distclean
|
117
|
+
install: install-so install-rb
|
118
|
+
|
119
|
+
install-so: $(RUBYARCHDIR)
|
120
|
+
install-so: $(RUBYARCHDIR)/$(DLLIB)
|
121
|
+
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
|
122
|
+
$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
|
123
|
+
install-rb: pre-install-rb install-rb-default
|
124
|
+
install-rb-default: pre-install-rb-default
|
125
|
+
pre-install-rb: Makefile
|
126
|
+
pre-install-rb-default: Makefile
|
127
|
+
$(RUBYARCHDIR):
|
128
|
+
$(MAKEDIRS) $@
|
129
|
+
|
130
|
+
site-install: site-install-so site-install-rb
|
131
|
+
site-install-so: install-so
|
132
|
+
site-install-rb: install-rb
|
133
|
+
|
134
|
+
.SUFFIXES: .c .m .cc .cxx .cpp .C .o
|
135
|
+
|
136
|
+
.cc.o:
|
137
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
138
|
+
|
139
|
+
.cxx.o:
|
140
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
141
|
+
|
142
|
+
.cpp.o:
|
143
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
144
|
+
|
145
|
+
.C.o:
|
146
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
|
147
|
+
|
148
|
+
.c.o:
|
149
|
+
$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
|
150
|
+
|
151
|
+
$(DLLIB): $(OBJS)
|
152
|
+
@-$(RM) $@
|
153
|
+
$(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
$(OBJS): ruby.h defines.h
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "TXParse"
|
2
|
+
|
3
|
+
class MyParse
|
4
|
+
include TXParse
|
5
|
+
|
6
|
+
def strong(tag)
|
7
|
+
unless tag.thing.nil?
|
8
|
+
"THE THING(" + tag.thing + ")"
|
9
|
+
else
|
10
|
+
"STRONG" unless tag.close?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def doctype(tag)
|
15
|
+
"<DOCTYPE HTML>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def body(tag)
|
19
|
+
"<BODY>" + self.parse(tag.thing) + "</BODY>"
|
20
|
+
end
|
21
|
+
|
22
|
+
def uppercase(tag)
|
23
|
+
self.parse(tag.thing).upcase
|
24
|
+
end
|
25
|
+
|
26
|
+
def count(tag)
|
27
|
+
return self.parse(tag.thing) if tag.attr["limit"].nil?
|
28
|
+
limit = tag.attr["limit"].to_i
|
29
|
+
range = if tag.attr["zerobased"].nil? or tag.attr["zerobased"] == "no"
|
30
|
+
(1..limit)
|
31
|
+
else
|
32
|
+
(0...limit)
|
33
|
+
end
|
34
|
+
out = []
|
35
|
+
range.each do |n|
|
36
|
+
@num = n
|
37
|
+
out << self.parse(tag.thing)
|
38
|
+
end
|
39
|
+
out.join("\n")
|
40
|
+
end
|
41
|
+
|
42
|
+
def num(tag)
|
43
|
+
@num.to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
txp = MyParse.new
|
49
|
+
|
50
|
+
orig = %{
|
51
|
+
<dmstk:doctype />
|
52
|
+
<dmstk:body>
|
53
|
+
<dmstk:uppercase>
|
54
|
+
<dmstk:count limit="5" zerobased="yes">
|
55
|
+
Línea <var:num />
|
56
|
+
Esto es una <dmstk:strong>primera <em>impresión</em> de</dmstk:strong>
|
57
|
+
prueba de var:parseo de cosas...
|
58
|
+
</dmstk:count>
|
59
|
+
</dmstk:uppercase>
|
60
|
+
</dmstk:body>
|
61
|
+
}
|
62
|
+
|
63
|
+
txt = txp.parse(orig)
|
64
|
+
|
65
|
+
puts txt
|
@@ -0,0 +1,139 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "txparse.h"
|
3
|
+
|
4
|
+
extern "C" VALUE txp_initialize(VALUE self)
|
5
|
+
{
|
6
|
+
return self;
|
7
|
+
}
|
8
|
+
|
9
|
+
extern "C" VALUE txp_domain(VALUE self)
|
10
|
+
{
|
11
|
+
// Dejo esto como ejemplo de llamada a "rb_funcall", quitar después...
|
12
|
+
// VALUE txt = rb_iv_get(self, "@texto");
|
13
|
+
// return rb_funcall(txt, rb_intern("size"), 0);
|
14
|
+
return rb_str_new2(txp_domain_str.c_str());
|
15
|
+
}
|
16
|
+
|
17
|
+
extern "C" VALUE txp_domain_set(VALUE self, VALUE new_domain)
|
18
|
+
{
|
19
|
+
txp_domain_str = StringValueCStr(new_domain);
|
20
|
+
return rb_str_new2(txp_domain_str.c_str());
|
21
|
+
}
|
22
|
+
|
23
|
+
extern "C" VALUE txp_parse(VALUE self, VALUE orig)
|
24
|
+
{
|
25
|
+
// Lanza una excepción si no hay bloque...
|
26
|
+
// (rb_yield lanza una excepcion "LocalJump... noseque" de todas formas,
|
27
|
+
// pero parece buena idea comprobar al principio y no hacer nada si
|
28
|
+
// no tenemos bloque)...
|
29
|
+
// rb_need_block();
|
30
|
+
|
31
|
+
// rb_check_type tampoco retorna... (rb_raise no retorna, y esta funcion
|
32
|
+
// llama a rb_raise(rb_eTypeError, ...) si los tipos no coinciden)
|
33
|
+
rb_check_type(orig, T_STRING);
|
34
|
+
|
35
|
+
// Mmmmhhh... Lo anterior no es muy "rubyish", quizá debería ser
|
36
|
+
// suficiente con llamar al "to_s" del @texto en caso de que éste no sea
|
37
|
+
// de tipo String, de esta forma podríamos usar más tipos, pero...
|
38
|
+
// a costa de la velocidad.
|
39
|
+
|
40
|
+
// OK, "semos" un string...
|
41
|
+
// NOTA: Acceder mediante el macro RSTRING es un poco peligroso, pero
|
42
|
+
// es rápido ya que accedemos directamente a la estructura que almacena
|
43
|
+
// un string en ruby. Lo podemos hacer aquí más o menos seguro porque
|
44
|
+
// nos hemos asegurado que @texto es un String. Para conversiones, mirar
|
45
|
+
// la referencia de las funciones "rb_string_value" y "rb_string_value_cstr"
|
46
|
+
string::const_iterator iter(RSTRING(orig)->ptr);
|
47
|
+
|
48
|
+
return txp_parse_private(self, iter, iter + RSTRING(orig)->len);
|
49
|
+
}
|
50
|
+
|
51
|
+
VALUE txp_parse_private(
|
52
|
+
VALUE self,
|
53
|
+
string::const_iterator begin,
|
54
|
+
string::const_iterator end
|
55
|
+
)
|
56
|
+
{
|
57
|
+
VALUE ret = rb_str_new2("");
|
58
|
+
string::const_iterator old = begin;
|
59
|
+
|
60
|
+
while (begin != end) {
|
61
|
+
begin = txp_find_tag(begin, end);
|
62
|
+
|
63
|
+
if (begin != old) {
|
64
|
+
// Texto normal antes de un tag...
|
65
|
+
// rb_yield(rb_str_new(&(*old), begin - old));
|
66
|
+
rb_str_cat(ret, &(*old), begin - old);
|
67
|
+
old = begin;
|
68
|
+
}
|
69
|
+
|
70
|
+
if (begin != end) {
|
71
|
+
// Estamos en un tag...
|
72
|
+
begin = txp_find_close(begin, end);
|
73
|
+
if (begin != end) {
|
74
|
+
// FIXME: Este es el primer elemento a optimizar. Al crear
|
75
|
+
// un tag, ahora mismo tenemos que hacer dos copias de texto,
|
76
|
+
// una para crear un VALUE para instanciar un TXParse::Tag y
|
77
|
+
// luego otra, para crear un std::string desde este VALUE...
|
78
|
+
VALUE tag_txt = rb_str_new2(string(old, begin).c_str());
|
79
|
+
VALUE tag = rb_class_new_instance(1, &tag_txt, rb_const_get(mTXParse, rb_intern("Tag")));
|
80
|
+
|
81
|
+
// OK, tenemos el tag... Debemos buscar el "par" de cierre
|
82
|
+
// en caso de que este tag no sea de "autocierre"
|
83
|
+
VALUE closed = rb_iv_get(tag, "@is_close");
|
84
|
+
if (closed == Qfalse) {
|
85
|
+
// Buscamos el tag de cierre...
|
86
|
+
old = begin;
|
87
|
+
begin = txp_find_par(begin, end, tag);
|
88
|
+
if (begin != end) {
|
89
|
+
rb_iv_set(tag, "@thing", rb_str_new2(string(old, begin).c_str()));
|
90
|
+
// Vale, aquí habría que adelantar "begin" para saltar
|
91
|
+
// el tag de cierre...
|
92
|
+
begin = txp_find_close(begin+1, end);
|
93
|
+
} else {
|
94
|
+
// TODO:
|
95
|
+
// Retomamos donde estábamos... ¿Debería ser ERROR?
|
96
|
+
// SI: Tag mal balanceado si el tag original NO era
|
97
|
+
// de autocierre...
|
98
|
+
|
99
|
+
// begin = old;
|
100
|
+
rb_raise(rb_eSyntaxError, "Unbalanced tag '%s'", RSTRING(rb_iv_get(tag, "@name"))->ptr);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
VALUE domain = rb_iv_get(tag, "@domain");
|
105
|
+
VALUE tag_name = rb_iv_get(tag, "@name");
|
106
|
+
rb_str_append(domain, rb_str_new2("_"));
|
107
|
+
rb_str_append(domain, tag_name);
|
108
|
+
VALUE tmp = rb_funcall2(self, rb_intern(StringValueCStr(domain)), 1, &tag);
|
109
|
+
// VALUE tmp = rb_yield(tag);
|
110
|
+
|
111
|
+
if (!NIL_P(tmp)) rb_str_append(ret, tmp);
|
112
|
+
} else {
|
113
|
+
rb_str_cat(ret, &(*old), begin - old);
|
114
|
+
}
|
115
|
+
old = begin;
|
116
|
+
}
|
117
|
+
}
|
118
|
+
return ret;
|
119
|
+
}
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
VALUE mTXParse = Qnil;
|
124
|
+
extern "C" void Init_TXParse()
|
125
|
+
{
|
126
|
+
mTXParse = rb_define_module("TXParse");
|
127
|
+
|
128
|
+
rb_define_method(mTXParse, "initialize", RUBY_METHOD_FUNC(txp_initialize), 0);
|
129
|
+
rb_define_method(mTXParse, "domain", RUBY_METHOD_FUNC(txp_domain), 0);
|
130
|
+
rb_define_method(mTXParse, "domain=", RUBY_METHOD_FUNC(txp_domain_set), 1);
|
131
|
+
rb_define_method(mTXParse, "parse", RUBY_METHOD_FUNC(txp_parse), 1);
|
132
|
+
|
133
|
+
Init_TXParseTag();
|
134
|
+
}
|
135
|
+
|
136
|
+
extern "C" void Init_txparse()
|
137
|
+
{
|
138
|
+
Init_TXParse();
|
139
|
+
}
|