misfortune 0.1.1

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.
@@ -0,0 +1,7 @@
1
+ require 'redcarpet'
2
+ require 'redcarpet/render_strip'
3
+
4
+ require 'misfortune/version'
5
+ require 'misfortune/render/terminal'
6
+ require 'misfortune/cookie_jar'
7
+ require 'misfortune/flavor'
@@ -0,0 +1,46 @@
1
+ module Misfortune
2
+ module CLI
3
+ class BingeCommand
4
+ attr_reader :options, :cookies, :flavor
5
+
6
+ def initialize(options)
7
+ @options = options
8
+ @cookies = CookieJar.new(options['source']).cookies
9
+ @flavor = Flavor.new(:terminal)
10
+
11
+ trap_interrupt
12
+ end
13
+
14
+ def run
15
+ current = 0
16
+ loop do
17
+ render(cookies[current % cookies_count])
18
+ current = select_cookie(current)
19
+ end
20
+ end
21
+
22
+ protected
23
+
24
+ def cookies_count
25
+ @cookies_count ||= cookies.count
26
+ end
27
+
28
+ def render(cookie)
29
+ system 'clear'
30
+ puts flavor.apply_to(cookie)
31
+ puts "\n\nPress ENTER to continue\n\n"
32
+ end
33
+
34
+ def select_cookie(current)
35
+ selection = STDIN.gets.chomp.to_i
36
+ selection > 0 ? selection : current + 1
37
+ end
38
+
39
+ def trap_interrupt
40
+ Signal.trap('INT') do
41
+ exit
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,18 @@
1
+ module Misfortune
2
+ module CLI
3
+ class RandomCommand
4
+ attr_reader :options
5
+
6
+ def initialize(options)
7
+ @options = options
8
+ end
9
+
10
+ def run
11
+ cookie = CookieJar.new(options['source']).cookies.sample
12
+ flavor = Flavor.new(options[:flavor])
13
+
14
+ puts flavor.apply_to(cookie)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ require 'thor'
2
+ require 'misfortune/cli/random_command'
3
+ require 'misfortune/cli/binge_command'
4
+
5
+ module Misfortune
6
+ module CLI
7
+ class Runner < Thor
8
+ def self.flavors
9
+ Misfortune::Flavor::FLAVORS_MAP.keys.join(', ')
10
+ end
11
+
12
+ default_task :random
13
+
14
+ class_option :source, type: :string, desc: 'Source markdown file'
15
+
16
+ desc 'random', 'Prints a random cookie.'
17
+ method_option :flavor,
18
+ type: :string,
19
+ default: :terminal,
20
+ desc: "Select output flavor. Available options: #{flavors}"
21
+
22
+ def random
23
+ RandomCommand.new(options).run
24
+ end
25
+
26
+ desc 'binge', 'Non-stop cookies'
27
+
28
+ def binge
29
+ BingeCommand.new(options).run
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ module Misfortune
2
+ class CookieJar
3
+ attr_reader :file
4
+
5
+ def initialize(file = nil)
6
+ @file = file || data_file_path('source')
7
+ end
8
+
9
+ def cookies
10
+ @cookies ||= file_chunks
11
+ end
12
+
13
+ protected
14
+
15
+ def file_chunks
16
+ File.read(file)
17
+ .split(/\n#\s/)
18
+ .map(&:strip)
19
+ .reject(&:empty?)
20
+ .map { |chunk| chunk.prepend '#' }
21
+ end
22
+
23
+ def data_file_path(name)
24
+ File.join(File.dirname(__FILE__), '..', '..', 'data', "#{name}.md")
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ module Misfortune
2
+ class Flavor
3
+ FLAVORS_MAP = {
4
+ html: Redcarpet::Render::HTML,
5
+ vanilla: Redcarpet::Render::StripDown,
6
+ terminal: Misfortune::Render::Terminal
7
+ }.freeze
8
+
9
+ REDCARPET_OPTIONS = {
10
+ fenced_code_blocks: true,
11
+ strikethrough: true,
12
+ autolink: true
13
+ }.freeze
14
+
15
+ attr_reader :markdown
16
+
17
+ def initialize(kind)
18
+ @markdown = Redcarpet::Markdown.new(
19
+ FLAVORS_MAP.fetch(kind.to_sym),
20
+ REDCARPET_OPTIONS
21
+ )
22
+ end
23
+
24
+ def apply_to(cookie)
25
+ markdown.render(cookie).chomp
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,135 @@
1
+ require 'pastel'
2
+
3
+ module Misfortune
4
+ module Render
5
+ class Terminal < Redcarpet::Render::StripDown
6
+ BLOCK_MAX_WITH = 80
7
+ BLOCK_DELIMITER = '~'.freeze
8
+ LIST_INDENTATION = ' '.freeze
9
+ LIST_ORDERED_ITEM_PREFIX = '<ENUM>'.freeze
10
+ LIST_ORDERED_ITEM_CHAR = '.'.freeze
11
+ LIST_UNORDERED_ITEM_CHAR = '-'.freeze
12
+
13
+ attr_reader :pastel
14
+
15
+ def initialize
16
+ @pastel = Pastel.new(enabled: $stdout.tty?, eachline: new_line)
17
+
18
+ super
19
+ end
20
+
21
+ def header(text, _header_level)
22
+ text = pastel.underline(text)
23
+ surround_with_line_breaks(text, 0, 2)
24
+ end
25
+
26
+ def block_code(code, language)
27
+ text = ''
28
+ text << labeled_hrule(language)
29
+ text << indent(code(code))
30
+ text << hrule
31
+
32
+ surround_with_line_breaks(text, 1, 2)
33
+ end
34
+
35
+ def block_quote(quote)
36
+ text = pastel.cyan(quote)
37
+ surround_with_line_breaks(text, 1, 2)
38
+ end
39
+
40
+ def paragraph(text)
41
+ surround_with_line_breaks(text, 0, 2)
42
+ end
43
+
44
+ def list(contents, list_type)
45
+ contents = enumerate_list(contents) if list_type == :ordered
46
+ contents = indent(contents)
47
+
48
+ surround_with_line_breaks(contents, 0, 1)
49
+ end
50
+
51
+ def list_item(text, list_type)
52
+ prefix =
53
+ case list_type
54
+ when :ordered
55
+ LIST_ORDERED_ITEM_PREFIX
56
+ when :unordered
57
+ LIST_UNORDERED_ITEM_CHAR
58
+ end
59
+
60
+ "#{prefix} #{text}"
61
+ end
62
+
63
+ def hrule
64
+ labeled_hrule('')
65
+ end
66
+
67
+ def emphasis(text)
68
+ pastel.underline(text)
69
+ end
70
+
71
+ def double_emphasis(text)
72
+ pastel.bold(text)
73
+ end
74
+
75
+ def triple_emphasis(text)
76
+ emphasis(double_emphasis(text))
77
+ end
78
+
79
+ def strikethrough(text)
80
+ pastel.strikethrough(text)
81
+ end
82
+
83
+ def link(link, _title, content)
84
+ "#{content} (#{pastel.blue(link)})"
85
+ end
86
+
87
+ def autolink(link, _link_type)
88
+ pastel.blue(link)
89
+ end
90
+
91
+ def codespan(code)
92
+ code(code)
93
+ end
94
+
95
+ protected
96
+
97
+ def surround_with_line_breaks(text, prepend_count, append_count)
98
+ text = clear_surrounding_line_breaks(text)
99
+ (new_line * prepend_count) << text << (new_line * append_count)
100
+ end
101
+
102
+ def clear_surrounding_line_breaks(text)
103
+ text.sub(/\A[\r\n]+/, '').sub(/[\r\n]+\z/, '')
104
+ end
105
+
106
+ def indent(text)
107
+ text.strip
108
+ .gsub(new_line, "#{new_line}#{LIST_INDENTATION}")
109
+ .prepend(LIST_INDENTATION)
110
+ end
111
+
112
+ def enumerate_list(text)
113
+ text.gsub(LIST_ORDERED_ITEM_PREFIX).with_index do |_, i|
114
+ "#{i + 1}#{LIST_ORDERED_ITEM_CHAR}"
115
+ end
116
+ end
117
+
118
+ def new_line
119
+ "\n"
120
+ end
121
+
122
+ def code(text)
123
+ pastel.green(text.chomp)
124
+ end
125
+
126
+ def labeled_hrule(text)
127
+ text = (text || '').to_s.upcase
128
+ text = text.center(10, ' ') unless text.empty?
129
+ text = text.center(BLOCK_MAX_WITH, BLOCK_DELIMITER)
130
+
131
+ surround_with_line_breaks(text, 1, 1)
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,3 @@
1
+ module Misfortune
2
+ VERSION = '0.1.1'.freeze
3
+ end
@@ -0,0 +1,38 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'misfortune/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'misfortune'
8
+ spec.version = Misfortune::VERSION
9
+ spec.date = '2016-03-24'
10
+ spec.summary = 'Unmaintainable fortune cookies'
11
+ spec.description = '"How To Write Unmaintainable Code" turned into fortune cookies'
12
+ spec.authors = ['Nikolay Bekirov']
13
+ spec.email = 'nbekirov@gmail.com'
14
+ spec.homepage = 'http://rubygems.org/gems/misfortune'
15
+ spec.license = 'MIT'
16
+
17
+ spec.bindir = 'bin'
18
+ spec.executables = ['misfortune']
19
+ spec.require_paths = ['lib']
20
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
21
+ f =~ %r{^(?:
22
+ spec.*
23
+ |Rakefile
24
+ |\.gitignore
25
+ |\.rubocop.yml
26
+ |\.rspec
27
+ |\.travis.yml
28
+ )$}x
29
+ end
30
+
31
+ spec.add_runtime_dependency('redcarpet', '~> 3.3')
32
+ spec.add_runtime_dependency('pastel', '~> 0.6')
33
+ spec.add_runtime_dependency('thor', '~> 0.19')
34
+ spec.add_development_dependency('rake', '~> 11.1')
35
+ spec.add_development_dependency('rspec', '~> 3.4')
36
+ spec.add_development_dependency('simplecov', '~> 0.11')
37
+ spec.add_development_dependency('bundler', '~> 1.11')
38
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: misfortune
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Nikolay Bekirov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redcarpet
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pastel
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.19'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.19'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '11.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '11.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.4'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.4'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.11'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.11'
97
+ - !ruby/object:Gem::Dependency
98
+ name: bundler
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.11'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.11'
111
+ description: '"How To Write Unmaintainable Code" turned into fortune cookies'
112
+ email: nbekirov@gmail.com
113
+ executables:
114
+ - misfortune
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - Gemfile
119
+ - README.md
120
+ - bin/misfortune
121
+ - bin/setup
122
+ - data/source.md
123
+ - lib/misfortune.rb
124
+ - lib/misfortune/cli/binge_command.rb
125
+ - lib/misfortune/cli/random_command.rb
126
+ - lib/misfortune/cli/runner.rb
127
+ - lib/misfortune/cookie_jar.rb
128
+ - lib/misfortune/flavor.rb
129
+ - lib/misfortune/render/terminal.rb
130
+ - lib/misfortune/version.rb
131
+ - misfortune.gemspec
132
+ homepage: http://rubygems.org/gems/misfortune
133
+ licenses:
134
+ - MIT
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 2.6.2
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: Unmaintainable fortune cookies
156
+ test_files: []