rmsgen 0.0.3
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 +6 -0
- data/Gemfile +11 -0
- data/LICENSE +674 -0
- data/README.md +55 -0
- data/Rakefile +13 -0
- data/bin/checkurl +2 -0
- data/bin/publish +3 -0
- data/bin/rmsgen +10 -0
- data/features/append_tabbed_line.feature +23 -0
- data/features/config/output_file.feature +59 -0
- data/features/config/reading_config.feature +24 -0
- data/features/link_to_polnote.feature +38 -0
- data/features/multiple_notes.feature +54 -0
- data/features/multiple_url.feature +31 -0
- data/features/raw_email.feature +101 -0
- data/features/setting_title.feature +22 -0
- data/features/standard_pol_note.feature +41 -0
- data/features/step_definitions/bin_steps.rb +3 -0
- data/features/step_definitions/file_steps.rb +3 -0
- data/features/step_definitions/polnote_steps.rb +25 -0
- data/features/step_definitions/title_steps.rb +10 -0
- data/features/step_definitions/urgent_polnote_steps.rb +24 -0
- data/features/support/env.rb +7 -0
- data/features/support/hooks.rb +8 -0
- data/features/urgent_polnote.feature +33 -0
- data/lib/rmsgen/cli/main.rb +21 -0
- data/lib/rmsgen/compresser.rb +33 -0
- data/lib/rmsgen/fs_polnote_group.rb +12 -0
- data/lib/rmsgen/imap_polnote_group.rb +66 -0
- data/lib/rmsgen/inquirer.rb +90 -0
- data/lib/rmsgen/link.rb +12 -0
- data/lib/rmsgen/part_group.rb +23 -0
- data/lib/rmsgen/polnote.rb +41 -0
- data/lib/rmsgen/runtime.rb +56 -0
- data/lib/rmsgen/script.rb +38 -0
- data/lib/rmsgen/titleizer.rb +43 -0
- data/lib/rmsgen/version.rb +3 -0
- data/lib/rmsgen.rb +21 -0
- data/lib/templates/polnote.erb +2 -0
- data/lib/templates/title.erb +1 -0
- data/rmsgen.gemspec +21 -0
- data/spec/fake_gets.rb +25 -0
- data/spec/fixtures/imap_note +3 -0
- data/spec/fixtures/link_to_polnote +7 -0
- data/spec/fixtures/multiline_note +9 -0
- data/spec/fixtures/urgent_note +39 -0
- data/spec/fs_polnote_group_spec.rb +37 -0
- data/spec/imap_polnote_group_spec.rb +43 -0
- data/spec/inqirer_spec.rb +55 -0
- data/spec/part_group_spec.rb +21 -0
- data/spec/polnote_spec.rb +60 -0
- data/spec/runtime_spec.rb +52 -0
- data/spec/support/fake_gets.rb +27 -0
- metadata +103 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module Rmsgen
|
|
2
|
+
class IMAPPolnoteGroup
|
|
3
|
+
require 'net/imap'
|
|
4
|
+
|
|
5
|
+
def initialize(imap, options={})
|
|
6
|
+
@imap = imap
|
|
7
|
+
@login = options['imap_login']
|
|
8
|
+
@password = options['imap_password']
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def fetch_notes
|
|
12
|
+
authenticate
|
|
13
|
+
follow_inbox
|
|
14
|
+
find_all_from_rms
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def note_ids
|
|
18
|
+
authenticate
|
|
19
|
+
follow_inbox
|
|
20
|
+
@imap.search(["FROM", 'rms@gnu.org'])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def find(id)
|
|
24
|
+
follow_inbox
|
|
25
|
+
fetch_message_body(id)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def archive_polnote(id)
|
|
29
|
+
authenticate
|
|
30
|
+
follow_inbox
|
|
31
|
+
archived = false
|
|
32
|
+
@imap.search(["FROM", 'rms@gnu.org']).each do |note_id|
|
|
33
|
+
if note_id.to_i == id.to_i
|
|
34
|
+
@imap.copy id.to_i, 'INBOX.old-messages'
|
|
35
|
+
@imap.store(id.to_i, "+FLAGS", [:Deleted])
|
|
36
|
+
@imap.expunge
|
|
37
|
+
archived = true
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
archived
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def authenticate
|
|
46
|
+
@imap.authenticate 'LOGIN', @login, @password
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def follow_inbox
|
|
50
|
+
@imap.select 'INBOX'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def find_all_from_rms
|
|
54
|
+
if note_ids && note_ids.any?
|
|
55
|
+
note_ids.map { |id| fetch_message_body(id) }
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def fetch_message_body(id)
|
|
60
|
+
fetch_result = @imap.fetch id, 'BODY[TEXT]'
|
|
61
|
+
if fetch_result && fetch_result.any?
|
|
62
|
+
fetch_result[0].attr['BODY[TEXT]']
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
module Rmsgen
|
|
2
|
+
class Inquirer
|
|
3
|
+
PARTS = { :url => /^http/,
|
|
4
|
+
:note =>/\[Link/,
|
|
5
|
+
:duration => /^For.*week.*$/,
|
|
6
|
+
:indendation => /^ /
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
attr_reader :polnote
|
|
10
|
+
|
|
11
|
+
def initialize polnote, stdout=$stdout, answers=nil
|
|
12
|
+
@parts_seen = []
|
|
13
|
+
@polnote = polnote
|
|
14
|
+
@parts = @polnote.parts
|
|
15
|
+
@stdout = stdout
|
|
16
|
+
@script = Script.new(stdout)
|
|
17
|
+
@answers = answers ||= []
|
|
18
|
+
run!
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def body
|
|
22
|
+
@parts_seen.join PartGroup::DELIMETER
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.inquire_about_note(note, stdout=$stdout)
|
|
26
|
+
stdout.puts note.body
|
|
27
|
+
stdout.puts
|
|
28
|
+
note.titleize
|
|
29
|
+
note.inquire
|
|
30
|
+
stdout.puts
|
|
31
|
+
note
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def run!
|
|
37
|
+
@parts.each do |part|
|
|
38
|
+
if part =~ PARTS[:duration]
|
|
39
|
+
inquire_about_expiration
|
|
40
|
+
elsif part =~ PARTS[:url]
|
|
41
|
+
inquire_about_link part
|
|
42
|
+
elsif part =~ PARTS[:note]
|
|
43
|
+
inquire_about_polnote_link part
|
|
44
|
+
elsif part =~ PARTS[:indendation]
|
|
45
|
+
append_to_previous_paragraph part
|
|
46
|
+
else
|
|
47
|
+
@parts_seen << part
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def inquire_about_link url
|
|
53
|
+
if @answers.empty?
|
|
54
|
+
@script.announce current_part
|
|
55
|
+
text = @script.prompt_for_text
|
|
56
|
+
else
|
|
57
|
+
text = @answers.shift
|
|
58
|
+
end
|
|
59
|
+
if text && !text.empty?
|
|
60
|
+
link = Link.new text, url
|
|
61
|
+
current_part.gsub! text, link.to_s
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def inquire_about_expiration
|
|
66
|
+
@polnote.expires_on = @script.prompt_for_expiry_date
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def append_to_previous_paragraph part
|
|
70
|
+
current_part << " #{part.strip}#{PartGroup::DELIMETER}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def current_part
|
|
74
|
+
@parts_seen.last
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def inquire_about_polnote_link part
|
|
78
|
+
if @answers.any?
|
|
79
|
+
href = @answers.shift
|
|
80
|
+
text = @answers.shift
|
|
81
|
+
else
|
|
82
|
+
href = @script.prompt_for_polnote_link part
|
|
83
|
+
@script.announce current_part
|
|
84
|
+
text = @script.prompt_for_text
|
|
85
|
+
end
|
|
86
|
+
link = Link.new text, href
|
|
87
|
+
current_part.gsub! text, link.to_s
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
data/lib/rmsgen/link.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class PartGroup < Array
|
|
2
|
+
attr_reader :text
|
|
3
|
+
|
|
4
|
+
DELIMETER = "\n\n"
|
|
5
|
+
|
|
6
|
+
def initialize(text)
|
|
7
|
+
@text = text
|
|
8
|
+
assign_parts!
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def assign_parts!
|
|
12
|
+
if @text.match /\r\n\r\n/
|
|
13
|
+
@text.gsub!(/\r\n\r\n/, "\n\n")
|
|
14
|
+
@text.gsub!(/\r\n/, " ")
|
|
15
|
+
@text.gsub!(/\n\n\n\n/, "")
|
|
16
|
+
else
|
|
17
|
+
@text.gsub!(/\n\n/, '[newline]')
|
|
18
|
+
@text.gsub!(/\n/, ' ')
|
|
19
|
+
@text.gsub!('[newline]', "\n\n")
|
|
20
|
+
end
|
|
21
|
+
@text.split(DELIMETER).delete_if(&:empty?).each { |p| self << p }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Rmsgen
|
|
2
|
+
class Polnote
|
|
3
|
+
attr_accessor :id, :title, :body, :expires_on
|
|
4
|
+
|
|
5
|
+
URGENT_SUBJECT = 'Subject: Urgent note'
|
|
6
|
+
TEMPLATE = File.join(File.dirname(__FILE__), '..', 'templates', 'polnote.erb')
|
|
7
|
+
|
|
8
|
+
def initialize(source, options={})
|
|
9
|
+
@body = source.dup
|
|
10
|
+
@urgent = source.include? URGENT_SUBJECT
|
|
11
|
+
@id = options[:id]
|
|
12
|
+
compress!
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def urgent?
|
|
16
|
+
@urgent
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def titleize
|
|
20
|
+
@title = Titleizer.new(self).body
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def inquire
|
|
24
|
+
@body = Inquirer.new(self).body
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def parts
|
|
28
|
+
PartGroup.new(@body)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_html
|
|
32
|
+
ERB.new(File.read(TEMPLATE)).result(binding)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def compress!
|
|
38
|
+
@body = Compresser.new(self).body
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Rmsgen
|
|
2
|
+
class Runtime
|
|
3
|
+
def initialize(config)
|
|
4
|
+
@config = config
|
|
5
|
+
raise "Ensure you have populated a config file" unless @config
|
|
6
|
+
@output = @config['output_file']
|
|
7
|
+
@notes = fetch_notes
|
|
8
|
+
run!
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def run!
|
|
12
|
+
if @notes
|
|
13
|
+
@notes.each do |note|
|
|
14
|
+
system('clear')
|
|
15
|
+
polnote = Rmsgen::Inquirer.inquire_about_note(note)
|
|
16
|
+
write(polnote)
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
puts 'no polnotes in queue'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def write(note)
|
|
26
|
+
if @output
|
|
27
|
+
File.open(@output, 'a') do |file|
|
|
28
|
+
file.puts note.to_html
|
|
29
|
+
end
|
|
30
|
+
else
|
|
31
|
+
puts note.to_html
|
|
32
|
+
puts
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def fetch_notes
|
|
37
|
+
if @config['email_dir']
|
|
38
|
+
notes = Dir["#{@config['email_dir']}/*"].map { |f| File.read(f) }
|
|
39
|
+
else
|
|
40
|
+
notes = fetch_notes_from_imap
|
|
41
|
+
end
|
|
42
|
+
notes.map { |note| Rmsgen::Polnote.new(note) } if notes
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def fetch_notes_from_imap
|
|
46
|
+
options = {
|
|
47
|
+
'imap_login' => @config['imap_login'],
|
|
48
|
+
'imap_password' => @config['imap_password']
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
imap = Net::IMAP.new(@config['imap_server'])
|
|
52
|
+
Rmsgen::IMAPPolnoteGroup.new(imap, options).fetch_notes
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Rmsgen
|
|
2
|
+
class Script
|
|
3
|
+
def initialize(stdout=$stdout)
|
|
4
|
+
@stdout = stdout
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def prompt_for_expiry_date
|
|
8
|
+
prompt "What day does it expire? ex) 08 July 2011:\n "
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def prompt_for_text
|
|
12
|
+
prompt "What is the text?"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def prompt_for_polnote_link part
|
|
16
|
+
label = part[1..-2] + "?:\n"
|
|
17
|
+
prompt("What is the #{label}")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def prompt_for_title
|
|
21
|
+
prompt "Type title:"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def announce message
|
|
25
|
+
@stdout.puts message
|
|
26
|
+
@stdout.puts
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def prompt(label)
|
|
32
|
+
announce label
|
|
33
|
+
input = $stdin.gets.chomp
|
|
34
|
+
@stdout.puts
|
|
35
|
+
input
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Rmsgen
|
|
2
|
+
class Titleizer
|
|
3
|
+
TEMPLATE = File.join(File.dirname(__FILE__), '..', 'templates', 'title.erb')
|
|
4
|
+
|
|
5
|
+
attr_reader :title
|
|
6
|
+
|
|
7
|
+
def initialize(polnote, options={})
|
|
8
|
+
@body = polnote.body
|
|
9
|
+
@title = options[:title]
|
|
10
|
+
|
|
11
|
+
@script = Script.new($stdout)
|
|
12
|
+
run!
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def body
|
|
16
|
+
ERB.new(File.read(TEMPLATE)).result(binding)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def today_format
|
|
20
|
+
Date.today.strftime('%d %B %Y')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def today_underscore
|
|
24
|
+
today_format.gsub(' ', '_')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def title_underscore
|
|
28
|
+
@title.gsub(' ', '_')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_html
|
|
32
|
+
body
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def run!
|
|
38
|
+
@title = @script.prompt_for_title unless @title
|
|
39
|
+
body
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
data/lib/rmsgen.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
require 'erb'
|
|
3
|
+
|
|
4
|
+
module Rmsgen
|
|
5
|
+
%w{ part_group
|
|
6
|
+
polnote
|
|
7
|
+
titleizer
|
|
8
|
+
compresser
|
|
9
|
+
script
|
|
10
|
+
inquirer
|
|
11
|
+
runtime
|
|
12
|
+
link
|
|
13
|
+
imap_polnote_group
|
|
14
|
+
fs_polnote_group
|
|
15
|
+
}.each do |fname|
|
|
16
|
+
require File.join(File.dirname(__FILE__), 'rmsgen', fname)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<p><li><a name='<%= today_underscore %>_(<%= title_underscore %>)' /><%= today_format %> (<a class='titlelink' href='#<%= today_underscore %>_(<%= title_underscore %>)'><%= title %></a>)</p>
|
data/rmsgen.gemspec
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "rmsgen/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "rmsgen"
|
|
7
|
+
s.version = Rmsgen::VERSION
|
|
8
|
+
s.platform = Gem::Platform::RUBY
|
|
9
|
+
s.authors = ["Lake Denman"]
|
|
10
|
+
s.email = ["lake@lakedenman.com"]
|
|
11
|
+
s.homepage = ""
|
|
12
|
+
s.summary = %q{A library to help generate html markup from RMS emails}
|
|
13
|
+
s.description = %q{A library to help generate html markup from RMS emails}
|
|
14
|
+
|
|
15
|
+
s.rubyforge_project = "rmsgen"
|
|
16
|
+
|
|
17
|
+
s.files = `git ls-files`.split("\n")
|
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
20
|
+
s.require_paths = ["lib"]
|
|
21
|
+
end
|
data/spec/fake_gets.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class FakeGet
|
|
2
|
+
def initialize(input)
|
|
3
|
+
@in = input
|
|
4
|
+
end
|
|
5
|
+
def gets
|
|
6
|
+
@in
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class FakeGetMany
|
|
11
|
+
attr_reader :answers
|
|
12
|
+
|
|
13
|
+
def initialize(*answers)
|
|
14
|
+
@answers = answers
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def answer
|
|
18
|
+
@answers.shift
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def gets
|
|
22
|
+
answer
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
Return-Path: <rms@gnu.org>
|
|
2
|
+
X-Original-To: stallman-helpers@netpurgatory.com
|
|
3
|
+
Delivered-To: x12197960@homiemail-mx23.g.dreamhost.com
|
|
4
|
+
Received: from fencepost.gnu.org (fencepost.gnu.org [140.186.70.10])
|
|
5
|
+
(using TLSv1 with cipher AES256-SHA (256/256 bits))
|
|
6
|
+
(No client certificate requested)
|
|
7
|
+
by homiemail-mx23.g.dreamhost.com (Postfix) with ESMTPS id BF11A3E04EC;
|
|
8
|
+
Thu, 30 Jun 2011 17:18:49 -0700 (PDT)
|
|
9
|
+
Received: from rms by fencepost.gnu.org with local (Exim 4.71)
|
|
10
|
+
(envelope-from <rms@gnu.org>)
|
|
11
|
+
id 1QcRRV-0006Q7-4B; Thu, 30 Jun 2011 20:18:45 -0400
|
|
12
|
+
Date: Thu, 30 Jun 2011 20:18:45 -0400
|
|
13
|
+
Message-Id: <E1QcRRV-0006Q7-4B@fencepost.gnu.org>
|
|
14
|
+
Content-Type: text/plain; charset=ISO-8859-15
|
|
15
|
+
From: Richard Stallman <rms@gnu.org>
|
|
16
|
+
To: stallman-org@gnu.org
|
|
17
|
+
Subject: Urgent note
|
|
18
|
+
Reply-to: rms@gnu.org
|
|
19
|
+
Content-Length: 519
|
|
20
|
+
|
|
21
|
+
For one week:
|
|
22
|
+
|
|
23
|
+
US citizens: tell Obama to stand firm against Republican demands
|
|
24
|
+
for raising the debt ceiling.
|
|
25
|
+
|
|
26
|
+
http://
|
|
27
|
+
|
|
28
|
+
Once in a while, when enough people demand it, Obama does what he
|
|
29
|
+
ought to do.
|
|
30
|
+
|
|
31
|
+
--
|
|
32
|
+
Dr Richard Stallman
|
|
33
|
+
President, Free Software Foundation
|
|
34
|
+
51 Franklin St
|
|
35
|
+
Boston MA 02110
|
|
36
|
+
USA
|
|
37
|
+
www.fsf.org www.gnu.org
|
|
38
|
+
Skype: No way! That's nonfree (freedom-denying) software.
|
|
39
|
+
Use free telephony http://directory.fsf.org/category/tel/
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'rmsgen'
|
|
2
|
+
|
|
3
|
+
describe Rmsgen::FsPolnoteGroup do
|
|
4
|
+
context '.all' do
|
|
5
|
+
context 'when zero polnotes are in the directory' do
|
|
6
|
+
it 'returns an empty collection' do
|
|
7
|
+
empty_dir = 'empty-dir'
|
|
8
|
+
splat_dir = "#{empty_dir}/*"
|
|
9
|
+
Dir.should_receive(:[]).with(splat_dir).and_return([])
|
|
10
|
+
group = Rmsgen::FsPolnoteGroup.new(empty_dir)
|
|
11
|
+
result = group.all
|
|
12
|
+
result.should be_empty
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context 'when one polnote is in the directory' do
|
|
17
|
+
let(:dir) { '/home/foo/dir' }
|
|
18
|
+
let(:splat_dir) { "#{dir}/*" }
|
|
19
|
+
let(:notes) { ['/home/foo/dir/polnote'] }
|
|
20
|
+
|
|
21
|
+
before do
|
|
22
|
+
Dir.should_receive(:[]).with(splat_dir).and_return(notes)
|
|
23
|
+
File.should_receive(:read).with(notes.first).and_return("hello world")
|
|
24
|
+
group = Rmsgen::FsPolnoteGroup.new(dir)
|
|
25
|
+
@result = group.all
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'returns one element' do
|
|
29
|
+
@result.size.should == 1
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'returns a polnote element' do
|
|
33
|
+
@result.first.should be_instance_of(Rmsgen::Polnote)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'rmsgen'
|
|
2
|
+
|
|
3
|
+
describe Rmsgen::IMAPPolnoteGroup do
|
|
4
|
+
context 'fetching notes' do
|
|
5
|
+
let(:imap) { double('imap') }
|
|
6
|
+
let(:options) do {
|
|
7
|
+
'imap_login' => 'login',
|
|
8
|
+
'imap_password' => 'password'}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
let(:do_fetch) do
|
|
12
|
+
imap.should_receive(:search).any_number_of_times
|
|
13
|
+
imap.should_receive(:authenticate).any_number_of_times
|
|
14
|
+
imap.should_receive(:select).any_number_of_times
|
|
15
|
+
Rmsgen::IMAPPolnoteGroup.new(imap, options).fetch_notes
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'authenticates with imap server' do
|
|
19
|
+
imap.should_receive(:authenticate).any_number_of_times.with('LOGIN', 'login', 'password')
|
|
20
|
+
do_fetch
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'selects the inbox folder' do
|
|
24
|
+
imap.should_receive(:select).any_number_of_times.with('INBOX')
|
|
25
|
+
do_fetch
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'searches for messages from rms' do
|
|
29
|
+
imap.should_receive(:search).once.with(["FROM", 'rms@gnu.org'])
|
|
30
|
+
do_fetch
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'fetches each message' do
|
|
34
|
+
message_id = double('message_id')
|
|
35
|
+
search_result = [message_id]
|
|
36
|
+
|
|
37
|
+
imap.stub(:search) { search_result }
|
|
38
|
+
|
|
39
|
+
imap.should_receive(:fetch).with(message_id, 'BODY[TEXT]')
|
|
40
|
+
do_fetch
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'rmsgen'
|
|
2
|
+
require 'fake_gets'
|
|
3
|
+
require 'rspec'
|
|
4
|
+
require 'stringio'
|
|
5
|
+
|
|
6
|
+
describe Rmsgen::Inquirer do
|
|
7
|
+
let(:stdout) { StringIO.new }
|
|
8
|
+
|
|
9
|
+
describe "inquires about a note which is indented" do
|
|
10
|
+
let(:note) { Rmsgen::Polnote.new("foo\n\nhttp://\n\n bar") }
|
|
11
|
+
|
|
12
|
+
subject { Rmsgen::Inquirer.new(note, stdout) }
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
$stdin = FakeGetMany.new("foo")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "merges the url" do
|
|
19
|
+
exp = "<a href='http://'>foo</a> bar\n\n"
|
|
20
|
+
subject.body.should == exp
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe "it inquires about each link in a note" do
|
|
25
|
+
let(:note) { Rmsgen::Polnote.new("foo\n\nhttp://\n\nbar\n\nhttp://") }
|
|
26
|
+
subject { Rmsgen::Inquirer.new(note, stdout) }
|
|
27
|
+
|
|
28
|
+
before do
|
|
29
|
+
$stdin = FakeGetMany.new("foo", "bar")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "inquires about each url" do
|
|
33
|
+
exp = "<a href='http://'>foo</a>\n\n<a href='http://'>bar</a>"
|
|
34
|
+
subject.body.should == exp
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe "inquiring about a duration" do
|
|
39
|
+
it "asks for the end date of the duration" do
|
|
40
|
+
note = Rmsgen::Polnote.new("For one week:\n\nUrgent: blah blah blah")
|
|
41
|
+
$stdin = FakeGetMany.new("July 1")
|
|
42
|
+
Rmsgen::Inquirer.new(note, stdout)
|
|
43
|
+
note.expires_on.should be == "July 1"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe 'when a blank answer is given' do
|
|
48
|
+
it 'returns the polnote text without links' do
|
|
49
|
+
note = Rmsgen::Polnote.new("foo bar\n\nhttp://")
|
|
50
|
+
$stdin = FakeGetMany.new("")
|
|
51
|
+
inquirer = Rmsgen::Inquirer.new(note, stdout)
|
|
52
|
+
inquirer.body.should be == "foo bar"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'rmsgen'
|
|
2
|
+
|
|
3
|
+
describe PartGroup do
|
|
4
|
+
it "accepts text as input" do
|
|
5
|
+
input = "hello\n\nworld"
|
|
6
|
+
p = PartGroup.new(input)
|
|
7
|
+
p.text.should be == input
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "output list of parts ordered by appearance" do
|
|
11
|
+
input = "\n\n\n\n1\n\n2\n\n3\n\n4"
|
|
12
|
+
p = PartGroup.new(input)
|
|
13
|
+
p.should == ['1', '2', '3', '4']
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "splits input into parts based on carriage return and newline" do
|
|
17
|
+
input = "1\r\n\r\n2\r\n\r\n3\r\n\r\n4"
|
|
18
|
+
p = PartGroup.new(input)
|
|
19
|
+
p.should == ['1', '2', '3', '4']
|
|
20
|
+
end
|
|
21
|
+
end
|