fmt 0.1.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +167 -93
- data/lib/fmt/boot.rb +50 -0
- data/lib/fmt/lru_cache.rb +181 -0
- data/lib/fmt/mixins/matchable.rb +26 -0
- data/lib/fmt/models/arguments.rb +194 -0
- data/lib/fmt/models/embed.rb +48 -0
- data/lib/fmt/models/macro.rb +58 -0
- data/lib/fmt/models/model.rb +66 -0
- data/lib/fmt/models/pipeline.rb +47 -0
- data/lib/fmt/models/template.rb +55 -0
- data/lib/fmt/node.rb +128 -0
- data/lib/fmt/parsers/arguments_parser.rb +43 -0
- data/lib/fmt/parsers/embed_parser.rb +54 -0
- data/lib/fmt/parsers/macro_parser.rb +113 -0
- data/lib/fmt/parsers/parser.rb +56 -0
- data/lib/fmt/parsers/pipeline_parser.rb +41 -0
- data/lib/fmt/parsers/template_parser.rb +125 -0
- data/lib/fmt/refinements/kernel_refinement.rb +38 -0
- data/lib/fmt/registries/native_registry.rb +66 -0
- data/lib/fmt/registries/rainbow_registry.rb +36 -0
- data/lib/fmt/registries/registry.rb +127 -0
- data/lib/fmt/renderer.rb +132 -0
- data/lib/fmt/sigils.rb +23 -0
- data/lib/fmt/token.rb +126 -0
- data/lib/fmt/tokenizer.rb +96 -0
- data/lib/fmt/version.rb +3 -1
- data/lib/fmt.rb +50 -12
- data/sig/generated/fmt/boot.rbs +2 -0
- data/sig/generated/fmt/lru_cache.rbs +122 -0
- data/sig/generated/fmt/mixins/matchable.rbs +18 -0
- data/sig/generated/fmt/models/arguments.rbs +115 -0
- data/sig/generated/fmt/models/embed.rbs +34 -0
- data/sig/generated/fmt/models/macro.rbs +37 -0
- data/sig/generated/fmt/models/model.rbs +45 -0
- data/sig/generated/fmt/models/pipeline.rbs +31 -0
- data/sig/generated/fmt/models/template.rbs +33 -0
- data/sig/generated/fmt/node.rbs +64 -0
- data/sig/generated/fmt/parsers/arguments_parser.rbs +25 -0
- data/sig/generated/fmt/parsers/embed_parser.rbs +36 -0
- data/sig/generated/fmt/parsers/macro_parser.rbs +60 -0
- data/sig/generated/fmt/parsers/parser.rbs +44 -0
- data/sig/generated/fmt/parsers/pipeline_parser.rbs +25 -0
- data/sig/generated/fmt/parsers/template_parser.rbs +50 -0
- data/sig/generated/fmt/refinements/kernel_refinement.rbs +23 -0
- data/sig/generated/fmt/registries/native_registry.rbs +19 -0
- data/sig/generated/fmt/registries/rainbow_registry.rbs +11 -0
- data/sig/generated/fmt/registries/registry.rbs +69 -0
- data/sig/generated/fmt/renderer.rbs +70 -0
- data/sig/generated/fmt/sigils.rbs +30 -0
- data/sig/generated/fmt/token.rbs +77 -0
- data/sig/generated/fmt/tokenizer.rbs +51 -0
- data/sig/generated/fmt/version.rbs +5 -0
- data/sig/generated/fmt.rbs +41 -0
- metadata +126 -18
- data/lib/fmt/embed.rb +0 -19
- data/lib/fmt/filter.rb +0 -32
- data/lib/fmt/filter_groups/filter_group.rb +0 -56
- data/lib/fmt/filter_groups/rainbow_filter_group.rb +0 -27
- data/lib/fmt/filter_groups/string_filter_group.rb +0 -28
- data/lib/fmt/formatter.rb +0 -60
- data/lib/fmt/scanners/base_scanner.rb +0 -41
- data/lib/fmt/scanners/embed_scanner.rb +0 -56
- data/lib/fmt/scanners/filter_scanner.rb +0 -31
- data/lib/fmt/scanners/key_scanner.rb +0 -15
- data/lib/fmt/scanners.rb +0 -3
- data/lib/fmt/transformer.rb +0 -57
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "filter_group"
|
4
|
-
|
5
|
-
module Fmt
|
6
|
-
class StringFilterGroup < FilterGroup
|
7
|
-
def initialize
|
8
|
-
super
|
9
|
-
|
10
|
-
# rubocop:disable Layout/ExtraSpacing AllowForAlignment
|
11
|
-
add :capitalize, ->(s) { s.capitalize }
|
12
|
-
add :chomp, ->(s) { s.chomp }
|
13
|
-
add :chop, ->(s) { s.chop }
|
14
|
-
add :downcase, ->(s) { s.downcase }
|
15
|
-
add :lstrip, ->(s) { s.lstrip }
|
16
|
-
add :reverse, ->(s) { s.reverse }
|
17
|
-
add :rstrip, ->(s) { s.rstrip }
|
18
|
-
add :shellescape, ->(s) { s.shellescape }
|
19
|
-
add :strip, ->(s) { s.strip }
|
20
|
-
add :succ, ->(s) { s.succ }
|
21
|
-
add :swapcase, ->(s) { s.swapcase }
|
22
|
-
add :undump, ->(s) { s.undump }
|
23
|
-
add :unicode_normalize, ->(s) { s.unicode_normalize }
|
24
|
-
add :upcase, ->(s) { s.upcase }
|
25
|
-
# rubocop:enable Layout/ExtraSpacing AllowForAlignment
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
data/lib/fmt/formatter.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "singleton"
|
4
|
-
require_relative "filter_groups/filter_group"
|
5
|
-
require_relative "filter_groups/rainbow_filter_group"
|
6
|
-
require_relative "filter_groups/string_filter_group"
|
7
|
-
require_relative "scanners"
|
8
|
-
require_relative "transformer"
|
9
|
-
|
10
|
-
module Fmt
|
11
|
-
class Formatter
|
12
|
-
include Singleton
|
13
|
-
|
14
|
-
attr_reader :filters
|
15
|
-
|
16
|
-
def add_rainbow_filters
|
17
|
-
filters.merge! Fmt::RainbowFilterGroup.new.to_h
|
18
|
-
end
|
19
|
-
|
20
|
-
def add_filter(...)
|
21
|
-
filters.add(...)
|
22
|
-
end
|
23
|
-
|
24
|
-
def format(string, **locals)
|
25
|
-
result = string.to_s
|
26
|
-
transformer = next_transformer(result)
|
27
|
-
|
28
|
-
while transformer
|
29
|
-
result = transformer.transform(result, **locals)
|
30
|
-
transformer = next_transformer(result)
|
31
|
-
end
|
32
|
-
|
33
|
-
result
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def initialize
|
39
|
-
super
|
40
|
-
@filters = Fmt::FilterGroup.new.merge!(Fmt::StringFilterGroup.new)
|
41
|
-
end
|
42
|
-
|
43
|
-
def next_transformer(string)
|
44
|
-
embed_scanner = Fmt::EmbedScanner.new(string)
|
45
|
-
embed_scanner.scan
|
46
|
-
|
47
|
-
key_scanner = Fmt::KeyScanner.new(string)
|
48
|
-
key = key_scanner.scan
|
49
|
-
return nil unless key
|
50
|
-
|
51
|
-
filter_scanner = Fmt::FilterScanner.new(key_scanner.rest, registered_filters: filters)
|
52
|
-
filter_string = filter_scanner.scan
|
53
|
-
|
54
|
-
Fmt::Transformer.new key.to_sym,
|
55
|
-
embeds: embed_scanner.embeds,
|
56
|
-
filters: filter_scanner.filters,
|
57
|
-
placeholder: "%{#{key}}#{filter_string}".strip
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "forwardable"
|
4
|
-
require "strscan"
|
5
|
-
|
6
|
-
module Fmt
|
7
|
-
class BaseScanner
|
8
|
-
extend Forwardable
|
9
|
-
|
10
|
-
def initialize(string)
|
11
|
-
@string_scanner = StringScanner.new(string)
|
12
|
-
end
|
13
|
-
|
14
|
-
def_delegators :string_scanner, :string, :rest
|
15
|
-
attr_reader :value
|
16
|
-
|
17
|
-
def performed?
|
18
|
-
!!@performed
|
19
|
-
end
|
20
|
-
|
21
|
-
def reset
|
22
|
-
@performed = false
|
23
|
-
string_scanner.reset
|
24
|
-
end
|
25
|
-
|
26
|
-
def scan
|
27
|
-
return if performed?
|
28
|
-
@performed = true
|
29
|
-
perform
|
30
|
-
value
|
31
|
-
end
|
32
|
-
|
33
|
-
protected
|
34
|
-
|
35
|
-
attr_reader :string_scanner
|
36
|
-
|
37
|
-
def perform
|
38
|
-
raise NotImplementedError
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "base_scanner"
|
4
|
-
require_relative "../embed"
|
5
|
-
|
6
|
-
module Fmt
|
7
|
-
class EmbedScanner < BaseScanner
|
8
|
-
def initialize(string, root: nil)
|
9
|
-
super(string)
|
10
|
-
@root ||= root || self
|
11
|
-
@embeds = []
|
12
|
-
end
|
13
|
-
|
14
|
-
def embeds
|
15
|
-
root? ? @embeds : root.embeds
|
16
|
-
end
|
17
|
-
|
18
|
-
attr_reader :root
|
19
|
-
|
20
|
-
def root?
|
21
|
-
root == self
|
22
|
-
end
|
23
|
-
|
24
|
-
protected
|
25
|
-
|
26
|
-
def includes_embed?(string)
|
27
|
-
string.match?(/[{]{2}/)
|
28
|
-
end
|
29
|
-
|
30
|
-
def next_scanner(string)
|
31
|
-
Fmt::EmbedScanner.new string, root: root
|
32
|
-
end
|
33
|
-
|
34
|
-
def scan_embeds(string)
|
35
|
-
return unless includes_embed?(string)
|
36
|
-
|
37
|
-
string = string[string.index(/[{]{2}/) + 2..]
|
38
|
-
scanner = next_scanner(string)
|
39
|
-
while (embed = scanner.scan)
|
40
|
-
embeds << Fmt::Embed.new(embed)
|
41
|
-
scanner = next_scanner(scanner.rest)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def perform?
|
46
|
-
!string.start_with?("}")
|
47
|
-
end
|
48
|
-
|
49
|
-
def perform
|
50
|
-
return unless perform?
|
51
|
-
scan_embeds string # <------------------------------------ extract embeds
|
52
|
-
string_scanner.scan_until(/[{]{2}/) # <------------------- advance to start
|
53
|
-
@value = string_scanner.scan_until(/[^}]*(?=[}]{2})/) # <- extract value
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "base_scanner"
|
4
|
-
|
5
|
-
module Fmt
|
6
|
-
class FilterScanner < BaseScanner
|
7
|
-
DELIMITER = "|"
|
8
|
-
|
9
|
-
def initialize(string, registered_filters:)
|
10
|
-
@registered_filters = registered_filters
|
11
|
-
@filters = []
|
12
|
-
super(string)
|
13
|
-
end
|
14
|
-
|
15
|
-
alias_method :filter_string, :value
|
16
|
-
attr_reader :filters
|
17
|
-
|
18
|
-
protected
|
19
|
-
|
20
|
-
attr_reader :registered_filters
|
21
|
-
|
22
|
-
def perform
|
23
|
-
@value = string_scanner.scan(/[^\s%]+/) # <- extract value
|
24
|
-
return unless string_scanner.matched?
|
25
|
-
|
26
|
-
@filters = value.split(DELIMITER)&.map do |name|
|
27
|
-
registered_filters.fetch name.to_sym, Fmt::Filter.new(name, name)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "base_scanner"
|
4
|
-
|
5
|
-
module Fmt
|
6
|
-
class KeyScanner < BaseScanner
|
7
|
-
protected
|
8
|
-
|
9
|
-
def perform
|
10
|
-
string_scanner.skip_until(/%[{]/) # <------------------------------ advance to start
|
11
|
-
@value = string_scanner.scan(/\w+/) if string_scanner.matched? # <- extract value
|
12
|
-
string_scanner.scan(/[}]/) if string_scanner.matched? # <---------- advance to end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
data/lib/fmt/scanners.rb
DELETED
data/lib/fmt/transformer.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Fmt
|
4
|
-
class Transformer
|
5
|
-
def initialize(key, embeds:, filters:, placeholder:)
|
6
|
-
@key = key
|
7
|
-
@embeds = embeds
|
8
|
-
@filters = filters
|
9
|
-
@placeholder = placeholder
|
10
|
-
end
|
11
|
-
|
12
|
-
attr_reader :key, :embeds, :filters, :placeholder, :proc_filters, :string_filters
|
13
|
-
|
14
|
-
def transform(string, **locals)
|
15
|
-
string = transform_embeds(string, **locals)
|
16
|
-
|
17
|
-
raise Fmt::Error, "Missing key! :#{key} <string=#{string.inspect} locals=#{locals.inspect}>" unless locals.key?(key)
|
18
|
-
|
19
|
-
replacement = locals[key]
|
20
|
-
|
21
|
-
filters.each do |filter|
|
22
|
-
if filter.string?
|
23
|
-
begin
|
24
|
-
replacement = sprintf("%#{filter.value}", replacement)
|
25
|
-
rescue
|
26
|
-
raise Fmt::Error, <<~MSG
|
27
|
-
Invalid filter! #{filter.inspect}
|
28
|
-
Verify it has been properly registered. SEE: Fmt.add_filter(:#{filter.name}, &block)
|
29
|
-
MSG
|
30
|
-
end
|
31
|
-
elsif filter.proc?
|
32
|
-
begin
|
33
|
-
replacement = filter.value.call(replacement)
|
34
|
-
rescue => error
|
35
|
-
raise Fmt::Error, <<~MSG
|
36
|
-
Error in filter! #{filter.inspect}
|
37
|
-
#{error.message}
|
38
|
-
MSG
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
result = string.sub(placeholder, replacement)
|
44
|
-
defined?(Rainbow) ? Rainbow(result) : result
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def transform_embeds(string, **locals)
|
50
|
-
while embeds.any?
|
51
|
-
embed = embeds.shift
|
52
|
-
string = string.sub(embed.placeholder, embed.format(**locals))
|
53
|
-
end
|
54
|
-
string
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|