cogger 0.23.0 → 0.24.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 206ff070eb7f86523ea8ce73f13b12ca5eaa8e13d81d8adf389e69d984193d7d
4
- data.tar.gz: 5445cfff99f24c1af2fed78cc741ef0c469718c80fa54c5a4c1dff99069085f5
3
+ metadata.gz: 2c178fc1648e2a2cb5681f4606ea28841441004fdf6f7bc8d3794535fb32b3a0
4
+ data.tar.gz: 13cbbd1098321e423ba912fc9c772854f47538229344a3a51651c7c126c86107
5
5
  SHA512:
6
- metadata.gz: fbbae623ca9b520bbe356f9fa37f35b1e3520b66e4deebeae2bc4d8dc8700ffa08531efde1c7db5ac49a37a428544ea1430b032594e90eed44ac006c1016a111
7
- data.tar.gz: 6c2a1e66c79d661e4131fb2a14d20984fcf945dac6746efd010043b7eaa4c62c69a1a451681cba7da531e8042639de0cc685ec46e92601820f2762c3f99585cd
6
+ metadata.gz: a4fa3db73c99e7ab46d3659dcce0279dcefb514c9537db0bdb22d17988c3d2da0cf69dfdb8afbbfb1197ecd10ee4df363ef4ad95c985663c467baa04579b997d
7
+ data.tar.gz: f61da5f577ed2d9511d8655922bd7b816353f13d21c60ae969b92360bdb8fddf5c8ed00ca6ac356cb960f1340fa8adc07677e6a978dad0034a9719dd7cf34bdd
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -10,25 +10,24 @@
10
10
 
11
11
  = Cogger
12
12
 
13
- Cogger is a portmanteau for custom logger (i.e. `[c]ustom + l[ogger] = cogger`) which enhances Ruby's native {logger_link} functionality with additional features such as dynamic emojis, colorized text, structured JSON, multiple outputs, and much more. 🚀
13
+ Cogger is a portmanteau for custom logger (i.e. `[c]ustom + l[ogger] = cogger`) which enhances Ruby's native {logger_link} functionality with additional features such as dynamic emojis, colorized text, structured JSON, multiple streams, and much more. 🚀
14
14
 
15
15
  toc::[]
16
16
 
17
17
  == Features
18
18
 
19
19
  * Enhances Ruby's default {logger_link} with additional functionality and firepower.
20
- * Provides dynamic/specific emoji output.
21
- * Provides dynamic/specific colorized output via the {tone_link} gem.
22
- * Provides customizable templates which leverage native {format_link}.
23
- * Provides customizable formatters for simple, color, emoji, JSON, and/or custom formats.
20
+ * Provides customizable templates that use keys, emojis, and/or elements as an enhanced form of the {format_link}.
21
+ * Provides colored output via the {tone_link} gem.
22
+ * Provides customizable formatters.
24
23
  * Provides multiple streams so you can log the same information to several outputs at once.
25
- * Provides global and individual log entry tagging.
24
+ * Provides global and individual tagging.
26
25
  * Provides filtering of sensitive information.
27
26
  * Provides {rack_link} middleware for HTTP request logging.
28
27
 
29
28
  == Screenshots
30
29
 
31
- image::https://alchemists.io/images/projects/cogger/screenshots/demo.png[Rack,width=713,height=1110]
30
+ image::https://alchemists.io/images/projects/cogger/screenshots/demo.png[Rack,width=724,height=1118]
32
31
 
33
32
  == Requirements
34
33
 
@@ -73,7 +72,7 @@ All behavior is provided by creating an instance of `Cogger`. Example:
73
72
  [source,ruby]
74
73
  ----
75
74
  logger = Cogger.new
76
- logger.info "Demo" # "Demo"
75
+ logger.info "Demo" # 🟢 [console] Demo
77
76
  ----
78
77
 
79
78
  If you set your logging level to `debug`, you can walk through each level:
@@ -162,7 +161,7 @@ export LOG_LEVEL=fatal
162
161
  export LOG_LEVEL=unknown
163
162
  ----
164
163
 
