├── .rspec ├── .gitignore ├── .travis.yml ├── Rakefile ├── spec ├── spec │ └── helper.rb └── tests │ └── lib │ ├── colorator │ └── core_ext_spec.rb │ └── colorator_spec.rb ├── lib ├── colorator │ └── core_ext.rb └── colorator.rb ├── Gemfile ├── .codeclimate.yml ├── History.markdown ├── colorator.gemspec ├── README.markdown ├── LICENSE └── .rubocop.yml /.rspec: -------------------------------------------------------------------------------- 1 | --tty --color 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | Gemfile.lock 3 | vendor/ 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: ruby 3 | rvm: 4 | - 2.1.8 5 | - 2.2.5 6 | - 2.3.1 7 | - jruby-9.0.5.0 8 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rspec/core/rake_task" 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task :default => :spec 7 | -------------------------------------------------------------------------------- /spec/spec/helper.rb: -------------------------------------------------------------------------------- 1 | require "colorator" 2 | require "luna/rspec/formatters/checks" 3 | RSpec.configure { |config| config.order = "random" } 4 | Dir[File.expand_path("../../support/**/*.rb", __FILE__)].each do |f| 5 | require f 6 | end 7 | -------------------------------------------------------------------------------- /lib/colorator/core_ext.rb: -------------------------------------------------------------------------------- 1 | class String 2 | Colorator::CORE_METHODS.each do |method| 3 | define_method method do |*args| 4 | Colorator.public_send(method, 5 | self, *args 6 | ) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | gemspec 3 | 4 | gem "rake" 5 | group :development do 6 | gem "rspec-helpers", :require => false 7 | gem "luna-rspec-formatters", :require => false 8 | gem "pry", :require => false unless ENV[ 9 | "CI" 10 | ] 11 | end 12 | -------------------------------------------------------------------------------- /spec/tests/lib/colorator/core_ext_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec/helper" 2 | 3 | describe String do 4 | subject do 5 | "I am a test string, y'know?" 6 | end 7 | 8 | Colorator::CORE_METHODS.each do |method| 9 | it "should respond_to #{method}" do 10 | expect(subject).to respond_to( 11 | method 12 | ) 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | rubocop: { enabled: true } 3 | fixme: { enabled: false } 4 | exclude_paths: 5 | - .rubocop.yml 6 | - .codeclimate.yml 7 | - .travis.yml 8 | - .gitignore 9 | - .rspec 10 | 11 | - Gemfile.lock 12 | - CHANGELOG.md 13 | - readme.md 14 | - README.md 15 | - Readme.md 16 | - ReadMe.md 17 | - COPYING 18 | - LICENSE 19 | - NEWS 20 | 21 | - test/**/* 22 | - vendor/**/* 23 | - features/**/* 24 | - script/**/* 25 | - spec/**/* 26 | ratings: 27 | paths: 28 | - lib/**/*.rb 29 | -------------------------------------------------------------------------------- /History.markdown: -------------------------------------------------------------------------------- 1 | ## 1.1.0 / 2016-06-28 2 | 3 | ### Minor Enhancements 4 | 5 | * Support jruby (#8) 6 | 7 | ## 1.0.0 / 2016-04-28 8 | 9 | ### Major enhancements 10 | 11 | - Merge Simple::ANSI and Colorator. (#7) 12 | 13 | ### Minor Enhancements 14 | 15 | - Delete unnecessary `Symbol#to_sym` (#2) 16 | - Change argument name of `Enumerator#each` for better code legibility (#3) 17 | 18 | ### Development Fixes 19 | 20 | - Convert to new RSpec expectation syntax (#1) 21 | - Fix `String#blue` result in README (#4) 22 | 23 | ## 0.1 / 2013-04-13 24 | 25 | Birthday! 26 | -------------------------------------------------------------------------------- /colorator.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require File.expand_path('lib/colorator.rb', __dir__) 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "colorator" 7 | spec.summary = "Colorize your text in the terminal." 8 | spec.version = Colorator::VERSION 9 | spec.authors = ["Parker Moore", "Brandon Mathis"] 10 | spec.email = ["parkrmoore@gmail.com", "brandon@imathis.com"] 11 | spec.homepage = "https://github.com/octopress/colorator" 12 | spec.licenses = ["MIT"] 13 | 14 | all = `git ls-files -z`.split("\x0").reject { |f| f.start_with?(".") } 15 | spec.files = all.select { |f| File.basename(f) == f || f =~ %r{^(bin|lib)/} } 16 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 17 | spec.require_paths = ["lib"] 18 | 19 | spec.extra_rdoc_files = ["README.markdown", "LICENSE"] 20 | spec.rdoc_options = ["--charset=UTF-8"] 21 | 22 | spec.add_development_dependency "rspec", "~> 3.1" 23 | end 24 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # colorator 2 | 3 | Colorize your text for the terminal 4 | 5 | [![Build Status](https://travis-ci.org/octopress/colorator.png?branch=master)](https://travis-ci.org/octopress/colorator) 6 | 7 | ## Example 8 | 9 | ```ruby 10 | "this string".red 11 | # => \e[31mthis string\e[0m 12 | "my string".blue 13 | # => \e[34mmy string\e[0m 14 | # etc... 15 | ``` 16 | 17 | ## Supported Colors 18 | 19 | - `red` 20 | - `black` 21 | - `green` 22 | - `yellow` 23 | - `magenta` 24 | - `white` 25 | - `blue` 26 | - `cyan` 27 | - `bold` 28 | 29 | ## Other supported Ansi methods 30 | 31 | - `clear_line` 32 | - `has_ansi?`, `has_color?` 33 | - `strip_ansi`, `strip_color` 34 | - `reset_ansi`, `reset_color` 35 | - `clear_screen` 36 | - `ansi_jump` 37 | 38 | ## Why 39 | 40 | There are a bunch of gems that provide functionality like this, but none have 41 | as simple an API as this. Just call `"string".color` and your text will be 42 | colorized. 43 | 44 | ## License 45 | 46 | MIT. Written as a single Ruby file by Brandon Mathis, converted into a gem by 47 | Parker Moore. 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) Parker Moore 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /spec/tests/lib/colorator_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec/helper" 2 | describe Colorator do 3 | Colorator::ANSI_COLORS.each do |color, code| 4 | it "colors the text #{color} properly" do 5 | expect(Colorator.send(color, "string")).to include code.to_s 6 | expect(Colorator.send(color, "string")).to eq( 7 | "\x1b[#{code}mstring\x1b[0m" 8 | ) 9 | end 10 | end 11 | 12 | # 13 | 14 | describe "#clear_line" do 15 | it "gives ansi to clear the line" do 16 | expect(subject.has_ansi?(subject.clear_line)).to( 17 | be_truthy 18 | ) 19 | end 20 | 21 | it "supports passing strings" do 22 | expect(subject.has_ansi?(subject.clear_line("hello"))).to( 23 | be_truthy 24 | ) 25 | end 26 | end 27 | 28 | # 29 | 30 | describe "#clear_screen" do 31 | it "gives ansi to clear the line" do 32 | expect(subject.has_ansi?(subject.clear_screen)).to( 33 | be_truthy 34 | ) 35 | end 36 | 37 | it "supports passing strings" do 38 | expect(subject.has_ansi?(subject.clear_screen("hello"))).to( 39 | be_truthy 40 | ) 41 | end 42 | end 43 | 44 | # 45 | 46 | describe "#has_ansi?" do 47 | it "should detect ansi" do 48 | expect(subject.has_ansi?(subject.blue("hello"))).to( 49 | be_truthy 50 | ) 51 | end 52 | end 53 | 54 | # 55 | 56 | describe "#strip_ansi" do 57 | it "should strip ansi" do 58 | expect(subject.strip_ansi(subject.red("hello"))).to eq( 59 | "hello" 60 | ) 61 | end 62 | 63 | # 64 | 65 | context "with reset" do 66 | it "should strip the reset too" do 67 | expect(subject.strip_ansi(subject.red(subject.reset_ansi("hello")))).to eq( 68 | "hello" 69 | ) 70 | end 71 | end 72 | 73 | # 74 | 75 | context "with multiple colors" do 76 | it "should strip it all" do 77 | expect(subject.strip_ansi(subject.red(subject.yellow("hello")))).to eq( 78 | "hello" 79 | ) 80 | end 81 | end 82 | end 83 | 84 | # 85 | 86 | describe "#ansi_jump" do 87 | it "should give ansi to jump up and down" do 88 | expect(subject.ansi_jump("hello", 1024)).to match( 89 | %r!\[1024A|\[1024B\Z! 90 | ) 91 | end 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | Metrics/LineLength: { Max: 112 } 2 | Metrics/BlockNesting: { Max: 4 } 3 | Metrics/ClassLength: { Max: 240 } 4 | Metrics/ModuleLength: { Max: 240 } 5 | Metrics/CyclomaticComplexity: { Max: 8 } 6 | Metrics/PerceivedComplexity: { Max: 8 } 7 | Metrics/ParameterLists: { Max: 6 } 8 | Metrics/MethodLength: { Max: 12 } 9 | Metrics/MethodLength: { Max: 24 } 10 | Metrics/AbcSize: { Max: 20 } 11 | 12 | Style/IndentHash: { EnforcedStyle: consistent } 13 | Style/SignalException: { EnforcedStyle: only_raise } 14 | Style/Semicolon: { AllowAsExpressionSeparator: true } 15 | Style/AlignParameters: { EnforcedStyle: with_fixed_indentation } 16 | Style/StringLiteralsInInterpolation: { EnforcedStyle: double_quotes } 17 | Style/RegexpLiteral: { EnforcedStyle: slashes, AllowInnerSlashes: true } 18 | Style/MultilineMethodCallIndentation: { EnforcedStyle: indented } 19 | Style/MultilineOperationIndentation: { EnforcedStyle: indented } 20 | Style/FirstParameterIndentation: { EnforcedStyle: consistent } 21 | Style/StringLiterals: { EnforcedStyle: double_quotes } 22 | Style/IndentArray: { EnforcedStyle: consistent } 23 | Style/ExtraSpacing: { AllowForAlignment: true } 24 | 25 | Style/PercentLiteralDelimiters: 26 | PreferredDelimiters: 27 | '%q': '{}' 28 | '%Q': '{}' 29 | '%r': '!!' 30 | '%s': '()' 31 | '%w': '()' 32 | '%W': '()' 33 | '%x': '()' 34 | 35 | Style/HashSyntax: { Enabled: false } 36 | Style/AlignArray: { Enabled: false } 37 | Style/StringLiterals: { Enabled: false } 38 | Style/Documentation: { Enabled: false } 39 | Style/DoubleNegation: { Enabled: false } 40 | Style/UnneededCapitalW: { Enabled: false } 41 | Style/MultilineTernaryOperator: { Enabled: false } 42 | Style/EmptyLinesAroundModuleBody: { Enabled: false } 43 | Style/EmptyLinesAroundAccessModifier: { Enabled: false } 44 | Style/BracesAroundHashParameters: { Enabled: false } 45 | Style/SpaceInsideBrackets: { Enabled: false } 46 | Style/IfUnlessModifier: { Enabled: false } 47 | Style/ModuleFunction: { Enabled: false } 48 | Style/RescueModifier: { Enabled: false } 49 | Style/GuardClause: { Enabled: false } 50 | Style/FileName: { Enabled: false } 51 | Lint/UselessAccessModifier: { Enabled: false } 52 | Style/SpaceAroundOperators: { Enabled: false } 53 | Style/RedundantReturn: { Enabled: false } 54 | 55 | AllCops: 56 | TargetRubyVersion: 2.0 57 | Include: 58 | - lib/**/*.rb 59 | 60 | Exclude: 61 | - .rubocop.yml 62 | - .codeclimate.yml 63 | - .travis.yml 64 | - .gitignore 65 | - .rspec 66 | 67 | - Gemfile.lock 68 | - CHANGELOG.md 69 | - readme.md 70 | - README.md 71 | - Readme.md 72 | - ReadMe.md 73 | - COPYING 74 | - LICENSE 75 | - NEWS 76 | 77 | - test/**/* 78 | - vendor/**/* 79 | - features/**/* 80 | - script/**/* 81 | - spec/**/* 82 | -------------------------------------------------------------------------------- /lib/colorator.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.dirname(__FILE__) 2 | 3 | module Colorator 4 | module_function 5 | VERSION = "1.1.0" 6 | 7 | # -------------------------------------------------------------------------- 8 | 9 | ANSI_MATCHR = /\x1b.*?[jkmsuABGKH]/ 10 | ANSI_COLORS = { 11 | :black => 30, 12 | :red => 31, 13 | :green => 32, 14 | :yellow => 33, 15 | :blue => 34, 16 | :magenta => 35, 17 | :cyan => 36, 18 | :white => 37, 19 | :bold => 1 20 | } 21 | 22 | # -------------------------------------------------------------------------- 23 | # Allows you to check if a string currently has ansi. 24 | # -------------------------------------------------------------------------- 25 | 26 | def has_ansi?(str) 27 | str.match(ANSI_MATCHR).is_a?( 28 | MatchData 29 | ) 30 | end 31 | 32 | # -------------------------------------------------------------------------- 33 | # Jump the cursor, moving it up and then back down to it's spot, allowing 34 | # you to do fancy things like multiple output (downloads) the way that Docker 35 | # does them in an async way without breaking term. 36 | # -------------------------------------------------------------------------- 37 | 38 | def ansi_jump(str, num) 39 | "\x1b[#{num}A#{clear_line(str)}\x1b[#{ 40 | num 41 | }B" 42 | end 43 | 44 | # -------------------------------------------------------------------------- 45 | 46 | def reset_ansi(str = "") 47 | "\x1b[0m#{ 48 | str 49 | }" 50 | end 51 | 52 | # -------------------------------------------------------------------------- 53 | 54 | def clear_line(str = "") 55 | "\x1b[2K\r#{ 56 | str 57 | }" 58 | end 59 | 60 | # -------------------------------------------------------------------------- 61 | # Strip ANSI from the current string, making it just a normal string. 62 | # -------------------------------------------------------------------------- 63 | 64 | def strip_ansi(str) 65 | str.gsub( 66 | ANSI_MATCHR, "" 67 | ) 68 | end 69 | 70 | # -------------------------------------------------------------------------- 71 | # Clear the screen's current view, so the user gets a clean output. 72 | # -------------------------------------------------------------------------- 73 | 74 | def clear_screen(str = "") 75 | "\x1b[H\x1b[2J#{ 76 | str 77 | }" 78 | end 79 | 80 | # -------------------------------------------------------------------------- 81 | 82 | def colorize(str = "", color) 83 | "\x1b[#{color}m#{str}\x1b[0m" 84 | end 85 | 86 | # -------------------------------------------------------------------------- 87 | 88 | Colorator::ANSI_COLORS.each do |color, code| 89 | define_singleton_method color do |str| 90 | colorize( 91 | str, code 92 | ) 93 | end 94 | end 95 | 96 | # -------------------------------------------------------------------------- 97 | 98 | class << self 99 | alias reset_color reset_ansi 100 | alias strip_color strip_ansi 101 | alias has_color? has_ansi? 102 | end 103 | 104 | # -------------------------------------------------------------------------- 105 | 106 | CORE_METHODS = ( 107 | public_methods - Object.methods 108 | ) 109 | end 110 | 111 | require "colorator/core_ext" 112 | --------------------------------------------------------------------------------