devver-germinate 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/.gitignore +2 -0
  2. data/History.txt +4 -0
  3. data/README.rdoc +132 -0
  4. data/Rakefile +43 -0
  5. data/bin/germ +133 -0
  6. data/cucumber.yml +2 -0
  7. data/examples/basic.rb +118 -0
  8. data/examples/short.rb +17 -0
  9. data/features/author-formats-article.feature +108 -0
  10. data/features/author-lists-info.feature +45 -0
  11. data/features/author-publishes-article-source.feature +5 -0
  12. data/features/author-publishes-article.feature +5 -0
  13. data/features/author-republishes-article.feature +5 -0
  14. data/features/author-selects-hunks.feature +26 -0
  15. data/features/author-updates-article-source.feature +5 -0
  16. data/features/author-views-stuff.feature +48 -0
  17. data/features/bin/quoter +6 -0
  18. data/features/bin/sorter +4 -0
  19. data/features/example_articles/code_samples.rb +89 -0
  20. data/features/example_articles/escaping.txt +12 -0
  21. data/features/example_articles/hello.rb +9 -0
  22. data/features/example_articles/pipelines.txt +25 -0
  23. data/features/example_articles/regexen.rb +24 -0
  24. data/features/example_articles/sample_offsets.rb +18 -0
  25. data/features/example_articles/specials.rb +19 -0
  26. data/features/example_articles/wrapping.rb +8 -0
  27. data/features/example_output/code_samples.txt +186 -0
  28. data/features/example_output/escaping.out +5 -0
  29. data/features/example_output/hello.txt +1 -0
  30. data/features/example_output/pipelines.out +28 -0
  31. data/features/example_output/regexen.txt +22 -0
  32. data/features/example_output/sample_offsets.txt +15 -0
  33. data/features/example_output/specials.txt +36 -0
  34. data/features/example_output/wrapping.txt +3 -0
  35. data/features/step_definitions/germinate.rb +30 -0
  36. data/features/support/env.rb +18 -0
  37. data/germinate.gemspec +55 -0
  38. data/lib/germinate.rb +54 -0
  39. data/lib/germinate/application.rb +62 -0
  40. data/lib/germinate/article_editor.rb +20 -0
  41. data/lib/germinate/article_formatter.rb +75 -0
  42. data/lib/germinate/formatter.rb +119 -0
  43. data/lib/germinate/hunk.rb +149 -0
  44. data/lib/germinate/implicit_insertion.rb +9 -0
  45. data/lib/germinate/insertion.rb +15 -0
  46. data/lib/germinate/librarian.rb +179 -0
  47. data/lib/germinate/pipeline.rb +11 -0
  48. data/lib/germinate/process.rb +67 -0
  49. data/lib/germinate/reader.rb +212 -0
  50. data/lib/germinate/selector.rb +95 -0
  51. data/lib/germinate/shared_style_attributes.rb +23 -0
  52. data/lib/germinate/text_transforms.rb +90 -0
  53. data/spec/germinate/application_spec.rb +14 -0
  54. data/spec/germinate/article_editor_spec.rb +97 -0
  55. data/spec/germinate/article_formatter_spec.rb +153 -0
  56. data/spec/germinate/code_hunk_spec.rb +45 -0
  57. data/spec/germinate/formatter_spec.rb +160 -0
  58. data/spec/germinate/hunk_spec.rb +77 -0
  59. data/spec/germinate/implicit_insertion_spec.rb +33 -0
  60. data/spec/germinate/insertion_spec.rb +18 -0
  61. data/spec/germinate/librarian_spec.rb +336 -0
  62. data/spec/germinate/pipeline_spec.rb +24 -0
  63. data/spec/germinate/process_spec.rb +64 -0
  64. data/spec/germinate/reader_spec.rb +306 -0
  65. data/spec/germinate/selector_spec.rb +65 -0
  66. data/spec/germinate/text_hunk_spec.rb +53 -0
  67. data/spec/germinate/text_transforms_spec.rb +154 -0
  68. data/spec/germinate_spec.rb +8 -0
  69. data/spec/spec.opts +1 -0
  70. data/spec/spec_helper.rb +16 -0
  71. data/tasks/ann.rake +80 -0
  72. data/tasks/bones.rake +20 -0
  73. data/tasks/cucumber.rake +5 -0
  74. data/tasks/gem.rake +201 -0
  75. data/tasks/git.rake +40 -0
  76. data/tasks/notes.rake +27 -0
  77. data/tasks/post_load.rake +34 -0
  78. data/tasks/rdoc.rake +51 -0
  79. data/tasks/rubyforge.rake +55 -0
  80. data/tasks/setup.rb +292 -0
  81. data/tasks/spec.rake +54 -0
  82. data/tasks/svn.rake +47 -0
  83. data/tasks/test.rake +40 -0
  84. data/tasks/zentest.rake +36 -0
  85. data/test/test_germinate.rb +0 -0
  86. metadata +209 -0