165
- While downcase is preferred for the log level, you can use upcased values as well. If the `LOG_LEVEL` environment variable is not set, `Cogger` will fall back to `"info"` unless overwritten during initialization. Example: `Cogger.new level: :debug`. Otherwise, an invalid log level will result in an `ArgumentError`.
164
+ While downcase is preferred for each log level value, you can use upcased values as well. If the `LOG_LEVEL` environment variable is not set, `Cogger` will fall back to `"info"` unless overwritten during initialization. Example: `Cogger.new level: :debug`. Otherwise, an invalid log level will result in an `ArgumentError`.
166
165
 
167
166
  === Mutations
168
167
 
@@ -187,65 +186,147 @@ Please see the {logger_link} documentation for more information.
187
186
 
188
187
  === Templates
189
188
 
190
- Templates are used by all formatters and adhere to the {format_link} as used by `Kernel#format`. All specifiers, flags, width, and precision are supported except for the following restrictions:
189
+ Templates are used by all formatters and adhere to an _enhanced_ version of the {format_link} as used by `Kernel#format`. All specifiers, flags, width, and precision are supported except for the following restrictions:
191
190
 
192
- - Use of _reference by name_ is required which means `%<demo>s` is allowed but `%{demo}` is not. This is because _reference by name_ is required for regular expressions and/or {pattern_matching_link}.
193
- - Use of the `n$` flag is prohibited because it's not compatible with the above.
191
+ * Use of _reference by name_ is required which means `%<demo>s` is allowed but `%{demo}` is not. This is because _reference by name_ is required for regular expressions and/or {pattern_matching_link}.
192
+ * Use of the `n$` flag is prohibited because it's not compatible with the above.
194
193
 
195
- In addition to the above, the {format_link} is further enhanced with the use of _universal_ and _individual_ directives which are primarily used by the _color_ formatter but can prove useful for other formatters. Example:
194
+ In addition to the above, the {format_link} is further enhanced with the use of keys, emojis, and/or elements. Each is explained in detail below.
195
+
196
+ ==== Keys
197
+
198
+ Template keys works exactly as you'd expect when formatting a string using the {format_link} where each key in the template will be replaced with the corresponding attribute that matches the key. Example:
196
199
 
197
200
  [source,ruby]
198
201
  ----
199
- # Universal: Dynamic (color is determined by level).
200
- "<dynamic>%<level>s %<at>s %<id>s %<message>s</dynamic>"
202
+ # Template
203
+ "%<level>s %<at>s %<id>s %<message>s"
204
+
205
+ # Output
206
+ # INFO 2024-08-25 10:44:58 -0600 console demo
207
+ ----
208
+
209
+ Each key can be _enhanced_ further by delimiting the key with a colon and supplying a directive. Directives can be any of the following:
201
210
 
202
- # Universal: Specific (uses the green color only).
203
- "<green>%<level>s %<at>s %<id>s %<message>s</green>"
211
+ * *Dynamic*: Color is automatically calculated based on current log level.
212
+ * *Literal*: Color is specific/static while ignoring current log level.
204
213
 
205
- # Individual: Dynamic (color is determined by level).
214
+ Here's a few examples to illustrate:
215
+
216
+ [source,ruby]
217
+ ----
218
+ # Dynamic
206
219
  "%<level:dynamic>s %<at:dynamic>s %<id:dynamic>s %<message:dynamic>s"
207
220
 
208
- # Individual: Specific (uses a rainbow of colors).
221
+ # Literal
209
222
  "%<level:purple>s %<at:yellow>s %<id:cyan>s %<message:green>s"
210
223
  ----
211
224
 
212
- Here's a detailed breakdown of the above:
225
+ In the dynamic example, the color of each key is determined by current log level (i.e. info, warn, error, etc) which is looked up via the `Cogger.aliases` hash:
226
+
227
+ [source,ruby]
228
+ ----
229
+ Cogger.aliases
230
+ # {
231
+ # debug: %i[white],
232
+ # info: %i[green],
233
+ # warn: %i[yellow],
234
+ # error: %i[red],
235
+ # fatal: %i[bold white on_red],
236
+ # any: %i[dim bright_white]
237
+ # }
238
+ ----
239
+
240
+ In the literal example, the color is exactly what is specified which means the `level` is purple, `at` is yellow, `id` is cyan, and `message` is green. This is means you can mix-n-match dynamic and literal directives as desired:
213
241
 
