pax_global_header00006660000000000000000000000064136240056110014510gustar00rootroot0000000000000052 comment=20f3b6811750d1696abcc6738ca5894c1cb23f85 paint-2.2.0/000077500000000000000000000000001362400561100126245ustar00rootroot00000000000000paint-2.2.0/.editorconfig000066400000000000000000000002471362400561100153040ustar00rootroot00000000000000root = true [*] indent_style = space indent_size = 2 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true [*.{md,rdoc,txt}] indent_size = 4 paint-2.2.0/.gitignore000066400000000000000000000000731362400561100146140ustar00rootroot00000000000000*.rbc Rakefile.compiled.rbc *.swp *~ pkg .rbx Gemfile.lock paint-2.2.0/.rspec000066400000000000000000000000401362400561100137330ustar00rootroot00000000000000--colour --format documentation paint-2.2.0/.travis.yml000066400000000000000000000004451362400561100147400ustar00rootroot00000000000000sudo: false language: ruby rvm: - 2.7 - 2.6 - 2.5 - 2.4 - 2.3 - 2.2 - 2.1 - 2.0 - 1.9.3 - ruby-head - jruby-head - jruby-9.2.9.0 - truffleruby matrix: allow_failures: - rvm: jruby-head - rvm: 2.3 - rvm: 2.2 - rvm: 2.1 - rvm: 2.0 - rvm: 1.9.3 - rvm: truffleruby paint-2.2.0/CHANGELOG.md000066400000000000000000000044151362400561100144410ustar00rootroot00000000000000# CHANGELOG ### 2.2.0 * Support NO_COLOR environment variable, implements #26 (see no-color.org) ### 2.1.1 * Blacklist True Color support for urxvt, fixes #25 ### 2.1.0 * Set True Color as default mode on more terminals, patch by @smoochbot ### 2.0.3 * Add `gray` alias for `white` color, patch by @AlexWayfer ### 2.0.2 * Remove `gunzip` deprecation warning ### 2.0.1 * Fix nested substitutions, patch by @mildmojo ### 2.0.0 #### Major Changes * New default color mode `0xFFFFFF`: 24bit - true color. If this breaks your code, add `Paint.mode = 256` to the beginning of your code * New `Paint%[]` API: Substitution mechanism for nested color strings #### Minor Changes * Smaller gem size (compress RGB color name data) * Remove `Paint.update_rgb_colors` and `Paint.rainbow` * Internal method `.hex` renamed to `.rgb_hex` and does not take "#" prefixed strings anymore * Minor refactorings and documentation updates ### 1.0.1 * Fix case of string arguments getting mutated (see gh#14) ### 1.0.0 * Improved performance * Option for :random colors removed (see readme) * Separate Paint::SHORTCUTS into extra gem * Drop support for Ruby 1 (inoffically still support 1.9.3) ### 0.9.0 * Don't colorize strings via shortcuts when Paint.mode == 0 * Freeze bundled ascii color data ### 0.8.7 * Fix caching bug for random ansi color ### 0.8.6 * Add missing require 'rbconfig' and travis test everything ### 0.8.5 * Support 256 color on windows' ConEmu ### 0.8.4 * Fix post-install message unicode ### 0.8.3 * Paint.[] also accepts uppercased hex strings (gh#2) * Performance tweaks (thanks to murphy) (gh#4, #5) * API change: deactivate colorizing with Paint.mode = 0 ### 0.8.2 * Paint.[] with only a single string argument does not colorize the string anymore, but returns the plain string * New pseudo color :random - returns a random ansi color ### 0.8.1 * Improve rgb function with better gray scale values * Add Paint.mode: * Set to 0 to deactivate colorizing * Set to 16 or 8 and all color generation methods will generate simple ansi colors * Set to 256 for 256 color support * Tries to automatically detect your terminal's features * Minor changes ### 0.8.0 * Initial release paint-2.2.0/CODE_OF_CONDUCT.md000066400000000000000000000062361362400561100154320ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at conduct@janlelis.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: https://contributor-covenant.org [version]: https://contributor-covenant.org/version/1/4/ paint-2.2.0/Gemfile000066400000000000000000000001251362400561100141150ustar00rootroot00000000000000source 'https://rubygems.org' gemspec name: 'paint' gemspec name: 'paint-shortcuts' paint-2.2.0/MIT-LICENSE.txt000066400000000000000000000020631362400561100150770ustar00rootroot00000000000000The MIT LICENSE Copyright (c) 2011-2020 Jan Lelis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. paint-2.2.0/README.md000066400000000000000000000202411362400561100141020ustar00rootroot00000000000000# Ruby Paint [](https://badge.fury.io/rb/paint) [](https://travis-ci.org/janlelis/paint) Paint creates terminal colors and effects for you. It combines the strengths of **term-ansicolor**, **rainbow**, and similar projects into a simple to use, however still flexible terminal colors gem with no core extensions by default. ## Features * No string extensions (suitable for library development) * Simple API * Faster than other terminal color gems ([as of January 2020](https://gist.github.com/janlelis/91413b9295c81ee873dc)) * Supports *true color* or 256 colors (for capable terminals) * Allows you to set any terminal effects * `Paint.mode`: Fall-back modes for terminals with less colors, supported modes: * 0xFFFFFF (= 16777215) colors (*true color*) * 256 colors (palette) * 16 colors (only ANSI colors, combined with bright effect) * 8 colors (only ANSI colors) * 0 colors (no colors / deactivate) ## Paint 2.0 | True Color Support Starting with **Paint 2.0**, *true color* mode is the new default mode, since most major terminals now support 24bit colors. If it happens to not work in your setup: - Manually set `Paint.mode = 256` at the beginning of your code - Please [open a new issue](https://github.com/janlelis/paint/issues/new) so we can figure out how to blacklist the terminal used ## Supported Rubies * **2.7**, **2.6**, **2.5**, **2.4** Unsupported, but might still work: * **2.3**, **2.2**, **2.1**, **2.0**, **1.9** ## Setup Add to `Gemfile`: ```ruby gem 'paint' ``` and run `bundle install`. In Ruby do: ```ruby require 'paint' ``` ## Usage The only method you need is: `Paint.[]` The first argument given to `Paint.[]` is the string to colorize (if the object is not a string, `to_s` will be called on it). The other arguments describe how to modify/colorize the string. Let's learn by example: ```ruby Paint['Ruby', :red] # Sets ANSI color red Paint['Ruby', :red, :bright] # Also applies bright/bold effect Paint['Ruby', :bright, :red] # Does the same as above Paint['Ruby', :red, :bright, :underline] # Effects can often be combined Paint['Ruby', :red, :blue] # The second color you define is for background Paint['Ruby', nil, :blue] # Pass a nil before a color to ignore foreground and only set background color Paint['Ruby', [100, 255, 5]] # You can define RGB colors. Depending on your terminal, this will create # a "true color" or map to 256/16/8 colors. Paint['Ruby', "gold", "snow"] # Paint supports rgb.txt color names, note that the arguments are strings # (:yellow != "yellow")! Paint['Ruby', "#123456"] # HTML like definitions are possible Paint['Ruby', "fff"] # Another HTML hex definition Paint['Ruby', :inverse] # Swaps fore- and background Paint['Ruby', :italic, :encircle, :rapid_blink, :overline] # Probably not supported effects Paint['Ruby'] # Don't pass any argument and the string will not be changed ``` When you pass multiple colors, the first one is taken as foreground color and the second one defines the background color, every following color will be ignored. To only change the background color, you have to pass a `nil` first. Effects can be passed in any order. [You can find more examples in the specs.](https://github.com/janlelis/paint/blob/master/spec/paint_spec.rb) [List of rgb.txt colors.](https://en.wikipedia.org/wiki/X11_color_names#Color_name_chart) ## Windows Support For ANSI support in Windows OS, you can use [ansicon](https://github.com/adoxa/ansicon) or [ConEmu](https://conemu.github.io/) or WSL(https://docs.microsoft.com/en-us/windows/wsl/install-win10). ## `Paint.mode` You can choose between five ways to use `Paint.[]` by setting `Paint.mode` to one of the following: * **0xFFFFFF**: Use 16777215 *true colors* * **256**: Use the 256 colors palette * **16**: Use the eight ANSI colors (combined with bright effect) * **8**: Use the eight ANSI colors * **0**: Don't colorize at all Paint tries to automatically detect the proper value your terminal is capable of, please [open an issue](https://github.com/janlelis/paint/issues/new) if `Paint.detect_mode` yields a wrong value for you. ## More Details About Terminal Colors and Effects Terminal colors/effects get created by [ANSI escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code). These are strings that look like this: `\e[X;X;X;X;X]m` where X are integers with some meaning. For example, `0` means *reset*, `31` means *red foreground* and `41` stands for red background. When you tell **Paint** to use one of the eight ANSI base colors as foreground color, it just inserts a number between `30` and `37` into the sequence. The following colors are available: * `:black` * `:red` * `:green` * `:yellow` * `:blue` * `:magenta` * `:cyan` * `:white`, `:gray` * (`:default`) When combined with the `:bright` (= `:bold`) effect, the color in the terminal emulator often differs a little bit, thus it is possible to represent 16 colors. Through special sequences it's also possible to set 256-colors, or even 16777215 colors, instead of only the 8 ANSI ones. However, this is not supported by all terminals. Paint automatically translates given RGB colors to a suitable color of the supported color spectrum. When using the `Paint.[]` method, Paint wraps the given string between the calculated escape sequence and an reset sequence (`"\e[0m"`). You can get the raw escape sequence by using the `Paint.color` method. ### Effects See [en.wikipedia.org/wiki/ANSI_escape_code](https://en.wikipedia.org/wiki/ANSI_escape_code) for a more detailed discussion: #### Often supported 0) :reset, :nothing 1) :bright, :bold 4) :underline 7) :inverse, :negative 8) :conceal, :hide 22) :clean 24) :underline_off 26) :inverse_off, :positive 27) :conceal_off, :show, :reveal #### Not widely supported 2) :faint 3) :italic 5) :blink, :slow_blink 6) :rapid_blink 9) :crossed, :crossed_out 10) :default_font, :font0 11-19) :font1, :font2, :font3, :font4, :font5, :font6, :font7, :font8, :font9 20) :fraktur 21) :bright_off, :bold_off, :double_underline 23) :italic_off, :fraktur_off 25) :blink_off 29) :crossed_off, :crossed_out_off 51) :frame 52) :encircle 53) :overline 54) :frame_off, :encircle_off 55) :overline_off ## Substitution & Nesting From time to time, you might find yourself in a situation where you want to colorize a substring differently from the rest of the string. Paint supports this via a simple templating approach using the `%` method with an array argument. Use the `%{var}` notation within a string, and pass the template variables as a hash: ```ruby Paint%['Yellow string with a %{blue_text} in it', :yellow, blue_text: ["blue text", :blue] ] # => "\e[33mYellow string with a \e[34mblue text\e[33m in it\e[0m" ``` ## Utilities The `Paint.random` method generates a random ANSI color you can pass into `Paint.[]`: ```ruby Paint['Ruby', Paint.random] # Get one of eight random ANSI foreground colors Paint['Ruby', Paint.random(true)] # Get one of eight random ANSI background colors ``` Another helper method is `Paint.unpaint`, which removes any ANSI colors: ```ruby Paint.unpaint( Paint['Ruby', :red, :bright] ).should == 'Ruby' ``` You can get a `p` like alternative for calling `puts Paint.[]`: ```ruby require 'paint/pa' pa "Ruby", :red, :underline # same as puts Paint["Ruby", :red, :underline] ``` ## Advanced Usage: Shortcuts There is an extension gem available which allows you to define custom color definitions, which you can reuse later. See [SHORTCUTS.md](https://github.com/janlelis/paint/blob/master/SHORTCUTS.md) for documentation. This is completely optional. ## J-_-L Copyright (c) 2011-2020 Jan Lelis , released under the MIT license. Thank you to [rainbow](https://github.com/sickill/rainbow) and [term-ansicolor](https://github.com/flori/term-ansicolor) for ideas and inspiration. Also, a lot of thanks to all the [contributors](https://github.com/janlelis/paint/contributors)! paint-2.2.0/Rakefile000066400000000000000000000021131362400561100142660ustar00rootroot00000000000000require 'fileutils' require 'rspec/core/rake_task' gemspecs = %w[ paint.gemspec paint-shortcuts.gemspec ] RSpec::Core::RakeTask.new(:spec) do |t| t.rspec_opts = [ '--colour', '--format documentation', '-r ' + File.expand_path( File.join( 'spec', 'spec_helper') ), ] end task :default => :spec task :test => :spec def gemspec_spec_for(gemspec) eval(File.read(gemspec), binding, gemspec) end desc "Build the gems" task :gems do FileUtils.mkdir_p 'pkg' gemspecs.each{ |gemspec| sh "gem build #{gemspec}" spec = gemspec_spec_for(gemspec) FileUtils.mv "#{spec.name}-#{spec.version}.gem", 'pkg' } end desc "Install the gem locally" task :install => :gems do gemspecs.each{ |gemspec| spec = gemspec_spec_for(gemspec) sh %{gem install pkg/#{spec.name}-#{spec.version}.gem --no-doc} } end desc "Run a Benchmark" task :benchmark do ruby 'benchmark.rb' end desc "Print 256 colors rainbow" task :rainbow256 do require_relative 'lib/paint' (0...256).each{ |color| print Paint[' ', 48, 5, color] # print empty bg color field } puts end paint-2.2.0/SHORTCUTS.md000066400000000000000000000036601362400561100145510ustar00rootroot00000000000000# Paint::SHORTCUTS [](https://badge.fury.io/rb/paint-shortcuts) This is an optional extension gem for [Paint](https://github.com/janlelis/paint) ## Setup Add to `Gemfile`: gem 'paint-shortcuts' and run `bundle install`. In Ruby do: require 'paint/shortcuts' ## Description You can create color shortcuts for your gems and scripts! Please note: You don't have to use this feature (and only stick to `Paint.[]` instead) All you need to do is to setup a hash of symbol keys and escaped color sequences at: `Paint::SHORTCUTS[:your_namespace]`: ```ruby Paint::SHORTCUTS[:example] = { :white => Paint.color(:black), :red => Paint.color(:red, :bright), :title => Paint.color(:underline), } ``` The methods become "rubymagically" available in a `Paint` child model: ```ruby Paint::Example.red 'Ruby' # => "\e[31;1mRuby\e[0m" Paint::Example.white # => "\e[37m" ``` As you can see, the helper methods look useful and can take either one (wrap string) or none (only color) arguments. You can also include them: ```ruby include Paint::Example red # => "\e[31;1m" white 'Ruby' # => "\e[30m" ``` All shortcuts, defined in your shortcut namespace at this time, are now (privately) available in your current namespace (without relying a `method_missing` implementation). Furthermore, there are variations of this approach. You get a different behaviour, when you include the `String` sub-module. ```ruby include Paint::Example::String "Ruby".title # => "\e[4mRuby\e[0m" 5.red # => "\e[31;1m5\e[0m" ``` In this case, `self` will be converted to a string and wrapped with the specific color code. Note, that the helper methods don't take any arguments when using this style of inclusion. The third way allows you to get a single color helper method to avoid cluttering namespaces: ```ruby include Paint::Example::Prefix::ExampleName "Ruby".example_name(:red) # => "\e[31;1mRuby\e[0m" ``` paint-2.2.0/benchmark.rb000066400000000000000000000027531362400561100151120ustar00rootroot00000000000000require 'benchmark/ips' # - - - require_relative 'lib/paint' require 'rainbow' require 'rainbow/version' require 'term/ansicolor' require 'pastel' pastel = Pastel.new require 'ansi/code' require 'ansi/version' require 'hansi' require 'hansi/version' # - - - puts "# TERMINAL ANSI COLORS BENCHMARK" puts puts " ruby: #{ RUBY_VERSION }" puts " paint: #{ Paint::VERSION }" puts " rainbow: #{ Rainbow::VERSION }" puts " term/ansicolor #{ Term::ANSIColor::VERSION }" puts " pastel #{ Pastel::VERSION }" puts " ansi #{ ANSI::VERSION }" puts " hansi #{ Hansi::VERSION }" puts puts "## ONLY FOREGROUND COLOR" puts # - - - Benchmark.ips do |x| x.report("paint"){ Paint['ANSI', :red] } x.report("paint w/ nesting"){ Paint%['ANSI', :red] } x.report("rainbow"){ Rainbow('ANSI').color(:red) } x.report("term/ansicolor"){ Term::ANSIColor.red('ANSI') } x.report("pastel"){ pastel.red('ANSI') } x.report("ansi"){ ANSI::Code.red('ANSI') } x.report("hansi"){ Hansi.render(:red, 'ANSI') } x.compare! end # - - - puts puts "## FOREGROUND + BACKGROUND COLOR" puts Benchmark.ips do |x| x.report("paint"){ Paint['ANSI', :red, :green] } x.report("paint w/ nesting"){ Paint%['ANSI', :red, :green] } x.report("rainbow"){ Rainbow('ANSI').fg(:red).bg(:green) } x.report("term/ansicolor"){ Term::ANSIColor.red(Term::ANSIColor.on_green('ANSI')) } x.report("pastel"){ pastel.red.on_green('ANSI') } x.compare! end paint-2.2.0/data/000077500000000000000000000000001362400561100135355ustar00rootroot00000000000000paint-2.2.0/data/rgb_colors.marshal.gz000066400000000000000000000123121362400561100176570ustar00rootroot00000000000000ZX}\{]Uybyݙ$T!Vҥ@$DbYғ'3sp! ( G%t ZUK* t TZŶP\1Õ5ηqw>g/u +t=q뷽x-( +&&[ȞI-;ȟQYܰ6$7DUF:ӭ)% T:[DvKlX1jnV㻉ݞ$ZH#W +/h7ކkMͮlYsޞdf|.Ǻ3èl&r{[7'Hޘn5F-oXl M};]noLOepكmNQ|w~i+ K.; |/P090;͎kLg^՞3"EuiΎO]Z0H=;)dh"dYՋ=ڴkvGE>m&"-MMR"l OpƬx hh介fh *Y& ٙ4;BkkFϏ&i];7nu*;ඤ$”PӸF: \"msɱ kfik :7=^\$UudeWj7E}* 71ٍJ}eA7jt~} ErpXj%Ӯޤf\7yn4kjpA6#e'0kMvJܨ9=Z]Bj!~y0鹷|) ("p.h4A;1\L5|Sݰ葴јXR5@z>鍰9^3#ʼFu*Tʮw&aX7Y(hxSE0Pq5.R FBZxckL+ _a=G{%^)jh|f"GSܲQtgۗͶ\6 4In~1e{hZ[V˞Tm@jԭœ˛  خMQ^!.jEj4!l6۰)X.";w1n{ѸK({pK0#>'PV.j.@v,Aȃ']0 E>dW#] KREpz^n?W.KRM.2R^aeekn~e $5ܙ0MTks+c)4C?%",v1 g PoM$l|UV S9t+-` QIt8g?t0B K80<96c)nxW]tAŕ8V-qc wzfepo[E.&xNMSNnk.k=)7n&K.6z^L*|K$ϫ~e׹!R6H0[{tr=LOO37jYwys]h.w9T@̖:=:wogq f3Nݝc>k`p/N'o+.+[MQwӰA>8>oᦶ@rbgW.$qt˜ߚZY"_]'5kT8t}h[,we᫩$mMVޤۈ;SurD&[ݑ4KMnNk貛)oNKBu }[q\l6Z ̙؈]^ܯ"-lԮwq;Q%amHpǍG5K_2Әcqf/t =pB! 0$)rKI)~3v_$5;JS]OP &LCޝ8GnM8(k7'tK9h}3fN33nyxy?ë˗@Q(V>*e=^Kcp^ѫv=~?G o@[_XTh}c֔O=a,%WL k7e5=.|0_rt^r >o] 3[?>ͷu>^:IJqʍW9 ]T B3u> am9|݄v㲿4N>kX30nMxJuWy, TR(FRux- O]y70~>cU>\wux(*iUV aƜ:]2 Wt^xVr]>QJl5UڈGhbee$r *fyh)]>&B6pP0?Fs\?[d9vx"ҁCHc9M;X2:wBɈe.Gٞ Kc\`\PERŷA1-9uCKnu9l<<8WϿ'yVj0}{.Du,<Ƚ"[h]=Т˴Zz[N_vsy.ϤSXrjw<KNrYpү_ːW/i* Vy8o9h,cY聅njG{Ԭ[czuQng=;nBB"q:BM>`A~_G4`#q XU>Tf'Z߽dx*'< 'o:>JVͼ_Çֹy;^ŹMLU\wíwa<0b#iwk7 ~]IfWZnuyxspn` `N\0]χ}Dd#hhкAxV=yr4 `T0 N Zk) ѽu%̺2 3r}U޾t۷ݼ$L7s3n9v\Dai y۫@G5: O;{$9Q`|9d+Ol ?!ae%{J}9_dt L^Hjzg1e=a*ndIwnTnO(,grF9qc&gY0߯U>xcH[ ]Hݝt1}'Pl IF42ZzwR=:~QK LRY㟯p*;XBtH`'DgV~LsFFZJzXLǍCRm|ăm_3Dy6MOͷs)>ߵ9 eYv>ݵly.l9\ʙγ}"@9{(Wuq]niZm Zx\,f7&wB]uӅ e:_aw' Lة }+LyaA#Vu1Vu1Vu1V xl)^^co{l9^^c{=^^cܙ;/|58w41Je Rx2A)!x3^APJފ(cS+1J e RBq*^APJ0V%c 2aK8&4ce Rx2A)8/2A)K1J zeFc /Q (%%c#^APJ8.K1 2R±T1J vDpK1J x2A)^APJ8r0+cqDpK1J $>2.+ (%>Yp%(cYDp\(c+e R±/Q (%e R?Gg,Nv`d?e{HA{k>^w4"$z\EI'qKs }>^G8%|]z#m>^?YrO8EIvE۸x}񏹈>^i.O8~85EIs}ϸ>^x7'qks}.OⰛ885s}.O8>EIǯq}.O85'qkEIoq} A78|hip}Sd}{\DAq'qk85s}%.O8EI"$_Wx}5.O885?"$z.O8'qk0b}>^xTIǟs}WR~A+n8&;fR~J +U#J8 ¿?PX JO 6hʧBΖP_D7cKpaint-2.2.0/lib/000077500000000000000000000000001362400561100133725ustar00rootroot00000000000000paint-2.2.0/lib/paint.rb000066400000000000000000000170031362400561100150330ustar00rootroot00000000000000require_relative 'paint/version' require_relative 'paint/constants' require_relative 'paint/util' module Paint autoload :RGB_COLORS, 'paint/rgb_colors' class << self # Takes a string and color options and colorizes the string, fast version without nesting def [](string, *options) return string.to_s if @mode.zero? || options.empty? options = options[0] if options.size == 1 && !options[0].respond_to?(:to_ary) @cache[options] + string.to_s + NOTHING end # Takes an array with string and color options and colorizes the string, # extended version with nesting and substitution support def %(paint_arguments, clear_color = NOTHING) string, *options = paint_arguments return string.to_s if options.empty? substitutions = options.pop if options[-1].is_a?(Hash) options = options[0] if options.size == 1 && !options[0].respond_to?(:to_ary) current_color = @cache[options] # Substitutions & Nesting if substitutions substitutions.each{ |key, value| string.gsub!( "%{#{key}}", (value.is_a?(Array) ? self.%(value, current_color) : value.to_s) ) } end # Wrap string (if Paint.mode > 0) if @mode.zero? string.to_s else current_color + string.to_s + clear_color end end # Transforms options into the desired color. Used by @cache def color(*options) return '' if @mode.zero? || options.empty? mix = [] color_seen = false colors = ANSI_COLORS_FOREGROUND options.each{ |option| case option when Symbol if color = colors[option] mix << color color_seen = :set elsif ANSI_EFFECTS.key?(option) mix << effect(option) else raise ArgumentError, "Unknown color or effect: #{ option }" end when Array if option.size == 3 && option.all?{ |n| n.is_a? Numeric } mix << rgb(*[*option, color_seen]) color_seen = :set else raise ArgumentError, "Array argument must contain 3 numerals" end when ::String if option =~ /\A#?(?[[:xdigit:]]{3}{1,2})\z/ # 3 or 6 hex chars mix << rgb_hex($~[:hex_color], color_seen) color_seen = :set else mix << rgb_name(option, color_seen) color_seen = :set end when Numeric integer = option.to_i color_seen = :set if (30..49).include?(integer) mix << integer when nil color_seen = :set else raise ArgumentError, "Invalid argument: #{ option.inspect }" end if color_seen == :set colors = ANSI_COLORS_BACKGROUND color_seen = true end } wrap(*mix) end # This variable influences the color code generation # Currently supported values: # * 0xFFFFFF - 24-bit (~16 million) colors, aka truecolor # * 256 - 256 colors # * 16 - only ansi colors and bright effect # * 8 - only ansi colors # * 0 - no colorization! attr_reader :mode def mode=(val) @cache.clear case val when 0, 8, 16, 256, TRUE_COLOR @mode = val when TrueClass @mode = TRUE_COLOR when nil @mode = 0 else raise ArgumentError, "Cannot set paint mode to value <#{val}>, possible values are: 0xFFFFFF (true), 256, 16, 8, 0 (nil)" end end # Adds ANSI sequence def wrap(*ansi_codes) "\033[" + ansi_codes*";" + "m" end # Creates simple ansi color by looking it up on Paint::ANSI_COLORS def simple(color_name, background = false) (background ? 40 : 30) + ANSI_COLORS[color_name] end # If not true_color, creates a 256-compatible color from rgb values, # otherwise, an exact 24-bit color def rgb(red, green, blue, background = false) case @mode when 8 "#{background ? 4 : 3}#{rgb_to_ansi(red, green, blue, false)}" when 16 "#{background ? 4 : 3}#{rgb_to_ansi(red, green, blue, true)}" when 256 "#{background ? 48 : 38}#{rgb_to_256(red, green, blue)}" when TRUE_COLOR "#{background ? 48 : 38}#{rgb_true(red, green, blue)}" end end # Creates RGB color from a HTML-like color definition string def rgb_hex(string, background = false) case string.size when 6 color_code = string.each_char.each_slice(2).map{ |hex_color| hex_color.join.to_i(16) } when 3 color_code = string.each_char.map{ |hex_color_half| (hex_color_half*2).to_i(16) } end rgb(*[*color_code, background]) end # Creates a RGB from a name found in Paint::RGB_COLORS (based on rgb.txt) def rgb_name(color_name, background = false) if color_code = RGB_COLORS[color_name] rgb(*[*color_code, background]) end end # Creates the specified effect by looking it up in Paint::ANSI_EFFECTS def effect(effect_name) ANSI_EFFECTS[effect_name] end # Determine supported colors # Note: there's no reliable test for 24-bit color support def detect_mode if ENV['NO_COLOR'] # see https://no-color.org/ 0 elsif RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ # windows if ENV['ANSICON'] 16 elsif ENV['ConEmuANSI'] == 'ON' TRUE_COLOR else 0 end else case ENV['TERM'] when /^rxvt-(?:.*)-256color$/ 256 when /-color$/, /^rxvt/ 16 else # optimistic default TRUE_COLOR end end end private # Returns 24-bit color value (see https://gist.github.com/XVilka/8346728) # in ANSI escape sequnce format, without fore-/background information def rgb_true(red, green, blue) ";2;#{red};#{green};#{blue}" end # Returns closest supported 256-color an RGB value, without fore-/background information # Inspired by the rainbow gem def rgb_to_256(red, green, blue, approx = true) return ";2;#{red};#{green};#{blue}" unless approx gray_possible = true sep = 42.5 while gray_possible if red < sep || green < sep || blue < sep gray = red < sep && green < sep && blue < sep gray_possible = false end sep += 42.5 end if gray ";5;#{ 232 + ((red.to_f + green.to_f + blue.to_f)/33).round }" else # rgb ";5;#{ [16, *[red, green, blue].zip([36, 6, 1]).map{ |color, mod| (6 * (color.to_f / 256)).to_i * mod }].inject(:+) }" end end # Returns best ANSI color matching an RGB value, without fore-/background information # See https://mail.python.org/pipermail/python-list/2008-December/1150496.html def rgb_to_ansi(red, green, blue, use_bright = false) color_pool = RGB_COLORS_ANSI.values color_pool += RGB_COLORS_ANSI_BRIGHT.values if use_bright ansi_color_rgb = color_pool.min_by{ |col| rgb_color_distance([red, green, blue],col) } if ansi_color = RGB_COLORS_ANSI.key(ansi_color_rgb) ANSI_COLORS[ansi_color] else ansi_color = RGB_COLORS_ANSI_BRIGHT.key(ansi_color_rgb) "#{ANSI_COLORS[ansi_color]};1" end end def rgb_color_distance(rgb1, rgb2) rgb1.zip(rgb2).inject(0){ |acc, (cur1, cur2)| acc + (cur1 - cur2)**2 } end end # init instance vars @mode = detect_mode @cache = Hash.new{ |h, k| h[k] = color(*k) } end paint-2.2.0/lib/paint/000077500000000000000000000000001362400561100145055ustar00rootroot00000000000000paint-2.2.0/lib/paint/constants.rb000066400000000000000000000063621362400561100170550ustar00rootroot00000000000000module Paint # Clears all colors NOTHING = "\033[0m".freeze # Number of possible colors in TRUE COLOR mode TRUE_COLOR = 0xFFFFFF # Basic colors (often, the color differs when using the bright effect) # Final color will be 30 + value for foreground and 40 + value for background ANSI_COLORS = { :black => 0, :red => 1, :green => 2, :yellow => 3, :blue => 4, :magenta => 5, :cyan => 6, :white => 7, :gray => 7, :default => 9, }.freeze ANSI_COLORS_FOREGROUND = { :black => 30, :red => 31, :green => 32, :yellow => 33, :blue => 34, :magenta => 35, :cyan => 36, :white => 37, :gray => 37, :default => 39, }.freeze ANSI_COLORS_BACKGROUND = { :black => 40, :red => 41, :green => 42, :yellow => 43, :blue => 44, :magenta => 45, :cyan => 46, :white => 47, :gray => 47, :default => 49, }.freeze # Terminal effects - most of them are not supported ;) # See https://en.wikipedia.org/wiki/ANSI_escape_code ANSI_EFFECTS = { :reset => 0, :nothing => 0, # usually supported :bright => 1, :bold => 1, # usually supported :faint => 2, :italic => 3, :underline => 4, # usually supported :blink => 5, :slow_blink => 5, :rapid_blink => 6, :inverse => 7, :swap => 7, # usually supported :conceal => 8, :hide => 9, :default_font => 10, :font0 => 10, :font1 => 11, :font2 => 12, :font3 => 13, :font4 => 14, :font5 => 15, :font6 => 16, :font7 => 17, :font8 => 18, :font9 => 19, :fraktur => 20, :bright_off => 21, :bold_off => 21, :double_underline => 21, :clean => 22, :italic_off => 23, :fraktur_off => 23, :underline_off => 24, :blink_off => 25, :inverse_off => 26, :positive => 26, :conceal_off => 27, :show => 27, :reveal => 27, :crossed_off => 29, :crossed_out_off => 29, :frame => 51, :encircle => 52, :overline => 53, :frame_off => 54, :encircle_off => 54, :overline_off => 55, }.freeze # A list of color names for standard ansi colors, needed for 16/8 color fallback mode # See https://en.wikipedia.org/wiki/ANSI_escape_code#Colors RGB_COLORS_ANSI = { :black => [ 0, 0, 0], :red => [205, 0, 0], :green => [ 0, 205, 0], :yellow => [205, 205, 0], :blue => [ 0, 0, 238], :magenta => [205, 0, 205], :cyan => [ 0, 205, 205], :white => [229, 229, 229], :gray => [229, 229, 229], }.each { |k, v| v.freeze }.freeze # A list of color names for standard bright ansi colors, needed for 16 color fallback mode # See https://en.wikipedia.org/wiki/ANSI_escape_code#Colors RGB_COLORS_ANSI_BRIGHT = { :black => [127, 127, 127], :red => [255, 0, 0], :green => [ 0, 255, 0], :yellow => [255, 255, 0], :blue => [ 92, 92, 255], :magenta => [255, 0, 255], :cyan => [ 0, 255, 255], :white => [255, 255, 255], :gray => [255, 255, 255], }.each { |k, v| v.freeze }.freeze end paint-2.2.0/lib/paint/pa.rb000066400000000000000000000003031362400561100154260ustar00rootroot00000000000000require 'paint' module Kernel private # A helper method similar to puts for printing a String on STDOUT # Passes all arguments to Paint.[] def pa(*args) puts Paint[*args] end end paint-2.2.0/lib/paint/rgb_colors.rb000066400000000000000000000006051362400561100171660ustar00rootroot00000000000000require "zlib" module Paint RGB_COLORS_INDEX_FILENAME = File.dirname(__FILE__) + "/../../data/rgb_colors.marshal.gz" # A list of color names, based on X11's rgb.txt File.open(RGB_COLORS_INDEX_FILENAME, "rb") do |file| serialized_data = Zlib::GzipReader.new(file).read serialized_data.force_encoding Encoding::BINARY RGB_COLORS = Marshal.load(serialized_data) end end paint-2.2.0/lib/paint/shortcuts.rb000066400000000000000000000054241362400561100170750ustar00rootroot00000000000000require_relative 'shortcuts_version' require 'paint' module Paint # Hash for defining color/effect shortcuts SHORTCUTS = { # :example => { # would create a Paint::Example constant... # :light_red => "\e[31;1m", # with a method .light_red # } } SHORTCUTS.default = {} class << self # Paint::SomeModule --> Paint::SHORTCUTS[:some_module] def const_missing(mod_name) # get shortcuts shortcuts = SHORTCUTS[mod_name.to_s.gsub(/[A-Z]/,'_\0').downcase[1..-1].to_sym] || [] # create module class_eval "module #{mod_name}; end" mod = const_get(mod_name) # define direct behaviour, class methods mod.define_singleton_method :method_missing do |color_name, *args| if color_code = shortcuts[color_name] string = Array(args).join return string if Paint.mode.zero? if args.empty? color_code else color_code + string + NOTHING end else nil end end mod.define_singleton_method :respond_to_missing? do |color_name, *args| shortcuts.include?(color_name) || super(color_name, *args) end # define include behaviour, instance methods mod.define_singleton_method :included do |_| shortcuts.each{ |color_name, color_code| define_method color_name do |*args| string = Array(args).join return string if Paint.mode.zero? if args.empty? color_code else color_code + string + NOTHING end end } private(*shortcuts.keys) unless shortcuts.empty? end # include variations, defined in child modules mod.class_eval "module String; end" string = mod.const_get(:String) string.define_singleton_method :included do |_| shortcuts.each{ |color_name, color_code| define_method color_name do if Paint.mode.zero? to_s else color_code + to_s + NOTHING end end } end # OK, let's take it one level further ;) mod.class_eval "module Prefix; end" prefix_prefix = mod.const_get(:Prefix) prefix_prefix.define_singleton_method :const_missing do |prefix_name| class_eval "module #{prefix_name}; end" prefix = const_get(prefix_name) prefix.define_singleton_method :included do |_| define_method prefix_name.to_s.gsub(/[A-Z]/,'_\0').downcase[1..-1].to_sym do |color_name| if color_code = shortcuts[color_name] return to_s if Paint.mode.zero? color_code + to_s + NOTHING end end end prefix end mod end end end paint-2.2.0/lib/paint/shortcuts_version.rb000066400000000000000000000000661362400561100206370ustar00rootroot00000000000000module Paint SHORTCUTS_VERSION = '2.0.0'.freeze end paint-2.2.0/lib/paint/util.rb000066400000000000000000000005661362400561100160160ustar00rootroot00000000000000module Paint # Standalone helpers which add functionality you sometimes need when working with terminal colors class << self # Removes any color and effect strings def unpaint(string) string.gsub(/\e\[(?:[0-9];?)+m/, '') end # Creates a random ANSI color def random(background = false) (background ? 40 : 30) + rand(8) end end end paint-2.2.0/lib/paint/version.rb000066400000000000000000000001041362400561100165120ustar00rootroot00000000000000# frozen_string_literal: true module Paint VERSION = "2.2.0" end paint-2.2.0/paint-shortcuts.gemspec000066400000000000000000000014161362400561100173420ustar00rootroot00000000000000# -*- encoding: utf-8 -*- require File.dirname(__FILE__) + "/lib/paint/shortcuts_version" Gem::Specification.new do |s| s.name = "paint-shortcuts" s.version = Paint::SHORTCUTS_VERSION s.authors = ["Jan Lelis"] s.email = ["hi@ruby.consulting"] s.homepage = "https://github.com/janlelis/paint" s.summary = "Terminal painter! Shortcut extension." s.description = "Extends the paint gem to support custom color shortcuts." s.license = 'MIT' s.files = %w[ paint-shortcuts.gemspec lib/paint/shortcuts.rb lib/paint/shortcuts_version.rb ] s.extra_rdoc_files = %w[ README.md SHORTCUTS.md CHANGELOG.md MIT-LICENSE.txt ] s.required_ruby_version = '>= 1.9.3' s.add_dependency 'paint', '>= 1.0', '< 3.0' end paint-2.2.0/paint.gemspec000066400000000000000000000024271362400561100153110ustar00rootroot00000000000000# -*- encoding: utf-8 -*- require File.dirname(__FILE__) + "/lib/paint/version" Gem::Specification.new do |s| s.name = "paint" s.version = Paint::VERSION s.authors = ["Jan Lelis"] s.email = ["hi@ruby.consulting"] s.homepage = "https://github.com/janlelis/paint" s.summary = "Terminal painter!" s.description = "Terminal painter with RGB and 256 (fallback) color and terminal effects support. No string extensions! Usage: Paint['string', :red, :bright]" s.license = 'MIT' s.files = %w[ paint.gemspec Rakefile .rspec .travis.yml lib/paint.rb lib/paint/pa.rb lib/paint/rgb_colors.rb lib/paint/constants.rb lib/paint/util.rb lib/paint/version.rb data/rgb_colors.marshal.gz ] s.extra_rdoc_files = %w[ README.md CHANGELOG.md MIT-LICENSE.txt ] s.required_ruby_version = '>= 1.9.3' s.add_development_dependency 'rspec', '~> 3.2' s.add_development_dependency 'rake', '~> 12.3' s.add_development_dependency 'benchmark-ips', '~> 2.7' s.add_development_dependency 'rainbow', '~> 3.0' s.add_development_dependency 'term-ansicolor', '~> 1.7' s.add_development_dependency 'ansi', '~> 1.5' s.add_development_dependency 'hansi', '~> 0.2' s.add_development_dependency 'pastel', '~> 0.7' end paint-2.2.0/spec/000077500000000000000000000000001362400561100135565ustar00rootroot00000000000000paint-2.2.0/spec/paint_methods_spec.rb000066400000000000000000000053411362400561100177560ustar00rootroot00000000000000require File.dirname(__FILE__) + '/spec_helper' describe 'Paint.color' do it 'only returns a the color escape sequence and is directly used by Paint.[] with all paramenters except the first; see there for specs' do end end describe 'Paint.simple' do it 'returns ansi code number for one of the eight ansi base colors' do Paint.simple(:red).should == 31 end it 'returns background ansi code number for one of the eight ansi base colors if second parameter is true' do Paint.simple(:red, true).should == 41 end end describe 'Paint.rgb' do context '(256 colors)' do before do Paint.mode = 256 end it 'returns ANSI code sequence for one of 256 colors' do Paint.rgb(1, 2, 3).should == '38;5;232' end it 'returns background ANSI code sequence for one of 256 colors if last parameter is true' do Paint.rgb(1, 2, 3, true).should == '48;5;232' end end context '(true colors)' do before do Paint.mode = 0xFFFFFF end it 'returns truecolor ANSI code sequence' do Paint.rgb(1, 2, 3).should == '38;2;1;2;3' end it 'returns truecolor background ANSI code sequence if last parameter is true' do Paint.rgb(1, 2, 3, true).should == '48;2;1;2;3' end end end describe 'Paint.rgb_hex' do before do Paint.mode = 256 end it 'returns ansi code sequence for one of 256 colors' do Paint.rgb_hex("fff").should == "38;5;255" end it 'returns background ansi code sequence for one of 256 colors if second parameter is true' do Paint.rgb_hex("123456", true).should == "48;5;24" end end describe 'Paint.rgb_name' do before do Paint.mode = 256 end it 'returns ansi code sequence for one of 256 colors' do Paint.rgb_name("gold").should == "38;5;226" end it 'returns background ansi code sequence for one of 256 colors if second parameter is true' do Paint.rgb_name("gold", true).should == "48;5;226" end end describe 'Paint.random' do it 'returns ansi code for one of the eight ansi base colors' do (30...38) === Paint.random.should end end describe 'Paint.effect' do it 'returns ansi code for effect using EFFECTS hash' do Paint.effect(:bright).should == 1 end end describe 'Paint.wrap' do it 'wraps an ansi color code (array of integers) into an ansi escape sequence' do Paint.wrap(31, 1).should == "\e[31;1m" end end # util.rb describe 'Paint.unpaint' do it 'removes any ansi color escape sequences in the string' do Paint.unpaint( Paint['J-_-L', :red, :bright] ).should == 'J-_-L' end end describe 'Paint.rainbow' do it 'prints all available 256 colors' do end end describe 'Paint.update_rgb_colors' do it 'updates the Paint::RGB_COLORS hash using rgb.txt (takes path to it as argument)' do end end paint-2.2.0/spec/paint_mode_spec.rb000066400000000000000000000017431362400561100172410ustar00rootroot00000000000000require File.dirname(__FILE__) + '/spec_helper' describe 'Paint.mode' do it "works with full color set if mode is 0xFFFFFF (16777215)" do Paint.mode = 0xFFFFFF Paint['J-_-L', 'gold'].should == "\e[38;2;255;215;0mJ-_-L\e[0m" end it "converts to a close color from the 256 colors palette if mode is 256" do Paint.mode = 256 Paint['J-_-L', 'gold'].should == "\e[38;5;226mJ-_-L\e[0m" end it "only uses the 8 ansi colors with bright effect if mode is 16" do Paint.mode = 16 Paint['J-_-L', 'gold'].should == "\e[33;1mJ-_-L\e[0m" end it "only uses the 8 ansi colors if mode is 8" do Paint.mode = 8 Paint['J-_-L', 'gold'].should == "\e[33mJ-_-L\e[0m" end it "doesn't colorize anything if mode is 0" do Paint.mode = 0 Paint['J-_-L', 'gold'].should == "J-_-L" end end describe 'Paint.detect_mode' do it 'does not colorize when NO_COLOR environment variable is set' do ENV['NO_COLOR'] = '' Paint.detect_mode.should == 0 end end paint-2.2.0/spec/paint_shortcuts_spec.rb000066400000000000000000000034161362400561100203520ustar00rootroot00000000000000require File.dirname(__FILE__) + '/spec_helper' require 'paint/shortcuts' describe 'Paint::SHORTCUTS' do before do Paint.mode = 256 Paint::SHORTCUTS[:example] = { :white => Paint.color(:black), :red => Paint.color(:red, :bright), :title => Paint.color(:underline), } end context 'Paint::Example.method_missing' do it 'returns a color defined in the SHORTCUTS hash under the :example key' do Paint::Example.red.should == "\e[31;1m" end it 'returns a color defined in the SHORTCUTS hash under the :some_module key; method takes string to colorize' do Paint::Example.red('J-_-L').should == "\e[31;1mJ-_-L\e[0m" end context 'Paint.mode is 0' do before do Paint.mode = 0 end it "doesn't colorize a string passed into a color defined in the SHORTCUTS hash under the :some_module key" do Paint::Example.red('J-_-L').should == 'J-_-L' end end end context 'include Paint::Example::String' do it 'adds shortcuts methods that colorize self' do class MyString < String include Paint::Example::String end MyString.new("J-_-L").red.should == "\e[31;1mJ-_-L\e[0m" end it 'adds shortcuts methods that colorize self (also works for non-String classes by calling to_s)' do Paint::SHORTCUTS[:example][:gold] = Paint.color "gold" class Integer include Paint::Example::String end 123.red.should == "\e[31;1m123\e[0m" end end context 'include Paint::Example::Prefix::ExampleName' do it 'sets a single color helper method to avoid cluttering namespaces' do class Object include Paint::Example::Prefix::ExampleName end "Ruby".example_name(:red).should == "\e[31;1mRuby\e[0m" end end end paint-2.2.0/spec/paint_spec.rb000066400000000000000000000107041362400561100162320ustar00rootroot00000000000000require File.dirname(__FILE__) + '/spec_helper' describe 'Paint.[]' do before do Paint.mode = 256 end context '(with no options)' do it "doesn't colorize at all" do Paint['J-_-L'].should == "J-_-L" end end context '(with one color)' do it 'understands a simple symbol color and use it as foreground color' do Paint['J-_-L', :yellow].should == "\e[33mJ-_-L\e[0m" end it 'understands an array as rgb color definition and use it as foreground color' do Paint['J-_-L', [255, 200, 0]].should == "\e[38;5;220mJ-_-L\e[0m" end it 'understands a hex string (with #, 6 digits) as rgb color definition and use it as foreground color' do Paint['J-_-L', "#123456"].should == "\e[38;5;24mJ-_-L\e[0m" end it 'understands a hex string (no #, 6 digits) as rgb color definition and use it as foreground color' do Paint['J-_-L', "123456"].should == "\e[38;5;24mJ-_-L\e[0m" end it 'understands a hex string (with #, 3 digits) as rgb color definition and use it as foreground color' do Paint['J-_-L', "#fff"].should == "\e[38;5;255mJ-_-L\e[0m" end it 'understands a hex string (no #, 3 digits) as rgb color definition and use it as foreground color' do Paint['J-_-L', "fff"].should == "\e[38;5;255mJ-_-L\e[0m" end it 'understands a hex string (with uppercased letters) as rgb color definition and use it as foreground color' do Paint['J-_-L', "#4183C4"].should == "\e[38;5;74mJ-_-L\e[0m" end it 'does not alter the passed in color string object' do source = '#FFFFFF' Paint['J-_-L', source] source.should == '#FFFFFF' end it 'understands a non-hex string as rgb color name (rgb.txt) and use it as foreground color' do Paint['J-_-L', "medium purple"].should == "\e[38;5;141mJ-_-L\e[0m" end it 'colorizes using a random ansi foreground color' do Paint['J-_-L', Paint.random].should =~ /\e\[3\dmJ-_-L\e\[0m/ end it 'does not cache randomness' do (0..99).map{ Paint['J-_-L', Paint.random] }.uniq.size.should > 1 end it 'does not cache background randomness' do (0..99).map{ Paint['J-_-L', Paint.random(true)] }.uniq.size.should > 1 end end context '(with two colors)' do it 'interprets the first color as foreground color and the second one as background color' do Paint['J-_-L', :yellow, :red].should == "\e[33;41mJ-_-L\e[0m" end it 'interprets the first color as foreground color and the second one as background color (rgb)' do Paint['J-_-L', '#424242', [42, 142, 242]].should == "\e[38;5;238;48;5;39mJ-_-L\e[0m" end it 'sets only a background color, if first color is nil' do Paint['J-_-L', nil, [42, 142, 242]].should == "\e[48;5;39mJ-_-L\e[0m" end end context '(with effects)' do it 'passes effects' do Paint['J-_-L', :bright].should == "\e[1mJ-_-L\e[0m" end it 'passes effects, mixed with colors' do Paint['J-_-L', :yellow, :bright].should == "\e[33;1mJ-_-L\e[0m" end it 'passes effects, mixed with colors, order does not matter' do Paint['J-_-L', :bright, :yellow].should == "\e[1;33mJ-_-L\e[0m" end it 'passes multiple effects' do Paint['J-_-L', :yellow, :red, :bright, :underline, :inverse].should == "\e[33;41;1;4;7mJ-_-L\e[0m" end end context '(with plain integers)' do it 'passes integers to final escape sequence' do Paint['J-_-L', 31, 1, 42].should == "\e[31;1;42mJ-_-L\e[0m" end it 'passes integers to final escape sequence (mixed with normal arguments)' do Paint['J-_-L', :red, :bright, 42, :underline].should == "\e[31;1;42;4mJ-_-L\e[0m" end end describe 'True color support' do before do Paint.mode = true end it 'will return a true color escape sequence' do Paint['J-_-L', [255, 200, 0]].should == "\e[38;2;255;200;0mJ-_-L\e[0m" end end describe "Nesting & Substitution" do it 'will replace %{template_variables}' do Paint%['J%{eye}%{nose}%{eye}L', :yellow, eye: '-', nose: '_'].should == "\e[33mJ-_-L\e[0m" end it 'will work with arbitrary nesting and produce optimized escape sequences' do (Paint%['first level - %{second} - first level', :yellow, second: ['second level - %{third} - second level', :red, third: ['third level', :green] ] ]).should == "\e[33mfirst level - \e[31msecond level - \e[32mthird level\e[31m - second level\e[33m - first level\e[0m" end end end paint-2.2.0/spec/spec_helper.rb000066400000000000000000000002221362400561100163700ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../lib/paint' RSpec.configure do |config| config.expect_with :rspec do |c| c.syntax = :should end end