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 ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
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,9 @@
1
+ #!/usr/bin/env ruby
2
+ # Command line utility for TXPRails
3
+
4
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
5
+ require 'txprails'
6
+ require 'txprails/commands'
7
+
8
+ opts = TXPRails::Commands.new(ARGV)
9
+ opts.parse!
@@ -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,8 @@
1
+ require 'mkmf'
2
+
3
+ case RUBY_PLATFORM
4
+ when /darwin/, /linux/
5
+ CONFIG['LDSHARED'] = "$(CXX) " + CONFIG['LDSHARED'].split[1..-1].join(' ')
6
+ end
7
+
8
+ create_makefile('txprails/txparse')
@@ -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
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef TXPARSE_H
2
+ #define TXPARSE_H
3
+
4
+ #include "txparse_lib.h"
5
+ #include "txparse_tag.h"
6
+
7
+ VALUE txp_parse_private(
8
+ VALUE self,
9
+ string::const_iterator begin,
10
+ string::const_iterator end
11
+ );
12
+
13
+ extern VALUE mTXParse;
14
+
15
+ #endif