devver-germinate 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|