devver-germinate 1.0.0
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/.gitignore +2 -0
- data/History.txt +4 -0
- data/README.rdoc +132 -0
- data/Rakefile +43 -0
- data/bin/germ +133 -0
- data/cucumber.yml +2 -0
- data/examples/basic.rb +118 -0
- data/examples/short.rb +17 -0
- data/features/author-formats-article.feature +108 -0
- data/features/author-lists-info.feature +45 -0
- data/features/author-publishes-article-source.feature +5 -0
- data/features/author-publishes-article.feature +5 -0
- data/features/author-republishes-article.feature +5 -0
- data/features/author-selects-hunks.feature +26 -0
- data/features/author-updates-article-source.feature +5 -0
- data/features/author-views-stuff.feature +48 -0
- data/features/bin/quoter +6 -0
- data/features/bin/sorter +4 -0
- data/features/example_articles/code_samples.rb +89 -0
- data/features/example_articles/escaping.txt +12 -0
- data/features/example_articles/hello.rb +9 -0
- data/features/example_articles/pipelines.txt +25 -0
- data/features/example_articles/regexen.rb +24 -0
- data/features/example_articles/sample_offsets.rb +18 -0
- data/features/example_articles/specials.rb +19 -0
- data/features/example_articles/wrapping.rb +8 -0
- data/features/example_output/code_samples.txt +186 -0
- data/features/example_output/escaping.out +5 -0
- data/features/example_output/hello.txt +1 -0
- data/features/example_output/pipelines.out +28 -0
- data/features/example_output/regexen.txt +22 -0
- data/features/example_output/sample_offsets.txt +15 -0
- data/features/example_output/specials.txt +36 -0
- data/features/example_output/wrapping.txt +3 -0
- data/features/step_definitions/germinate.rb +30 -0
- data/features/support/env.rb +18 -0
- data/germinate.gemspec +55 -0
- data/lib/germinate.rb +54 -0
- data/lib/germinate/application.rb +62 -0
- data/lib/germinate/article_editor.rb +20 -0
- data/lib/germinate/article_formatter.rb +75 -0
- data/lib/germinate/formatter.rb +119 -0
- data/lib/germinate/hunk.rb +149 -0
- data/lib/germinate/implicit_insertion.rb +9 -0
- data/lib/germinate/insertion.rb +15 -0
- data/lib/germinate/librarian.rb +179 -0
- data/lib/germinate/pipeline.rb +11 -0
- data/lib/germinate/process.rb +67 -0
- data/lib/germinate/reader.rb +212 -0
- data/lib/germinate/selector.rb +95 -0
- data/lib/germinate/shared_style_attributes.rb +23 -0
- data/lib/germinate/text_transforms.rb +90 -0
- data/spec/germinate/application_spec.rb +14 -0
- data/spec/germinate/article_editor_spec.rb +97 -0
- data/spec/germinate/article_formatter_spec.rb +153 -0
- data/spec/germinate/code_hunk_spec.rb +45 -0
- data/spec/germinate/formatter_spec.rb +160 -0
- data/spec/germinate/hunk_spec.rb +77 -0
- data/spec/germinate/implicit_insertion_spec.rb +33 -0
- data/spec/germinate/insertion_spec.rb +18 -0
- data/spec/germinate/librarian_spec.rb +336 -0
- data/spec/germinate/pipeline_spec.rb +24 -0
- data/spec/germinate/process_spec.rb +64 -0
- data/spec/germinate/reader_spec.rb +306 -0
- data/spec/germinate/selector_spec.rb +65 -0
- data/spec/germinate/text_hunk_spec.rb +53 -0
- data/spec/germinate/text_transforms_spec.rb +154 -0
- data/spec/germinate_spec.rb +8 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +16 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/cucumber.rake +5 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +292 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/tasks/zentest.rake +36 -0
- data/test/test_germinate.rb +0 -0
- metadata +209 -0
data/.gitignore
ADDED
data/History.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
= germinate
|
2
|
+
|
3
|
+
by Avdi Grimm
|
4
|
+
|
5
|
+
http://github.com/devver/germinate/
|
6
|
+
|
7
|
+
== SYNOPSIS
|
8
|
+
|
9
|
+
germ generate > my_article.rb
|
10
|
+
germ format my_article.rb > my_article.txt
|
11
|
+
|
12
|
+
== DESCRIPTION
|
13
|
+
|
14
|
+
Germinate is a tool for writing about code. With Germinate, the source code IS
|
15
|
+
the article.
|
16
|
+
|
17
|
+
For example, given the following source code:
|
18
|
+
|
19
|
+
# #!/usr/bin/env ruby
|
20
|
+
# :BRACKET_CODE: <pre>, </pre>
|
21
|
+
# :PROCESS: ruby, "ruby %f"
|
22
|
+
|
23
|
+
# :SAMPLE: hello
|
24
|
+
def hello(who)
|
25
|
+
puts "Hello, #{who}"
|
26
|
+
end
|
27
|
+
|
28
|
+
hello("World")
|
29
|
+
|
30
|
+
# :TEXT:
|
31
|
+
# Check out my amazing program! Here's the hello method:
|
32
|
+
# :INSERT: @hello:/def/../end/
|
33
|
+
|
34
|
+
# And here's the output:
|
35
|
+
# :INSERT: @hello|ruby
|
36
|
+
|
37
|
+
When we run the <tt>germ format</tt> command the following output is generated:
|
38
|
+
|
39
|
+
Check out my amazing program! Here's the hello method:
|
40
|
+
<pre>
|
41
|
+
def hello(who)
|
42
|
+
puts "Hello, #{who}"
|
43
|
+
end
|
44
|
+
</pre>
|
45
|
+
And here's the output:
|
46
|
+
<pre>
|
47
|
+
Hello, World
|
48
|
+
</pre>
|
49
|
+
|
50
|
+
To get a better idea of how this works, please take a look at
|
51
|
+
link:examples/basic.rb, or run:
|
52
|
+
|
53
|
+
germ generate > basic.rb
|
54
|
+
|
55
|
+
To generate an example article to play with.
|
56
|
+
|
57
|
+
Germinate is particularly useful for writing articles, such as blog posts, which
|
58
|
+
contain code excerpts. Instead of forcing you to keep a source code file and an
|
59
|
+
article document in sync throughout the editing process, the Germinate motto is
|
60
|
+
"The source code IS the article". Specially marked comment sections in your
|
61
|
+
code file become the article text. Wherever you need to reference the source
|
62
|
+
code in the article, use insertion directives to tell Germinate what parts of
|
63
|
+
the code to excerpt. An advanced selector syntax enables you to be very
|
64
|
+
specific about which lines of code you want to insert.
|
65
|
+
|
66
|
+
If you also want to show the output of your code, Germinate has you covered.
|
67
|
+
Special "process" directives enable you to define arbitrary commands which can
|
68
|
+
be run on your code. The output of the command then becomes the excerpt text.
|
69
|
+
You can define an arbitrary number of processes and have different excerpts
|
70
|
+
showing the same code as processed by different commands. You can even string
|
71
|
+
processes together into pipelines.
|
72
|
+
|
73
|
+
Development of Germinate is graciously sponsored by Devver, purveyor of fine
|
74
|
+
cloud-based services to busy Ruby developers. If you like this tool please
|
75
|
+
check them out at http://devver.net.
|
76
|
+
|
77
|
+
== FEATURES
|
78
|
+
|
79
|
+
* Language and markup agnostic
|
80
|
+
* Advanced selector syntax for excerpting code
|
81
|
+
* Define arbitrary command pipelines to preprocess excerpts
|
82
|
+
* Article text is reformatted to be more compatible with popular blogging
|
83
|
+
engines, e.g. WordPress.
|
84
|
+
* Introspection commands make it easy to experiment
|
85
|
+
* Fully tested
|
86
|
+
|
87
|
+
== KNOWN ISSUES
|
88
|
+
|
89
|
+
* Directive syntax conflicts with RDoc. Doh!
|
90
|
+
|
91
|
+
== FUTURE
|
92
|
+
|
93
|
+
* Integration with blogging platforms, e.g. WordPress
|
94
|
+
* Integration with Github's Gist
|
95
|
+
|
96
|
+
== REQUIREMENTS
|
97
|
+
|
98
|
+
* main
|
99
|
+
* fattr
|
100
|
+
* ick
|
101
|
+
* orderedhash
|
102
|
+
* arrayfields
|
103
|
+
* alter-ego
|
104
|
+
|
105
|
+
== INSTALL:
|
106
|
+
|
107
|
+
gem install --source http://gems.rubyforge.org devver-germinate
|
108
|
+
|
109
|
+
== LICENSE:
|
110
|
+
|
111
|
+
(The MIT License)
|
112
|
+
|
113
|
+
Copyright (c) 2008
|
114
|
+
|
115
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
116
|
+
a copy of this software and associated documentation files (the
|
117
|
+
'Software'), to deal in the Software without restriction, including
|
118
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
119
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
120
|
+
permit persons to whom the Software is furnished to do so, subject to
|
121
|
+
the following conditions:
|
122
|
+
|
123
|
+
The above copyright notice and this permission notice shall be
|
124
|
+
included in all copies or substantial portions of the Software.
|
125
|
+
|
126
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
127
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
128
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
129
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
130
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
131
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
132
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Look in the tasks/setup.rb file for the various options that can be
|
2
|
+
# configured in this Rakefile. The .rake files in the tasks directory
|
3
|
+
# are where the options are used.
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bones'
|
7
|
+
Bones.setup
|
8
|
+
rescue LoadError
|
9
|
+
begin
|
10
|
+
load 'tasks/setup.rb'
|
11
|
+
rescue LoadError
|
12
|
+
raise RuntimeError, '### please install the "bones" gem ###'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ensure_in_path 'lib'
|
17
|
+
require 'germinate'
|
18
|
+
|
19
|
+
task :default => 'spec:run'
|
20
|
+
|
21
|
+
PROJ.name = 'germinate'
|
22
|
+
PROJ.authors = 'Avdi Grimm'
|
23
|
+
PROJ.email = 'avdi@avdi.org'
|
24
|
+
PROJ.url = 'http://github.com/devver/germinate/'
|
25
|
+
PROJ.version = Germinate::VERSION
|
26
|
+
PROJ.rubyforge.name = 'germinate'
|
27
|
+
|
28
|
+
PROJ.spec.opts << '--color'
|
29
|
+
|
30
|
+
PROJ.ruby_opts = []
|
31
|
+
|
32
|
+
PROJ.readme_file = "README.rdoc"
|
33
|
+
PROJ.rdoc.main = "README.rdoc"
|
34
|
+
PROJ.rdoc.exclude << "features"
|
35
|
+
|
36
|
+
depend_on "ick", "~> 0.3.0"
|
37
|
+
depend_on "fattr", "~> 1.0.3"
|
38
|
+
depend_on "arrayfields", "~> 4.7.3"
|
39
|
+
depend_on "orderedhash", "~> 0.0.6"
|
40
|
+
depend_on "alter-ego", "~> 1.0.0"
|
41
|
+
depend_on "main", "~> 2.8.3"
|
42
|
+
|
43
|
+
# EOF
|
data/bin/germ
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.expand_path(
|
4
|
+
File.join(File.dirname(__FILE__), %w[.. lib germinate]))
|
5
|
+
|
6
|
+
require 'main'
|
7
|
+
|
8
|
+
Main do
|
9
|
+
description <<-END
|
10
|
+
Germinate - A tool for writing about code.
|
11
|
+
|
12
|
+
With Germinate, your source code is also your article text. Special
|
13
|
+
directives tell Germinate which parts to format as article text and
|
14
|
+
where to insert source code excerpts and program output.
|
15
|
+
|
16
|
+
To get started, execute:
|
17
|
+
|
18
|
+
germ generate > my_article.rb
|
19
|
+
|
20
|
+
to have Germinate generate a basic example article.
|
21
|
+
|
22
|
+
For more information, see the project homepage at
|
23
|
+
http://github.com/devver/germinate/
|
24
|
+
|
25
|
+
Development of Germinate is graciously sponsored by Devver, purveyor
|
26
|
+
of fine cloud-based services to busy Ruby developers. If you like
|
27
|
+
this tool please check them out at http://devver.net.
|
28
|
+
END
|
29
|
+
|
30
|
+
author "Avdi Grimm <avdi@avdi.org>"
|
31
|
+
|
32
|
+
version Germinate::VERSION
|
33
|
+
|
34
|
+
def self.source_argument
|
35
|
+
argument :source do
|
36
|
+
arity 1
|
37
|
+
validate{|source| Pathname(source).readable?}
|
38
|
+
description "Source file"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
mode :format do
|
43
|
+
description "Format an article for publishing"
|
44
|
+
source_argument
|
45
|
+
def run
|
46
|
+
Germinate.logger = self
|
47
|
+
with_source_file do |source|
|
48
|
+
application = Germinate::Application.new
|
49
|
+
application.format(source, $stdout, $stderr)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
mode :list do
|
55
|
+
description "List various article components"
|
56
|
+
source_argument
|
57
|
+
COLLECTIONS = [:sections, :samples, :processes]
|
58
|
+
COLLECTIONS.each do |collection|
|
59
|
+
option collection do
|
60
|
+
description "List all #{collection}"
|
61
|
+
cast :bool
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def run
|
66
|
+
things_to_list = []
|
67
|
+
COLLECTIONS.each do |collection|
|
68
|
+
things_to_list << collection if params[collection].value
|
69
|
+
end
|
70
|
+
with_source_file do |source|
|
71
|
+
application = Germinate::Application.new
|
72
|
+
application.list(source, things_to_list, $stdout)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
mode :show do
|
78
|
+
description "Show details about various article components"
|
79
|
+
source_argument
|
80
|
+
TYPES = [:section, :sample, :process]
|
81
|
+
TYPES.each do |type|
|
82
|
+
option type do
|
83
|
+
description "Show details about a #{type}"
|
84
|
+
argument_required
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def run
|
89
|
+
selection = TYPES.inject({}) {|sel, type|
|
90
|
+
sel[type] = params[type].values
|
91
|
+
sel
|
92
|
+
}
|
93
|
+
with_source_file do |source|
|
94
|
+
application = Germinate::Application.new
|
95
|
+
application.show(source, selection, $stdout)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
mode :select do
|
101
|
+
description "Test out a selector"
|
102
|
+
source_argument
|
103
|
+
option(:selector, :s) do
|
104
|
+
arity 1
|
105
|
+
required
|
106
|
+
argument_required
|
107
|
+
description "The selector to search for"
|
108
|
+
end
|
109
|
+
|
110
|
+
def run
|
111
|
+
with_source_file do |source|
|
112
|
+
application = Germinate::Application.new
|
113
|
+
application.select(source, params[:selector].value, $stdout)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
mode :generate do
|
119
|
+
description "Generate a sample article"
|
120
|
+
|
121
|
+
def run
|
122
|
+
example = File.expand_path("../doc/examples/basic.rb",
|
123
|
+
File.dirname(__FILE__))
|
124
|
+
stdout.write(File.read(example))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def with_source_file(&block)
|
129
|
+
File.open(params['source'].value, &block)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# EOF
|
data/cucumber.yml
ADDED
data/examples/basic.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# A basic example of a Germinate article.
|
2
|
+
#
|
3
|
+
# This text is "front matter" and will not be included in the final article.
|
4
|
+
# The article doesn't begin until the first text directive.
|
5
|
+
#
|
6
|
+
# Let's set up code bracketing so that code excerpts will be surrounded by HTML
|
7
|
+
# <pre>...</pre> tags.
|
8
|
+
#
|
9
|
+
# :BRACKET_CODE: <pre>, </pre>
|
10
|
+
#
|
11
|
+
# :TEXT:
|
12
|
+
# This is the first line of the article text. For the formatted article,
|
13
|
+
# Germinate will remove the comment prefixes ("# ") and join paragraphs into
|
14
|
+
# single lines.
|
15
|
+
#
|
16
|
+
# We're coming up on our first code section. If some code immediately follows a
|
17
|
+
# text section it will automatically be inserted into the formatted article
|
18
|
+
# text.
|
19
|
+
def my_func
|
20
|
+
# ...
|
21
|
+
end
|
22
|
+
# :END:
|
23
|
+
#
|
24
|
+
# The END directive above ends that particular code sample. This text will not
|
25
|
+
# be included in the final article.
|
26
|
+
#
|
27
|
+
# We don't want to have to write our source code in the order it appears in
|
28
|
+
# the article. Let's define a named code sample.
|
29
|
+
#
|
30
|
+
# :SAMPLE: hello
|
31
|
+
def hello
|
32
|
+
puts "Hello, #{ARGV[0]}"
|
33
|
+
end
|
34
|
+
hello
|
35
|
+
|
36
|
+
# :TEXT:
|
37
|
+
# We're back in the article text now. Let's insert our named sample now.
|
38
|
+
# :INSERT: @hello
|
39
|
+
#
|
40
|
+
# Now lets define some processes and experiment with running the sample through
|
41
|
+
# them.
|
42
|
+
#
|
43
|
+
# :PROCESS: fred, "ruby %f Fred"
|
44
|
+
# :PROCESS: jane, "ruby %f Jane"
|
45
|
+
# :PROCESS: quote, "ruby -n -e 'puts \"> #{$_}\"'"
|
46
|
+
#
|
47
|
+
# Note that the "quote" process has no %f placeholder for the filename.
|
48
|
+
# If it doesn't find a %f, Germinate will pipe the source sample into the
|
49
|
+
# command on its STDIN.
|
50
|
+
#
|
51
|
+
# Here's the result of \:INSERT: @hello|fred
|
52
|
+
# :INSERT: @hello|fred
|
53
|
+
#
|
54
|
+
# Here's the result of :INSERT: @hello|jane
|
55
|
+
# :INSERT: @hello|jane
|
56
|
+
#
|
57
|
+
# We can even chain processes together. Here's the result of
|
58
|
+
# \:INSERT: @hello|jane|quote
|
59
|
+
# :INSERT: @hello|jane|quote
|
60
|
+
#
|
61
|
+
# It's not necessary to quote whole code samples. We can select specific lines
|
62
|
+
# to excerpt using more advanced selectors.
|
63
|
+
#
|
64
|
+
# Select a single line
|
65
|
+
# \:INSERT: @foo:2
|
66
|
+
# :INSERT: @foo:2
|
67
|
+
#
|
68
|
+
# Select an inclusive range
|
69
|
+
# \:INSERT: @foo:2..4
|
70
|
+
# :INSERT: @foo:2..4
|
71
|
+
#
|
72
|
+
# Select an exclusive range
|
73
|
+
# \:INSERT: @foo:1...3
|
74
|
+
# :INSERT: @foo:1...3
|
75
|
+
#
|
76
|
+
# Select by starting line and length
|
77
|
+
# \:INSERT: @foo:4,4
|
78
|
+
# :INSERT: @foo:4,4
|
79
|
+
#
|
80
|
+
# Select by starting and ending regular expressions
|
81
|
+
# \:INSERT: @foo:/do_stuff/../end/
|
82
|
+
# :INSERT: @foo:/do_stuff/../end/
|
83
|
+
#
|
84
|
+
# Select by regex and length
|
85
|
+
# \:INSERT: @foo:/attr_reader/,3
|
86
|
+
# :INSERT: @foo:/attr_reader/,3
|
87
|
+
#
|
88
|
+
# :SAMPLE: foo
|
89
|
+
class Foo
|
90
|
+
attr_reader :bar
|
91
|
+
attr_reader :baz
|
92
|
+
attr_reader :buz
|
93
|
+
|
94
|
+
def do_stuff
|
95
|
+
# ...
|
96
|
+
end
|
97
|
+
end
|
98
|
+
# :END:
|
99
|
+
|
100
|
+
# :TEXT:
|
101
|
+
# Finally, we can include all of the code samples in a single chunk with
|
102
|
+
# \:INSERT: $CODE
|
103
|
+
# :INSERT: $CODE
|
104
|
+
#
|
105
|
+
# There are some other special section names, such as $SOURCE and $TEXT. See
|
106
|
+
# the Germinate documentation for more.
|
107
|
+
#
|
108
|
+
# :CUT:
|
109
|
+
#
|
110
|
+
# You can format this article for publishing by running:
|
111
|
+
#
|
112
|
+
# germ format <filename>
|
113
|
+
#
|
114
|
+
# If you want to experiment with the selector syntax, try:
|
115
|
+
#
|
116
|
+
# germ select -s <selector>
|
117
|
+
#
|
118
|
+
# Enjoy!
|
data/examples/short.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# #!/usr/bin/env ruby
|
2
|
+
# :BRACKET_CODE: <pre>, </pre>
|
3
|
+
# :PROCESS: ruby, "ruby %f"
|
4
|
+
|
5
|
+
# :SAMPLE: hello
|
6
|
+
def hello(who)
|
7
|
+
puts "Hello, #{who}"
|
8
|
+
end
|
9
|
+
|
10
|
+
hello("World")
|
11
|
+
|
12
|
+
# :TEXT:
|
13
|
+
# Check out my amazing program! Here's the hello method:
|
14
|
+
# :INSERT: @hello:/def/../end/
|
15
|
+
|
16
|
+
# And here's the output:
|
17
|
+
# :INSERT: @hello|ruby
|