@@ -0,0 +1,19 @@
1
+ # :SAMPLE: A
2
+ a_line_1 = 1
3
+ a_line_2 = 2
4
+ a_line_3 = 3
5
+ a_line_4 = 4
6
+
7
+ # :SAMPLE: B
8
+ b_line_1 = 1
9
+ b_line_2 = 2
10
+
11
+ # :TEXT:
12
+ # We can paste in all the code:
13
+ # :INSERT: $CODE
14
+ #
15
+ # Or all the text:
16
+ # :INSERT: $TEXT
17
+ #
18
+ # Or the entire source file
19
+ # :INSERT: $SOURCE
@@ -0,0 +1,8 @@
1
+ # An example of text-wrappeing
2
+ #
3
+ # :TEXT:
4
+ # 'Twas brillig and the slithy toves
5
+ # Did gyre and gimbal in the wabe
6
+ #
7
+ # All mimsy were the borogroves
8
+ # And the momeraths outgrabe
@@ -0,0 +1,186 @@
1
+ Hi there! Here's a Hello, World method:
2
+
3
+ def hello
4
+ puts "Hello, World!"
5
+ end
6
+
7
+ The immediately following code sample can be implicitly referenced:
8
+
9
+ def nameless
10
+ puts "I have no name"
11
+ end
12
+
13
+ Or explicitly referenced
14
+
15
+ def foo
16
+ puts "foo"
17
+ end
18
+
19
+ Samples can be referenced by name
20
+
21
+ def fred
22
+ # This comment is part of the sample
23
+ puts "Hello, my name is Fred"
24
+ puts "la la la"
25
+ end
26
+
27
+ Or by index:
28
+
29
+ def boring
30
+ 1 + 1
31
+ end
32
+
33
+ SOURCE is a special sample which contains this entire source file.
34
+
35
+ # This example demonstrates the use of code samples.
36
+
37
+ # :TEXT:
38
+ # Hi there! Here's a Hello, World method:
39
+
40
+ def hello
41
+ puts "Hello, World!"
42
+ end
43
+
44
+ # :CUT:
45
+ # Here's some boring support code we don't want to show the world.
46
+
47
+ def boring
48
+ 1 + 1
49
+ end
50
+
51
+ # Here are two a named samples:
52
+ # :SAMPLE: fred
53
+
54
+ def fred
55
+ # This comment is part of the sample
56
+ puts "Hello, my name is Fred"
57
+ puts "la la la"
58
+ end
59
+
60
+ # :SAMPLE: sally
61
+
62
+ def sally
63
+ puts "Hello, my name is Sally"
64
+ end
65
+
66
+ # :END:
67
+ # Sample "sally" ends above, and does not include the following.
68
+
69
+ def wizard
70
+ puts "Pay no attention to the man behind the curtain!"
71
+ end
72
+
73
+ # Samples can be inside comment blocks
74
+ # :SAMPLE: george
75
+ # (defun george () (format "Hello from George"))
76
+ # :CUT:
77
+
78
+ # Samples can have comment markers stripped
79
+ # :SAMPLE: mary, { uncomment: true }
80
+ # (defun mary () (format "Hello from Mary"))
81
+ # :CUT:
82
+
83
+ # :TEXT:
84
+ # The immediately following code sample can be implicitly referenced:
85
+ # :INSERT:
86
+ # :CUT:
87
+ def nameless
88
+ puts "I have no name"
89
+ end
90
+
91
+ # :TEXT:
92
+ # Or explicitly referenced
93
+ # :INSERT: FOLLOWING
94
+ # :CUT:
95
+ def foo
96
+ puts "foo"
97
+ end
98
+
99
+ # :TEXT:
100
+ # Samples can be referenced by name
101
+ # :INSERT: fred
102
+ #
103
+ # Or by index:
104
+ # :INSERT: #2
105
+ #
106
+ # SOURCE is a special sample which contains this entire source file.
107
+ # :INSERT: SOURCE, { indent: 4 }
108
+ #
109
+ # CODE is a special sample which contains all the non-text portions of this
110
+ # file.
111
+ # :INSERT: CODE, { indent: " > " }
112
+ #
113
+ # We can select specific lines:
114
+ # :INSERT: sally:2
115
+ #
116
+ # Or ranges of lines:
117
+ # :INSERT: sally:2..3
118
+ #
119
+ # Or lines matching a regex:
120
+ # :INSERT: sally:/def/
121
+ #
122
+ # Or ranges of regexen:
123
+ # :INSERT: fred:/puts/.../end/
124
+
125
+ CODE is a special sample which contains all the non-text portions of this file.
126
+
127
+ > # This example demonstrates the use of code samples.
128
+ >
129
+ > def hello
130
+ > puts "Hello, World!"
131
+ > end
132
+ >
133
+ > # Here's some boring support code we don't want to show the world.
134
+ >
135
+ > def boring
136
+ > 1 + 1
137
+ > end
138
+ >
139
+ > # Here are two a named samples:
140
+ >
141
+ > def fred
142
+ > # This comment is part of the sample
143
+ > puts "Hello, my name is Fred"
144
+ > puts "la la la"
145
+ > end
146
+ >
147
+ > def sally
148
+ > puts "Hello, my name is Sally"
149
+ > end
150
+ >
151
+ > # Sample "sally" ends above, and does not include the following.
152
+ >
153
+ > def wizard
154
+ > puts "Pay no attention to the man behind the curtain!"
155
+ > end
156
+ >
157
+ > # Samples can be inside comment blocks
158
+ >
159
+ > # Samples can have comment markers stripped
160
+ >
161
+ > def nameless
162
+ > puts "I have no name"
163
+ > end
164
+ >
165
+ > def foo
166
+ > puts "foo"
167
+ > end
168
+
169
+ We can select specific lines:
170
+
171
+ puts "Hello, my name is Sally"
172
+
173
+ Or ranges of lines:
174
+
175
+ puts "Hello, my name is Sally"
176
+ end
177
+
178
+ Or lines matching a regex:
179
+
180
+ def sally
181
+
182
+ # Or ranges of regexen:
183
+
184
+ puts "Hello, my name is Fred"
185
+ puts "la la la"
186
+
@@ -0,0 +1,5 @@
1
+ Here are some Germinate directives :TEXT: :SAMPLE: :INSERT: You get the idea.
2
+
3
+ It works in code too:
4
+
5
+ # :PROCESS: foo, bar
@@ -0,0 +1 @@
1
+ Hello, world!
@@ -0,0 +1,28 @@
1
+ Sorting the sample:
2
+ aaron
3
+ george
4
+ joe
5
+ sally
6
+ susan
7
+ zack
8
+
9
+ Quoting the sample:
10
+ > joe
11
+ > sally
12
+ > aaron
13
+ > george
14
+ > zack
15
+ > susan
16
+
17
+ We can combine pipelines with excerpting:
18
+ > sally
19
+ > aaron
20
+ > george
21
+
22
+ And we can chain processes to form a true pipeline:
23
+ > aaron
24
+ > george
25
+ > joe
26
+ > sally
27
+ > susan
28
+ > zack
@@ -0,0 +1,22 @@
1
+ We can select code by regexp
2
+ def foo
3
+ # ...
4
+ end
5
+
6
+ Or with a regex and a length
7
+ def bar
8
+ # ...
9
+ end
10
+
11
+ class Frob
12
+ # ...
13
+ end
14
+
15
+ Ending offset can be exclusive
16
+ def foo
17
+ # ...
18
+ end
19
+
20
+ def bar
21
+ # ...
22
+ end
@@ -0,0 +1,15 @@
1
+ We can specify a starting offset:
2
+ a_line_2 = 2
3
+
4
+ And an ending offset
5
+ a_line_2 = 2
6
+ a_line_3 = 3
7
+
8
+ Ending offset can be exclusive
9
+ a_line_1 = 1
10
+ a_line_2 = 2
11
+
12
+ We can specify offset and count instead
13
+ a_line_2 = 2
14
+ a_line_3 = 3
15
+ a_line_4 = 4
@@ -0,0 +1,36 @@
1
+ We can paste in all the code:
2
+ a_line_1 = 1
3
+ a_line_2 = 2
4
+ a_line_3 = 3
5
+ a_line_4 = 4
6
+
7
+ b_line_1 = 1
8
+ b_line_2 = 2
9
+
10
+ Or all the text:
11
+ # We can paste in all the code:
12
+ #
13
+ # Or all the text:
14
+ #
15
+ # Or the entire source file
16
+
17
+ Or the entire source file
18
+ # :SAMPLE: A
19
+ a_line_1 = 1
20
+ a_line_2 = 2
21
+ a_line_3 = 3
22
+ a_line_4 = 4
23
+
24
+ # :SAMPLE: B
25
+ b_line_1 = 1
26
+ b_line_2 = 2
27
+
28
+ # :TEXT:
29
+ # We can paste in all the code:
30
+ # :INSERT: $CODE
31
+ #
32
+ # Or all the text:
33
+ # :INSERT: $TEXT
34
+ #
35
+ # Or the entire source file
36
+ # :INSERT: $SOURCE
@@ -0,0 +1,3 @@
1
+ 'Twas brillig and the slithy toves Did gyre and gimbal in the wabe
2
+
3
+ All mimsy were the borogroves And the momeraths outgrabe
@@ -0,0 +1,30 @@
1
+ require 'tempfile'
2
+
3
+ Given /^the article "([^\"]*)"$/ do |article_file|
4
+ @filename = (EXAMPLE_ARTICLES + article_file)
5
+ end
6
+
7
+ When /^I run the format command on the article$/ do
8
+ run_germinate("format #{@filename}")
9
+ end
10
+
11
+ When /^I run the command "([^\"]*)" on the article$/ do |command|
12
+ run_germinate(command.sub(/^germ /,"") + " #{@filename}")
13
+ end
14
+
15
+ Then /^the output should look like "([^\"]*)"$/ do |output_file|
16
+ example_path = (EXAMPLE_OUTPUT + output_file)
17
+ example_output = example_path.read
18
+ @output.should == example_output
19
+ end
20
+
21
+ Given /^an article with the contents:$/ do |contents|
22
+ Tempfile.open("germinate_example_article") do |file|
23
+ file.write(contents)
24
+ @filename = Pathname(file.path)
25
+ end
26
+ end
27
+
28
+ Then /^the output should be as follows:$/ do |example_output|
29
+ @output.strip.should == example_output.strip
30
+ end
@@ -0,0 +1,18 @@
1
+ require 'English'
2
+ require 'pathname'
3
+ require 'spec/expectations'
4
+ require File.expand_path('../../lib/germinate', File.dirname(__FILE__))
5
+
6
+ EXAMPLE_ARTICLES = (Pathname(__FILE__).dirname + '../example_articles')
7
+ EXAMPLE_OUTPUT = (Pathname(__FILE__).dirname + '../example_output')
8
+ EXAMPLE_BIN = (Pathname(__FILE__).dirname + '../bin')
9
+
10
+ ENV['PATH'] += ":" + EXAMPLE_BIN.to_s
11
+
12
+ def run_germinate(arguments, permit_failure=false)
13
+ exec_path = (Pathname(__FILE__).dirname + '..' + '..' + 'bin/germ').expand_path
14
+ command = "#{exec_path} #{arguments}"
15
+ @output = `#{command}`
16
+ @result = $CHILD_STATUS
17
+ raise "Command `#{command}` failed" unless @result.success? or permit_failure
18
+ end
data/germinate.gemspec ADDED
@@ -0,0 +1,55 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{germinate}
5
+ s.version = "1.0.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Avdi Grimm"]
9
+ s.date = %q{2009-07-10}
10
+ s.default_executable = %q{germ}
11
+ s.description = %q{Germinate is a tool for writing about code. With Germinate, the source code IS the article. For example, given the following source code: # #!/usr/bin/env ruby # :BRACKET_CODE: <pre>, </pre> # :PROCESS: ruby, "ruby %f" # :SAMPLE: hello def hello(who) puts "Hello, #{who}" end hello("World") # :TEXT: # Check out my amazing program! Here's the hello method: # :INSERT: @hello:/def/../end/ # And here's the output: # :INSERT: @hello|ruby When we run the <tt>germ format</tt> command the following output is generated: Check out my amazing program! Here's the hello method: <pre> def hello(who) puts "Hello, #{who}" end </pre> And here's the output: <pre> Hello, World </pre> To get a better idea of how this works, please take a look at link:examples/basic.rb, or run: germ generate > basic.rb To generate an example article to play with. Germinate is particularly useful for writing articles, such as blog posts, which contain code excerpts. Instead of forcing you to keep a source code file and an article document in sync throughout the editing process, the Germinate motto is "The source code IS the article". Specially marked comment sections in your code file become the article text. Wherever you need to reference the source code in the article, use insertion directives to tell Germinate what parts of the code to excerpt. An advanced selector syntax enables you to be very specific about which lines of code you want to insert. If you also want to show the output of your code, Germinate has you covered. Special "process" directives enable you to define arbitrary commands which can be run on your code. The output of the command then becomes the excerpt text. You can define an arbitrary number of processes and have different excerpts showing the same code as processed by different commands. You can even string processes together into pipelines. Development of Germinate is graciously sponsored by Devver, purveyor of fine cloud-based services to busy Ruby developers. If you like this tool please check them out at http://devver.net.}
12
+ s.email = %q{avdi@avdi.org}
13
+ s.executables = ["germ"]
14
+ s.extra_rdoc_files = ["History.txt", "README.rdoc", "bin/germ"]
15
+ s.files = [".gitignore", "History.txt", "README.rdoc", "Rakefile", "bin/germ", "cucumber.yml", "examples/basic.rb", "examples/short.rb", "features/author-formats-article.feature", "features/author-lists-info.feature", "features/author-publishes-article-source.feature", "features/author-publishes-article.feature", "features/author-republishes-article.feature", "features/author-selects-hunks.feature", "features/author-updates-article-source.feature", "features/author-views-stuff.feature", "features/bin/quoter", "features/bin/sorter", "features/example_articles/code_samples.rb", "features/example_articles/escaping.txt", "features/example_articles/hello.rb", "features/example_articles/pipelines.txt", "features/example_articles/regexen.rb", "features/example_articles/sample_offsets.rb", "features/example_articles/specials.rb", "features/example_articles/wrapping.rb", "features/example_output/code_samples.txt", "features/example_output/escaping.out", "features/example_output/hello.txt", "features/example_output/pipelines.out", "features/example_output/regexen.txt", "features/example_output/sample_offsets.txt", "features/example_output/specials.txt", "features/example_output/wrapping.txt", "features/step_definitions/germinate.rb", "features/support/env.rb", "germinate.gemspec", "lib/germinate.rb", "lib/germinate/application.rb", "lib/germinate/article_editor.rb", "lib/germinate/article_formatter.rb", "lib/germinate/formatter.rb", "lib/germinate/hunk.rb", "lib/germinate/implicit_insertion.rb", "lib/germinate/insertion.rb", "lib/germinate/librarian.rb", "lib/germinate/pipeline.rb", "lib/germinate/process.rb", "lib/germinate/reader.rb", "lib/germinate/selector.rb", "lib/germinate/shared_style_attributes.rb", "lib/germinate/text_transforms.rb", "spec/germinate/application_spec.rb", "spec/germinate/article_editor_spec.rb", "spec/germinate/article_formatter_spec.rb", "spec/germinate/code_hunk_spec.rb", "spec/germinate/formatter_spec.rb", "spec/germinate/hunk_spec.rb", "spec/germinate/implicit_insertion_spec.rb", "spec/germinate/insertion_spec.rb", "spec/germinate/librarian_spec.rb", "spec/germinate/pipeline_spec.rb", "spec/germinate/process_spec.rb", "spec/germinate/reader_spec.rb", "spec/germinate/selector_spec.rb", "spec/germinate/text_hunk_spec.rb", "spec/germinate/text_transforms_spec.rb", "spec/germinate_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/ann.rake", "tasks/bones.rake", "tasks/cucumber.rake", "tasks/gem.rake", "tasks/git.rake", "tasks/notes.rake", "tasks/post_load.rake", "tasks/rdoc.rake", "tasks/rubyforge.rake", "tasks/setup.rb", "tasks/spec.rake", "tasks/svn.rake", "tasks/test.rake", "tasks/zentest.rake", "test/test_germinate.rb"]
16
+ s.has_rdoc = true
17
+ s.homepage = %q{http://github.com/devver/germinate/}
18
+ s.rdoc_options = ["--main", "README.rdoc"]
19
+ s.require_paths = ["lib"]
20
+ s.rubyforge_project = %q{germinate}
21
+ s.rubygems_version = %q{1.3.1}
22
+ s.summary = %q{Germinate is a tool for writing about code}
23
+ s.test_files = ["test/test_germinate.rb"]
24
+
25
+ if s.respond_to? :specification_version then
26
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
27
+ s.specification_version = 2
28
+
29
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
30
+ s.add_runtime_dependency(%q<ick>, ["~> 0.3.0"])
31
+ s.add_runtime_dependency(%q<fattr>, ["~> 1.0.3"])
32
+ s.add_runtime_dependency(%q<arrayfields>, ["~> 4.7.3"])
33
+ s.add_runtime_dependency(%q<orderedhash>, ["~> 0.0.6"])
34
+ s.add_runtime_dependency(%q<alter-ego>, ["~> 1.0.0"])
35
+ s.add_runtime_dependency(%q<main>, ["~> 2.8.3"])
36
+ s.add_development_dependency(%q<bones>, [">= 2.5.1"])
37
+ else
38
+ s.add_dependency(%q<ick>, ["~> 0.3.0"])
39
+ s.add_dependency(%q<fattr>, ["~> 1.0.3"])
40
+ s.add_dependency(%q<arrayfields>, ["~> 4.7.3"])
41
+ s.add_dependency(%q<orderedhash>, ["~> 0.0.6"])
42
+ s.add_dependency(%q<alter-ego>, ["~> 1.0.0"])
43
+ s.add_dependency(%q<main>, ["~> 2.8.3"])
44
+ s.add_dependency(%q<bones>, [">= 2.5.1"])
45
+ end
46
+ else
47
+ s.add_dependency(%q<ick>, ["~> 0.3.0"])
48
+ s.add_dependency(%q<fattr>, ["~> 1.0.3"])
49
+ s.add_dependency(%q<arrayfields>, ["~> 4.7.3"])
50
+ s.add_dependency(%q<orderedhash>, ["~> 0.0.6"])
51
+ s.add_dependency(%q<alter-ego>, ["~> 1.0.0"])
52
+ s.add_dependency(%q<main>, ["~> 2.8.3"])
53
+ s.add_dependency(%q<bones>, [">= 2.5.1"])
54
+ end
55
+ end