codeless_code 0.1.7 → 0.1.8
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 +4 -4
- data/.gitmodules +1 -1
- data/.reek.yml +14 -0
- data/.rubocop.yml +18 -0
- data/.ruby-version +1 -0
- data/{test/test_codeless_code.rb → .travis.yml} +12 -10
- data/Gemfile +5 -0
- data/Gemfile.lock +21 -0
- data/Guardfile +13 -1
- data/README.md +6 -0
- data/Rakefile +26 -11
- data/VERSION +1 -1
- data/bin/codeless_code +3 -1
- data/codeless_code.gemspec +33 -12
- data/lib/codeless_code/catalog.rb +3 -1
- data/lib/codeless_code/cli.rb +56 -24
- data/lib/codeless_code/commands/filter_fables.rb +15 -10
- data/lib/codeless_code/commands/list_translations.rb +3 -0
- data/lib/codeless_code/fable.rb +42 -53
- data/lib/codeless_code/fable_set.rb +8 -6
- data/lib/codeless_code/filters/builders.rb +4 -2
- data/lib/codeless_code/filters/composite.rb +3 -1
- data/lib/codeless_code/filters/date.rb +40 -30
- data/lib/codeless_code/filters/from_options.rb +45 -28
- data/lib/codeless_code/filters/headers/base.rb +61 -0
- data/lib/codeless_code/filters/{header_integer.rb → headers/integer.rb} +16 -19
- data/lib/codeless_code/filters/{header_string.rb → headers/string.rb} +12 -22
- data/lib/codeless_code/filters/lang.rb +3 -0
- data/lib/codeless_code/filters/translator.rb +7 -2
- data/lib/codeless_code/filters.rb +16 -8
- data/lib/codeless_code/formats/base.rb +20 -7
- data/lib/codeless_code/formats/parsers/base.rb +106 -0
- data/lib/codeless_code/formats/parsers/plain.rb +49 -0
- data/lib/codeless_code/formats/parsers/term.rb +79 -0
- data/lib/codeless_code/formats/plain.rb +21 -12
- data/lib/codeless_code/formats/raw.rb +2 -0
- data/lib/codeless_code/formats/term.rb +21 -15
- data/lib/codeless_code/language_set.rb +7 -4
- data/lib/codeless_code/options.rb +5 -3
- data/lib/codeless_code/renderers/fable.rb +13 -8
- data/lib/codeless_code/renderers/term_page.rb +46 -31
- data/lib/codeless_code.rb +119 -106
- data/test/codeless_code/commands/test_filter_fables.rb +89 -0
- data/test/codeless_code/filters/headers/test_integer.rb +86 -0
- data/test/codeless_code/filters/headers/test_string.rb +86 -0
- data/test/codeless_code/filters/test_builders.rb +4 -2
- data/test/codeless_code/filters/test_composite.rb +70 -0
- data/test/codeless_code/filters/test_date.rb +99 -0
- data/test/codeless_code/filters/test_langs.rb +50 -0
- data/test/codeless_code/filters/test_translator.rb +51 -0
- data/test/codeless_code/renderers/test_fable.rb +98 -0
- data/test/codeless_code/renderers/test_term_page.rb +87 -0
- data/test/codeless_code/test_catalog.rb +12 -5
- data/test/codeless_code/test_cli.rb +85 -0
- data/test/codeless_code/test_fable.rb +19 -10
- data/test/codeless_code/test_fable_set.rb +17 -5
- data/test/codeless_code/test_language_set.rb +16 -3
- data/test/codeless_code/test_options.rb +3 -11
- data/test/helper.rb +36 -10
- data/test/support/fs.rb +103 -0
- metadata +65 -11
- data/.document +0 -5
- data/data/README.md +0 -34
- data/lib/codeless_code/formats/plain_generator.rb +0 -157
- data/lib/codeless_code/formats/term_generator.rb +0 -167
- data/test/codeless_code/filters/test_header_integer.rb +0 -82
- data/test/codeless_code/filters/test_header_string.rb +0 -82
data/lib/codeless_code/fable.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# codeless_code filters and prints fables from http://thecodelesscode.com
|
2
4
|
# Copyright (C) 2018 Jon Sangster
|
3
5
|
#
|
@@ -23,27 +25,43 @@ module CodelessCode
|
|
23
25
|
|
24
26
|
HEADER_PATTERN = /([^:\s]+)\s*:\s*(.+)\s*$/.freeze
|
25
27
|
|
26
|
-
|
28
|
+
RAW_ATTRS = %w[Title Tagline Credits].freeze
|
29
|
+
INTEGER_ATTRS = %w[Number Geekiness].freeze
|
30
|
+
LIST_ATTRS = %w[Names Topics].freeze
|
31
|
+
|
32
|
+
attr_reader :file, :has_read_headers
|
27
33
|
|
28
|
-
|
34
|
+
alias read_headers? has_read_headers
|
29
35
|
def_delegators :headers, :[], :fetch, :key?
|
30
36
|
|
31
37
|
def initialize(file)
|
32
38
|
@file = file
|
33
|
-
@
|
34
|
-
@body_pos =
|
39
|
+
@has_read_headers = false
|
40
|
+
@body_pos = 0
|
35
41
|
end
|
36
42
|
|
37
43
|
# @return [String] the actual story, including MediaWiki markup
|
38
44
|
def body
|
39
45
|
@body ||= read_body.freeze
|
40
46
|
end
|
41
|
-
|
47
|
+
alias to_s body
|
48
|
+
|
49
|
+
# Read, or re-read, the body of the fable from the disk
|
50
|
+
# @see #body
|
51
|
+
def read_body
|
52
|
+
headers unless read_headers?
|
53
|
+
|
54
|
+
io = file.open
|
55
|
+
io.seek @body_pos
|
56
|
+
io.read.strip
|
57
|
+
ensure
|
58
|
+
io&.close
|
59
|
+
end
|
42
60
|
|
43
61
|
# @return [Hash<String, String>] the story's metadata
|
44
62
|
def headers
|
45
63
|
@headers ||= begin
|
46
|
-
@
|
64
|
+
@has_read_headers = true
|
47
65
|
read_headers.freeze
|
48
66
|
end
|
49
67
|
end
|
@@ -52,11 +70,6 @@ module CodelessCode
|
|
52
70
|
headers.key?(key)
|
53
71
|
end
|
54
72
|
|
55
|
-
# @return [::Date, nil]
|
56
|
-
def date
|
57
|
-
::Date.parse(self['Date']) if header?('Date')
|
58
|
-
end
|
59
|
-
|
60
73
|
# @return [Symbol]
|
61
74
|
def lang
|
62
75
|
@lang ||= dir_parts.first.to_sym
|
@@ -66,70 +79,46 @@ module CodelessCode
|
|
66
79
|
@translator ||= dir_parts.last
|
67
80
|
end
|
68
81
|
|
69
|
-
|
70
|
-
self[
|
71
|
-
end
|
72
|
-
|
73
|
-
def tagline
|
74
|
-
self['Tagline']
|
82
|
+
RAW_ATTRS.each do |attr|
|
83
|
+
define_method(attr.downcase.to_sym) { self[attr] }
|
75
84
|
end
|
76
85
|
|
77
|
-
|
78
|
-
self[
|
86
|
+
INTEGER_ATTRS.each do |attr|
|
87
|
+
define_method(attr.downcase.to_sym) { self[attr].to_i }
|
79
88
|
end
|
80
89
|
|
81
|
-
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
def geekiness
|
86
|
-
self['Geekiness'].to_i
|
87
|
-
end
|
88
|
-
|
89
|
-
def names
|
90
|
-
list('Names')
|
91
|
-
end
|
92
|
-
|
93
|
-
def topics
|
94
|
-
list('Topics')
|
90
|
+
LIST_ATTRS.each do |attr|
|
91
|
+
define_method(attr.downcase.to_sym) { list(attr) }
|
95
92
|
end
|
96
93
|
|
97
94
|
private
|
98
95
|
|
99
|
-
def
|
100
|
-
headers unless read_headers?
|
101
|
-
|
96
|
+
def read_headers
|
102
97
|
io = file.open
|
103
|
-
io
|
104
|
-
io.read.strip
|
98
|
+
parse_headers(io)
|
105
99
|
ensure
|
106
100
|
io&.close
|
107
101
|
end
|
108
102
|
|
109
|
-
|
110
|
-
|
103
|
+
# :reek:FeatureEnvy
|
104
|
+
def parse_headers(io, head = {})
|
105
|
+
until io.eof?
|
106
|
+
@body_pos = io.pos
|
107
|
+
match = HEADER_PATTERN.match(io.gets)
|
108
|
+
break if match.nil?
|
111
109
|
|
112
|
-
|
113
|
-
until io.eof?
|
114
|
-
@body_pos = io.pos
|
115
|
-
if (m = HEADER_PATTERN.match(io.gets))
|
116
|
-
head[m[1].strip] = m[2]&.strip
|
117
|
-
else
|
118
|
-
break
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
massage_headers(head)
|
110
|
+
head[match[1].strip] = match[2]&.strip
|
123
111
|
end
|
124
|
-
|
125
|
-
io&.close
|
112
|
+
massage_headers(head)
|
126
113
|
end
|
127
114
|
|
115
|
+
# :reek:UtilityFunction
|
128
116
|
def massage_headers(head)
|
129
117
|
if head.key?('Series')
|
130
118
|
head['Series'] = head['Title']
|
131
119
|
head['Title'] = head.delete('Subtitle')
|
132
120
|
end
|
121
|
+
head
|
133
122
|
end
|
134
123
|
|
135
124
|
def list(key)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# codeless_code filters and prints fables from http://thecodelesscode.com
|
2
4
|
# Copyright (C) 2018 Jon Sangster
|
3
5
|
#
|
@@ -22,14 +24,14 @@ module CodelessCode
|
|
22
24
|
extend Forwardable
|
23
25
|
include Enumerable
|
24
26
|
|
25
|
-
FILE_PATTERN = '*.txt'
|
26
|
-
LANG_SEP = '-'
|
27
|
+
FILE_PATTERN = '*.txt'
|
28
|
+
LANG_SEP = '-'
|
27
29
|
|
28
|
-
|
30
|
+
attr_reader :dir
|
29
31
|
def_delegator :fables, :each
|
30
32
|
|
31
33
|
def initialize(dir)
|
32
|
-
|
34
|
+
@dir = dir
|
33
35
|
end
|
34
36
|
|
35
37
|
def lang
|
@@ -41,11 +43,11 @@ module CodelessCode
|
|
41
43
|
end
|
42
44
|
|
43
45
|
def fables
|
44
|
-
@fables ||= files.map { |
|
46
|
+
@fables ||= files.map { |file| Fable.new(file) }.sort_by(&:number)
|
45
47
|
end
|
46
48
|
|
47
49
|
def filter(filt)
|
48
|
-
select { |
|
50
|
+
select { |fable| filt.call(fable) }
|
49
51
|
end
|
50
52
|
|
51
53
|
private
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# codeless_code filters and prints fables from http://thecodelesscode.com
|
2
4
|
# Copyright (C) 2018 Jon Sangster
|
3
5
|
#
|
@@ -20,11 +22,11 @@ module CodelessCode
|
|
20
22
|
module_function
|
21
23
|
|
22
24
|
def header_integer_filter(name)
|
23
|
-
subclass_filter(
|
25
|
+
subclass_filter(Headers::Integer, name)
|
24
26
|
end
|
25
27
|
|
26
28
|
def header_string_filter(name)
|
27
|
-
subclass_filter(
|
29
|
+
subclass_filter(Headers::String, name)
|
28
30
|
end
|
29
31
|
|
30
32
|
def subclass_filter(klass, name)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# codeless_code filters and prints fables from http://thecodelesscode.com
|
2
4
|
# Copyright (C) 2018 Jon Sangster
|
3
5
|
#
|
@@ -35,7 +37,7 @@ module CodelessCode
|
|
35
37
|
end
|
36
38
|
|
37
39
|
def call(fable)
|
38
|
-
select(&:enabled?).all? { |filter| filter.call(fable) }
|
40
|
+
any? && select(&:enabled?).all? { |filter| filter.call(fable) }
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# codeless_code filters and prints fables from http://thecodelesscode.com
|
2
4
|
# Copyright (C) 2018 Jon Sangster
|
3
5
|
#
|
@@ -17,43 +19,40 @@ require 'date'
|
|
17
19
|
|
18
20
|
module CodelessCode
|
19
21
|
module Filters
|
20
|
-
|
22
|
+
# Matches {Fable fables} that were published on, before, or after a given
|
23
|
+
# date.
|
24
|
+
class Date < Headers::Base
|
25
|
+
# :reek:BooleanParameter
|
21
26
|
def initialize(exact: nil, min: nil, max: nil, exclude: false)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
@exclude = exclude
|
27
|
+
super('Date', exclude, [Matcher.parse(exact), :==],
|
28
|
+
[Matcher.parse(min), :<=],
|
29
|
+
[Matcher.parse(max), :>=])
|
26
30
|
end
|
27
31
|
|
28
|
-
|
29
|
-
|
32
|
+
# :reek:UtilityFunction
|
33
|
+
def parse(val)
|
34
|
+
::Date.parse(val)
|
30
35
|
end
|
31
36
|
|
32
|
-
def
|
33
|
-
|
34
|
-
return false unless @exact.nil? || @exact == val
|
35
|
-
return false unless @min.nil? || @min <= val
|
36
|
-
return false unless @max.nil? || @max >= val
|
37
|
-
true
|
38
|
-
else
|
39
|
-
@exclude
|
40
|
-
end
|
37
|
+
def test_single(val, operator, test)
|
38
|
+
test.send(operator, val)
|
41
39
|
end
|
42
40
|
|
41
|
+
# Wraps a {::Date} and matches it against "date substrings". ie:
|
42
|
+
# +2010-12+ will matches any dates in December, 2010 and +2010+ will
|
43
|
+
# match any dates in that year.
|
43
44
|
class Matcher
|
44
45
|
# param str [String] A date like +2010+, +2010-12+, or +2010-12-23+
|
45
46
|
def self.parse(str)
|
46
|
-
|
47
|
+
return nil unless str
|
47
48
|
|
48
49
|
if str.size == 4
|
49
|
-
|
50
|
-
match = :year
|
50
|
+
new(::Date.parse("#{str}-01-01"), match: :year)
|
51
51
|
elsif str.size == 7
|
52
|
-
|
53
|
-
|
52
|
+
new(::Date.parse("#{str}-01"), match: :month)
|
53
|
+
else
|
54
|
+
new(::Date.parse(str), match: :day)
|
54
55
|
end
|
55
|
-
|
56
|
-
new(::Date.parse(str), match: match)
|
57
56
|
end
|
58
57
|
|
59
58
|
def initialize(date, match:)
|
@@ -62,27 +61,38 @@ module CodelessCode
|
|
62
61
|
end
|
63
62
|
|
64
63
|
def ==(other)
|
65
|
-
|
64
|
+
compare(@date, other, :==, @match)
|
66
65
|
end
|
67
66
|
|
68
67
|
def >=(other)
|
69
|
-
|
68
|
+
compare(@date, other, :>=, @match)
|
70
69
|
end
|
71
70
|
|
72
71
|
def <=(other)
|
73
|
-
|
72
|
+
compare(@date, other, :<=, @match)
|
74
73
|
end
|
75
74
|
|
76
75
|
private
|
77
76
|
|
78
|
-
|
77
|
+
# :reek:ControlParameter
|
78
|
+
# :reek:FeatureEnvy
|
79
|
+
def compare(first, second, operator, match)
|
79
80
|
case match
|
80
81
|
when :year
|
81
|
-
|
82
|
+
first.year.send(operator, second.year)
|
82
83
|
when :month
|
83
|
-
|
84
|
+
compare_month(first, second, operator)
|
85
|
+
else
|
86
|
+
first.send(operator, second)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# :reek:FeatureEnvy
|
91
|
+
def compare_month(first, second, operator)
|
92
|
+
if first.year == second.year
|
93
|
+
first.month.send(operator, second.month)
|
84
94
|
else
|
85
|
-
|
95
|
+
compare(first, second, operator, :year)
|
86
96
|
end
|
87
97
|
end
|
88
98
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# codeless_code filters and prints fables from http://thecodelesscode.com
|
2
4
|
# Copyright (C) 2018 Jon Sangster
|
3
5
|
#
|
@@ -37,28 +39,46 @@ module CodelessCode
|
|
37
39
|
end
|
38
40
|
|
39
41
|
def filters
|
40
|
-
@filters ||=
|
41
|
-
|
42
|
+
@filters ||=
|
43
|
+
string_filters +
|
44
|
+
integer_filters +
|
45
|
+
[
|
46
|
+
filter(:Date, :date),
|
47
|
+
new_filter(:Lang, exact: lang),
|
48
|
+
number_filter,
|
49
|
+
translator_filter
|
50
|
+
]
|
51
|
+
end
|
42
52
|
|
43
|
-
|
44
|
-
casecmp: @opts[:translator]),
|
53
|
+
private
|
45
54
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
Filters::Tagline.new(**str_args(:tagline)),
|
50
|
-
Filters::Title.new(**str_args(:title)),
|
55
|
+
def string_filters
|
56
|
+
%i[Credits Name Tagline Title Series].map { |name| filter(name, :str) }
|
57
|
+
end
|
51
58
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end),
|
59
|
+
def integer_filters
|
60
|
+
%i[Geekiness].map { |name| filter(name, :int) }
|
61
|
+
end
|
56
62
|
|
57
|
-
|
58
|
-
]
|
63
|
+
def number_filter
|
64
|
+
filter(:Number, :int) { |args| args[:exact] ||= @opts.args.last&.to_i }
|
59
65
|
end
|
60
66
|
|
61
|
-
|
67
|
+
def translator_filter
|
68
|
+
new_filter(:Translator, exact: @opts[:translator_exact],
|
69
|
+
casecmp: @opts[:translator])
|
70
|
+
end
|
71
|
+
|
72
|
+
def filter(name, type, &blk)
|
73
|
+
new_filter(name,
|
74
|
+
**send(:"#{type.downcase}_args", name.to_s.downcase.to_s),
|
75
|
+
&blk)
|
76
|
+
end
|
77
|
+
|
78
|
+
def new_filter(name, **args)
|
79
|
+
yield args if block_given?
|
80
|
+
Filters.const_get(name).new(**args)
|
81
|
+
end
|
62
82
|
|
63
83
|
def fallback_lang
|
64
84
|
lang = ENV['LANG']&.split(/_|\./)&.first&.downcase&.to_sym
|
@@ -66,13 +86,14 @@ module CodelessCode
|
|
66
86
|
end
|
67
87
|
|
68
88
|
def non_defaults_enabled?
|
69
|
-
filters.reject { |
|
89
|
+
filters.reject { |filter| filter.is_a?(Filters::Lang) }.any?(&:enabled?)
|
70
90
|
end
|
71
91
|
|
72
92
|
def str_args(name)
|
73
93
|
Hash[
|
74
94
|
%i[exact start_with end_with exclude].zip(
|
75
|
-
@opts.slice(
|
95
|
+
@opts.slice(:"#{name}", :"#{name}_start", :"#{name}_end",
|
96
|
+
:"no_#{name}").values
|
76
97
|
)
|
77
98
|
].tap do |args|
|
78
99
|
args[:start_with] ||= '' if @opts[:"has_#{name}"]
|
@@ -82,7 +103,7 @@ module CodelessCode
|
|
82
103
|
def int_args(name)
|
83
104
|
Hash[
|
84
105
|
%i[exact min max exclude].zip(
|
85
|
-
@opts.slice(
|
106
|
+
@opts.slice(:"#{name}", :"#{name}_gte", :"#{name}_lte")
|
86
107
|
.values
|
87
108
|
.map { |num| num&.to_i }
|
88
109
|
.push(@opts[:"no_#{name}"])
|
@@ -90,18 +111,14 @@ module CodelessCode
|
|
90
111
|
]
|
91
112
|
end
|
92
113
|
|
93
|
-
def date_args
|
114
|
+
def date_args(name)
|
94
115
|
{
|
95
|
-
exact:
|
96
|
-
min:
|
97
|
-
max:
|
98
|
-
exclude: @opts[:
|
116
|
+
exact: @opts[:"#{name}"],
|
117
|
+
min: @opts[:"#{name}_after"],
|
118
|
+
max: @opts[:"#{name}_before"],
|
119
|
+
exclude: @opts[:"no_#{name}"]
|
99
120
|
}
|
100
121
|
end
|
101
|
-
|
102
|
-
def date(arg)
|
103
|
-
arg && Filters::Date::Matcher.parse(arg)
|
104
|
-
end
|
105
122
|
end
|
106
123
|
end
|
107
124
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# codeless_code filters and prints fables from http://thecodelesscode.com
|
4
|
+
# Copyright (C) 2018 Jon Sangster
|
5
|
+
#
|
6
|
+
# This program is free software: you can redistribute it and/or modify it under
|
7
|
+
# the terms of the GNU General Public License as published by the Free Software
|
8
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
9
|
+
# version.
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
12
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
13
|
+
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
14
|
+
# details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License along with
|
17
|
+
# this program. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module CodelessCode
|
19
|
+
module Filters
|
20
|
+
module Headers
|
21
|
+
# Abstract base class for all generic filters that test a {Fable fable's}
|
22
|
+
# headers.
|
23
|
+
class Base
|
24
|
+
def initialize(key, exclude, *tests)
|
25
|
+
@key = key
|
26
|
+
@exclude = exclude
|
27
|
+
@tests ||= tests.select(&:first).freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
def enabled?
|
31
|
+
@tests.any? || @exclude
|
32
|
+
end
|
33
|
+
|
34
|
+
def call(fable)
|
35
|
+
if fable.header?(@key)
|
36
|
+
@tests.any? ? test(parse(fable[@key])) : !@exclude
|
37
|
+
else
|
38
|
+
@exclude
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
# :reek:UtilityFunction
|
45
|
+
def parse(val)
|
46
|
+
val
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_single(val, operator, test)
|
50
|
+
val.send(operator, test)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def test(val)
|
56
|
+
@tests.any? { |(test, op)| test_single(val, op, test) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# codeless_code filters and prints fables from http://thecodelesscode.com
|
2
4
|
# Copyright (C) 2018 Jon Sangster
|
3
5
|
#
|
@@ -15,27 +17,22 @@
|
|
15
17
|
# this program. If not, see <https://www.gnu.org/licenses/>.
|
16
18
|
module CodelessCode
|
17
19
|
module Filters
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
module Headers
|
21
|
+
# Matches {Fable fables} that have an integer header equal to, less than,
|
22
|
+
# or greater than the given parameters.
|
23
|
+
class Integer < Base
|
24
|
+
# :reek:BooleanParameter
|
25
|
+
def initialize(key, exact: nil, min: nil, max: nil, exclude: false)
|
26
|
+
super(key, exclude, [exact, :==],
|
27
|
+
[min, :>=],
|
28
|
+
[max, :<=])
|
29
|
+
end
|
26
30
|
|
27
|
-
|
28
|
-
@exact || @min || @max || @exclude
|
29
|
-
end
|
31
|
+
protected
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
return false unless @min.nil? || val >= @min.to_i
|
35
|
-
return false unless @max.nil? || val <= @max.to_i
|
36
|
-
!@exclude
|
37
|
-
else
|
38
|
-
@exclude
|
33
|
+
# :reek:UtilityFunction
|
34
|
+
def parse(val)
|
35
|
+
val.to_i
|
39
36
|
end
|
40
37
|
end
|
41
38
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# codeless_code filters and prints fables from http://thecodelesscode.com
|
2
4
|
# Copyright (C) 2018 Jon Sangster
|
3
5
|
#
|
@@ -15,28 +17,16 @@
|
|
15
17
|
# this program. If not, see <https://www.gnu.org/licenses/>.
|
16
18
|
module CodelessCode
|
17
19
|
module Filters
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def enabled?
|
29
|
-
@exact || @start_with || @end_with || @exclude
|
30
|
-
end
|
31
|
-
|
32
|
-
def call(fable)
|
33
|
-
if fable.header?(@key) && (val = fable[@key])
|
34
|
-
return false unless @exact.nil? || val == @exact
|
35
|
-
return false unless @start_with.nil? || val.start_with?(@start_with)
|
36
|
-
return false unless @end_with.nil? || val.end_with?(@end_with)
|
37
|
-
!@exclude
|
38
|
-
else
|
39
|
-
@exclude
|
20
|
+
module Headers
|
21
|
+
# Matches {Fable fables} that have an string header equal to, that starts
|
22
|
+
# with, or ends with the given parameters.
|
23
|
+
class String < Base
|
24
|
+
# :reek:BooleanParameter
|
25
|
+
def initialize(key, exact: nil, start_with: nil, end_with: nil,
|
26
|
+
exclude: false)
|
27
|
+
super(key, exclude, [exact, :==],
|
28
|
+
[start_with, :start_with?],
|
29
|
+
[end_with, :end_with?])
|
40
30
|
end
|
41
31
|
end
|
42
32
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# codeless_code filters and prints fables from http://thecodelesscode.com
|
2
4
|
# Copyright (C) 2018 Jon Sangster
|
3
5
|
#
|
@@ -15,6 +17,7 @@
|
|
15
17
|
# this program. If not, see <https://www.gnu.org/licenses/>.
|
16
18
|
module CodelessCode
|
17
19
|
module Filters
|
20
|
+
# Matches {Fable fables} in the given language (code).
|
18
21
|
class Lang
|
19
22
|
def initialize(exact: nil)
|
20
23
|
@exact = exact
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# codeless_code filters and prints fables from http://thecodelesscode.com
|
2
4
|
# Copyright (C) 2018 Jon Sangster
|
3
5
|
#
|
@@ -15,6 +17,7 @@
|
|
15
17
|
# this program. If not, see <https://www.gnu.org/licenses/>.
|
16
18
|
module CodelessCode
|
17
19
|
module Filters
|
20
|
+
# Matches {Fable fables} translated by the person with the given name.
|
18
21
|
class Translator
|
19
22
|
def initialize(exact: nil, casecmp: nil)
|
20
23
|
@exact = exact
|
@@ -26,8 +29,10 @@ module CodelessCode
|
|
26
29
|
end
|
27
30
|
|
28
31
|
def call(fable)
|
29
|
-
|
30
|
-
@
|
32
|
+
trans = fable.translator
|
33
|
+
return false unless @exact.nil? || @exact == trans
|
34
|
+
|
35
|
+
@casecmp.nil? || @casecmp.casecmp?(trans)
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|