fmt 0.1.3 → 0.3.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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +179 -86
  3. data/lib/fmt/boot.rb +50 -0
  4. data/lib/fmt/lru_cache.rb +181 -0
  5. data/lib/fmt/mixins/matchable.rb +26 -0
  6. data/lib/fmt/models/arguments.rb +194 -0
  7. data/lib/fmt/models/embed.rb +48 -0
  8. data/lib/fmt/models/macro.rb +58 -0
  9. data/lib/fmt/models/model.rb +66 -0
  10. data/lib/fmt/models/pipeline.rb +47 -0
  11. data/lib/fmt/models/template.rb +55 -0
  12. data/lib/fmt/node.rb +128 -0
  13. data/lib/fmt/parsers/arguments_parser.rb +43 -0
  14. data/lib/fmt/parsers/embed_parser.rb +54 -0
  15. data/lib/fmt/parsers/macro_parser.rb +113 -0
  16. data/lib/fmt/parsers/parser.rb +56 -0
  17. data/lib/fmt/parsers/pipeline_parser.rb +41 -0
  18. data/lib/fmt/parsers/template_parser.rb +125 -0
  19. data/lib/fmt/refinements/kernel_refinement.rb +33 -0
  20. data/lib/fmt/registries/native_registry.rb +66 -0
  21. data/lib/fmt/registries/rainbow_registry.rb +36 -0
  22. data/lib/fmt/registries/registry.rb +127 -0
  23. data/lib/fmt/renderer.rb +132 -0
  24. data/lib/fmt/sigils.rb +23 -0
  25. data/lib/fmt/token.rb +126 -0
  26. data/lib/fmt/tokenizer.rb +96 -0
  27. data/lib/fmt/version.rb +3 -1
  28. data/lib/fmt.rb +50 -12
  29. data/sig/generated/fmt/boot.rbs +2 -0
  30. data/sig/generated/fmt/lru_cache.rbs +122 -0
  31. data/sig/generated/fmt/mixins/matchable.rbs +18 -0
  32. data/sig/generated/fmt/models/arguments.rbs +115 -0
  33. data/sig/generated/fmt/models/embed.rbs +34 -0
  34. data/sig/generated/fmt/models/macro.rbs +37 -0
  35. data/sig/generated/fmt/models/model.rbs +45 -0
  36. data/sig/generated/fmt/models/pipeline.rbs +31 -0
  37. data/sig/generated/fmt/models/template.rbs +33 -0
  38. data/sig/generated/fmt/node.rbs +64 -0
  39. data/sig/generated/fmt/parsers/arguments_parser.rbs +25 -0
  40. data/sig/generated/fmt/parsers/embed_parser.rbs +36 -0
  41. data/sig/generated/fmt/parsers/macro_parser.rbs +60 -0
  42. data/sig/generated/fmt/parsers/parser.rbs +44 -0
  43. data/sig/generated/fmt/parsers/pipeline_parser.rbs +25 -0
  44. data/sig/generated/fmt/parsers/template_parser.rbs +50 -0
  45. data/sig/generated/fmt/refinements/kernel_refinement.rbs +23 -0
  46. data/sig/generated/fmt/registries/native_registry.rbs +19 -0
  47. data/sig/generated/fmt/registries/rainbow_registry.rbs +11 -0
  48. data/sig/generated/fmt/registries/registry.rbs +69 -0
  49. data/sig/generated/fmt/renderer.rbs +70 -0
  50. data/sig/generated/fmt/sigils.rbs +30 -0
  51. data/sig/generated/fmt/token.rbs +77 -0
  52. data/sig/generated/fmt/tokenizer.rbs +51 -0
  53. data/sig/generated/fmt/version.rbs +5 -0
  54. data/sig/generated/fmt.rbs +41 -0
  55. metadata +126 -18
  56. data/lib/fmt/embed.rb +0 -19
  57. data/lib/fmt/filter.rb +0 -32
  58. data/lib/fmt/filter_groups/filter_group.rb +0 -56
  59. data/lib/fmt/filter_groups/rainbow_filter_group.rb +0 -27
  60. data/lib/fmt/filter_groups/string_filter_group.rb +0 -28
  61. data/lib/fmt/formatter.rb +0 -60
  62. data/lib/fmt/scanners/base_scanner.rb +0 -41
  63. data/lib/fmt/scanners/embed_scanner.rb +0 -56
  64. data/lib/fmt/scanners/filter_scanner.rb +0 -31
  65. data/lib/fmt/scanners/key_scanner.rb +0 -15
  66. data/lib/fmt/scanners.rb +0 -3
  67. 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
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Dir[File.join(__dir__, "scanners", "*.rb")].each { |file| require file }
@@ -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