214
- * *Universal*: Applies color universally to the _entire_ template and requires you to:
215
- ** Wrap your entire template in a and start (`<dynamic>`) and end tag (`</dynamic>`) which works much like an HTML tag in this context.
216
- ** Your tag names must either be `<dynamic></dynamic>`, any default color (example: `<green></green>`), or alias (i.e. `<your_alias></your_alias>`) as supported by the {tone_link} gem.
217
- * *Individual*: Individual templates allow you to apply color to _specific_ attributes and require you to:
218
- ** Format your attributes as `attribute:directive`. The colon delimiter is required to separate your attribute for your color choice.
219
- ** The color value (what follows after the colon) can be `dynamic`, any default color (example: `green`), or alias (i.e. `your_alias`) as supported by the {tone_link} gem.
242
+ [source,ruby]
243
+ ----
244
+ "%<level:dynamic>s %<at:yellow>s %<id:dynamic>s %<message:green>s"
245
+ ----
220
246
 
221
- In addition to the general categorization of universal and individual tags, each support the following directives:
247
+ Assuming the current log level is _info_, then `level` is green; `at` is yellow; `id` is green; and `message` is green.
222
248
 
223
- * *Dynamic*: A dynamic directive means color will be determined by log level only. This means if info level is used, the associated color (alias) for info will be applied. Same goes for warn, error, etc.
224
- * *Specific*: A specific directive means the color you use will be applied without any further processing regardless of log level. This gives you the ability to customize your colors further in situations where dynamic coloring isn't enough.
249
+ ==== Emojis
225
250
 
226
- At this point, you might have gathered that there are specific keys you can use for the log event metadata in your template and everything else is up to you. This stems from the fact that {logger_link} entries always have the following metadata:
251
+ Template emojis work similar to _keys_ but the `emoji` key is _special_ in that you can't use `emoji` as a key in your log messages. In other words the `emoji` key can only be used in templates. That said, emojis can be dynamic or literal. Example:
227
252
 
228
- * `id`: The program/process ID you created your logger with (i.e. `Cogger.new id: :demo`).
229
- * `level`: The level at which you messaged your logger (i.e. `logger.info`).
230
- * `at`: The date/time as which your log event was created.
253
+ [source,ruby]
254
+ ----
255
+ # Dynamic
256
+ "%<emoji:dynamic>s %<message:dynamic>s"
231
257
 
232
- This also means if you pass in these same keys as a log event (example: `logger.info id: :bad, at: Time.now, level: :bogus`) they will be ignored.
258
+ # Literal
259
+ "%<emoji:any>s %<message:dynamic>s"
260
+ ----
233
261
 
234
- The last key (or keys) is customizable to your needs and is known as the log event message. The only special key is the `tags` key which will be explained later. Here a couple of examples to illustrate:
262
+ In the dynamic example, the emoji is determined by current log level (i.e. info, warn, error, etc) which is looked up via the `Cogger.emojis` hash:
235
263
 
236
264
  [source,ruby]
237
265
  ----
238
- # Available as "%<message>s" in your template.
239
- logger.info "demo"
266
+ Cogger.emojis
267
+ # {
268
+ # :debug => "🔎",
269
+ # :info => "🟢",
270
+ # :warn => "⚠️",
271
+ # :error => "🛑",
272
+ # :fatal => "🔥",
273
+ # :any => "⚫️"
274
+ # }
275
+ ----
276
+
277
+ In the literal example, the emoji will be rendered exactly as defined.
240
278
 
241
- # Available as "%<message>s" in your template.
242
- logger.info message: "demo"
279
+ ==== Elements
280
+
281
+ Template elements are slightly different than _keys_ and _emojis_ in that they behave more like HTML elements. This means you can use open and close tags to use dynamic or literal colors. Example:
282
+
283
+ [source,ruby]
284
+ ----
285
+ # Dynamic
286
+ "<dynamic>%<level>s %<at>s %<id>s %<message>s</dynamic>"
243
287
 
