gitscribe 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +16 -0
- data/VERSION.yml +4 -0
- data/bin/gitscribe +8 -0
- data/lib/gitscribe.rb +51 -0
- data/lib/gitscribe/models.rb +67 -0
- data/lib/gitscribe/options.rb +39 -0
- data/lib/gitscribe/template.erb +20 -0
- data/test/gitscribe_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +72 -0
data/README.markdown
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# GitScribe: Create tutorials and articles with Git
|
2
|
+
|
3
|
+
## Installing
|
4
|
+
|
5
|
+
# Run the following if you haven't done so before:
|
6
|
+
gem sources -a http://gems.github.com
|
7
|
+
# Install the gem:
|
8
|
+
sudo gem install dima-gitscribe
|
9
|
+
|
10
|
+
## Using
|
11
|
+
|
12
|
+
gitscribe --title 'Working with RestfulX Model Attachments' rx_model_attachments
|
13
|
+
|
14
|
+
# License
|
15
|
+
|
16
|
+
Copyright (c) 2009 Dima Berastau. Released under MIT License
|
data/VERSION.yml
ADDED
data/bin/gitscribe
ADDED
data/lib/gitscribe.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'git'
|
2
|
+
require 'erb'
|
3
|
+
require 'gitscribe/options'
|
4
|
+
require 'gitscribe/models'
|
5
|
+
|
6
|
+
class GitScribe
|
7
|
+
class << self
|
8
|
+
def run!(*arguments)
|
9
|
+
options = GitScribe::Options.new(arguments)
|
10
|
+
|
11
|
+
if options[:show_help]
|
12
|
+
$stderr.puts options.opts
|
13
|
+
return 1
|
14
|
+
end
|
15
|
+
|
16
|
+
unless arguments.size == 1
|
17
|
+
$stderr.puts options.opts
|
18
|
+
return 1
|
19
|
+
end
|
20
|
+
|
21
|
+
g = Git.open(arguments.first)
|
22
|
+
|
23
|
+
tags = Array.new
|
24
|
+
g.tags.sort_by { |x| g.object(x.objectish).date }.each { |t| tags << t.name }
|
25
|
+
|
26
|
+
chapters = Array.new
|
27
|
+
if tags.empty?
|
28
|
+
chapter = Chapter.new
|
29
|
+
g.log.each { |c| add_section(chapter.sections, c) }
|
30
|
+
chapters << chapter
|
31
|
+
else
|
32
|
+
tags.each_index do |i|
|
33
|
+
chapter = Chapter.new(tags[i])
|
34
|
+
g.log.between(tags[i], tags[i + 1]).each { |c| add_section(chapter.sections, c) } if i + 1 < tags.size
|
35
|
+
chapters << chapter if !chapter.sections.empty?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
template = File.read(File.dirname(__FILE__) + "/gitscribe/template.erb")
|
40
|
+
|
41
|
+
f = File.new(options[:output], "w+")
|
42
|
+
f.puts(ERB.new(template).result(binding))
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_section(target, c)
|
46
|
+
target << GitScribe::Section.new(c.message(), c.parent().diff(c)) if c.parent()
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
class GitScribe
|
2
|
+
class Chapter
|
3
|
+
attr_accessor :title, :sections
|
4
|
+
|
5
|
+
def initialize(title = 'Chapter X', sections = [])
|
6
|
+
@title, @sections = title, sections
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Section
|
11
|
+
attr_reader :message
|
12
|
+
|
13
|
+
def initialize(message, diff)
|
14
|
+
@message, @diff = message, diff
|
15
|
+
end
|
16
|
+
|
17
|
+
def diff
|
18
|
+
@diff.select { |f| valid_file(f.path) }.map do |f|
|
19
|
+
type = f.type == "new" ? file_type(f.path) : "diff"
|
20
|
+
code, target_file = parse_diff(f.patch, f.type)
|
21
|
+
"File: #{target_file}\n\n{% highlight #{type} %}\n#{code}\n{% endhighlight %}\n\n"
|
22
|
+
end.join
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def parse_diff(patch, type)
|
27
|
+
offset = patch.index(/@@ -\d+,\d+ \+\d+,\d+ @@/) - 1
|
28
|
+
header = patch.slice!(0 .. offset)
|
29
|
+
target_file = /diff --git a\/(.*?) b\/(.*?)/.match(header)[1]
|
30
|
+
patch = patch.split("\n").select { |l|!l.include?("No newline at end of file") }.map do |l|
|
31
|
+
l = l[1..-1] unless l.match(/@@ -\d+,\d+ \+\d+,\d+ @@/)
|
32
|
+
#split(l)
|
33
|
+
end.join("\n") if type == "new"
|
34
|
+
patch = patch.gsub(/\t/m, " ")
|
35
|
+
[patch, target_file]
|
36
|
+
end
|
37
|
+
|
38
|
+
# This is pretty doggy, would be nice to have a decent lexical analizer that can
|
39
|
+
# reformat code based on a width parameter
|
40
|
+
def split(line)
|
41
|
+
line.split("\n").map do |l|
|
42
|
+
if l.size > 80
|
43
|
+
offset = l.rindex(/\s/)
|
44
|
+
first_part = l.slice!(0 .. offset)
|
45
|
+
"#{first_part}\n #{l}"
|
46
|
+
else
|
47
|
+
l
|
48
|
+
end
|
49
|
+
end.join("\n")
|
50
|
+
end
|
51
|
+
|
52
|
+
# needs to be configurable
|
53
|
+
def valid_file(f)
|
54
|
+
f =~ /\.rb$|\.mxml$|\.as$/
|
55
|
+
end
|
56
|
+
|
57
|
+
def file_type(f)
|
58
|
+
result = case f
|
59
|
+
when /.rb$/ : "ruby"
|
60
|
+
when /.mxml$/ : "xml"
|
61
|
+
when /.as$/ : "as3"
|
62
|
+
else
|
63
|
+
"unknown"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class GitScribe
|
2
|
+
class Options < Hash
|
3
|
+
attr_reader :opts
|
4
|
+
|
5
|
+
def initialize(args)
|
6
|
+
super()
|
7
|
+
|
8
|
+
self[:title] = "Cool Tutorial"
|
9
|
+
self[:location] = "Vancouver, BC"
|
10
|
+
|
11
|
+
@opts = OptionParser.new do |o|
|
12
|
+
o.banner = "Usage: #{File.basename($0)} [options] reponame\ne.g. #{File.basename($0)} cool-tutorial"
|
13
|
+
|
14
|
+
o.on('--output [FILE]', 'Output file to generate blog post to') do |output|
|
15
|
+
self[:output] = output
|
16
|
+
end
|
17
|
+
|
18
|
+
o.on('--title [TITLE]', 'Blog post title to use', "Default: #{self[:title]}") do |title|
|
19
|
+
self[:title] = title
|
20
|
+
self[:output] = default_output unless self[:output]
|
21
|
+
end
|
22
|
+
|
23
|
+
o.on('--location [LOCATION]', 'Add geo location to the blog post', "Default: #{self[:location]}") do |location|
|
24
|
+
self[:location] = location
|
25
|
+
end
|
26
|
+
|
27
|
+
o.on_tail('-h', '--help', 'display this help and exit') do
|
28
|
+
self[:show_help] = true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
@opts.parse!(args)
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_output
|
36
|
+
"#{Date.today.strftime("%Y-%m-%d")}-#{self[:title].gsub(/\s/, '-').downcase}.textile"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
---
|
2
|
+
layout: post
|
3
|
+
title: <%= options[:title] %>
|
4
|
+
---
|
5
|
+
|
6
|
+
h1. {{ page.title }}
|
7
|
+
|
8
|
+
p(meta). <%= Date.today.strftime("%d %b %Y") %> - <%= options[:location] %>
|
9
|
+
|
10
|
+
<% chapters.each do |chapter| %>
|
11
|
+
h2. <%= chapter.title %>
|
12
|
+
|
13
|
+
<% chapter.sections.reverse.each do |section| %>
|
14
|
+
h3. Section
|
15
|
+
|
16
|
+
<%= section.message %>
|
17
|
+
|
18
|
+
<%= section.diff %>
|
19
|
+
<% end %>
|
20
|
+
<% end %>
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gitscribe
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dima Berastau
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-22 00:00:00 -08:00
|
13
|
+
default_executable: gitscribe
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: schacon-git
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description:
|
26
|
+
email: dima@ruboss.com
|
27
|
+
executables:
|
28
|
+
- gitscribe
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files: []
|
32
|
+
|
33
|
+
files:
|
34
|
+
- README.markdown
|
35
|
+
- VERSION.yml
|
36
|
+
- bin/gitscribe
|
37
|
+
- lib/gitscribe
|
38
|
+
- lib/gitscribe/models.rb
|
39
|
+
- lib/gitscribe/options.rb
|
40
|
+
- lib/gitscribe/template.erb
|
41
|
+
- lib/gitscribe.rb
|
42
|
+
- test/gitscribe_test.rb
|
43
|
+
- test/test_helper.rb
|
44
|
+
has_rdoc: true
|
45
|
+
homepage: http://github.com/dima/gitscribe
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --inline-source
|
49
|
+
- --charset=UTF-8
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.3.1
|
68
|
+
signing_key:
|
69
|
+
specification_version: 2
|
70
|
+
summary: Create code-intensive tutorials and articles with Git
|
71
|
+
test_files: []
|
72
|
+
|