sai 0.3.1 → 0.3.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c45105e60b5f7a3a93d837080975996e96a340aef0ad3fd86cd4b5a1be17e8f
4
- data.tar.gz: baf93c18ef40221c86c329deeeaabbe7a3619744d3a80a9349314624a4af3995
3
+ metadata.gz: '091a65a91b7e31cfea072bfad910f4af966edf3370301aa1bfbad8e6292d8e25'
4
+ data.tar.gz: 2296a5bb8b8b8d4c713b91afdbd777d7e69b16dd3550683d8a799dc6ac9c434d
5
5
  SHA512:
6
- metadata.gz: c1540fe3fd55f0a338ff04ff6f9794e831b831c040637f4cdd4f0de0ab0a689a55f95d5c1a744f3ae25b0bc7452983044568e83b6e665439672142cd2abd811b
7
- data.tar.gz: 4244b0401b7fd0af26665a0a5b5622dd09bd364e4166bc8d12a6c69f94a52b09511d56afe2cd8eaedf1401c402b3ba63845aa900c147e408312221dcc243e21d
6
+ metadata.gz: 548ca06d57fe14768900f6d04191b52d876c38a9c5cca96b26da9d2c8afc3b7dffdd44b9d075b92bda97d1d80e2b6b75d3d8782c3e592d1a4547dfc72dceba1f
7
+ data.tar.gz: 48d9f58551111cd95a61c7c11ba2e83506239bf7e4805c93a3c38c653f28dfb94680637f35cf4a0325702ad4fe320f32060d794b26be2c308dd0b216f9cfbf64
data/CHANGELOG.md CHANGED
@@ -6,6 +6,13 @@ The format is based on [Keep a Changelog], and this project adheres to [Break Ve
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.3.2] - 2025-01-22
10
+
11
+ ### Added
12
+
13
+ * [#15](https://github.com/aaronmallen/sai/pull/15) - Add support for registering custom named colors by
14
+ [@aaronmallen](https://github.com/aaronmallen)
15
+
9
16
  ## [0.3.1] - 2025-01-22
10
17
 
11
18
  ### Added
@@ -64,7 +71,8 @@ The format is based on [Keep a Changelog], and this project adheres to [Break Ve
64
71
 
65
72
  <!-- versions -->
66
73
 
67
- [Unreleased]: https://github.com/aaronmallen/sai/compare/0.3.1..HEAD
74
+ [Unreleased]: https://github.com/aaronmallen/sai/compare/0.3.2..HEAD
75
+ [0.3.2]: https://github.com/aaronmallen/sai/compare/0.3.1..0.3.2
68
76
  [0.3.1]: https://github.com/aaronmallen/sai/compare/0.3.0..0.3.1
69
77
  [0.3.0]: https://github.com/aaronmallen/sai/compare/0.2.0..0.3.0
70
78
  [0.2.0]: https://github.com/aaronmallen/sai/compare/0.1.0..0.2.0
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Sai Codacy grade](https://img.shields.io/codacy/grade/0f9a91b573ed4768a773867b95ed4894/main?style=for-the-badge&logo=codacy&logoColor=white&logoSize=auto)](https://app.codacy.com/gh/aaronmallen/sai)
5
5
  [![Sai Codacy coverage](https://img.shields.io/codacy/coverage/0f9a91b573ed4768a773867b95ed4894/main?style=for-the-badge&logo=codacy&logoColor=white&logoSize=auto)](https://app.codacy.com/gh/aaronmallen/sai/coverage)
6
6
  [![Sai License](https://img.shields.io/github/license/aaronmallen/sai?style=for-the-badge&logo=opensourceinitiative&logoColor=white&logoSize=auto)](./LICENSE)
7
- [![Sai Docs](https://img.shields.io/badge/rubydoc-blue?style=for-the-badge&logo=readthedocs&logoColor=white&logoSize=auto&label=docs)](https://rubydoc.info/gems/sai/0.3.1)
7
+ [![Sai Docs](https://img.shields.io/badge/rubydoc-blue?style=for-the-badge&logo=readthedocs&logoColor=white&logoSize=auto&label=docs)](https://rubydoc.info/gems/sai/0.3.2)
8
8
  [![Sai Open Issues](https://img.shields.io/github/issues-search/aaronmallen/sai?query=state%3Aopen&style=for-the-badge&logo=github&logoColor=white&logoSize=auto&label=issues&color=red)](https://github.com/aaronmallen/sai/issues?q=state%3Aopen%20)
9
9
 
10
10
  An elegant color management system for crafting sophisticated CLI applications
@@ -88,7 +88,7 @@ puts text.stripped # Get plain text
88
88
  ## Documentation
89
89
 
90
90
  * [Complete Usage Guide](docs/USAGE.md) - Comprehensive documentation of all features
91
- * [API Documentation](https://rubydoc.info/gems/sai/0.3.1) - Detailed API reference
91
+ * [API Documentation](https://rubydoc.info/gems/sai/0.3.2) - Detailed API reference
92
92
 
93
93
  ## Contributing
94
94
 
data/docs/USAGE.md CHANGED
@@ -107,6 +107,20 @@ For a complete list of available colors, see:
107
107
  * [Online Color Reference](https://github.com/aaronmallen/sai/blob/main/docs/AVAILABLE_NAMED_COLORS.md)
108
108
  * `Sai::NamedColors.names` in your code
109
109
 
110
+ #### Registering Custom Named Colors
111
+
112
+ Sai allows you to register custom named colors for easy reuse with `Sai.register`:
113
+
114
+ ```ruby
115
+ # Register custom colors
116
+ Sai.register(:my_color, '#CF4C5F')
117
+
118
+ # or alternatively
119
+ Sai.register(:my_color, [207, 76, 95])
120
+
121
+ Sai.my_color.decorate('Hello, world!')
122
+ ```
123
+
110
124
  ### Color Manipulation
111
125
 
112
126
  Adjust the brightness of colors:
@@ -52,6 +52,7 @@ module Sai
52
52
  methods = collect_delegatable_methods.reject { |m| ignored_methods.include?(m) }
53
53
 
54
54
  methods.each do |method|
55
+ klass.undef_method(method) if klass.method_defined?(method)
55
56
  klass.define_method(method) do |*args, **kwargs|
56
57
  Decorator.new(mode: Sai.mode.auto).public_send(method, *args, **kwargs)
57
58
  end
@@ -749,15 +749,27 @@ module Sai
749
749
  # def yellow_green: () -> Decorator
750
750
  # def yellow_system: () -> Decorator
751
751
 
752
- Sai::NamedColors.names.each do |color|
753
- define_method(color) do
754
- apply_named_color(:foreground, color)
755
- end
756
- define_method(:"on_#{color}") do
757
- apply_named_color(:background, color)
752
+ # Install a color method on the {Decorator} class
753
+ #
754
+ # @author {https://aaronmallen.me Aaron Allen}
755
+ # @since 0.3.2
756
+ #
757
+ # @api private
758
+ #
759
+ # @param color_name [Symbol] the name of the color to install
760
+ #
761
+ # @return [void]
762
+ # @rbs (Symbol color_name) -> void
763
+ def self.install(color_name)
764
+ { color_name => :foreground, :"on_#{color_name}" => :background }.each do |method_name, style_type|
765
+ # @type var style_type: Sai::Conversion::ColorSequence::style_type
766
+ Sai::Decorator.undef_method(method_name) if Sai::Decorator.method_defined?(method_name)
767
+ Sai::Decorator.define_method(method_name) { apply_named_color(style_type, color_name) }
758
768
  end
759
769
  end
760
770
 
771
+ Sai::NamedColors.names.each { |color| Sai::Decorator::NamedColors.install(color) }
772
+
761
773
  private
762
774
 
763
775
  # Apply a named color to the specified style type
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'sai/conversion/rgb'
4
+
3
5
  module Sai
4
6
  # A collection of named colors and their RGB values
5
7
  #
@@ -406,32 +408,115 @@ module Sai
406
408
  }.freeze #: Hash[Symbol, Array[Integer]]
407
409
  # rubocop:enable Naming/VariableNumber
408
410
 
409
- # Look up an RGB value by color name
410
- #
411
- # @author {https://aaronmallen.me Aaron Allen}
412
- # @since 0.3.1
413
- #
414
- # @api private
415
- #
416
- # @param name [String, Symbol] the color name
417
- #
418
- # @return [Array<Integer>] the RGB value
419
- # @rbs (String | Symbol name) -> Array[Integer]?
420
- def self.[](name)
421
- key = name.to_sym
422
- ANSI.fetch(key, XTERM.fetch(key, CSS.fetch(key, nil)))
423
- end
411
+ class << self
412
+ # Look up an RGB value by color name
413
+ #
414
+ # @author {https://aaronmallen.me Aaron Allen}
415
+ # @since 0.3.1
416
+ #
417
+ # @api private
418
+ #
419
+ # @param name [String, Symbol] the color name
420
+ #
421
+ # @return [Array<Integer>] the RGB value
422
+ # @rbs (String | Symbol name) -> Array[Integer]?
423
+ def [](name)
424
+ registry[name.to_sym]
425
+ end
424
426
 
425
- # Get a list of all color names
426
- #
427
- # @author {https://aaronmallen.me Aaron Allen}
428
- # @since 0.3.1
429
- #
430
- # @api private
431
- #
432
- # @return [Array<Symbol>] the color names
433
- def self.names
434
- (ANSI.keys + CSS.keys + XTERM.keys).uniq.sort
427
+ # Get a list of all color names
428
+ #
429
+ # @author {https://aaronmallen.me Aaron Allen}
430
+ # @since 0.3.1
431
+ #
432
+ # @api private
433
+ #
434
+ # @return [Array<Symbol>] the color names
435
+ def names
436
+ @names ||= registry.keys.uniq.sort
437
+ end
438
+
439
+ # Register a named color with an RGB or Hexadecimal value
440
+ #
441
+ # @author {https://aaronmallen.me Aaron Allen}
442
+ # @since 0.3.2
443
+ #
444
+ # @api private
445
+ #
446
+ # @param name [String, Symbol] the name of the color being registered
447
+ # @param rgb_or_hex [Array<Integer>, String] the RGB or Hexadecimal value of the color
448
+ #
449
+ # @return [Boolean] `true` if the color was registered
450
+ # @rbs (String | Symbol name, Array[Integer] | String rgb_or_hex) -> void
451
+ def register(name, rgb_or_hex)
452
+ key = name.to_s.downcase.to_sym
453
+ provision_color(key, rgb_or_hex)
454
+ install_color(key)
455
+ true
456
+ end
457
+
458
+ private
459
+
460
+ # Install the color methods onto {Sai} and {Sai::Decorator}
461
+ #
462
+ # @author {https://aaronmallen.me Aaron Allen}
463
+ # @since 0.3.2
464
+ #
465
+ # @api private
466
+ #
467
+ # @param name [Symbol] the name of the color to install
468
+ #
469
+ # @return [void]
470
+ # @rbs (Symbol name) -> void
471
+ def install_color(name)
472
+ Sai::Decorator::NamedColors.install(name)
473
+ Sai::Decorator::Delegation.install(Sai)
474
+ end
475
+
476
+ # Provision a color for the registry
477
+ #
478
+ # @author {https://aaronmallen.me Aaron Allen}
479
+ # @since 0.3.2
480
+ #
481
+ # @api private
482
+ #
483
+ # @param name [Symbol] the name of the color to register
484
+ # @param rgb_or_hex [Array<Integer>, String] the RGB or Hexadecimal value of the color
485
+ #
486
+ # @return [void]
487
+ # @rbs (Symbol name, Array[Integer] | String rgb_or_hex) -> void
488
+ def provision_color(name, rgb_or_hex)
489
+ rgb = Conversion::RGB.resolve(rgb_or_hex)
490
+ registry[name] = rgb
491
+ @names = nil
492
+ end
493
+
494
+ # The Sai named colors registry
495
+ #
496
+ # @author {https://aaronmallen.me Aaron Allen}
497
+ # @since 0.3.2
498
+ #
499
+ # @api private
500
+ #
501
+ # @return [Hash{Symbol => Array<Integer>}] the named colors registry
502
+ def registry
503
+ thread_lock.synchronize do
504
+ @registry ||= CSS.merge(XTERM).merge(ANSI)
505
+ end
506
+ end
507
+
508
+ # A Mutex for thread safety
509
+ #
510
+ # @author {https://aaronmallen.me Aaron Allen}
511
+ # @since 0.3.2
512
+ #
513
+ # @api private
514
+ #
515
+ # @return [Mutex] the thread lock
516
+ # @rbs () -> Mutex
517
+ def thread_lock
518
+ @thread_lock ||= Mutex.new
519
+ end
435
520
  end
436
521
  end
437
522
  end
data/lib/sai.rb CHANGED
@@ -833,6 +833,28 @@ module Sai
833
833
  ModeSelector
834
834
  end
835
835
 
836
+ # Register a custom name and color
837
+ #
838
+ # @author {https://aaronmallen.me Aaron Allen}
839
+ # @since 0.3.2
840
+ #
841
+ # @api public
842
+ #
843
+ # @example Register a color
844
+ # Sai.register(:my_color, '#CF4C5F')
845
+ # Sai.register(:my_color, [207, 76, 95])
846
+ #
847
+ # Sai.my_color.decorate('Hello, world!').to_s #=> "\e[38;2;207;76;95mHello, world!\e[0m"
848
+ #
849
+ # @param name [String, Symbol] the name of the color to register
850
+ # @param rgb_or_hex [Array<Integer>, String] the RGB values or hex code to register
851
+ #
852
+ # @return [void]
853
+ # @rbs (String | Symbol name, Array[Integer] | String rgb_or_hex) -> void
854
+ def register(name, rgb_or_hex)
855
+ NamedColors.register(name, rgb_or_hex)
856
+ end
857
+
836
858
  # Sequence a string with ANSI escape codes
837
859
  #
838
860
  # @author {https://aaronmallen.me Aaron Allen}
@@ -1471,6 +1471,19 @@ module Sai
1471
1471
 
1472
1472
  def yellow_system: () -> Decorator
1473
1473
 
1474
+ # Install a color method on the {Decorator} class
1475
+ #
1476
+ # @author {https://aaronmallen.me Aaron Allen}
1477
+ # @since 0.3.2
1478
+ #
1479
+ # @api private
1480
+ #
1481
+ # @param color_name [Symbol] the name of the color to install
1482
+ #
1483
+ # @return [void]
1484
+ # @rbs (Symbol color_name) -> void
1485
+ def self.install: (Symbol color_name) -> void
1486
+
1474
1487
  private
1475
1488
 
1476
1489
  # Apply a named color to the specified style type
@@ -61,5 +61,67 @@ module Sai
61
61
  #
62
62
  # @return [Array<Symbol>] the color names
63
63
  def self.names: () -> untyped
64
+
65
+ # Register a named color with an RGB or Hexadecimal value
66
+ #
67
+ # @author {https://aaronmallen.me Aaron Allen}
68
+ # @since 0.3.2
69
+ #
70
+ # @api private
71
+ #
72
+ # @param name [String, Symbol] the name of the color being registered
73
+ # @param rgb_or_hex [Array<Integer>, String] the RGB or Hexadecimal value of the color
74
+ #
75
+ # @return [Boolean] `true` if the color was registered
76
+ # @rbs (String | Symbol name, Array[Integer] | String rgb_or_hex) -> void
77
+ def self.register: (String | Symbol name, Array[Integer] | String rgb_or_hex) -> void
78
+
79
+ # Install the color methods onto {Sai} and {Sai::Decorator}
80
+ #
81
+ # @author {https://aaronmallen.me Aaron Allen}
82
+ # @since 0.3.2
83
+ #
84
+ # @api private
85
+ #
86
+ # @param name [Symbol] the name of the color to install
87
+ #
88
+ # @return [void]
89
+ # @rbs (Symbol name) -> void
90
+ private def self.install_color: (Symbol name) -> void
91
+
92
+ # Provision a color for the registry
93
+ #
94
+ # @author {https://aaronmallen.me Aaron Allen}
95
+ # @since 0.3.2
96
+ #
97
+ # @api private
98
+ #
99
+ # @param name [Symbol] the name of the color to register
100
+ # @param rgb_or_hex [Array<Integer>, String] the RGB or Hexadecimal value of the color
101
+ #
102
+ # @return [void]
103
+ # @rbs (Symbol name, Array[Integer] | String rgb_or_hex) -> void
104
+ private def self.provision_color: (Symbol name, Array[Integer] | String rgb_or_hex) -> void
105
+
106
+ # The Sai named colors registry
107
+ #
108
+ # @author {https://aaronmallen.me Aaron Allen}
109
+ # @since 0.3.2
110
+ #
111
+ # @api private
112
+ #
113
+ # @return [Hash{Symbol => Array<Integer>}] the named colors registry
114
+ private def self.registry: () -> untyped
115
+
116
+ # A Mutex for thread safety
117
+ #
118
+ # @author {https://aaronmallen.me Aaron Allen}
119
+ # @since 0.3.2
120
+ #
121
+ # @api private
122
+ #
123
+ # @return [Mutex] the thread lock
124
+ # @rbs () -> Mutex
125
+ private def self.thread_lock: () -> Mutex
64
126
  end
65
127
  end
data/sig/sai.rbs CHANGED
@@ -1574,6 +1574,26 @@ module Sai
1574
1574
  # @rbs () -> singleton(ModeSelector)
1575
1575
  def self.mode: () -> singleton(ModeSelector)
1576
1576
 
1577
+ # Register a custom name and color
1578
+ #
1579
+ # @author {https://aaronmallen.me Aaron Allen}
1580
+ # @since 0.3.2
1581
+ #
1582
+ # @api public
1583
+ #
1584
+ # @example Register a color
1585
+ # Sai.register(:my_color, '#CF4C5F')
1586
+ # Sai.register(:my_color, [207, 76, 95])
1587
+ #
1588
+ # Sai.my_color.decorate('Hello, world!').to_s #=> "\e[38;2;207;76;95mHello, world!\e[0m"
1589
+ #
1590
+ # @param name [String, Symbol] the name of the color to register
1591
+ # @param rgb_or_hex [Array<Integer>, String] the RGB values or hex code to register
1592
+ #
1593
+ # @return [void]
1594
+ # @rbs (String | Symbol name, Array[Integer] | String rgb_or_hex) -> void
1595
+ def self.register: (String | Symbol name, Array[Integer] | String rgb_or_hex) -> void
1596
+
1577
1597
  # Sequence a string with ANSI escape codes
1578
1598
  #
1579
1599
  # @author {https://aaronmallen.me Aaron Allen}
metadata CHANGED
@@ -1,10 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Allen
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
11
  date: 2025-01-22 00:00:00.000000000 Z
@@ -79,10 +80,11 @@ licenses:
79
80
  - MIT
80
81
  metadata:
81
82
  bug_tracker_uri: https://github.com/aaronmallen/sai/issues
82
- changelog_uri: https://github.com/aaronmallen/sai/releases/tag/0.3.1
83
+ changelog_uri: https://github.com/aaronmallen/sai/releases/tag/0.3.2
83
84
  homepage_uri: https://github.com/aaronmallen/sai
84
85
  rubygems_mfa_required: 'true'
85
- source_code_uri: https://github.com/aaronmallen/sai/tree/0.3.1
86
+ source_code_uri: https://github.com/aaronmallen/sai/tree/0.3.2
87
+ post_install_message:
86
88
  rdoc_options: []
87
89
  require_paths:
88
90
  - lib
@@ -97,7 +99,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
99
  - !ruby/object:Gem::Version
98
100
  version: '0'
99
101
  requirements: []
100
- rubygems_version: 3.6.2
102
+ rubygems_version: 3.3.27
103
+ signing_key:
101
104
  specification_version: 4
102
105
  summary: An elegant color management system for crafting sophisticated CLI applications
103
106
  test_files: []