signore 0.1.2 → 0.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.
- checksums.yaml +7 -0
- data/.rubocop.yml +23 -0
- data/.ruby-version +1 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +30 -9
- data/README.md +1 -1
- data/Rakefile +10 -8
- data/config/reek.yml +14 -0
- data/lib/signore/database.rb +11 -14
- data/lib/signore/executable.rb +48 -26
- data/lib/signore/signature.rb +23 -18
- data/lib/signore.rb +3 -2
- data/signore.gemspec +8 -7
- data/spec/fixtures/wrapper.yml +43 -29
- data/spec/signore/database_spec.rb +19 -36
- data/spec/signore/executable_spec.rb +56 -53
- data/spec/signore/signature_spec.rb +51 -31
- data/spec/spec_helper.rb +4 -4
- metadata +50 -39
- data/.rvmrc +0 -2
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1ae3bd13eb44a22d1617a29fe32e78f4b3f9abe1
|
4
|
+
data.tar.gz: bc38ff309685c63d6c4cc37b687bf6f37f7af13a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8946f12a8af7ec349e419f688e95c9b98504b582bfbee04471aa33b8f3c61fd9336d17faeac680059556cf26c6f4bc844f5eb7df981d54a126842c5cadc4e6cf
|
7
|
+
data.tar.gz: ca59fe6dd1077779a688f8bbce6722d2c9ceb6fe71f5ae912b7f074cafc625d11a598474a2668f0d717ebe2f3608899e2e6b74a8a39de906bede9c630b6dfa4e
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
AccessModifierIndentation:
|
2
|
+
Enabled: false
|
3
|
+
|
4
|
+
AlignHash:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
AlignParameters:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
AndOr:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Documentation:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
EndAlignment:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
IndentationWidth:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
MethodDefParentheses:
|
23
|
+
Enabled: false
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1
|
data/Gemfile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
gemspec
|
data/Gemfile.lock
CHANGED
@@ -2,21 +2,42 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
signore (0.1.2)
|
5
|
-
|
6
|
-
trollop
|
5
|
+
lovely_rufus (~> 0.1.0)
|
7
6
|
|
8
7
|
GEM
|
9
|
-
remote:
|
8
|
+
remote: https://rubygems.org/
|
10
9
|
specs:
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
ast (1.1.0)
|
11
|
+
json (1.8.1)
|
12
|
+
lovely_rufus (0.1.0)
|
13
|
+
minitest (5.2.3)
|
14
|
+
parser (2.1.4)
|
15
|
+
ast (~> 1.1)
|
16
|
+
slop (~> 3.4, >= 3.4.5)
|
17
|
+
powerpack (0.0.9)
|
18
|
+
rainbow (2.0.0)
|
19
|
+
reek (1.3.6)
|
20
|
+
ruby2ruby (~> 2.0.7)
|
21
|
+
ruby_parser (~> 3.2)
|
22
|
+
sexp_processor
|
23
|
+
rubocop (0.18.1)
|
24
|
+
json (>= 1.7.7, < 2)
|
25
|
+
parser (~> 2.1.3)
|
26
|
+
powerpack (~> 0.0.6)
|
27
|
+
rainbow (>= 1.99.1, < 3.0)
|
28
|
+
ruby2ruby (2.0.7)
|
29
|
+
ruby_parser (~> 3.1)
|
30
|
+
sexp_processor (~> 4.0)
|
31
|
+
ruby_parser (3.4.1)
|
32
|
+
sexp_processor (~> 4.1)
|
33
|
+
sexp_processor (4.4.1)
|
34
|
+
slop (3.4.7)
|
15
35
|
|
16
36
|
PLATFORMS
|
17
37
|
ruby
|
18
38
|
|
19
39
|
DEPENDENCIES
|
20
|
-
minitest (
|
21
|
-
|
40
|
+
minitest (~> 5.0)
|
41
|
+
reek (~> 1.3)
|
42
|
+
rubocop (~> 0.18.0)
|
22
43
|
signore!
|
data/README.md
CHANGED
@@ -105,4 +105,4 @@ signore requires Ruby 1.9 and works best with Ruby 1.9.2 compiled with Psych (fo
|
|
105
105
|
|
106
106
|
---
|
107
107
|
|
108
|
-
© MMIX-
|
108
|
+
© MMIX-MMXIII Piotr Szotkowski <chastell@chastell.net>, licensed under AGPL 3 (see LICENCE)
|
data/Rakefile
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
require 'rake/testtask'
|
2
|
+
require 'reek/rake/task'
|
3
|
+
require 'rubocop/rake_task'
|
4
|
+
|
5
|
+
task default: %i[spec rubocop reek]
|
2
6
|
|
3
7
|
Rake::TestTask.new :spec do |task|
|
4
8
|
task.test_files = FileList['spec/**/*_spec.rb']
|
9
|
+
task.warning = true
|
5
10
|
end
|
6
11
|
|
7
|
-
|
8
|
-
task
|
9
|
-
|
10
|
-
|
11
|
-
include Signore
|
12
|
-
ARGV.clear
|
13
|
-
IRB.start
|
12
|
+
Reek::Rake::Task.new do |task|
|
13
|
+
task.config_files = 'config/reek.yml'
|
14
|
+
task.fail_on_error = false
|
15
|
+
task.reek_opts = '--quiet'
|
14
16
|
end
|
15
17
|
|
16
|
-
|
18
|
+
Rubocop::RakeTask.new
|
data/config/reek.yml
ADDED
data/lib/signore/database.rb
CHANGED
@@ -1,27 +1,24 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
module Signore class Database
|
4
|
-
|
5
2
|
def initialize path
|
6
3
|
@store = YAML::Store.new path
|
7
4
|
end
|
8
5
|
|
9
6
|
def << sig
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
store.transaction do
|
8
|
+
store['signatures'] ||= []
|
9
|
+
store['signatures'] << sig
|
13
10
|
end
|
14
11
|
end
|
15
12
|
|
16
|
-
def find
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
.
|
22
|
-
.reject { |sig| opts[:no_tags].any? { |tag| sig.tagged_with? tag } }
|
23
|
-
.shuffle.first
|
13
|
+
def find(forbidden_tags: [], random: Random.new, required_tags: [])
|
14
|
+
store.transaction true do
|
15
|
+
store['signatures']
|
16
|
+
.select { |sig| required_tags.all? { |tag| sig.tagged_with? tag } }
|
17
|
+
.reject { |sig| forbidden_tags.any? { |tag| sig.tagged_with? tag } }
|
18
|
+
.sample random: random
|
24
19
|
end
|
25
20
|
end
|
26
21
|
|
22
|
+
attr_reader :store
|
23
|
+
private :store
|
27
24
|
end end
|
data/lib/signore/executable.rb
CHANGED
@@ -1,34 +1,23 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
module Signore class Executable
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
def initialize args = ARGV, db_factory: Database
|
3
|
+
@settings = settings_from args
|
4
|
+
@db = db_factory.new settings.db_path
|
5
|
+
unless %w[prego pronto].include? settings.action
|
6
|
+
abort 'usage: signore prego|pronto [tag, …]'
|
8
7
|
end
|
9
|
-
Trollop.die 'usage: signore prego|pronto [label, …]' unless ['prego', 'pronto'].include? args.first
|
10
|
-
|
11
|
-
@db = db_class.new opts[:database]
|
12
|
-
|
13
|
-
@action = args.shift
|
14
|
-
|
15
|
-
@no_tags, @tags = args.partition { |tag| tag.start_with? '~' }
|
16
|
-
@no_tags.map! { |tag| tag[1..-1] }
|
17
8
|
end
|
18
9
|
|
19
|
-
def run
|
20
|
-
case
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
params = get_params input
|
25
|
-
sig = Signature.new params[:text], params[:author], params[:source], params[:subject], @tags
|
26
|
-
@db << sig
|
27
|
-
end
|
28
|
-
|
10
|
+
def run(input: $stdin)
|
11
|
+
sig = case settings.action
|
12
|
+
when 'prego' then handle_prego settings
|
13
|
+
when 'pronto' then handle_pronto input
|
14
|
+
end
|
29
15
|
puts sig.to_s
|
30
16
|
end
|
31
17
|
|
18
|
+
attr_reader :db, :settings
|
19
|
+
private :db, :settings
|
20
|
+
|
32
21
|
private
|
33
22
|
|
34
23
|
def get_param param, input
|
@@ -38,10 +27,43 @@ module Signore class Executable
|
|
38
27
|
value.strip
|
39
28
|
end
|
40
29
|
|
41
|
-
def
|
42
|
-
|
30
|
+
def handle_prego settings
|
31
|
+
db.find required_tags: settings.required_tags,
|
32
|
+
forbidden_tags: settings.forbidden_tags
|
33
|
+
end
|
34
|
+
|
35
|
+
def handle_pronto input
|
36
|
+
params = params_from input
|
37
|
+
sig = Signature.new params.text, params.author, params.source,
|
38
|
+
params.subject, settings.required_tags
|
39
|
+
db << sig
|
40
|
+
sig
|
41
|
+
end
|
42
|
+
|
43
|
+
def settings_from args
|
44
|
+
OpenStruct.new.tap do |settings|
|
45
|
+
db_dir = ENV.fetch('XDG_DATA_HOME') { File.expand_path '~/.local/share' }
|
46
|
+
settings.db_path = "#{db_dir}/signore/signatures.yml"
|
47
|
+
parse_settings args, settings
|
48
|
+
settings.action = args.shift
|
49
|
+
settings.forbidden_tags, settings.required_tags = args.partition do |tag|
|
50
|
+
tag.start_with? '~'
|
51
|
+
end
|
52
|
+
settings.forbidden_tags.map! { |tag| tag[1..-1] }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def params_from input
|
57
|
+
OpenStruct.new Hash[[:text, :author, :subject, :source].map do |param|
|
43
58
|
[param, get_param(param, input)]
|
44
59
|
end].reject { |_, value| value.empty? }
|
45
60
|
end
|
46
61
|
|
62
|
+
def parse_settings args, settings
|
63
|
+
OptionParser.new do |opts|
|
64
|
+
opts.on '-d', '--database PATH', 'Database location' do |path|
|
65
|
+
settings.db_path = path
|
66
|
+
end
|
67
|
+
end.parse! args
|
68
|
+
end
|
47
69
|
end end
|
data/lib/signore/signature.rb
CHANGED
@@ -1,34 +1,39 @@
|
|
1
|
-
module Signore
|
1
|
+
module Signore Signature = Struct.new(*%i[text author source subject tags]) do
|
2
|
+
class << self
|
3
|
+
undef :[]
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.[](author: nil, source: nil, subject: nil, tags: nil, text: nil)
|
7
|
+
new text, author, source, subject, tags
|
8
|
+
end
|
2
9
|
|
3
10
|
def tagged_with? tag
|
4
11
|
tags and tags.include? tag
|
5
12
|
end
|
6
13
|
|
7
14
|
def to_s
|
8
|
-
wrapped
|
9
|
-
|
15
|
+
wrapped = LovelyRufus::TextWrapper.wrap text.gsub("\n", "\n\n"), width: 80
|
16
|
+
squeezed = wrapped.gsub("\n\n", "\n").chomp
|
17
|
+
squeezed + meta_for(squeezed)
|
10
18
|
end
|
11
19
|
|
12
20
|
private
|
13
21
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
when author && subject then "#{author} #{subject}"
|
18
|
-
when author && source then "#{author}, #{source}"
|
19
|
-
when author then "#{author}"
|
20
|
-
when source then "#{source}"
|
21
|
-
when subject then "#{subject}"
|
22
|
-
end
|
22
|
+
def indent_size_for text
|
23
|
+
indent = text_width(text) - meta.size - 2
|
24
|
+
indent < 0 ? 0 : indent
|
23
25
|
end
|
24
26
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
spaces = indent > 0 ? ' ' * indent : ''
|
27
|
+
def meta
|
28
|
+
stem = [author, subject].compact.join ' '
|
29
|
+
stem.empty? ? "#{source}" : [stem, source].compact.join(', ')
|
30
|
+
end
|
30
31
|
|
31
|
-
|
32
|
+
def meta_for text
|
33
|
+
meta.empty? ? '' : "\n#{' ' * indent_size_for(text)}[#{meta}]"
|
32
34
|
end
|
33
35
|
|
36
|
+
def text_width text
|
37
|
+
text.split("\n").map(&:size).max
|
38
|
+
end
|
34
39
|
end end
|
data/lib/signore.rb
CHANGED
data/signore.gemspec
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
2
|
gem.name = 'signore'
|
3
|
-
gem.version = '0.
|
3
|
+
gem.version = '0.2.0'
|
4
4
|
gem.summary = 'signore: an email signature manager/randomiser'
|
5
5
|
gem.homepage = 'http://github.com/chastell/signore'
|
6
6
|
gem.author = 'Piotr Szotkowski'
|
7
7
|
gem.email = 'chastell@chastell.net'
|
8
8
|
|
9
9
|
gem.files = `git ls-files -z`.split "\0"
|
10
|
-
gem.executables =
|
11
|
-
gem.test_files =
|
10
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |path| File.basename path }
|
11
|
+
gem.test_files = gem.files.grep %r{^spec/.*\.rb$}
|
12
12
|
|
13
|
-
gem.add_dependency '
|
14
|
-
|
15
|
-
gem.add_development_dependency 'minitest', '
|
16
|
-
gem.add_development_dependency '
|
13
|
+
gem.add_dependency 'lovely_rufus', '~> 0.1.0'
|
14
|
+
|
15
|
+
gem.add_development_dependency 'minitest', '~> 5.0'
|
16
|
+
gem.add_development_dependency 'reek', '~> 1.3'
|
17
|
+
gem.add_development_dependency 'rubocop', '~> 0.18.0'
|
17
18
|
end
|
data/spec/fixtures/wrapper.yml
CHANGED
@@ -1,35 +1,42 @@
|
|
1
1
|
# wrapping doesn’t affect one-liners
|
2
|
-
- :
|
3
|
-
|
2
|
+
- - !ruby/struct:Signore::Signature
|
3
|
+
text: Patches are like Free Software love letters.
|
4
|
+
- |-
|
5
|
+
Patches are like Free Software love letters.
|
4
6
|
|
5
7
|
# meta info is right-aligned on its own line
|
6
|
-
- :
|
7
|
-
|
8
|
-
|
8
|
+
- - !ruby/struct:Signore::Signature
|
9
|
+
text: I have a fever and it’s not disco related.
|
10
|
+
author: opi
|
11
|
+
- |-
|
9
12
|
I have a fever and it’s not disco related.
|
10
13
|
[opi]
|
11
14
|
|
12
15
|
# more-than-80-column signatures are be wrapped, with the result being as short as possible
|
13
|
-
- :
|
14
|
-
|
16
|
+
- - !ruby/struct:Signore::Signature
|
17
|
+
text: It may look like I’m just sitting here doing nothing. But I’m really actively waiting for all my problems to go away.
|
18
|
+
- |-
|
15
19
|
It may look like I’m just sitting here doing nothing. But
|
16
20
|
I’m really actively waiting for all my problems to go away.
|
17
21
|
|
18
22
|
# meta info is right-aligned to the longest line
|
19
|
-
- :
|
20
|
-
|
21
|
-
|
23
|
+
- - !ruby/struct:Signore::Signature
|
24
|
+
text: No, no, it’s spelled Raymond Luxury Yacht, but it’s pronounced Throatwobbler Mangrove.
|
25
|
+
source: Monty Python
|
26
|
+
- |-
|
22
27
|
No, no, it’s spelled Raymond Luxury Yacht,
|
23
28
|
but it’s pronounced Throatwobbler Mangrove.
|
24
29
|
[Monty Python]
|
25
30
|
|
26
31
|
# multi-line signatures are wrapped on a line-by-line basis
|
27
|
-
- :
|
32
|
+
- - !ruby/struct:Signore::Signature
|
33
|
+
text: |-
|
28
34
|
‘The Ruby community should proceed with all deliberate speed towards ISO standardization of the language.’
|
29
35
|
‘Yeah, look what it did to Forth.’
|
30
36
|
‘Don’t just say it, show it. <http://vividpicture.com/aleks/atari/forth.jpg>’
|
31
|
-
|
32
|
-
|
37
|
+
author: M. Edward (Ed) Borasky, Matt Lawrence, Gregory Brown
|
38
|
+
source: ruby-talk
|
39
|
+
- |-
|
33
40
|
‘The Ruby community should proceed with all deliberate
|
34
41
|
speed towards ISO standardization of the language.’
|
35
42
|
‘Yeah, look what it did to Forth.’
|
@@ -37,13 +44,15 @@
|
|
37
44
|
[M. Edward (Ed) Borasky, Matt Lawrence, Gregory Brown, ruby-talk]
|
38
45
|
|
39
46
|
# long meta info is flushed left
|
40
|
-
- :
|
47
|
+
- - !ruby/struct:Signore::Signature
|
48
|
+
text: |-
|
41
49
|
‘The Guardian also had a pre-election column, in which an allegedly “ironic joke” was open to other interpretations: “John Wilkes Booth, Lee Harvey Oswald, John Hinckley Jr., where are you now that we need you?” They removed the column from on-line access and apologized.’
|
42
50
|
‘They should have. Hinckley missed the vital spot, so who needs him?’
|
43
51
|
‘As everybody knows, Reagan was killed in that attack and a lookalike was substituted.’
|
44
52
|
‘You mean we were governed all those years by an ACTOR!’
|
45
|
-
|
46
|
-
|
53
|
+
author: Spehro Pefhany, CyberCypher, Jess Askin, don groves
|
54
|
+
source: alt.usage.english
|
55
|
+
- |-
|
47
56
|
‘The Guardian also had a pre-election column, in which an allegedly
|
48
57
|
“ironic joke” was open to other interpretations: “John Wilkes Booth,
|
49
58
|
Lee Harvey Oswald, John Hinckley Jr., where are you now that we need
|
@@ -55,26 +64,31 @@
|
|
55
64
|
[Spehro Pefhany, CyberCypher, Jess Askin, don groves, alt.usage.english]
|
56
65
|
|
57
66
|
# wrapping doesn’t left one-letter words at the end of lines
|
58
|
-
- :
|
59
|
-
|
60
|
-
|
67
|
+
- - !ruby/struct:Signore::Signature
|
68
|
+
text: I’ve been trying for some time to develop a lifestyle that doesn’t require my presence.
|
69
|
+
author: Gary Trudeau
|
70
|
+
- |-
|
61
71
|
I’ve been trying for some time to develop
|
62
72
|
a lifestyle that doesn’t require my presence.
|
63
73
|
[Gary Trudeau]
|
64
74
|
|
65
75
|
# there are no hangouts
|
66
|
-
- :
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
76
|
+
- - !ruby/struct:Signore::Signature
|
77
|
+
text: Better to teach a man to fish than to give him a fish. And if he can’t be bothered to learn to fish and starves to death, that’s a good enough outcome for me.
|
78
|
+
author: Steve VanDevender
|
79
|
+
- |-
|
80
|
+
Better to teach a man to fish than to give him
|
81
|
+
a fish. And if he can’t be bothered to learn to
|
82
|
+
fish and starves to death, that’s a good enough outcome for me.
|
83
|
+
[Steve VanDevender]
|
73
84
|
|
74
85
|
# for two-line signatures, first line is considered for hangouts
|
75
|
-
- :
|
76
|
-
|
77
|
-
|
86
|
+
- - !ruby/struct:Signore::Signature
|
87
|
+
text: Well, the old ones go mmmmmbbbbzzzzttteeeeeep as they start up and the new ones go whupwhupwhupwhooopwhooooopwhooooooommmmmmmmmm.
|
88
|
+
author: Graham Reed
|
89
|
+
subject: on subway engines
|
90
|
+
source: asr
|
91
|
+
- |-
|
78
92
|
Well, the old ones go mmmmmbbbbzzzzttteeeeeep as they start up
|
79
93
|
and the new ones go whupwhupwhupwhooopwhooooopwhooooooommmmmmmmmm.
|
80
94
|
[Graham Reed on subway engines, asr]
|
@@ -1,60 +1,43 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
require_relative '../spec_helper'
|
4
2
|
|
5
3
|
module Signore describe Database do
|
6
|
-
|
7
4
|
describe '#find' do
|
8
|
-
|
9
|
-
|
10
|
-
srand
|
11
|
-
@db = Database.new 'spec/fixtures/signatures.yml'
|
12
|
-
end
|
5
|
+
let(:db) { Database.new path }
|
6
|
+
let(:path) { 'spec/fixtures/signatures.yml' }
|
13
7
|
|
14
8
|
it 'returns a random signature by default' do
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
9
|
+
Database.new(path).find(random: Random.new(1981)).text
|
10
|
+
.must_include 'Amateur fighter pilot ignores orders'
|
11
|
+
Database.new(path).find(random: Random.new(2009)).text
|
12
|
+
.must_include '// sometimes I believe compiler ignores all my comments'
|
19
13
|
end
|
20
14
|
|
21
15
|
it 'returns a random signature if the tags are empty' do
|
22
|
-
|
23
|
-
|
16
|
+
Database.new(path).find(required_tags: [], random: Random.new(2013)).text
|
17
|
+
.must_equal '// sometimes I believe compiler ignores all my comments'
|
24
18
|
end
|
25
19
|
|
26
20
|
it 'returns a random signature based on provided tags' do
|
27
|
-
|
28
|
-
|
21
|
+
db.find(required_tags: ['programming']).text
|
22
|
+
.must_equal '// sometimes I believe compiler ignores all my comments'
|
23
|
+
db.find(required_tags: ['work']).text
|
24
|
+
.must_equal 'You do have to be mad to work here, but it doesn’t help.'
|
29
25
|
end
|
30
26
|
|
31
27
|
it 'returns a random signature based on required and forbidden tags' do
|
32
|
-
|
28
|
+
forbidden_tags = %w[programming security]
|
29
|
+
db.find(required_tags: ['tech'], forbidden_tags: forbidden_tags).text
|
30
|
+
.must_equal 'You do have to be mad to work here, but it doesn’t help.'
|
33
31
|
end
|
34
|
-
|
35
32
|
end
|
36
33
|
|
37
|
-
describe '
|
38
|
-
|
34
|
+
describe '#<<' do
|
39
35
|
it 'saves the provided signature to disk' do
|
36
|
+
text = 'Normaliser Unix c’est comme pasteuriser le camembert.'
|
40
37
|
file = Tempfile.new ''
|
41
38
|
db = Database.new file.path
|
42
|
-
|
43
|
-
|
44
|
-
db << sig
|
45
|
-
|
46
|
-
file.read.must_equal <<-end.dedent
|
47
|
-
---
|
48
|
-
signatures:
|
49
|
-
- !ruby/struct:Signore::Signature
|
50
|
-
text: Normaliser Unix c’est comme pasteuriser le camembert.
|
51
|
-
author:
|
52
|
-
source:
|
53
|
-
subject:
|
54
|
-
tags:
|
55
|
-
end
|
39
|
+
db << Signature.new(text)
|
40
|
+
file.read.must_include text
|
56
41
|
end
|
57
|
-
|
58
42
|
end
|
59
|
-
|
60
43
|
end end
|
@@ -1,86 +1,89 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
require_relative '../spec_helper'
|
4
2
|
|
5
3
|
module Signore describe Executable do
|
6
|
-
|
7
4
|
describe '#initialize' do
|
8
|
-
|
9
5
|
it 'prints usage if no command is given' do
|
10
|
-
|
11
|
-
|
6
|
+
capture_io do
|
7
|
+
-> { Executable.new [] }.must_raise SystemExit
|
8
|
+
end.last.must_include 'usage: signore prego|pronto [tag, …]'
|
12
9
|
end
|
13
10
|
|
14
11
|
it 'prints usage if a bogus command is given' do
|
15
|
-
|
16
|
-
|
12
|
+
capture_io do
|
13
|
+
-> { Executable.new ['bogus'] }.must_raise SystemExit
|
14
|
+
end.last.must_include 'usage: signore prego|pronto [tag, …]'
|
17
15
|
end
|
18
16
|
|
19
17
|
it 'loads the signature database from the specified location' do
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
db_class.verify
|
18
|
+
db_factory = MiniTest::Mock.new.expect :new, nil, ['signatures.yml']
|
19
|
+
Executable.new %w[-d signatures.yml prego], db_factory: db_factory
|
20
|
+
db_factory.verify
|
24
21
|
end
|
25
22
|
|
26
|
-
it '
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
23
|
+
it 'defaults to ~/.local/share/signore/signatures.yml' do
|
24
|
+
begin
|
25
|
+
orig = ENV.delete 'XDG_DATA_HOME'
|
26
|
+
default_path = File.expand_path '~/.local/share/signore/signatures.yml'
|
27
|
+
db_factory = MiniTest::Mock.new
|
28
|
+
db_factory.expect :new, nil, [default_path]
|
29
|
+
Executable.new ['prego'], db_factory: db_factory
|
30
|
+
db_factory.verify
|
31
|
+
ensure
|
32
|
+
ENV['XDG_DATA_HOME'] = orig if orig
|
33
|
+
end
|
32
34
|
end
|
33
35
|
|
34
|
-
it '
|
36
|
+
it 'defaults to $XDG_DATA_HOME/signore/signatures.yml' do
|
35
37
|
begin
|
36
|
-
|
38
|
+
orig = ENV.delete 'XDG_DATA_HOME'
|
37
39
|
ENV['XDG_DATA_HOME'] = Dir.tmpdir
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
default_path = "#{ENV['XDG_DATA_HOME']}/signore/signatures.yml"
|
41
|
+
db_factory = MiniTest::Mock.new
|
42
|
+
db_factory.expect :new, nil, [default_path]
|
43
|
+
Executable.new ['prego'], db_factory: db_factory
|
44
|
+
db_factory.verify
|
42
45
|
ensure
|
43
|
-
|
46
|
+
orig ? ENV['XDG_DATA_HOME'] = orig : ENV.delete('XDG_DATA_HOME')
|
44
47
|
end
|
45
48
|
end
|
46
|
-
|
47
49
|
end
|
48
50
|
|
49
51
|
describe '#run' do
|
50
|
-
|
51
52
|
describe 'prego' do
|
52
|
-
|
53
53
|
it 'prints a signature tagged with the provided tags' do
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
args = %w[-d spec/fixtures/signatures.yml prego tech programming]
|
55
|
+
output = "// sometimes I believe compiler ignores all my comments\n"
|
56
|
+
stdout = capture_io { Executable.new(args).run }.first
|
57
|
+
stdout.must_equal output
|
58
58
|
end
|
59
59
|
|
60
60
|
it 'prints a signature based on allowed and forbidden tags' do
|
61
|
-
|
62
|
-
|
61
|
+
path = 'spec/fixtures/signatures.yml'
|
62
|
+
args = %W[-d #{path} prego ~programming tech ~security]
|
63
|
+
out = capture_io { Executable.new(args).run }.first
|
64
|
+
out.must_equal <<-end.dedent
|
63
65
|
You do have to be mad to work here, but it doesn’t help.
|
64
66
|
[Gary Barnes, asr]
|
65
67
|
end
|
66
68
|
end
|
67
|
-
|
68
69
|
end
|
69
70
|
|
70
71
|
describe 'pronto' do
|
71
|
-
|
72
72
|
before do
|
73
73
|
@file = Tempfile.new ''
|
74
74
|
end
|
75
75
|
|
76
|
-
it 'asks about signature parts and saves
|
76
|
+
it 'asks about signature parts and saves resulting signature' do
|
77
77
|
input = StringIO.new <<-end.dedent
|
78
|
-
The Wikipedia page on ADHD is like 20 pages long. That’s just cruel
|
78
|
+
The Wikipedia page on ADHD is like 20 pages long. That’s just cruel.
|
79
|
+
|
79
80
|
Mark Pilgrim\n\n\n
|
80
81
|
end
|
81
82
|
|
82
|
-
|
83
|
-
|
83
|
+
capture_io do
|
84
|
+
args = %W[-d #{@file.path} pronto Wikipedia ADHD]
|
85
|
+
Executable.new(args).run input: input
|
86
|
+
end.first.must_equal <<-end.dedent
|
84
87
|
text?
|
85
88
|
author?
|
86
89
|
subject?
|
@@ -89,8 +92,9 @@ module Signore describe Executable do
|
|
89
92
|
[Mark Pilgrim]
|
90
93
|
end
|
91
94
|
|
92
|
-
|
93
|
-
|
95
|
+
capture_io do
|
96
|
+
Executable.new(%W[-d #{@file.path} prego Wikipedia ADHD]).run
|
97
|
+
end.first.must_equal <<-end.dedent
|
94
98
|
The Wikipedia page on ADHD is like 20 pages long. That’s just cruel.
|
95
99
|
[Mark Pilgrim]
|
96
100
|
end
|
@@ -98,25 +102,24 @@ module Signore describe Executable do
|
|
98
102
|
|
99
103
|
it 'handles multi-line signatures' do
|
100
104
|
input = StringIO.new <<-end.dedent
|
101
|
-
‘
|
102
|
-
‘
|
103
|
-
|
105
|
+
‘You’ve got an interesting accent. Subtle. I can’t place it.’
|
106
|
+
‘It’s text-to-speech… I was raised by smartphones.’
|
107
|
+
|
108
|
+
Patrick Ewing\n\n\n
|
104
109
|
end
|
105
110
|
|
106
|
-
|
107
|
-
|
111
|
+
capture_io do
|
112
|
+
Executable.new(['-d', @file.path, 'pronto']).run input: input
|
113
|
+
end.first.must_equal <<-end.dedent
|
108
114
|
text?
|
109
115
|
author?
|
110
116
|
subject?
|
111
117
|
source?
|
112
|
-
‘
|
113
|
-
‘
|
114
|
-
|
118
|
+
‘You’ve got an interesting accent. Subtle. I can’t place it.’
|
119
|
+
‘It’s text-to-speech… I was raised by smartphones.’
|
120
|
+
[Patrick Ewing]
|
115
121
|
end
|
116
122
|
end
|
117
|
-
|
118
123
|
end
|
119
|
-
|
120
124
|
end
|
121
|
-
|
122
125
|
end end
|
@@ -1,56 +1,84 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
require_relative '../spec_helper'
|
4
2
|
|
5
3
|
module Signore describe Signature do
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
describe '.[]' do
|
5
|
+
it 'instantiates Signatures via parameters' do
|
6
|
+
source = 'A History of Modern Computing'
|
7
|
+
text = 'In 1940 he summarized his work in an influential book, ' \
|
8
|
+
'‘Punched Card Methods in Scientific Computation’.'
|
9
|
+
sig = Signature[author: 'Paul E. Ceruzzi', source: source,
|
10
|
+
subject: 'on Wallace Eckert', tags: ['punched cards'], text: text]
|
11
|
+
sig.author.must_equal 'Paul E. Ceruzzi'
|
12
|
+
sig.source.must_equal source
|
13
|
+
sig.subject.must_equal 'on Wallace Eckert'
|
14
|
+
sig.tags.must_equal ['punched cards']
|
15
|
+
sig.text.must_equal text
|
16
|
+
end
|
9
17
|
end
|
10
18
|
|
11
19
|
describe '#tagged_with?' do
|
12
|
-
|
13
20
|
it 'says whether a tagged signature is tagged with a given tag' do
|
14
|
-
|
15
|
-
|
16
|
-
assert
|
21
|
+
sig = Signature[tags: %w[programming tech]]
|
22
|
+
refute sig.tagged_with? 'fnord'
|
23
|
+
assert sig.tagged_with? 'programming'
|
24
|
+
assert sig.tagged_with? 'tech'
|
17
25
|
end
|
18
26
|
|
19
27
|
it 'says that an untagged signature is not tagged with any tag' do
|
20
|
-
refute
|
28
|
+
refute Signature.new.tagged_with? 'fnord'
|
21
29
|
end
|
22
|
-
|
23
30
|
end
|
24
31
|
|
25
32
|
describe '#to_s' do
|
33
|
+
it 'does not show meta if there’s nothing to show' do
|
34
|
+
text = '// sometimes I believe compiler ignores all my comments'
|
35
|
+
sig = Signature.new text
|
36
|
+
sig.to_s.must_equal text
|
37
|
+
end
|
26
38
|
|
27
|
-
it '
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
@dads.to_s.must_equal <<-end.dedent.strip
|
39
|
+
it 'shows author on its own' do
|
40
|
+
sig = Signature.new 'stay-at-home executives vs. wallstreet dads', 'kodz'
|
41
|
+
sig.to_s.must_equal <<-end.dedent.strip
|
33
42
|
stay-at-home executives vs. wallstreet dads
|
34
43
|
[kodz]
|
35
44
|
end
|
45
|
+
end
|
36
46
|
|
37
|
-
|
47
|
+
it 'shows author and source, comma-separated' do
|
48
|
+
text = 'You do have to be mad to work here, but it doesn’t help.'
|
49
|
+
sig = Signature.new text, 'Gary Barnes', 'asr'
|
50
|
+
sig.to_s.must_equal <<-end.dedent.strip
|
38
51
|
You do have to be mad to work here, but it doesn’t help.
|
39
52
|
[Gary Barnes, asr]
|
40
53
|
end
|
54
|
+
end
|
41
55
|
|
42
|
-
|
56
|
+
it 'shows source on its own' do
|
57
|
+
text = 'Bruce Schneier knows Alice and Bob’s shared secret.'
|
58
|
+
sig = Signature[text: text, source: 'Bruce Schneier Facts']
|
59
|
+
sig.to_s.must_equal <<-end.dedent.strip
|
43
60
|
Bruce Schneier knows Alice and Bob’s shared secret.
|
44
61
|
[Bruce Schneier Facts]
|
45
62
|
end
|
63
|
+
end
|
46
64
|
|
47
|
-
|
65
|
+
it 'shows author and subject, space separated' do
|
66
|
+
text = 'She was good at playing abstract confusion ' \
|
67
|
+
'in the same way a midget is good at being short.'
|
68
|
+
sig = Signature[text: text, author: 'Clive James',
|
69
|
+
subject: 'on Marilyn Monroe']
|
70
|
+
sig.to_s.must_equal <<-end.dedent.strip
|
48
71
|
She was good at playing abstract confusion in
|
49
72
|
the same way a midget is good at being short.
|
50
73
|
[Clive James on Marilyn Monroe]
|
51
74
|
end
|
75
|
+
end
|
52
76
|
|
53
|
-
|
77
|
+
it 'shows subject on its own' do
|
78
|
+
text = 'Amateur fighter pilot ignores orders, listens ' \
|
79
|
+
'to the voices in his head and slaughters thousands.'
|
80
|
+
sig = Signature[text: text, subject: 'Star Wars ending explained']
|
81
|
+
sig.to_s.must_equal <<-end.dedent.strip
|
54
82
|
Amateur fighter pilot ignores orders, listens to
|
55
83
|
the voices in his head and slaughters thousands.
|
56
84
|
[Star Wars ending explained]
|
@@ -58,17 +86,9 @@ module Signore describe Signature do
|
|
58
86
|
end
|
59
87
|
|
60
88
|
it 'handles edge cases properly' do
|
61
|
-
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
YAML.load_file('spec/fixtures/wrapper.yml').each do |sample|
|
66
|
-
sig = SignatureWithMeta.new sample[:text]
|
67
|
-
sig.meta = sample[:meta]
|
68
|
-
sig.to_s.must_equal sample[:wrapped]
|
89
|
+
YAML.load_file('spec/fixtures/wrapper.yml').each do |sig, wrapped|
|
90
|
+
sig.to_s.must_equal wrapped
|
69
91
|
end
|
70
92
|
end
|
71
|
-
|
72
93
|
end
|
73
|
-
|
74
94
|
end end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
|
1
|
+
require 'bundler/setup'
|
2
2
|
require 'minitest/autorun'
|
3
|
-
|
3
|
+
require 'minitest/pride'
|
4
4
|
require 'pathname'
|
5
5
|
require 'tempfile'
|
6
6
|
require 'tmpdir'
|
7
7
|
|
8
|
-
|
8
|
+
require 'signore'
|
9
9
|
|
10
10
|
class String
|
11
11
|
def dedent
|
12
|
-
gsub
|
12
|
+
gsub(/^#{self[/\A\s*/]}/, '')
|
13
13
|
end
|
14
14
|
end
|
metadata
CHANGED
@@ -1,60 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: signore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Piotr Szotkowski
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-02-18 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
requirement:
|
17
|
-
none: false
|
14
|
+
name: lovely_rufus
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.0
|
19
|
+
version: 0.1.0
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.0
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
27
|
-
requirement:
|
28
|
-
none: false
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
|
-
- -
|
31
|
+
- - "~>"
|
31
32
|
- !ruby/object:Gem::Version
|
32
|
-
version: '0'
|
33
|
-
type: :
|
33
|
+
version: '5.0'
|
34
|
+
type: :development
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.0'
|
36
41
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
-
requirement:
|
39
|
-
none: false
|
42
|
+
name: reek
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
40
44
|
requirements:
|
41
|
-
- -
|
45
|
+
- - "~>"
|
42
46
|
- !ruby/object:Gem::Version
|
43
|
-
version:
|
47
|
+
version: '1.3'
|
44
48
|
type: :development
|
45
49
|
prerelease: false
|
46
|
-
version_requirements:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
47
55
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
49
|
-
requirement:
|
50
|
-
none: false
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
51
58
|
requirements:
|
52
|
-
- -
|
59
|
+
- - "~>"
|
53
60
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
61
|
+
version: 0.18.0
|
55
62
|
type: :development
|
56
63
|
prerelease: false
|
57
|
-
version_requirements:
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.18.0
|
58
69
|
description:
|
59
70
|
email: chastell@chastell.net
|
60
71
|
executables:
|
@@ -62,13 +73,15 @@ executables:
|
|
62
73
|
extensions: []
|
63
74
|
extra_rdoc_files: []
|
64
75
|
files:
|
65
|
-
- .
|
76
|
+
- ".rubocop.yml"
|
77
|
+
- ".ruby-version"
|
66
78
|
- Gemfile
|
67
79
|
- Gemfile.lock
|
68
80
|
- LICENCE
|
69
81
|
- README.md
|
70
82
|
- Rakefile
|
71
83
|
- bin/signore
|
84
|
+
- config/reek.yml
|
72
85
|
- lib/signore.rb
|
73
86
|
- lib/signore/database.rb
|
74
87
|
- lib/signore/executable.rb
|
@@ -82,31 +95,29 @@ files:
|
|
82
95
|
- spec/spec_helper.rb
|
83
96
|
homepage: http://github.com/chastell/signore
|
84
97
|
licenses: []
|
98
|
+
metadata: {}
|
85
99
|
post_install_message:
|
86
100
|
rdoc_options: []
|
87
101
|
require_paths:
|
88
102
|
- lib
|
89
103
|
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
104
|
requirements:
|
92
|
-
- -
|
105
|
+
- - ">="
|
93
106
|
- !ruby/object:Gem::Version
|
94
107
|
version: '0'
|
95
108
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
-
none: false
|
97
109
|
requirements:
|
98
|
-
- -
|
110
|
+
- - ">="
|
99
111
|
- !ruby/object:Gem::Version
|
100
112
|
version: '0'
|
101
113
|
requirements: []
|
102
114
|
rubyforge_project:
|
103
|
-
rubygems_version:
|
115
|
+
rubygems_version: 2.2.0
|
104
116
|
signing_key:
|
105
|
-
specification_version:
|
106
|
-
summary:
|
117
|
+
specification_version: 4
|
118
|
+
summary: 'signore: an email signature manager/randomiser'
|
107
119
|
test_files:
|
108
|
-
- spec/
|
120
|
+
- spec/signore/database_spec.rb
|
109
121
|
- spec/signore/executable_spec.rb
|
110
122
|
- spec/signore/signature_spec.rb
|
111
|
-
- spec/
|
112
|
-
has_rdoc:
|
123
|
+
- spec/spec_helper.rb
|
data/.rvmrc
DELETED