244
- # Available as "%<verb>s" and "%<path>s" in your template.
245
- logger.info verb: "GET", path: "/"`
288
+ # Literal
289
+ "<purple>%<level>s %<at>s %<id>s %<message>s</purple>"
246
290
  ----
247
291
 
248
- 💡 In situations where a message hash is logged but the keys of that hash don't match the keys in the template, then an empty message will be logged. This applies to all formatters except the JSON formatter which will log any key/value that doesn't have a `nil` value.
292
+ In the dynamic example, all characters within the template string will use the same color as determined by the current log level. In the literal example, all characters will be purple.
293
+
294
+ Using template elements, in this manner, keeps your templates simple when needing to apply the same color to multiple characters at once.
295
+
296
+ ==== Combinations
297
+
298
+ Now that you know how template keys; emojis; and elements works, this means you can mix and match them in interesting combinations. Example:
299
+
300
+ [source,ruby]
301
+ ----
302
+ "[%<id:purple>s] <dynamic>[%<level>s] [%<at>s]</dynamic> %<message:cyan>s"
303
+ ----
304
+
305
+ The above will render as follows:
306
+
307
+ * The opening and closing brackets will be white (default color).
308
+ * The `id` will be purple.
309
+ * The `level` and `at` will be dynamic in color based on current log level (this includes the bracket characters).
310
+ * The `message` will be cyan.
311
+
312
+ ==== Guidelines
313
+
314
+ Each log entry provides you with default keys you can use for the log event metadata in your templates. This stems from the fact that {logger_link} entries always have the following keys:
315
+
316
+ * `id`: The program/process ID you created your logger with (i.e. `Cogger.new id: :demo`).
317
+ * `level`: The level at which you messaged your logger (i.e. `Cogger#info`).
318
+ * `at`: The date/time as which your log event was created.
319
+
320
+ Additional keys as provided by your message hash and/or tags can be customized as desired but the above is _always_ available to you.
321
+
322
+ Template keys, emojis, and elements do have a few restrictions:
323
+
324
+ * Use the special `emoji` key to provide dynamic or literal emoji logging.
325
+ * Use the special `tags` key to provide tagged logging. More information on tags can be found later in this document.
326
+ * Avoid supplying the same keys as the default keys. Example: `logger.info id: :bad, at: Time.now, level: :bogus`. This is because these keys will be ignored. In other words, you can't _override_ the default keys.
327
+ * Avoid wrapping keys and/or emojis in elements because nesting isn't supported and can lead to strange output. Example: `<green>%<emoji:error>s %<id:dynamic>s</green>`.
328
+ * Avoid wrapping elements within elements because nesting isn't supported and can lead to strange output. Example: `<dynamic><cyan>%<message>s</cyan></dynamic>`.
329
+ * Avoid situations where a message hash doesn't match the keys in the template because an empty message will be logged instead. This applies to all formatters except the JSON formatter which will log any key/value that doesn't have a `nil` value.
249
330
 
250
331
  === Emojis
251
332
 
@@ -359,7 +440,7 @@ Cogger.formatters
359
440
  # }
360
441
  ----
361
442
 
362
- You can add a formatter by providing a key, class, and _optional_ template. If a template isn't supplied, then the formatter's default template will be used instead (more on that shortly). Example:
443
+ You can add a formatter by providing a key, class, and _optional_ template. If a template isn't supplied, then the formatter's default template will be used instead (more on this shortly). Example:
363
444
 
364
445
  [source,ruby]
365
446
  ----
@@ -380,10 +461,17 @@ Symbols or strings can be used interchangeably when adding/getting formatters. A
380
461
 
381
462
  [source,ruby]
382
463
  ----
383
- Cogger::Formatters::Color::TEMPLATE # "%<message:dynamic>s"
384
- Cogger::Formatters::Emoji::TEMPLATE # "%<emoji:dynamic>s %<message:dynamic>s"
385
- Cogger::Formatters::JSON::TEMPLATE # nil
386
- Cogger::Formatters::Simple::TEMPLATE # "%<message>s"
464
+ Cogger::Formatters::Color::TEMPLATE
465
+ # "<dynamic>[%<id>s]</dynamic> %<message:dynamic>s"
466
+
467
+ Cogger::Formatters::Emoji::TEMPLATE
468
+ # "%<emoji:dynamic>s <dynamic>[%<id>s]</dynamic> %<message:dynamic>s"
469
+
470
+ Cogger::Formatters::JSON::TEMPLATE
471
+ # nil
472
+
473
+ Cogger::Formatters::Simple::TEMPLATE
474
+ # "[%<id>s] %<message>s"
387
475
  ----
