txprails 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|