fmt 0.1.2 → 0.3.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 +4 -4
- data/README.md +170 -87
- 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 +51 -11
- 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 -16
- data/lib/fmt/embed.rb +0 -19
- data/lib/fmt/filter.rb +0 -32
- data/lib/fmt/filters.rb +0 -76
- data/lib/fmt/formatter.rb +0 -50
- 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 -63
data/lib/fmt/formatter.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "singleton"
|
4
|
-
require_relative "filters"
|
5
|
-
require_relative "scanners"
|
6
|
-
require_relative "transformer"
|
7
|
-
|
8
|
-
module Fmt
|
9
|
-
class Formatter
|
10
|
-
include Singleton
|
11
|
-
|
12
|
-
attr_reader :filters
|
13
|
-
|
14
|
-
def format(string, **locals)
|
15
|
-
result = string.to_s
|
16
|
-
transformer = next_transformer(result)
|
17
|
-
|
18
|
-
while transformer
|
19
|
-
result = transformer.transform(result, **locals)
|
20
|
-
transformer = next_transformer(result)
|
21
|
-
end
|
22
|
-
|
23
|
-
result
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def initialize
|
29
|
-
super
|
30
|
-
@filters = Fmt::Filters.new
|
31
|
-
end
|
32
|
-
|
33
|
-
def next_transformer(string)
|
34
|
-
embed_scanner = Fmt::EmbedScanner.new(string)
|
35
|
-
embed_scanner.scan
|
36
|
-
|
37
|
-
key_scanner = Fmt::KeyScanner.new(string)
|
38
|
-
key = key_scanner.scan
|
39
|
-
return nil unless key
|
40
|
-
|
41
|
-
filter_scanner = Fmt::FilterScanner.new(key_scanner.rest, registered_filters: filters)
|
42
|
-
filter_string = filter_scanner.scan
|
43
|
-
|
44
|
-
Fmt::Transformer.new key.to_sym,
|
45
|
-
embeds: embed_scanner.embeds,
|
46
|
-
filters: filter_scanner.filters,
|
47
|
-
placeholder: "%{#{key}}#{filter_string}".strip
|
48
|
-
end
|
49
|
-
end
|
50
|
-
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,63 +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 => error
|
26
|
-
message = <<~MSG
|
27
|
-
Invalid filter!
|
28
|
-
#{filter.inspect}
|
29
|
-
Verify it's either a valid native filter or is registered with Fmt.
|
30
|
-
Example: Fmt.add_filter(:#{filter.name}, &block)
|
31
|
-
#{error.message}
|
32
|
-
MSG
|
33
|
-
raise Fmt::Error, message
|
34
|
-
end
|
35
|
-
elsif filter.proc?
|
36
|
-
begin
|
37
|
-
replacement = filter.value.call(replacement)
|
38
|
-
rescue => error
|
39
|
-
message = <<~MSG
|
40
|
-
Error in filter!
|
41
|
-
#{filter.inspect}
|
42
|
-
#{error.message}
|
43
|
-
MSG
|
44
|
-
raise Fmt::Error, message
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
result = string.sub(placeholder, replacement)
|
50
|
-
defined?(Rainbow) ? Rainbow(result) : result
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
def transform_embeds(string, **locals)
|
56
|
-
while embeds.any?
|
57
|
-
embed = embeds.shift
|
58
|
-
string = string.sub(embed.placeholder, embed.format(**locals))
|
59
|
-
end
|
60
|
-
string
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|