388
476
 
389
477
  💡 When you find yourself customizing any of the default formatters, you can reduce typing by adding your custom configuration to the registry and then referring to it via it's associated key when initializing a new logger.
@@ -409,7 +497,7 @@ logger = Cogger.new formatter: :rack
409
497
 
410
498
  ==== Color
411
499
 
412
- The color formatter allows you to have color coded logs and can be configured as follows:
500
+ The color formatter allows you to have color coded logs and can be used as follows:
413
501
 
414
502
  [source,ruby]
415
503
  ----
@@ -457,7 +545,7 @@ The emoji formatter is enabled by default and is the equivalent of initializing
457
545
  ----
458
546
  logger = Cogger.new
459
547
  logger = Cogger.new formatter: :emoji
460
- logger = Cogger.new formatter: Cogger::Formatters::Emoji.new("%<emoji:dynamic>s %<message:dynamic>s")
548
+ logger = Cogger.new formatter: Cogger::Formatters::Emoji.new
461
549
  ----
462
550
 
463
551
  All of the above examples are identical so you can see how different formatters can be used and customized further. The default emojis are registered as follows:
@@ -586,7 +674,7 @@ logger.info "Demo"
586
674
  # I, [2023-10-15T14:32:55.061777 #72801] INFO -- console: #<data Cogger::Entry id="console", level=:info, at=2023-10-15 14:32:55.061734 -0600, message="Demo", tags=[], payload={}>
587
675
  ----
588
676
 
589
- While the above doesn't cause an error, you only get a dump of the `Cogger::Entry` which is not what you want. To replicate native {logger_link} functionality, you can do use the simple formatter as follows to produce the rough equivalent:
677
+ While the above doesn't cause an error, you only get a dump of the `Cogger::Entry` which is not what you want. To replicate native {logger_link} functionality, you can use the `Simple` formatter as follows:
590
678
 
591
679
  [source,ruby]
592
680
  ----
@@ -599,6 +687,8 @@ logger.info "Demo"
599
687
  # INFO, [2023-10-15 15:07:13 -0600] INFO -- console: Demo
600
688
  ----
601
689
 
690
+ The above is the rough equivalent of what {logger_link} provides for you by default.
691
+
602
692
  ==== Custom
603
693
 
604
694
  Should none of the built-in formatters be to your liking, you can implement, use, and/or register a custom formatter as well. The most minimum, bare bones, skeleton would be:
@@ -1042,6 +1132,8 @@ bin/rake
1042
1132
 
1043
1133
  == link:https://alchemists.io/policies/contributions[Contributions]
1044
1134
 
1135
+ == link:https://alchemists.io/policies/developer_certificate_of_origin[Developer Certificate of Origin]
1136
+
1045
1137
  == link:https://alchemists.io/projects/cogger/versions[Versions]
1046
1138
 
1047
1139
  == link:https://alchemists.io/community[Community]
data/cogger.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "cogger"
5
- spec.version = "0.23.0"
5
+ spec.version = "0.24.1"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/cogger"
@@ -4,7 +4,7 @@ module Cogger
4
4
  module Formatters
5
5
  # Formats by color.
6
6
  class Color
7
- TEMPLATE = "[%<id:dynamic>s] %<message:dynamic>s"
7
+ TEMPLATE = "<dynamic>[%<id>s]</dynamic> %<message:dynamic>s"
8
8
 
9
9
  def initialize template = TEMPLATE, processor: Processors::Color.new
10
10
  @template = template
@@ -4,7 +4,7 @@ module Cogger
4
4
  module Formatters
5
5
  # Formats by emoji and color.
6
6
  class Emoji < Color
7
- TEMPLATE = "%<emoji:dynamic>s [%<id:dynamic>s] %<message:dynamic>s"
7
+ TEMPLATE = "%<emoji:dynamic>s <dynamic>[%<id>s]</dynamic> %<message:dynamic>s"
8
8
 
9
9
  def initialize(template = TEMPLATE, ...)
10
10
  super
