devver-germinate 1.1.0 → 1.2.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/History.txt +12 -0
- data/README.rdoc +26 -4
- data/TODO +80 -8
- data/bin/germ +162 -38
- data/examples/basic.rb +14 -9
- data/examples/short.rb +2 -0
- data/features/author-formats-article.feature +3 -3
- data/features/{author-lists-info.feature → author-lists-info.pending_feature} +3 -0
- data/features/author-publishes-article.feature +52 -0
- data/features/author-selects-hunks.feature +1 -1
- data/features/author-sets-variables.feature +88 -0
- data/features/{author-views-stuff.feature → author-views-stuff.pending_feature} +4 -0
- data/features/example_articles/escaping.txt +1 -0
- data/features/example_articles/specials.rb +3 -3
- data/features/example_output/specials.txt +9 -5
- data/features/step_definitions/germinate.rb +9 -0
- data/germinate.gemspec +3 -3
- data/lib/germinate.rb +1 -1
- data/lib/germinate/application.rb +82 -31
- data/lib/germinate/hunk.rb +20 -0
- data/lib/germinate/insertion.rb +10 -2
- data/lib/germinate/librarian.rb +129 -31
- data/lib/germinate/origin.rb +5 -0
- data/lib/germinate/pipeline.rb +2 -0
- data/lib/germinate/publisher.rb +57 -0
- data/lib/germinate/reader.rb +51 -8
- data/lib/germinate/selector.rb +18 -6
- data/lib/germinate/shared_style_attributes.rb +18 -1
- data/lib/germinate/{process.rb → shell_process.rb} +27 -8
- data/lib/germinate/shell_publisher.rb +19 -0
- data/lib/germinate/simple_publisher.rb +7 -0
- data/lib/germinate/source_file.rb +41 -0
- data/lib/germinate/text_transforms.rb +38 -9
- data/lib/germinate/transform_process.rb +25 -0
- data/lib/germinate/variable.rb +23 -0
- data/sample.rb +14 -0
- data/spec/germinate/application_spec.rb +18 -1
- data/spec/germinate/article_editor_spec.rb +3 -3
- data/spec/germinate/code_hunk_spec.rb +28 -0
- data/spec/germinate/file_hunk_spec.rb +1 -0
- data/spec/germinate/hunk_spec.rb +1 -0
- data/spec/germinate/insertion_spec.rb +2 -1
- data/spec/germinate/librarian_spec.rb +280 -85
- data/spec/germinate/pipeline_spec.rb +10 -0
- data/spec/germinate/process_spec.rb +31 -6
- data/spec/germinate/publisher_spec.rb +130 -0
- data/spec/germinate/reader_spec.rb +58 -2
- data/spec/germinate/selector_spec.rb +34 -14
- data/spec/germinate/shell_publisher_spec.rb +61 -0
- data/spec/germinate/source_file_spec.rb +99 -0
- data/spec/germinate/text_hunk_spec.rb +45 -0
- data/spec/germinate/text_transforms_spec.rb +90 -2
- data/spec/germinate/transform_process_spec.rb +50 -0
- data/spec/germinate/variable_spec.rb +14 -0
- metadata +19 -7
- data/lib/germinate/article_formatter.rb +0 -75
- data/spec/germinate/article_formatter_spec.rb +0 -153
data/History.txt
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
== 1.2.0 / 2009-07-21
|
2
|
+
|
3
|
+
* 4 major enhancements
|
4
|
+
* Added "publish" command and pluggable publishers
|
5
|
+
* Added builtin publisher "shell" for publishing via shell command
|
6
|
+
* Added variables, settable with the :SET: directive
|
7
|
+
* Added the ability for commands to write changes back to the source file
|
8
|
+
(with backups)
|
9
|
+
* 2 minor enhancements
|
10
|
+
* Refactored standard text transforms to be just another process
|
11
|
+
* Made the list/show/select command arguments easier to use
|
12
|
+
|
1
13
|
== 1.1.0 / 2009-07-12
|
2
14
|
|
3
15
|
* 1 major enhancement
|
data/README.rdoc
CHANGED
@@ -74,6 +74,24 @@ Development of Germinate is graciously sponsored by Devver, purveyor of fine
|
|
74
74
|
cloud-based services to busy Ruby developers. If you like this tool please
|
75
75
|
check them out at http://devver.net.
|
76
76
|
|
77
|
+
== WHAT GERMINATE IS NOT
|
78
|
+
|
79
|
+
Germinate is not a markup language like HTML, Textile, or Markdown. It is
|
80
|
+
completely markup-agnostic, although it can be configured to automatically
|
81
|
+
pre-process your articles with markup tools before publishing. Germinate
|
82
|
+
concerns itslf strictly with bringing together your words and your code, and
|
83
|
+
with automating the process of publishing the finished product.
|
84
|
+
|
85
|
+
Germinate is not a code documentation tool. While it facilitates the process of
|
86
|
+
writing *about* code, it has no understanding of the code itself. Germinate is
|
87
|
+
orthogonal to tools such as RDoc or Doxygen.
|
88
|
+
|
89
|
+
Germinate is not a blogging engine. It is designed to integrate with your
|
90
|
+
favorite blogging engine through publisher plugins.
|
91
|
+
|
92
|
+
Germinate is none of these things, but it is designed to complement all of
|
93
|
+
them.
|
94
|
+
|
77
95
|
== FEATURES
|
78
96
|
|
79
97
|
* Language and markup agnostic
|
@@ -81,20 +99,22 @@ check them out at http://devver.net.
|
|
81
99
|
* Define arbitrary command pipelines to preprocess excerpts
|
82
100
|
* Article text is reformatted to be more compatible with popular blogging
|
83
101
|
engines, e.g. WordPress.
|
102
|
+
* Extensable with plugins for publishing to Gist, WordPress, etc.
|
84
103
|
* Introspection commands make it easy to experiment
|
85
|
-
* Fully tested
|
86
104
|
|
87
105
|
== KNOWN ISSUES
|
88
106
|
|
89
107
|
* Directive syntax conflicts with RDoc. Doh!
|
108
|
+
* Focus is currently on features. Documentation is lacking. Have a look at the
|
109
|
+
features/ directory to get a better idea of various Germinate features.
|
90
110
|
|
91
111
|
== FUTURE
|
92
112
|
|
93
|
-
*
|
94
|
-
* Integration with Github's Gist
|
113
|
+
* See the TODO file
|
95
114
|
|
96
115
|
== REQUIREMENTS
|
97
116
|
|
117
|
+
* Ruby 1.8
|
98
118
|
* main
|
99
119
|
* fattr
|
100
120
|
* ick
|
@@ -105,12 +125,14 @@ check them out at http://devver.net.
|
|
105
125
|
== INSTALL:
|
106
126
|
|
107
127
|
gem install --source http://gems.rubyforge.org devver-germinate
|
128
|
+
gem install --source http://gems.rubyforge.org devver-germinate-gist
|
129
|
+
gem install --source http://gems.rubyforge.org devver-germinate-atompub
|
108
130
|
|
109
131
|
== LICENSE:
|
110
132
|
|
111
133
|
(The MIT License)
|
112
134
|
|
113
|
-
Copyright (c)
|
135
|
+
Copyright (c) 2009
|
114
136
|
|
115
137
|
Permission is hereby granted, free of charge, to any person obtaining
|
116
138
|
a copy of this software and associated documentation files (the
|
data/TODO
CHANGED
@@ -11,13 +11,33 @@
|
|
11
11
|
* DONE Make $SOURCE use the actual source file path in processes
|
12
12
|
CLOSED: [2009-07-12 Sun 19:46]
|
13
13
|
|
14
|
-
*
|
15
|
-
|
14
|
+
* DONE Improve error message for non-matching regexen in selectors :usability:
|
15
|
+
CLOSED: [2009-07-13 Mon 02:17]
|
16
|
+
* DONE Make text transforms just another process for pipelines :techdebt:
|
17
|
+
CLOSED: [2009-07-19 Sun 16:33]
|
18
|
+
This should help make [[*Make%20it%20possible%20for%20publishers%20to%20use%20formatted%20text%20as%20input][this item]] possible.
|
19
|
+
* DONE Add standard "select" option to publishers
|
20
|
+
CLOSED: [2009-07-19 Sun 16:33]
|
21
|
+
The select option would define a selector to be used to get the input for the
|
22
|
+
publisher. Another step towards [[*Make%20it%20possible%20for%20publishers%20to%20use%20formatted%20text%20as%20input][this]].
|
23
|
+
|
24
|
+
This MAY make the current "pipeline" option redundant.
|
25
|
+
* DONE Make it possible for publishers to use formatted text as input :feature:
|
26
|
+
CLOSED: [2009-07-19 Sun 16:33]
|
27
|
+
Pretty useless without this...
|
28
|
+
|
29
|
+
* TODO Refactor format command into a null publisher :techdebt:
|
30
|
+
This just needs one last step of pre-loading a "stdout publisher" and then we
|
31
|
+
can do e.g.:
|
32
|
+
|
33
|
+
: germ publish stdout my_article.c
|
16
34
|
* TODO Output line numbers for Reader errors :usability:
|
17
35
|
|
18
|
-
*
|
36
|
+
* DONE Gist uploads :feature:
|
37
|
+
CLOSED: [2009-07-21 Tue 10:54]
|
19
38
|
|
20
|
-
*
|
39
|
+
* DONE Publishing to WordPress blogs (Atompub) :feature:
|
40
|
+
CLOSED: [2009-07-21 Tue 10:54]
|
21
41
|
|
22
42
|
* TODO Alternate directive syntax :usability:
|
23
43
|
one that doesn't conflict with RDoc
|
@@ -37,6 +57,7 @@
|
|
37
57
|
* TODO Format Pipelines :feature:
|
38
58
|
Define a pipeline to be run on the entire article after formatting
|
39
59
|
|
60
|
+
Or maybe just demote "format" to be a built-in publisher.
|
40
61
|
* TODO ERB Substitution :feature:
|
41
62
|
Should be run on TEXT sections.
|
42
63
|
|
@@ -44,8 +65,6 @@
|
|
44
65
|
A helper for ERB subtitution which inserts the line# of a given selector.
|
45
66
|
|
46
67
|
* TODO Plugin API :feature:
|
47
|
-
Should use gems to discover plugins.
|
48
|
-
|
49
68
|
* TODO User-global preference file :feature:
|
50
69
|
|
51
70
|
* TODO Multiple file support :feature:
|
@@ -60,12 +79,65 @@
|
|
60
79
|
|
61
80
|
Workaround: Authors can just include 2>&1 in their process definitions.
|
62
81
|
|
63
|
-
* DONE Syntax for post-process excerpting
|
82
|
+
* DONE Syntax for post-process excerpting :feature:
|
64
83
|
CLOSED: [2009-07-12 Sun 20:50]
|
65
84
|
E.g. "$SOURCE|ruby:/---/../---/"
|
66
85
|
|
67
86
|
This would cause the process to be run on $SOURCE and then a subset of the
|
68
87
|
output to be excerpted.
|
69
88
|
|
70
|
-
* TODO Named Styles
|
89
|
+
* TODO Named Styles :feature:
|
71
90
|
A way to group together a bunch of style attributes in a reusable way.
|
91
|
+
* DONE A way to set arbitrary variables for later substitution :feature:
|
92
|
+
CLOSED: [2009-07-16 Thu 11:51]
|
93
|
+
* DONE Standard "pipeline" option for publishers :feature:
|
94
|
+
CLOSED: [2009-07-15 Wed 01:32]
|
95
|
+
Defines a pipeline which will be run on $SOURCE before publishing.
|
96
|
+
* TODO Plugin discovery :feature:
|
97
|
+
Should use gems to discover plugins.
|
98
|
+
|
99
|
+
* TODO Line continuations for directives :usability:
|
100
|
+
After some thought I think what I really want is a second syntax for long-form
|
101
|
+
directives, wherein the YAML arguments go in between directive opening and
|
102
|
+
closing lines. E.g.
|
103
|
+
|
104
|
+
: # :PUBLISHER: ---
|
105
|
+
: # - source
|
106
|
+
: # - shell
|
107
|
+
: # -
|
108
|
+
: # command: cat
|
109
|
+
: # pipeline: markdown
|
110
|
+
: # :END:
|
111
|
+
* DONE Variables
|
112
|
+
CLOSED: [2009-07-16 Thu 19:47]
|
113
|
+
Syntax:
|
114
|
+
: :SET: foo, 123
|
115
|
+
*** Reader records what line they were set on
|
116
|
+
*** SourceFile class which can set and re-set variables
|
117
|
+
- Backs the file up first
|
118
|
+
- Verifies the backup
|
119
|
+
- Locks the file and the backup
|
120
|
+
- Removes the old line
|
121
|
+
- Replaces it with a new :SET: line
|
122
|
+
- Or adds a new :SET: line to the end
|
123
|
+
- Re-reads and verifies value
|
124
|
+
- Restores the backup if there is a problem
|
125
|
+
|
126
|
+
*** Variables are available to processes as environment vars
|
127
|
+
* TODO Add processing/style options to TEXT sections :feature:
|
128
|
+
* TODO Add console modes :feature:
|
129
|
+
*** TODO Shell console
|
130
|
+
In this version we just exec $SHELL with some custom environment. A
|
131
|
+
GERMINATE_SOURCE variable should point to the source file, and all germ
|
132
|
+
commands should use it if no explicit source is specified.
|
133
|
+
|
134
|
+
In addition, aliases for all the common germ modes should be installed -
|
135
|
+
publish, format, list, etc.
|
136
|
+
*** TODO Debug console
|
137
|
+
An IRB session with Germinate preloaded.
|
138
|
+
|
139
|
+
* TODO Clean up output during tests :techdebt:
|
140
|
+
* TODO Add a dry-run mode :feature:
|
141
|
+
* TODO Add a TITLE variable
|
142
|
+
Should be used by publishers.
|
143
|
+
* TODO Make publishers more configurable
|
data/bin/germ
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require File.expand_path(
|
4
4
|
File.join(File.dirname(__FILE__), %w[.. lib germinate]))
|
5
5
|
|
6
|
+
require 'English'
|
6
7
|
require 'main'
|
7
8
|
|
8
9
|
Main do
|
@@ -39,78 +40,93 @@ Main do
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
43
|
+
option(:debug, :d) do
|
44
|
+
cast :bool
|
45
|
+
end
|
46
|
+
|
47
|
+
def run
|
48
|
+
help!
|
49
|
+
end
|
50
|
+
|
42
51
|
mode :format do
|
43
52
|
description "Format an article for publishing"
|
44
53
|
source_argument
|
45
54
|
def run
|
46
|
-
Germinate.logger = self
|
47
55
|
with_source_file do |source, path|
|
48
|
-
application
|
49
|
-
application.format(source, path, $stdout, $stderr)
|
56
|
+
@application.format(source, path)
|
50
57
|
end
|
51
58
|
end
|
52
59
|
end
|
53
60
|
|
54
61
|
mode :list do
|
55
|
-
description "List
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
cast :bool
|
62
|
-
end
|
62
|
+
description "List info about the source file"
|
63
|
+
argument :collection do
|
64
|
+
arity 1
|
65
|
+
required
|
66
|
+
argument_required
|
67
|
+
description "One of: sections, samples, processes, publishers, variables"
|
63
68
|
end
|
69
|
+
source_argument
|
64
70
|
|
65
71
|
def run
|
66
|
-
things_to_list = []
|
67
|
-
COLLECTIONS.each do |collection|
|
68
|
-
things_to_list << collection if params[collection].value
|
69
|
-
end
|
70
72
|
with_source_file do |source, path|
|
71
|
-
application
|
72
|
-
application.list(source, path, things_to_list, $stdout)
|
73
|
+
@application.list(source, path, params[:collection].value)
|
73
74
|
end
|
74
75
|
end
|
75
76
|
end
|
76
77
|
|
77
78
|
mode :show do
|
78
79
|
description "Show details about various article components"
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
argument_required
|
85
|
-
end
|
80
|
+
argument :type do
|
81
|
+
arity 1
|
82
|
+
required
|
83
|
+
argument_required
|
84
|
+
description "One of: section, sample, process, publisher, variable"
|
86
85
|
end
|
86
|
+
argument :item do
|
87
|
+
arity 1
|
88
|
+
required
|
89
|
+
argument_required
|
90
|
+
description "The specific item to show details about"
|
91
|
+
end
|
92
|
+
source_argument
|
87
93
|
|
88
94
|
def run
|
89
|
-
selection = TYPES.inject({}) {|sel, type|
|
90
|
-
sel[type] = params[type].values
|
91
|
-
sel
|
92
|
-
}
|
93
95
|
with_source_file do |source, path|
|
94
|
-
application
|
95
|
-
application.show(source, path, selection, $stdout)
|
96
|
+
@application.show(source, path, params['type'].value, params['item'].value)
|
96
97
|
end
|
97
98
|
end
|
98
99
|
end
|
99
100
|
|
100
101
|
mode :select do
|
101
102
|
description "Test out a selector"
|
102
|
-
|
103
|
-
option(:selector, :s) do
|
103
|
+
argument :selector do
|
104
104
|
arity 1
|
105
105
|
required
|
106
106
|
argument_required
|
107
|
-
description "The selector to
|
107
|
+
description "The selector to retrieve"
|
108
|
+
end
|
109
|
+
source_argument
|
110
|
+
|
111
|
+
Germinate::TextTransforms.singleton_methods.each do |transform|
|
112
|
+
option(transform) do
|
113
|
+
description "Enable/disable the '#{transform}' text transform"
|
114
|
+
cast :bool
|
115
|
+
end
|
108
116
|
end
|
109
117
|
|
110
118
|
def run
|
119
|
+
options = Germinate::TextTransforms.singleton_methods.inject({}) do
|
120
|
+
|opts, transform|
|
121
|
+
if params[transform].given?
|
122
|
+
opts[transform] = params[transform].value
|
123
|
+
logger.info "Text transform '#{transform}' " +
|
124
|
+
(params[transform].value ? "enabled" : "disabled")
|
125
|
+
end
|
126
|
+
opts
|
127
|
+
end
|
111
128
|
with_source_file do |source, path|
|
112
|
-
application
|
113
|
-
application.select(source, path, params[:selector].value, $stdout)
|
129
|
+
@application.select(source, path, params[:selector].value, options)
|
114
130
|
end
|
115
131
|
end
|
116
132
|
end
|
@@ -125,12 +141,120 @@ Main do
|
|
125
141
|
end
|
126
142
|
end
|
127
143
|
|
144
|
+
mode :publish do
|
145
|
+
description "Publish the article using the named publisher"
|
146
|
+
argument :publisher
|
147
|
+
source_argument
|
148
|
+
option 'publish-options' do
|
149
|
+
arity 1
|
150
|
+
end
|
151
|
+
|
152
|
+
def run
|
153
|
+
with_source_file do |source, path|
|
154
|
+
options = YAML.load(params['publish-options'].value || "{}")
|
155
|
+
@application.publish(source, path, params[:publisher].value, options)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
mode :set do
|
161
|
+
description "Set a named value in the article"
|
162
|
+
argument :name do
|
163
|
+
description "Variable name"
|
164
|
+
cast :string
|
165
|
+
end
|
166
|
+
argument :value do
|
167
|
+
description "Variable value"
|
168
|
+
cast :string
|
169
|
+
end
|
170
|
+
source_argument
|
171
|
+
|
172
|
+
def run
|
173
|
+
with_source_file do |source, path|
|
174
|
+
@application.set(
|
175
|
+
source,
|
176
|
+
path,
|
177
|
+
params[:name].value,
|
178
|
+
params[:value].value)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def initialize
|
184
|
+
@command = "#{$PROGRAM_NAME} #{ARGV.join(' ')}"
|
185
|
+
Germinate.logger = logger
|
186
|
+
logger.progname = "germinate"
|
187
|
+
logger.formatter = lambda { |severity, time, progname, message|
|
188
|
+
lines = case message
|
189
|
+
when ::String then message.split("\n")
|
190
|
+
when ::Exception then
|
191
|
+
Array(message.message) + Array(message.backtrace)
|
192
|
+
else
|
193
|
+
message.inspect
|
194
|
+
end
|
195
|
+
lines.map{|l| "#{severity} -- #{progname}: #{l}"}.join("\n") + "\n"
|
196
|
+
}
|
197
|
+
@application = Germinate::Application.new(stdout, stderr)
|
198
|
+
@application.load_plugins!
|
199
|
+
end
|
200
|
+
|
201
|
+
def pre_parse_parameters
|
202
|
+
end
|
203
|
+
|
204
|
+
def pre_run
|
205
|
+
logger.level = params['debug'].value ? Logger::DEBUG : Logger::INFO
|
206
|
+
end
|
207
|
+
|
128
208
|
def with_source_file
|
129
|
-
|
130
|
-
|
131
|
-
|
209
|
+
rescue_errors do
|
210
|
+
path = params['source'].value
|
211
|
+
File.open(path) do |file|
|
212
|
+
yield file, path
|
213
|
+
end
|
132
214
|
end
|
133
215
|
end
|
216
|
+
|
217
|
+
def rescue_errors
|
218
|
+
yield
|
219
|
+
rescue RuntimeError => error
|
220
|
+
raise if params['debug'].value
|
221
|
+
log_user_error(error)
|
222
|
+
rescue Exception => error
|
223
|
+
raise if params['debug'].value
|
224
|
+
log_program_error(error)
|
225
|
+
end
|
226
|
+
|
227
|
+
def log_user_error(error)
|
228
|
+
log_fatal_error <<-END
|
229
|
+
Germinate could not complete your command.
|
230
|
+
Please check your command and article for proper syntax.
|
231
|
+
#{command_report}
|
232
|
+
#{error_report(error)}
|
233
|
+
For more information, re-run the command with the --debug flag.
|
234
|
+
END
|
235
|
+
end
|
236
|
+
|
237
|
+
def log_program_error(error)
|
238
|
+
log_fatal_error <<-END
|
239
|
+
Germinate encountered an error while executing your command.
|
240
|
+
#{command_report}
|
241
|
+
#{error_report(error)}
|
242
|
+
Please re-run the command with the --debug flag, and file a problem report at
|
243
|
+
http://github.com/devver/germinate/
|
244
|
+
END
|
245
|
+
end
|
246
|
+
|
247
|
+
def command_report
|
248
|
+
"The command was: '#{@command}'"
|
249
|
+
end
|
250
|
+
|
251
|
+
def error_report(error)
|
252
|
+
"The error was: '#{error.message}'"
|
253
|
+
end
|
254
|
+
|
255
|
+
def log_fatal_error(error)
|
256
|
+
logger.fatal(error)
|
257
|
+
end
|
134
258
|
end
|
135
259
|
|
136
260
|
# EOF
|