fmt 0.1.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +167 -93
  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 +38 -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