@@ -10,9 +10,9 @@ module Cogger
10
10
  TEMPLATE = nil
11
11
 
12
12
  def initialize template = TEMPLATE,
13
- parser: Parsers::Individual.new,
13
+ parser: Parsers::KeyExtractor.new,
14
14
  sanitizer: Kit::Sanitizer
15
- @positions = template ? parser.call(template).last.keys : Core::EMPTY_ARRAY
15
+ @positions = template ? parser.call(template) : Core::EMPTY_ARRAY
16
16
  @sanitizer = sanitizer
17
17
  end
18
18
 
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cogger
4
+ module Formatters
5
+ module Parsers
6
+ # An abstrct class with default functionality.
7
+ class Abstract
8
+ def initialize registry: Cogger, colorizer: Kit::Colorizer, expressor: Regexp
9
+ @registry = registry
10
+ @colorizer = colorizer
11
+ @expressor = expressor
12
+ end
13
+
14
+ def call(_template, **)
15
+ fail NoMethodError,
16
+ "`#{self.class}##{__method__} #{method(__method__).parameters}` must be implemented."
17
+ end
18
+
19
+ protected
20
+
21
+ attr_reader :registry, :colorizer, :expressor
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cogger
4
+ module Formatters
5
+ module Parsers
6
+ # Parses template literals, emojis, and keys for specific and dynamic colors.
7
+ class Combined
8
+ STEPS = [Element.new, Emoji.new, Specific.new].freeze
9
+
10
+ def initialize steps: STEPS
11
+ @steps = steps
12
+ end
13
+
14
+ def call(template, **attributes)
15
+ steps.reduce(template.dup) { |modification, step| step.call modification, **attributes }
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :steps
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cogger
4
+ module Formatters
5
+ module Parsers
6
+ # Parses template elements for specific and dynamic colors.
7
+ class Element < Abstract
8
+ PATTERN = %r(
9
+ < # Tag open start.
10
+ (?<name>\w+) # Tag open name.
11
+ > # Tag open end.
12
+ (?<content>.+?) # Content.
13
+ </ # Tag close start.
14
+ \w+ # Tag close.
15
+ > # Tag close end.
16
+ )mx
17
+
18
+ def initialize pattern: PATTERN
19
+ super()
20
+ @pattern = pattern
21
+ end
22
+
23
+ def call(template, **)
24
+ template.gsub! pattern do
25
+ captures = expressor.last_match.named_captures
26
+ color = colorizer.call(captures["name"], **)
27
+ registry.color[captures["content"], color]
28
+ end
29
+
30
+ template
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :pattern
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cogger
4
+ module Formatters
5
+ module Parsers
6
+ # Parses template emojis for specific and dynamic colors.
7
+ class Emoji < Abstract
8
+ PATTERN = /
9
+ %< # Start.
10
+ emoji # Name.
11
+ : # Delimiter.
12
+ (?<color>\w+) # Color.
13
+ >s # End.
14
+ /x
15
+
16
+ def initialize pattern: PATTERN
17
+ super()
18
+ @pattern = pattern
19
+ end
20
+
21
+ def call(template, **)
22
+ template.gsub! pattern do
23
+ captures = expressor.last_match.named_captures
24
+ color = colorizer.call(captures["color"], **)
25
+
26
+ registry.get_emoji color
27
+ end
28
+
29
+ template
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :pattern
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cogger
4
+ module Formatters
5
+ module Parsers
6
+ # Parses template and extracts keys.
7
+ class KeyExtractor
8
+ PATTERN = /
9
+ % # Start.
10
+ ? # Flag, width, or precision.
11
+ < # Reference start.
12
+ (?<name>\w+) # Name.
13
+ (?::[\w]+)? # Optional delimiter and or color.
14
+ > # Reference end.
15
+ ? # Specifier.
16
+ /x
17
+
18
+ def initialize pattern: PATTERN
19
+ @pattern = pattern
20
+ end
21
+
22
+ def call(template) = template.scan(pattern).map { |match| match.first.to_sym }
23
+
24
+ private
25
+
26
+ attr_reader :pattern
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "core"
4
+
5
+ module Cogger
6
+ module Formatters
7
+ module Parsers
8
+ # Parses template for specific and dynamic string format specifiers.
9
+ class Specific < Abstract
10
+ PATTERN = /
11
+ % # Start.
12
+ (?<flag>[\s#+-0*])? # Optional flag.
13
+ (?<width>\d+)? # Optional width.
14
+ \.? # Optional precision delimiter.
15
+ (?<precision>\d+)? # Optional precision value.
16
+ < # Reference start.
17
+ (?<name>\w+) # Name.
18
+ : # Delimiter.
19
+ (?<color>\w+) # Color.
20
+ > # Reference end.
21
+ (?<specifier>[ABEGXabcdefgiopsux]) # Specifier.
22
+ /x
23
+
24
+ def initialize pattern: PATTERN
25
+ super()
26
+ @pattern = pattern
27
+ end
28
+
29
+ # :reek:TooManyStatements
30
+ def call(template, **)
31
+ template.gsub! pattern do |match|
32
+ captures = expressor.last_match.named_captures
33
+ original_color = captures["color"]
34
+ color = colorizer.call(original_color, **)
35
+
36
+ match.sub! ":#{original_color}", Core::EMPTY_STRING
37
+ registry.color[match, color]
38
+ end
39
+
40
+ template
41
+ end
42
+
43
+ private
44
+
45
+ attr_reader :pattern
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,58 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "tone"
4
-
5
3
  module Cogger
6
4
  module Formatters
7
5
  module Processors
8
- # Processes emojis and colors.
6
+ # Processes template with entry input using all template parsers.
9
7
  class Color
10
- def initialize parser: Parsers::Dynamic.new,
11
- kit: {sanitizer: Kit::Sanitizer, colorizer: Kit::Colorizer},
12
- registry: Cogger
8
+ def initialize parser: Parsers::Combined.new, sanitizer: Kit::Sanitizer
13
9
  @parser = parser
14
- @kit = kit
15
- @registry = registry
10
+ @sanitizer = sanitizer
16
11
  end
17
12
 
18
13
  def call(template, *input)
19
14
  attributes = sanitizer.call(*input).tagged
20
-
21
- case parser.call template
22
- in [String => body, String => style] then universal body, style, **attributes
23
- in [String => body, Hash => styles] then individual body, attributes, styles
24
- # :nocov:
25
- end
15
+ [parser.call(template, **attributes), attributes]
26
16
  end
27
17
 
28
18
  private
29
19
 
30
- attr_reader :parser, :kit, :registry
31
-
32
- def universal body, style, **attributes
33
- [registry.color[body, colorizer.call(style, attributes)], attributes]
34
- end
35
-
36
- def individual body, attributes, styles
37
- attributes = attributes.each.with_object({}) do |(key, value), collection|
38
- collection[key] = registry.color[value, colorizer.call(styles[key], attributes)]
39
- end
40
-
41
- emojify attributes, styles
42
- [body, attributes]
43
- end
44
-
45
- def emojify attributes, styles
46
- style = styles[:emoji]
47
-
48
- return unless style
49
-
50
- attributes[:emoji] = registry.get_emoji colorizer.call(style, attributes)
51
- end
52
-
53
- def sanitizer = kit.fetch :sanitizer
54
-
55
- def colorizer = kit.fetch :colorizer
20
+ attr_reader :parser, :sanitizer
56
21
  end
57
22
  end
58
23
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cogger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.0
4
+ version: 0.24.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -35,7 +35,7 @@ cert_chain:
35
35
  3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
36
36
  gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
37
37
  -----END CERTIFICATE-----
38
- date: 2024-08-16 00:00:00.000000000 Z
38
+ date: 2024-08-25 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: core
@@ -114,9 +114,12 @@ files:
114
114
  - lib/cogger/formatters/json.rb
115
115
  - lib/cogger/formatters/kit/colorizer.rb
116
116
  - lib/cogger/formatters/kit/sanitizer.rb
117
- - lib/cogger/formatters/parsers/dynamic.rb
118
- - lib/cogger/formatters/parsers/individual.rb
119
- - lib/cogger/formatters/parsers/universal.rb
117
+ - lib/cogger/formatters/parsers/abstract.rb
118
+ - lib/cogger/formatters/parsers/combined.rb
119
+ - lib/cogger/formatters/parsers/element.rb
120
+ - lib/cogger/formatters/parsers/emoji.rb
121
+ - lib/cogger/formatters/parsers/key_extractor.rb
122
+ - lib/cogger/formatters/parsers/specific.rb
120
123
  - lib/cogger/formatters/processors/color.rb
121
124
  - lib/cogger/formatters/simple.rb
122
125
  - lib/cogger/hub.rb
metadata.gz.sig CHANGED
Binary file
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Cogger
4
- module Formatters
5
- module Parsers
6
- # Dynamically extracts the universal or individual template attributes for log entry parsing.
7
- class Dynamic
8
- # Order matters.
9
- DELEGATES = [Universal.new, Individual.new].freeze
10
-
11
- def initialize delegates: DELEGATES
12
- @delegates = delegates
13
- end
14
-
15
- def call(template) = parse(template) || template
16
-
17
- private
18
-
19
- attr_reader :delegates
20
-
21
- def parse template
22
- delegates.find do |delegate|
23
- result = delegate.call template
24
- break result unless result == template
25
- end
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Cogger
4
- module Formatters
5
- module Parsers
6
- # Sanitizes and extracts individual directives from a template.
7
- class Individual
8
- # rubocop:todo Lint/MixedRegexpCaptureTypes
9
- PATTERN = /
10
- % # Strict reference syntax.
11
- (?<flag>[\s#+-0*])? # Optional flag.
12
- (?<width>\d+)? # Optional width.
13
- \.? # Optional precision delimiter.
14
- (?<precision>\d+)? # Optional precision value.
15
- < # Reference start.
16
- ( # Conditional start.
17
- (?<key>\w+) # Key.
18
- : # Directive delimiter.
19
- (?<directive>\w+) # Value.
20
- | # Conditional.
21
- (?<key>\w+) # Key.
22
- ) # Conditional end.
23
- > # Reference end.
24
- (?<specifier>[ABEGXabcdefgiopsux]) # Specifier.
25
- /mx
26
- # rubocop:enable Lint/MixedRegexpCaptureTypes
27
-
28
- def initialize pattern: PATTERN
29
- @pattern = pattern
30
- end
31
-
32
- def call template
33
- attributes = {}
34
-
35
- return [template, attributes] unless template.match? pattern
36
-
37
- template = sanitize_and_extract template, attributes
38
- [template, attributes]
39
- end
40
-
41
- private
42
-
43
- attr_reader :pattern
44
-
45
- # :reek:FeatureEnvy
46
- # :reek:TooManyStatements
47
- def sanitize_and_extract template, attributes
48
- template.gsub pattern do
49
- captures = Regexp.last_match.named_captures symbolize_names: true
50
- attributes[captures[:key].to_sym] = captures[:directive]
51
-
52
- captures.reduce(+"%") do |body, (key, value)|
53
- next body if key == :directive
54
-
55
- body.concat key == :key ? "<#{value}>" : value.to_s
56
- end
57
- end
58
- end
59
- end
60
- end
61
- end
62
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "core"
4
-
5
- module Cogger
6
- module Formatters
7
- module Parsers
8
- # Sanitizes and extracts the universal directive a template.
9
- class Universal
10
- # rubocop:todo Lint/MixedRegexpCaptureTypes
11
- PATTERN = %r(
12
- ( # Conditional start.
13
- \A # Search start.
14
- < # Tag start.
15
- (?<directive>\w+) # Directive.
16
- > # Tag end.
17
- | # Conditional pipe.
18
- < # Tag start.
19
- / # Tag close.
20
- (?<directive>\w+) # Directive.
21
- > # Tag end.
22
- \Z # Search end.
23
- ) # Conditional end.
24
- )mx
25
- # rubocop:enable Lint/MixedRegexpCaptureTypes
26
-
27
- KEY = "directive"
28
-
29
- def initialize pattern: PATTERN, key: KEY
30
- @pattern = pattern
31
- @key = key
32
- end
33
-
34
- def call template
35
- return template unless template.match? pattern
36
-
37
- [template.gsub(pattern, Core::EMPTY_STRING), template.match(pattern)[key]]
38
- end
39
-
40
- private
41
-
42
- attr_reader :pattern, :key
43
- end
44
- end
45
- end
46
- end