walrus 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/walrus +44 -0
- data/ext/jindex/extconf.rb +11 -0
- data/ext/jindex/jindex.c +79 -0
- data/ext/mkdtemp/extconf.rb +11 -0
- data/ext/mkdtemp/mkdtemp.c +41 -0
- data/lib/walrus/additions/module.rb +36 -0
- data/lib/walrus/additions/string.rb +37 -0
- data/lib/walrus/additions/test/unit/error_collector.rb +62 -0
- data/lib/walrus/compile_error.rb +28 -0
- data/lib/walrus/compiler.rb +124 -0
- data/lib/walrus/contrib/spec/walruscloth_spec.rb +32 -0
- data/lib/walrus/contrib/walruscloth.rb +82 -0
- data/lib/walrus/diff.rb +89 -0
- data/lib/walrus/document.rb +98 -0
- data/lib/walrus/grammar/additions/proc.rb +20 -0
- data/lib/walrus/grammar/additions/regexp.rb +21 -0
- data/lib/walrus/grammar/additions/string.rb +52 -0
- data/lib/walrus/grammar/additions/symbol.rb +42 -0
- data/lib/walrus/grammar/and_predicate.rb +40 -0
- data/lib/walrus/grammar/array_result.rb +19 -0
- data/lib/walrus/grammar/continuation_wrapper_exception.rb +28 -0
- data/lib/walrus/grammar/left_recursion_exception.rb +27 -0
- data/lib/walrus/grammar/location_tracking.rb +105 -0
- data/lib/walrus/grammar/match_data_wrapper.rb +65 -0
- data/lib/walrus/grammar/memoizing.rb +41 -0
- data/lib/walrus/grammar/memoizing_cache.rb +94 -0
- data/lib/walrus/grammar/node.rb +60 -0
- data/lib/walrus/grammar/not_predicate.rb +40 -0
- data/lib/walrus/grammar/parse_error.rb +39 -0
- data/lib/walrus/grammar/parser_state.rb +181 -0
- data/lib/walrus/grammar/parslet.rb +28 -0
- data/lib/walrus/grammar/parslet_choice.rb +120 -0
- data/lib/walrus/grammar/parslet_combination.rb +26 -0
- data/lib/walrus/grammar/parslet_combining.rb +154 -0
- data/lib/walrus/grammar/parslet_merge.rb +88 -0
- data/lib/walrus/grammar/parslet_omission.rb +57 -0
- data/lib/walrus/grammar/parslet_repetition.rb +97 -0
- data/lib/walrus/grammar/parslet_repetition_default.rb +58 -0
- data/lib/walrus/grammar/parslet_sequence.rb +202 -0
- data/lib/walrus/grammar/predicate.rb +57 -0
- data/lib/walrus/grammar/proc_parslet.rb +52 -0
- data/lib/walrus/grammar/regexp_parslet.rb +73 -0
- data/lib/walrus/grammar/skipped_substring_exception.rb +36 -0
- data/lib/walrus/grammar/string_enumerator.rb +45 -0
- data/lib/walrus/grammar/string_parslet.rb +75 -0
- data/lib/walrus/grammar/string_result.rb +24 -0
- data/lib/walrus/grammar/symbol_parslet.rb +63 -0
- data/lib/walrus/grammar.rb +170 -0
- data/lib/walrus/no_parameter_marker.rb +19 -0
- data/lib/walrus/parser.rb +420 -0
- data/lib/walrus/runner.rb +356 -0
- data/lib/walrus/template.rb +75 -0
- data/lib/walrus/walrus_grammar/assignment_expression.rb +24 -0
- data/lib/walrus/walrus_grammar/block_directive.rb +28 -0
- data/lib/walrus/walrus_grammar/comment.rb +24 -0
- data/lib/walrus/walrus_grammar/def_directive.rb +64 -0
- data/lib/walrus/walrus_grammar/echo_directive.rb +44 -0
- data/lib/walrus/walrus_grammar/escape_sequence.rb +24 -0
- data/lib/walrus/walrus_grammar/import_directive.rb +44 -0
- data/lib/walrus/walrus_grammar/include_directive.rb +27 -0
- data/lib/walrus/walrus_grammar/instance_variable.rb +24 -0
- data/lib/walrus/walrus_grammar/literal.rb +24 -0
- data/lib/walrus/walrus_grammar/message_expression.rb +25 -0
- data/lib/walrus/walrus_grammar/multiline_comment.rb +54 -0
- data/lib/walrus/walrus_grammar/placeholder.rb +40 -0
- data/lib/walrus/walrus_grammar/raw_directive.rb +42 -0
- data/lib/walrus/walrus_grammar/raw_text.rb +45 -0
- data/lib/walrus/walrus_grammar/ruby_directive.rb +29 -0
- data/lib/walrus/walrus_grammar/ruby_expression.rb +31 -0
- data/lib/walrus/walrus_grammar/set_directive.rb +24 -0
- data/lib/walrus/walrus_grammar/silent_directive.rb +44 -0
- data/lib/walrus/walrus_grammar/slurp_directive.rb +25 -0
- data/lib/walrus/walrus_grammar/super_directive.rb +27 -0
- data/lib/walrus.rb +64 -0
- data/spec/acceptance/acceptance_spec.rb +97 -0
- data/spec/acceptance/block/basic_block.expected +1 -0
- data/spec/acceptance/block/basic_block.tmpl +3 -0
- data/spec/acceptance/block/nested_blocks.expected +5 -0
- data/spec/acceptance/block/nested_blocks.tmpl +11 -0
- data/spec/acceptance/comments/comments_and_text.expected +3 -0
- data/spec/acceptance/comments/comments_and_text.tmpl +6 -0
- data/spec/acceptance/comments/single_comment.expected +0 -0
- data/spec/acceptance/comments/single_comment.tmpl +1 -0
- data/spec/acceptance/def/alternative_def_calling_conventions.expected +3 -0
- data/spec/acceptance/def/alternative_def_calling_conventions.tmpl +18 -0
- data/spec/acceptance/def/basic_def_block_no_output.expected +0 -0
- data/spec/acceptance/def/basic_def_block_no_output.tmpl +17 -0
- data/spec/acceptance/def/defs_can_be_called_multiple_times.expected +3 -0
- data/spec/acceptance/def/defs_can_be_called_multiple_times.tmpl +6 -0
- data/spec/acceptance/def/defs_can_be_dynamic.expected +4 -0
- data/spec/acceptance/def/defs_can_be_dynamic.tmpl +12 -0
- data/spec/acceptance/echo/echo_directive_with_numeric_literal.expected +1 -0
- data/spec/acceptance/echo/echo_directive_with_numeric_literal.tmpl +1 -0
- data/spec/acceptance/echo/echo_expression_list.expected +1 -0
- data/spec/acceptance/echo/echo_expression_list.tmpl +1 -0
- data/spec/acceptance/echo/echo_short_notation.expected +1 -0
- data/spec/acceptance/echo/echo_short_notation.tmpl +1 -0
- data/spec/acceptance/echo/echo_simple_expression.expected +1 -0
- data/spec/acceptance/echo/echo_simple_expression.tmpl +1 -0
- data/spec/acceptance/echo/echo_single_quoted_string_literal.expected +1 -0
- data/spec/acceptance/echo/echo_single_quoted_string_literal.tmpl +1 -0
- data/spec/acceptance/echo/multiple_echo_statements.expected +1 -0
- data/spec/acceptance/echo/multiple_echo_statements.tmpl +2 -0
- data/spec/acceptance/includes/basic_included_file.txt +1 -0
- data/spec/acceptance/includes/basic_includer.complex +3 -0
- data/spec/acceptance/includes/basic_includer.expected +3 -0
- data/spec/acceptance/includes/basic_includer.rb +38 -0
- data/spec/acceptance/includes/complicated_included_file.txt +3 -0
- data/spec/acceptance/includes/complicated_includer.complex +3 -0
- data/spec/acceptance/includes/complicated_includer.expected +3 -0
- data/spec/acceptance/includes/complicated_includer.rb +41 -0
- data/spec/acceptance/includes/nested_include_1.txt +3 -0
- data/spec/acceptance/includes/nested_include_2.txt +1 -0
- data/spec/acceptance/includes/nested_includer.complex +3 -0
- data/spec/acceptance/includes/nested_includer.expected +4 -0
- data/spec/acceptance/includes/nested_includer.rb +41 -0
- data/spec/acceptance/inheritance/basic_child.complex +10 -0
- data/spec/acceptance/inheritance/basic_child.expected +9 -0
- data/spec/acceptance/inheritance/basic_child.rb +54 -0
- data/spec/acceptance/inheritance/basic_parent.complex +5 -0
- data/spec/acceptance/inheritance/basic_parent.expected +3 -0
- data/spec/acceptance/inheritance/basic_parent.rb +41 -0
- data/spec/acceptance/inheritance/importing_child.complex +8 -0
- data/spec/acceptance/inheritance/importing_child.expected +7 -0
- data/spec/acceptance/inheritance/importing_child.rb +46 -0
- data/spec/acceptance/inheritance/subdirectory/importing_child_in_subdirectory.complex +8 -0
- data/spec/acceptance/inheritance/subdirectory/importing_child_in_subdirectory.expected +7 -0
- data/spec/acceptance/inheritance/subdirectory/importing_child_in_subdirectory.rb +44 -0
- data/spec/acceptance/multiline_comments/multiline_comment_with_directives_inside.expected +0 -0
- data/spec/acceptance/multiline_comments/multiline_comment_with_directives_inside.tmpl +15 -0
- data/spec/acceptance/multiline_comments/simple_multiline_comment.expected +2 -0
- data/spec/acceptance/multiline_comments/simple_multiline_comment.tmpl +4 -0
- data/spec/acceptance/raw/complicated_raw_example.expected +57 -0
- data/spec/acceptance/raw/complicated_raw_example.tmpl +79 -0
- data/spec/acceptance/raw-text/UTF_8.expected +12 -0
- data/spec/acceptance/raw-text/UTF_8.tmpl +12 -0
- data/spec/acceptance/raw-text/empty_file.expected +0 -0
- data/spec/acceptance/raw-text/empty_file.tmpl +0 -0
- data/spec/acceptance/raw-text/multi_line.expected +4 -0
- data/spec/acceptance/raw-text/multi_line.tmpl +4 -0
- data/spec/acceptance/raw-text/single_line.expected +1 -0
- data/spec/acceptance/raw-text/single_line.tmpl +1 -0
- data/spec/acceptance/raw-text/single_line_whitespace.expected +1 -0
- data/spec/acceptance/raw-text/single_line_whitespace.tmpl +1 -0
- data/spec/acceptance/ruby/ruby_directive_is_just_like_silent.expected +1 -0
- data/spec/acceptance/ruby/ruby_directive_is_just_like_silent.tmpl +4 -0
- data/spec/acceptance/ruby/ruby_directive_using_here_doc.expected +1 -0
- data/spec/acceptance/ruby/ruby_directive_using_here_doc.tmpl +4 -0
- data/spec/acceptance/ruby/ruby_directive_using_here_doc_alt_syntax.expected +1 -0
- data/spec/acceptance/ruby/ruby_directive_using_here_doc_alt_syntax.tmpl +4 -0
- data/spec/acceptance/ruby/ruby_directive_with_accumulate.expected +1 -0
- data/spec/acceptance/ruby/ruby_directive_with_accumulate.tmpl +4 -0
- data/spec/acceptance/ruby/ruby_directive_with_accumulate_and_block.expected +1 -0
- data/spec/acceptance/ruby/ruby_directive_with_accumulate_and_block.tmpl +6 -0
- data/spec/acceptance/set/unused_set.expected +0 -0
- data/spec/acceptance/set/unused_set.tmpl +1 -0
- data/spec/acceptance/set/used_set.expected +1 -0
- data/spec/acceptance/set/used_set.tmpl +2 -0
- data/spec/acceptance/silent/silent_and_echo_combined.expected +1 -0
- data/spec/acceptance/silent/silent_and_echo_combined.tmpl +2 -0
- data/spec/acceptance/silent/silent_short_notation.expected +1 -0
- data/spec/acceptance/silent/silent_short_notation.tmpl +1 -0
- data/spec/acceptance/silent/simple_silent_directive.expected +0 -0
- data/spec/acceptance/silent/simple_silent_directive.tmpl +1 -0
- data/spec/acceptance/slurp/basic_slurp_demo.expected +1 -0
- data/spec/acceptance/slurp/basic_slurp_demo.tmpl +4 -0
- data/spec/acceptance/super/super_with_no_effect.expected +4 -0
- data/spec/acceptance/super/super_with_no_effect.tmpl +5 -0
- data/spec/additions/module_spec.rb +126 -0
- data/spec/additions/string_spec.rb +99 -0
- data/spec/compiler_spec.rb +55 -0
- data/spec/grammar/additions/proc_spec.rb +25 -0
- data/spec/grammar/additions/regexp_spec.rb +37 -0
- data/spec/grammar/additions/string_spec.rb +106 -0
- data/spec/grammar/and_predicate_spec.rb +29 -0
- data/spec/grammar/continuation_wrapper_exception_spec.rb +23 -0
- data/spec/grammar/match_data_wrapper_spec.rb +41 -0
- data/spec/grammar/memoizing_cache_spec.rb +112 -0
- data/spec/grammar/node_spec.rb +126 -0
- data/spec/grammar/not_predicate_spec.rb +29 -0
- data/spec/grammar/parser_state_spec.rb +172 -0
- data/spec/grammar/parslet_choice_spec.rb +49 -0
- data/spec/grammar/parslet_combining_spec.rb +287 -0
- data/spec/grammar/parslet_merge_spec.rb +33 -0
- data/spec/grammar/parslet_omission_spec.rb +58 -0
- data/spec/grammar/parslet_repetition_spec.rb +77 -0
- data/spec/grammar/parslet_sequence_spec.rb +49 -0
- data/spec/grammar/parslet_spec.rb +23 -0
- data/spec/grammar/predicate_spec.rb +53 -0
- data/spec/grammar/proc_parslet_spec.rb +52 -0
- data/spec/grammar/regexp_parslet_spec.rb +347 -0
- data/spec/grammar/string_enumerator_spec.rb +94 -0
- data/spec/grammar/string_parslet_spec.rb +143 -0
- data/spec/grammar/symbol_parslet_spec.rb +30 -0
- data/spec/grammar_spec.rb +545 -0
- data/spec/parser_spec.rb +1418 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/walrus_grammar/comment_spec.rb +39 -0
- data/spec/walrus_grammar/echo_directive_spec.rb +63 -0
- data/spec/walrus_grammar/escape_sequence_spec.rb +85 -0
- data/spec/walrus_grammar/literal_spec.rb +41 -0
- data/spec/walrus_grammar/message_expression_spec.rb +37 -0
- data/spec/walrus_grammar/multiline_comment_spec.rb +58 -0
- data/spec/walrus_grammar/placeholder_spec.rb +48 -0
- data/spec/walrus_grammar/raw_directive_spec.rb +81 -0
- data/spec/walrus_grammar/raw_text_spec.rb +65 -0
- data/spec/walrus_grammar/silent_directive_spec.rb +34 -0
- metadata +291 -0
data/bin/walrus
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright 2007 Wincent Colaiuta
|
3
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
4
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
5
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
6
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
7
|
+
#
|
8
|
+
# $Id: diff.rb 89 2007-02-26 15:35:56Z wincent $
|
9
|
+
|
10
|
+
module Walrus
|
11
|
+
|
12
|
+
EXIT_LOAD_ERROR = 1
|
13
|
+
EXIT_ARGUMENT_ERROR = 2
|
14
|
+
EXIT_OTHER_ERROR = 3
|
15
|
+
|
16
|
+
begin
|
17
|
+
require 'walrus/runner'
|
18
|
+
rescue LoadError => e
|
19
|
+
$stderr.puts <<-HERE
|
20
|
+
Error: load error (#{e.to_s})
|
21
|
+
|
22
|
+
If you are trying to run Walrus but have not yet installed it, it may be that
|
23
|
+
Ruby cannot find the Walrus files. You can help Ruby to find the Walrus "lib"
|
24
|
+
and "ext" directories by adding them to the RUBYLIB environment variable. For
|
25
|
+
example, you could do the following if you are using the Bash shell,
|
26
|
+
substituting absolute paths for "lib" and "ext":
|
27
|
+
|
28
|
+
export RUBYLIB="${RUBYLIB}:lib:ext"
|
29
|
+
|
30
|
+
HERE
|
31
|
+
exit EXIT_LOAD_ERROR
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
Runner.new.run
|
36
|
+
rescue Runner::ArgumentError => e
|
37
|
+
$stderr.puts "Error: #{e.to_s}", "For usage information type: #{$0} --help"
|
38
|
+
exit EXIT_ARGUMENT_ERROR
|
39
|
+
rescue Runner::Error => e
|
40
|
+
$stderr.puts "Error: #{e.to_s}"
|
41
|
+
exit EXIT_OTHER_ERROR
|
42
|
+
end
|
43
|
+
|
44
|
+
end # module Walrus
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
6
|
+
#
|
7
|
+
# $Id$
|
8
|
+
|
9
|
+
require 'mkmf'
|
10
|
+
create_makefile('jindex')
|
11
|
+
|
data/ext/jindex/jindex.c
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
/*
|
2
|
+
Copyright 2007 Wincent Colaiuta
|
3
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
4
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
5
|
+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
6
|
+
in the accompanying file, "LICENSE.txt", for more details.
|
7
|
+
|
8
|
+
$Id$
|
9
|
+
*/
|
10
|
+
|
11
|
+
#include <ruby.h>
|
12
|
+
|
13
|
+
/*
|
14
|
+
|
15
|
+
Common code used by almost identical "jindex" and "jrindex" methods. A C extension is necessary here because with direct access to the rb_backref_get and rb_backref_set API there is no way to propagate $~ back to the caller after invoking the "index" and "rindex" methods. The code is basically equivalent to the following Ruby code:
|
16
|
+
|
17
|
+
def index arg1, optional_arg
|
18
|
+
index = super # plus code here for deciding whether or not to pass optional argument
|
19
|
+
match = ($~ ? $~.clone : nil)
|
20
|
+
index unpack('C*')[0...index].pack('C*').jlength # jlength clobbers $~ as a side effect, should consider rewriting it
|
21
|
+
$~ = match # in pure Ruby setting $~ here has only a local effect (not seen by caller)
|
22
|
+
index
|
23
|
+
end
|
24
|
+
|
25
|
+
*/
|
26
|
+
static VALUE walrus_str_index_common(ID func, int argc, VALUE *argv, VALUE str)
|
27
|
+
{
|
28
|
+
VALUE jindex = Qnil; /* default return value */
|
29
|
+
VALUE index = rb_funcall2(str, func, argc, argv); /* call String#index or String#rindex*/
|
30
|
+
VALUE match = rb_backref_get(); /* save $~ */
|
31
|
+
if (!NIL_P(index))
|
32
|
+
{
|
33
|
+
VALUE packing_format = rb_str_new2("C*");
|
34
|
+
VALUE unpacked = rb_funcall(str, rb_intern("unpack"), 1, packing_format); /* unpack('C*') */
|
35
|
+
VALUE range = rb_funcall(rb_cRange, rb_intern("new"), 3, INT2FIX(0), index, Qtrue);
|
36
|
+
VALUE slice = rb_funcall(unpacked, rb_intern("slice"), 1, range); /* [0...idx] */
|
37
|
+
VALUE packed = rb_funcall(slice, rb_intern("pack"), 1, packing_format); /* pack('C*') */
|
38
|
+
jindex = rb_funcall(packed, rb_intern("jlength"), 0); /* jlength */
|
39
|
+
}
|
40
|
+
rb_backref_set(match); /* restore $~ */
|
41
|
+
return jindex;
|
42
|
+
}
|
43
|
+
|
44
|
+
/*
|
45
|
+
|
46
|
+
call-seq:
|
47
|
+
str.jindex(substring [, offset]) -> Fixnum or nil
|
48
|
+
str.jindex(fixnum [, offset]) -> Fixnum or nil
|
49
|
+
str.jindex(regexp [, offset]) -> Fixnum or nil
|
50
|
+
|
51
|
+
Multibyte-friendly equivalent of the String#index method. If $KCODE is appropriately set will return an accurate index based on character count rather than byte counts.
|
52
|
+
|
53
|
+
*/
|
54
|
+
static VALUE walrus_str_jindex_m(int argc, VALUE *argv, VALUE str)
|
55
|
+
{
|
56
|
+
return walrus_str_index_common(rb_intern("index"), argc, argv, str);
|
57
|
+
}
|
58
|
+
|
59
|
+
/*
|
60
|
+
|
61
|
+
call-seq:
|
62
|
+
str.jrindex(substring [, offset]) -> Fixnum or nil
|
63
|
+
str.jrindex(fixnum [, offset]) -> Fixnum or nil
|
64
|
+
str.jrindex(regexp [, offset]) -> Fixnum or nil
|
65
|
+
|
66
|
+
Multibyte-friendly equivalent of the String#rindex method. If $KCODE is appropriately set will return an accurate index based on character count rather than byte counts.
|
67
|
+
|
68
|
+
*/
|
69
|
+
static VALUE walrus_str_jrindex_m(int argc, VALUE *argv, VALUE str)
|
70
|
+
{
|
71
|
+
return walrus_str_index_common(rb_intern("rindex"), argc, argv, str);
|
72
|
+
}
|
73
|
+
|
74
|
+
void Init_jindex()
|
75
|
+
{
|
76
|
+
rb_define_method(rb_cString, "jindex", walrus_str_jindex_m, -1);
|
77
|
+
rb_define_method(rb_cString, "jrindex", walrus_str_jrindex_m, -1);
|
78
|
+
}
|
79
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
6
|
+
#
|
7
|
+
# $Id$
|
8
|
+
|
9
|
+
require 'mkmf'
|
10
|
+
create_makefile('mkdtemp')
|
11
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
/*
|
2
|
+
Copyright 2007 Wincent Colaiuta
|
3
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
4
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
5
|
+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
6
|
+
in the accompanying file, "LICENSE.txt", for more details.
|
7
|
+
|
8
|
+
$Id$
|
9
|
+
*/
|
10
|
+
|
11
|
+
#include <ruby.h>
|
12
|
+
#include <errno.h>
|
13
|
+
|
14
|
+
/*
|
15
|
+
|
16
|
+
call-seq:
|
17
|
+
Dir.mkdtemp([string]) -> String or nil
|
18
|
+
|
19
|
+
This method securely creates temporary directories. It is a wrapper for the mkdtemp() function in the standard C library. It takes an optional String parameter as a template describing the desired form of the directory name; if no template is supplied then "/tmp/temp.XXXXXX" is used as a default.
|
20
|
+
|
21
|
+
*/
|
22
|
+
static VALUE walrus_dir_mkdtemp_m(int argc, VALUE *argv, VALUE self)
|
23
|
+
{
|
24
|
+
VALUE template;
|
25
|
+
if (rb_scan_args(argc, argv, "01", &template) == 0) /* check for 0 mandatory arguments, 1 optional argument */
|
26
|
+
template = Qnil; /* default to nil if no argument passed */
|
27
|
+
if (NIL_P(template))
|
28
|
+
template = rb_str_new2("/tmp/temp.XXXXXX"); /* fallback to this template if passed nil */
|
29
|
+
SafeStringValue(template); /* raises if template is tainted and SAFE level > 0 */
|
30
|
+
VALUE safe = StringValue(template); /* duck typing support */
|
31
|
+
char *path = mkdtemp(RSTRING(safe)->ptr);
|
32
|
+
if (path == NULL)
|
33
|
+
rb_raise(rb_eSystemCallError, "mkdtemp failed (error: %d)", errno);
|
34
|
+
return rb_str_new2(path);
|
35
|
+
}
|
36
|
+
|
37
|
+
void Init_mkdtemp()
|
38
|
+
{
|
39
|
+
rb_define_module_function(rb_cDir, "mkdtemp", walrus_dir_mkdtemp_m, -1);
|
40
|
+
}
|
41
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
6
|
+
#
|
7
|
+
# $Id$
|
8
|
+
|
9
|
+
require 'walrus'
|
10
|
+
|
11
|
+
class Module
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def attr_accessor_bycopy(*symbols)
|
16
|
+
symbols.each { |symbol| attr_bycopy(symbol, true) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def attr_bycopy(symbol, writeable = false)
|
20
|
+
attr_reader symbol
|
21
|
+
attr_writer_bycopy(symbol) if writeable
|
22
|
+
end
|
23
|
+
|
24
|
+
def attr_writer_bycopy(*symbols)
|
25
|
+
symbols.each do |symbol|
|
26
|
+
self.module_eval %Q{
|
27
|
+
def #{symbol.id2name}=(value)
|
28
|
+
@#{symbol.id2name} = value.clone
|
29
|
+
rescue TypeError
|
30
|
+
@#{symbol.id2name} = value
|
31
|
+
end
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end # class Module
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
6
|
+
#
|
7
|
+
# $Id$
|
8
|
+
|
9
|
+
require 'walrus'
|
10
|
+
|
11
|
+
# Additions to String class for Unicode support.
|
12
|
+
class String
|
13
|
+
|
14
|
+
# Converts the receiver of the form "FooBar" to "foo_bar".
|
15
|
+
# Concretely, the receiver is split into words, each word lowercased, and the words are joined together using a lower-case separator. "Words" are considered to be runs of characters starting with an initial capital letter (note that words may begin with consecutive capital letters), and numbers may mark the start or the end of a word.
|
16
|
+
# Note that some information loss may be incurred; for example, "EOLToken" would be reduced to "eol_token".
|
17
|
+
def to_require_name
|
18
|
+
base = self.gsub(/([^A-Z_])([A-Z])/, '\1_\2') # insert an underscore before any initial capital letters
|
19
|
+
base.gsub!(/([A-Z])([A-Z])([^A-Z0-9_])/, '\1_\2\3') # consecutive capitals are words too, excluding any following capital that belongs to the next word
|
20
|
+
base.gsub!(/([^0-9_])(\d)/, '\1_\2') # numbers mark the start of a new word
|
21
|
+
base.gsub!(/(\d)([^0-9_])/, '\1_\2') # numbers also mark the end of a word
|
22
|
+
base.downcase # lowercase everything
|
23
|
+
end
|
24
|
+
|
25
|
+
# Converts the receiver of the form "foo_bar" to "FooBar".
|
26
|
+
# Specifically, the receiver is split into pieces delimited by underscores, each component is then converted to captial case (the first letter is capitalized and the remaining letters are lowercased) and finally the components are joined.
|
27
|
+
# Note that this method cannot recover information lost during a conversion using the require_name_from_classname method; for example, "EOL", when converted to "token", would be transformed back to "EolToken". Likewise, "Foo__bar" would be reduced to "foo__bar" and then in the reverse conversion would become "FooBar".
|
28
|
+
def to_class_name
|
29
|
+
self.split('_').collect { |component| component.capitalize}.join
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns a copy of the receiver with occurrences of \ replaced with \\, and occurrences of ' replaced with \'
|
33
|
+
def to_source_string
|
34
|
+
gsub(/[\\']/, '\\\\\&')
|
35
|
+
end
|
36
|
+
|
37
|
+
end # class String
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
2
|
+
# $Id$
|
3
|
+
|
4
|
+
require 'walrus'
|
5
|
+
|
6
|
+
module Test
|
7
|
+
module Unit
|
8
|
+
|
9
|
+
# See http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/138320
|
10
|
+
# Usage:
|
11
|
+
#
|
12
|
+
# require 'test/unit'
|
13
|
+
# require 'walrus/additions/test/unit/error_collector'
|
14
|
+
#
|
15
|
+
# class TestClass < Test::Unit::TestCase
|
16
|
+
#
|
17
|
+
# include Test::Unit::ErrorCollector
|
18
|
+
#
|
19
|
+
# def test_method
|
20
|
+
# collecting_errors do
|
21
|
+
# assert false
|
22
|
+
# assert false
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
module ErrorCollector
|
29
|
+
|
30
|
+
def collecting_errors
|
31
|
+
# save state prior to yielding to block
|
32
|
+
is_collecting = @is_collecting
|
33
|
+
@is_collecting = true
|
34
|
+
yield
|
35
|
+
ensure
|
36
|
+
# restore state on leaving block
|
37
|
+
@is_collecting = is_collecting
|
38
|
+
end
|
39
|
+
|
40
|
+
def raise(*)
|
41
|
+
super
|
42
|
+
rescue Test::Unit::AssertionFailedError
|
43
|
+
handle_error(:add_failure, $!)
|
44
|
+
rescue StandardError, ScriptError
|
45
|
+
handle_error(:add_error, $!)
|
46
|
+
end
|
47
|
+
|
48
|
+
def handle_error(method, error)
|
49
|
+
backtrace = error.backtrace
|
50
|
+
backtrace.shift # raise shouldn't appear in the backtrace
|
51
|
+
if @is_collecting
|
52
|
+
backtrace.slice!(5, 2) # remove collecting_errors and corresponding block
|
53
|
+
send(method, error.message, backtrace)
|
54
|
+
else
|
55
|
+
Kernel.raise(error, error.message, backtrace)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
6
|
+
#
|
7
|
+
# $Id$
|
8
|
+
|
9
|
+
require 'walrus'
|
10
|
+
|
11
|
+
module Walrus
|
12
|
+
class Grammar
|
13
|
+
|
14
|
+
class CompileError < Exception
|
15
|
+
|
16
|
+
# take an optional hash (for packing extra info into exception?)
|
17
|
+
# position in AST/source file
|
18
|
+
# line number, column number
|
19
|
+
# filename
|
20
|
+
def initialize(message, info = {})
|
21
|
+
super message
|
22
|
+
end
|
23
|
+
|
24
|
+
end # class CompileError
|
25
|
+
|
26
|
+
end # class Grammar
|
27
|
+
end # module Walrus
|
28
|
+
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
6
|
+
#
|
7
|
+
# $Id: /mirrors/Walrus/trunk/walrus/lib/walrus/compiler.rb 6709 2007-04-10T05:38:46.657919Z wincent $
|
8
|
+
|
9
|
+
require 'walrus'
|
10
|
+
require 'pathname'
|
11
|
+
|
12
|
+
module Walrus
|
13
|
+
class Compiler
|
14
|
+
|
15
|
+
BODY_INDENT = ' ' * 8
|
16
|
+
OUTSIDE_INDENT = ' ' * 6
|
17
|
+
DEFAULT_CLASS = 'DocumentSubclass'
|
18
|
+
|
19
|
+
# The public compiler class serves as the interface with the outside world. For thread-safety and concurrency, an inner, private Instance class is spawned in order to perform the actual compilation.
|
20
|
+
class Instance
|
21
|
+
|
22
|
+
def initialize(options)
|
23
|
+
@class_name = (options[:class_name] || DEFAULT_CLASS).to_s
|
24
|
+
@template_body = [] # will accumulate items for body, and joins them at the end of processing
|
25
|
+
@outside_body = [] # will accumulate items for outside of body, and joins them at the end of processing
|
26
|
+
end
|
27
|
+
|
28
|
+
def compile_subtree(subtree)
|
29
|
+
template_body = [] # local variable
|
30
|
+
outside_body = [] # local variable
|
31
|
+
subtree = [subtree] unless subtree.respond_to? :each
|
32
|
+
options = { :compiler_instance => self } # reset
|
33
|
+
subtree.each do |element|
|
34
|
+
# def/block and include directives may return two items
|
35
|
+
if element.kind_of? WalrusGrammar::DefDirective or element.kind_of? WalrusGrammar::IncludeDirective
|
36
|
+
inner, outer = element.compile(options)
|
37
|
+
outer.each { |line| outside_body << OUTSIDE_INDENT + line } if outer
|
38
|
+
inner.each { |line| template_body << BODY_INDENT + line } if inner
|
39
|
+
elsif element.instance_of? WalrusGrammar::ExtendsDirective # defines superclass and automatically invoke #super (super) at the head of the template_body
|
40
|
+
raise CompileError.new('#extends may be used only once per template') unless @extends_directive.nil?
|
41
|
+
raise CompileError.new('illegal #extends (#import already used in this template)') unless @import_directive.nil?
|
42
|
+
@extends_directive = element.compile(options)
|
43
|
+
elsif element.instance_of? WalrusGrammar::ImportDirective # defines superclass with no automatic invocation of #super on the template_body
|
44
|
+
raise CompileError.new('#import may be used only once per template') unless @import_directive.nil?
|
45
|
+
raise CompileError.new('illegal #import (#extends already used in this template)') unless @extends_directive.nil?
|
46
|
+
@import_directive = element.compile(options)
|
47
|
+
elsif element.kind_of? WalrusGrammar::Comment and element.column_start == 0 # special case if comment is only thing on input line
|
48
|
+
template_body << BODY_INDENT + element.compile(options)
|
49
|
+
options[:slurping] = true
|
50
|
+
next
|
51
|
+
else # everything else gets added to the template_body
|
52
|
+
element.compile(options).each { |line| template_body << BODY_INDENT + line } # indent by 6 spaces
|
53
|
+
end
|
54
|
+
options = { :compiler_instance => self } # reset
|
55
|
+
end
|
56
|
+
[template_body, outside_body]
|
57
|
+
end
|
58
|
+
|
59
|
+
def compile(tree)
|
60
|
+
inner, outer = compile_subtree(tree)
|
61
|
+
@template_body.concat inner if inner
|
62
|
+
@outside_body.concat outer if outer
|
63
|
+
if @import_directive
|
64
|
+
superclass_name = @import_directive.class_name
|
65
|
+
require_line = "require 'walrus/document'\n" + @import_directive.require_line
|
66
|
+
elsif @extends_directive
|
67
|
+
superclass_name = @extends_directive.class_name
|
68
|
+
require_line = "require 'walrus/document'\n" + @extends_directive.require_line
|
69
|
+
@template_body.unshift BODY_INDENT + "super # (invoked automatically due to Extends directive)\n"
|
70
|
+
else
|
71
|
+
superclass_name = 'Document'
|
72
|
+
require_line = "require 'walrus/document'"
|
73
|
+
end
|
74
|
+
|
75
|
+
<<-RETURN
|
76
|
+
\#!/usr/bin/env ruby
|
77
|
+
\# Generated #{Time.new.to_s} by Walrus version #{VERSION}
|
78
|
+
|
79
|
+
begin
|
80
|
+
require 'rubygems'
|
81
|
+
rescue LoadError
|
82
|
+
# installing Walrus via RubyGems is recommended
|
83
|
+
# otherwise Walrus must be installed in the RUBYLIB load path
|
84
|
+
end
|
85
|
+
|
86
|
+
#{require_line}
|
87
|
+
|
88
|
+
module Walrus
|
89
|
+
|
90
|
+
class WalrusGrammar
|
91
|
+
|
92
|
+
class #{@class_name} < #{superclass_name}
|
93
|
+
|
94
|
+
def template_body
|
95
|
+
|
96
|
+
#{@template_body.join}
|
97
|
+
end
|
98
|
+
|
99
|
+
#{@outside_body.join}
|
100
|
+
if __FILE__ == $0 # when run from the command line the default action is to call 'run'
|
101
|
+
new.run
|
102
|
+
end
|
103
|
+
|
104
|
+
end \# #{@class_name}
|
105
|
+
|
106
|
+
end \# WalrusGrammar
|
107
|
+
|
108
|
+
end \# Walrus
|
109
|
+
|
110
|
+
RETURN
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
# Walks the Abstract Syntax Tree, tree, that represents a parsed Walrus template.
|
117
|
+
# Returns a String that defines a Document subclass corresponding to the compiled version of the tree.
|
118
|
+
def compile(tree, options = {})
|
119
|
+
Instance.new(options).compile(tree)
|
120
|
+
end
|
121
|
+
|
122
|
+
end # class Compiler
|
123
|
+
end # module Walrus
|
124
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright 2007 Wincent Colaiuta
|
3
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
4
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
5
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
6
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
7
|
+
#
|
8
|
+
# $Id: /mirrors/Walrus/trunk/walrus/lib/walrus/contrib/spec/walruscloth_spec.rb 6702 2007-04-09T15:04:40.448669Z wincent $
|
9
|
+
|
10
|
+
require 'rubygems'
|
11
|
+
require 'spec'
|
12
|
+
require File.join(File.dirname(__FILE__), '..', 'walruscloth')
|
13
|
+
|
14
|
+
describe 'using WalrusCloth' do
|
15
|
+
|
16
|
+
it 'should be able to create an unordered list' do
|
17
|
+
# => "<ul>\n\t<li>hello</li>\n\t</ul>"
|
18
|
+
WalrusCloth.new('* hello').to_html.should == RedCloth.new('* hello').to_html
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should be able to create an ordered list' do
|
22
|
+
# => "<ol>\n\t<li>hello</li>\n\t</ol>"
|
23
|
+
WalrusCloth.new('` hello').to_html.should == RedCloth.new('# hello').to_html
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should be able to nest lists' do
|
27
|
+
# => "<ol>\n\t<li>hello\n\t<ul>\n\t<li>world</li>\n\t</ol></li>\n\t</ul>"
|
28
|
+
WalrusCloth.new("` hello\n`* world").to_html.should == RedCloth.new("# hello\n#* world").to_html
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
6
|
+
#
|
7
|
+
# $Id$
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
gem 'RedCloth', '= 3.0.4'; require 'redcloth'
|
11
|
+
|
12
|
+
# WalrusCloth is a RedCloth subclass that makes minimal modifications for ease of use with Walrus. Specifically, it makes two changes:
|
13
|
+
#
|
14
|
+
# 1. The hash or pound character (#) no longer indicates an ordered list; the backtick (`) character is used instead.
|
15
|
+
# 2. Only Textile rules are used by default, instead of Textile and Markdown.
|
16
|
+
#
|
17
|
+
# These changes are made because the hash character already has special meaning in Walrus as a directive marker. Textile is preferred over Markdown because it uses the hash character less extensively (in Markdown it is used as a heading indicator) and does not allow the backslash to be used as an escape marker (which again clashes with Walrus). Without these modifications it would be difficult to use RedCloth as a pre- or post-processor for Walrus templates because many characters would have to be specially escaped. This is particularly the case for the Walrus documentation itself where the documentation includes a lot of literal hash characters.
|
18
|
+
#
|
19
|
+
# I considered a number of possible workarounds to the problem, including making a fork of RedCloth. This fork basically consisted of a clean export of the latest RedCloth release with a project-wide replacement of "WalrusCloth" for "RedCloth" and "walruscloth" for "redcloth"; file names were also changed accordingly. Then the regular expressions that define Textile lists were modified. The benefit of this method was that there was no possibility of clashes with any installed version of RedCloth, but it was decidedly inelegant and the changes broke the RedCloth tests.
|
20
|
+
#
|
21
|
+
# In the end I decided to subclass RedCloth and override the list-detection regular expressions dynamically. This is somewhat cleaner and easier to maintain although it is still not a perfect solution (see limitations below). It's because of these limitations, together with the fact that I don't want to introduce a dependency on a third-party gem, that WalrusCloth is in the "contrib" subdirectory rather than in the Walrus core.
|
22
|
+
#
|
23
|
+
# Usage
|
24
|
+
# =====
|
25
|
+
#
|
26
|
+
# require 'walrus/contrib/walruscloth'
|
27
|
+
# WalrusCloth.new("` hello\n` world").to_html # note the space between the backtick and the list item content
|
28
|
+
# # => "<ul>\n\t<li>hello</li>\n\t\t<li>world</li>\n\t</ul>"
|
29
|
+
#
|
30
|
+
# Limitations
|
31
|
+
# ===========
|
32
|
+
#
|
33
|
+
# * Fragility: This technique could break for any future release of RedCloth if the way in which list-detection is implemented is changed.
|
34
|
+
# * Threading: Because this technique changes constants in the RedCloth namespace (albeit temporarily) it is not necessarily very "thread-friendly" if two threads are concurrently trying to use RedCloth and WalrusCloth concurrently. The only way to avoid this issues would be to reimplement the block_textile_lists entirely and that would again be a fragility consideration and a maintenance burden.
|
35
|
+
# * Warnings: This technique temporarily overrides constants and then restores them to their initial values; this would normally cause "already initialized constant" warnings but they are suppressed here by temporarily altering the $VERBOSE global variable, which is not very elegant.
|
36
|
+
# * Imparity: Given that this is only a partial override it is possible that some edge and corner cases will fail: for example, inspection of the RedCloth code indicates that it may be necessary to override the "blocks" method (and possibly others) to achieve total parity.
|
37
|
+
#
|
38
|
+
class WalrusCloth < RedCloth
|
39
|
+
|
40
|
+
def to_html(*rules)
|
41
|
+
rules = :textile if rules.empty?
|
42
|
+
begin
|
43
|
+
old_lists_re = RedCloth::LISTS_RE # save original values
|
44
|
+
old_lists_content_re = RedCloth::LISTS_CONTENT_RE
|
45
|
+
silently do # override
|
46
|
+
RedCloth::const_set('LISTS_RE', /^([`*]+?#{RedCloth::C} .*?)$(?![^`*])/m)
|
47
|
+
RedCloth::const_set('LISTS_CONTENT_RE', /^([`*]+)(#{RedCloth::A}#{RedCloth::C}) (.*)$/m)
|
48
|
+
end
|
49
|
+
super rules # process
|
50
|
+
ensure # restore original values
|
51
|
+
silently do
|
52
|
+
RedCloth::const_set('LISTS_RE', old_lists_re)
|
53
|
+
RedCloth::const_set('LISTS_CONTENT_RE', old_lists_content_re)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# "lT" presumably stands for "list type" (ordered or unordered)
|
59
|
+
def lT( text )
|
60
|
+
#text =~ /\#$/ ? 'o' : 'u'
|
61
|
+
text =~ /`$/ ? 'o' : 'u'
|
62
|
+
end
|
63
|
+
|
64
|
+
def hard_break( text )
|
65
|
+
#text.gsub!( /(.)\n(?!\Z| *([#*=]+(\s|$)|[{|]))/, "\\1<br />" ) if hard_breaks
|
66
|
+
text.gsub!( /(.)\n(?!\Z| *([`*=]+(\s|$)|[{|]))/, "\\1<br />" ) if hard_breaks
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# Nasty hack to prevent Ruby from emitting "already initialized constant" warnings when overriding constants.
|
72
|
+
# Sets $VERBOSE to nil, executes the passed block, then restores $VERBOSE to its previous state.
|
73
|
+
def silently &block
|
74
|
+
begin
|
75
|
+
verbose = $VERBOSE; $VERBOSE = nil # save
|
76
|
+
yield
|
77
|
+
ensure
|
78
|
+
$VERBOSE = verbose # restore
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end # WalrusCloth
|