[DRE-commits] [ruby-awesome-print] 01/04: Imported Upstream version 1.2.0
Tim Potter
tpot-guest at moszumanska.debian.org
Wed Jul 30 01:08:26 UTC 2014
This is an automated email from the git hooks/post-receive script.
tpot-guest pushed a commit to branch master
in repository ruby-awesome-print.
commit de8b7327a18783b4a482f1dc8ca247f3740db941
Author: Tim Potter <tpot at hp.com>
Date: Fri Jul 25 12:11:01 2014 +1000
Imported Upstream version 1.2.0
---
.gitignore | 24 ++
CHANGELOG | 96 +++++
Gemfile | 3 +
Gemfile.lock | 26 ++
LICENSE | 22 +
README.md | 366 ++++++++++++++++
Rakefile | 11 +
lib/ap.rb | 10 +
lib/awesome_print.rb | 35 ++
lib/awesome_print/core_ext/array.rb | 81 ++++
lib/awesome_print/core_ext/class.rb | 22 +
lib/awesome_print/core_ext/kernel.rb | 26 ++
lib/awesome_print/core_ext/logger.rb | 20 +
lib/awesome_print/core_ext/method.rb | 21 +
lib/awesome_print/core_ext/object.rb | 22 +
lib/awesome_print/core_ext/string.rb | 31 ++
lib/awesome_print/ext/action_view.rb | 18 +
lib/awesome_print/ext/active_record.rb | 69 ++++
lib/awesome_print/ext/active_support.rb | 47 +++
lib/awesome_print/ext/mongo_mapper.rb | 121 ++++++
lib/awesome_print/ext/mongoid.rb | 65 +++
lib/awesome_print/ext/no_brainer.rb | 58 +++
lib/awesome_print/ext/nokogiri.rb | 45 ++
lib/awesome_print/ext/ripple.rb | 72 ++++
lib/awesome_print/ext/sequel.rb | 57 +++
lib/awesome_print/formatter.rb | 407 ++++++++++++++++++
lib/awesome_print/inspector.rb | 171 ++++++++
lib/awesome_print/version.rb | 10 +
metadata.yml | 117 ++++++
spec/colors_spec.rb | 106 +++++
spec/formats_spec.rb | 712 ++++++++++++++++++++++++++++++++
spec/methods_spec.rb | 459 ++++++++++++++++++++
spec/misc_spec.rb | 229 ++++++++++
spec/objects_spec.rb | 85 ++++
spec/spec_helper.rb | 64 +++
35 files changed, 3728 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..14f43a2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,24 @@
+## MAC OS
+.DS_Store
+
+## TEXTMATE
+*.tmproj
+tmtags
+
+## EMACS
+*~
+\#*
+.\#*
+
+## VIM
+*.swp
+
+## PROJECT::GENERAL
+coverage
+rdoc
+pkg
+Gemfile.lock
+
+## PROJECT::SPECIFIC
+.rvmrc
+.idea
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 0000000..f84e868
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,96 @@
+1.2.0 <-- NOTE: This is the *last* release supporting Ruby < v1.9.3 and Rails < v3.
+ - Added Sequel ORM plugin (Jonathan Davies)
+ - Added Ripple plugin (Ruby modeling layer for Riak, Scott Hyndman)
+ - Added NoBrainer plugin (Ruby ORM for RethinkDB, Nicolas Viennot)
+ - Added formatting for Ruby set objects (Richard Hall)
+ - Fixed HTML formatting (Mike McQuaid)
+ - Other minor bugs and enhancements
+
+1.1.0
+ - Objects are no longer recursively formatted by default. Reenable by using :raw => true option.
+ - ap(object) now returns nil when running under IRB or Pry
+ - Added support for Mongoid 3 and Moped (Nikolaj Nikolajsen)
+ - Improved formatting of MongoMapper objects (George .)
+ - ActiveRecord::Relation now renders as array (Dan Lynn)
+ - Formatting BigDecimal no longer looses precision (Evan Senter)
+ - Added AwesomePrint.irb! and AwesomePrint.pry! convenience methods
+ - Fixed conflict with the colorize gem
+ - Misc tweaks and bug fixes
+
+1.0.2
+ - Added formatting of Mongoid documents (Adam Doppelt)
+ - ActiveRecord objects display attributes only. Use :raw => true to display the entire object
+ - ActiveSupport::Date objects get formatted as regular Date
+ - Rails.logger.ap colorizes output based on ActiveSupport::LogSubscriber.colorize_logging (default is true)
+ - Improved formatting of methods array
+
+1.0.1
+ - Updated repo tags for Rubygems.org
+
+1.0.0 Thanksgiving edition
+ - Added ability to format *arbitrary* Ruby object
+ - Added :limit option to limit large output for arrays and hashes (Andrew Horsman)
+ - Improved HTML formatting when :html => true (Daniel Johnson)
+ - Added Mongoid extension (Adam Doppelt)
+ - Added Nokogiri extension (Adam Doppelt)
+ - Removed Jeweler gem dependency
+
+0.4.0
+ - 'ap object' now returns the object (Stephan Hagemann)
+ - Added :html => true option to enable HTML colors rather that ANSI (ex. Sinatra templates)
+ - Added AwesomePrint.force_colors! to allow color output on demand (Andrew O'Brien)
+ - Added MongoMapper formatter mixin (Elpizo Choi)
+ - Fixed formatting of methods array when object#method is overridden
+ - Fixed potential stack errors by checking whether AwesomePrint is already loaded
+ - Improved Ruby 1.8.6 and 1.8.7 compatibility
+ - Improved Windows compatibility (Viktar Basharymau)
+
+0.3.2
+ - Make sure Rails mixins get loaded in Rails console when required from .irbrc
+ - Fixed an issue with classes that define their own #send method (ex: Socket)
+ - Fixed compatibility issue with Liquid gem that defines Module#liquid_methods
+ - Fixed hash spec for Ruby < 1.9 where order of hash keys is not guaranteed
+ - Added :sorted_hash_keys option to sort hash keys (Ed Ruder)
+
+0.3.1 RubyConf X edition
+ - Fixed Ruby 1.8.6 compatibility issues (thanks, Tim!)
+ - Fixed stack overflow issue with Rails 2.3.x console
+
+0.3.0
+ - Display object.methods and family in human readable format
+ - Objects inherited from Array, Hash, File, Dir, and Struct are shown as their base class
+ - Added option to suppress array index in output (Sean Gallagher)
+ - Updated README on how to set up ~/.irbrc for MacRuby (Eloy Duran)
+ - Specs pass 100% with Ruby 1.8.7/RSpec 1.3 and Ruby 1.9.2/RSpec 2.0
+
+0.2.1
+ - ap can now be used within Rails templates (ex. <%= ap object %>)
+ - Added support for printing Struct
+
+0.2.0
+ - Added support for logger.ap (including Rails logger)
+ - Added support for HashWithIndifferentAccess from ActiveSupport
+ - ap now works with scripts that use ActiveRecord/ActiveSupport outside Rails
+ - ap now correctly shows file and directory names with fancy characters (shell escape)
+
+0.1.4
+ - Format BigDecimal and Rational objects as Float scalars
+ - Explicit options parameter can override custom defaults
+ - Custom defaults are not interfering when running specs
+ - Custom defaults now work correctly with Ruby 1.9.x
+
+0.1.3
+ - Added support for setting custom defaults in ~/.aprc
+
+0.1.2
+ - Correctly handle empty arrays and hashes
+ - Use alias_method instead of alias (fixes non-tty method aliasing)
+ - Added awesome_inspect method
+
+0.1.1
+ - Added support for tableless ActiveRecord models
+ - Left align hash keys if @options[:indent] is negative
+
+0.1.0
+ - Initial Release.
+
\ No newline at end of file
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..b47bb79
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,3 @@
+source "https://rubygems.org"
+gemspec
+
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..285fa51
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,26 @@
+PATH
+ remote: .
+ specs:
+ awesome_print (1.1.0)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ diff-lcs (1.1.3)
+ fakefs (0.3.2)
+ rspec (2.11.0)
+ rspec-core (~> 2.11.0)
+ rspec-expectations (~> 2.11.0)
+ rspec-mocks (~> 2.11.0)
+ rspec-core (2.11.1)
+ rspec-expectations (2.11.2)
+ diff-lcs (~> 1.1.3)
+ rspec-mocks (2.11.2)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ awesome_print!
+ fakefs (>= 0.2.1)
+ rspec (>= 2.6.0)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..c835968
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2010-2013 Michael Dvorkin
+http://www.dvorkin.net
+%w(mike dvorkin.net) * "@" || %w(mike fatfreecrm.com) * "@"
+
+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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..689fafd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,366 @@
+## Awesome Print ##
+Awesome Print is a Ruby library that pretty prints Ruby objects in full color
+exposing their internal structure with proper indentation. Rails ActiveRecord
+objects and usage within Rails templates are supported via included mixins.
+
+__NOTE__: awesome_print v1.2.0 is the last release supporting Ruby versions
+prior to v1.9.3 and Rails versions prior to v3.0. The upcoming awesome_print
+v2.0 will *require* Ruby v1.9.3 or later and Rails v3.0 or later.
+
+### Installation ###
+ # Installing as Ruby gem
+ $ gem install awesome_print
+
+ # Cloning the repository
+ $ git clone git://github.com/michaeldv/awesome_print.git
+
+### Usage ###
+
+```ruby
+require "awesome_print"
+ap object, options = {}
+```
+
+Default options:
+
+```ruby
+:indent => 4, # Indent using 4 spaces.
+:index => true, # Display array indices.
+:html => false, # Use ANSI color codes rather than HTML.
+:multiline => true, # Display in multiple lines.
+:plain => false, # Use colors.
+:raw => false, # Do not recursively format object instance variables.
+:sort_keys => false, # Do not sort hash keys.
+:limit => false, # Limit large output for arrays and hashes. Set to a boolean or integer.
+:color => {
+ :args => :pale,
+ :array => :white,
+ :bigdecimal => :blue,
+ :class => :yellow,
+ :date => :greenish,
+ :falseclass => :red,
+ :fixnum => :blue,
+ :float => :blue,
+ :hash => :pale,
+ :keyword => :cyan,
+ :method => :purpleish,
+ :nilclass => :red,
+ :rational => :blue,
+ :string => :yellowish,
+ :struct => :pale,
+ :symbol => :cyanish,
+ :time => :greenish,
+ :trueclass => :green,
+ :variable => :cyanish
+}
+```
+
+Supported color names:
+
+```ruby
+:gray, :red, :green, :yellow, :blue, :purple, :cyan, :white
+:black, :redish, :greenish, :yellowish, :blueish, :purpleish, :cyanish, :pale
+```
+
+### Examples ###
+
+```ruby
+$ cat > 1.rb
+require "awesome_print"
+data = [ false, 42, %w(forty two), { :now => Time.now, :class => Time.now.class, :distance => 42e42 } ]
+ap data
+^D
+$ ruby 1.rb
+[
+ [0] false,
+ [1] 42,
+ [2] [
+ [0] "forty",
+ [1] "two"
+ ],
+ [3] {
+ :class => Time < Object,
+ :now => Fri Apr 02 19:55:53 -0700 2010,
+ :distance => 4.2e+43
+ }
+]
+
+$ cat > 2.rb
+require "awesome_print"
+data = { :now => Time.now, :class => Time.now.class, :distance => 42e42 }
+ap data, :indent => -2 # <-- Left align hash keys.
+^D
+$ ruby 2.rb
+{
+ :class => Time < Object,
+ :now => Fri Apr 02 19:55:53 -0700 2010,
+ :distance => 4.2e+43
+}
+
+$ cat > 3.rb
+require "awesome_print"
+data = [ false, 42, %w(forty two) ]
+data << data # <-- Nested array.
+ap data, :multiline => false
+^D
+$ ruby 3.rb
+[ false, 42, [ "forty", "two" ], [...] ]
+
+$ cat > 4.rb
+require "awesome_print"
+class Hello
+ def self.world(x, y, z = nil, &blk)
+ end
+end
+ap Hello.methods - Class.methods
+^D
+$ ruby 4.rb
+[
+ [0] world(x, y, *z, &blk) Hello
+]
+
+$ cat > 5.rb
+require "awesome_print"
+ap (''.methods - Object.methods).grep(/!/)
+^D
+$ ruby 5.rb
+[
+ [ 0] capitalize!() String
+ [ 1] chomp!(*arg1) String
+ [ 2] chop!() String
+ [ 3] delete!(*arg1) String
+ [ 4] downcase!() String
+ [ 5] encode!(*arg1) String
+ [ 6] gsub!(*arg1) String
+ [ 7] lstrip!() String
+ [ 8] next!() String
+ [ 9] reverse!() String
+ [10] rstrip!() String
+ [11] slice!(*arg1) String
+ [12] squeeze!(*arg1) String
+ [13] strip!() String
+ [14] sub!(*arg1) String
+ [15] succ!() String
+ [16] swapcase!() String
+ [17] tr!(arg1, arg2) String
+ [18] tr_s!(arg1, arg2) String
+ [19] upcase!() String
+]
+
+$ cat > 6.rb
+require "awesome_print"
+ap 42 == ap(42)
+^D
+$ ruby 6.rb
+42
+true
+$ cat 7.rb
+require "awesome_print"
+some_array = (1..1000).to_a
+ap some_array, :limit => true
+^D
+$ ruby 7.rb
+[
+ [ 0] 1,
+ [ 1] 2,
+ [ 2] 3,
+ [ 3] .. [996],
+ [997] 998,
+ [998] 999,
+ [999] 1000
+]
+
+$ cat 8.rb
+require "awesome_print"
+some_array = (1..1000).to_a
+ap some_array, :limit => 5
+^D
+$ ruby 8.rb
+[
+ [ 0] 1,
+ [ 1] 2,
+ [ 2] .. [997],
+ [998] 999,
+ [999] 1000
+]
+```
+
+### Example (Rails console) ###
+```ruby
+$ rails console
+rails> require "awesome_print"
+rails> ap Account.limit(2).all
+[
+ [0] #<Account:0x1033220b8> {
+ :id => 1,
+ :user_id => 5,
+ :assigned_to => 7,
+ :name => "Hayes-DuBuque",
+ :access => "Public",
+ :website => "http://www.hayesdubuque.com",
+ :toll_free_phone => "1-800-932-6571",
+ :phone => "(111)549-5002",
+ :fax => "(349)415-2266",
+ :deleted_at => nil,
+ :created_at => Sat, 06 Mar 2010 09:46:10 UTC +00:00,
+ :updated_at => Sat, 06 Mar 2010 16:33:10 UTC +00:00,
+ :email => "info at hayesdubuque.com",
+ :background_info => nil
+ },
+ [1] #<Account:0x103321ff0> {
+ :id => 2,
+ :user_id => 4,
+ :assigned_to => 4,
+ :name => "Ziemann-Streich",
+ :access => "Public",
+ :website => "http://www.ziemannstreich.com",
+ :toll_free_phone => "1-800-871-0619",
+ :phone => "(042)056-1534",
+ :fax => "(106)017-8792",
+ :deleted_at => nil,
+ :created_at => Tue, 09 Feb 2010 13:32:10 UTC +00:00,
+ :updated_at => Tue, 09 Feb 2010 20:05:01 UTC +00:00,
+ :email => "info at ziemannstreich.com",
+ :background_info => nil
+ }
+]
+rails> ap Account
+class Account < ActiveRecord::Base {
+ :id => :integer,
+ :user_id => :integer,
+ :assigned_to => :integer,
+ :name => :string,
+ :access => :string,
+ :website => :string,
+ :toll_free_phone => :string,
+ :phone => :string,
+ :fax => :string,
+ :deleted_at => :datetime,
+ :created_at => :datetime,
+ :updated_at => :datetime,
+ :email => :string,
+ :background_info => :string
+}
+rails>
+```
+
+### IRB integration ###
+To use awesome_print as default formatter in irb and Rails console add the following
+code to your ~/.irbrc file:
+
+```ruby
+require "awesome_print"
+AwesomePrint.irb!
+```
+
+### PRY integration ###
+If you miss awesome_print's way of formatting output, here's how you can use it in place
+of the formatting which comes with pry. Add the following code to your ~/.pryrc:
+
+```ruby
+require "awesome_print"
+AwesomePrint.pry!
+```
+
+### Logger Convenience Method ###
+awesome_print adds the 'ap' method to the Logger and ActiveSupport::BufferedLogger classes
+letting you call:
+
+ logger.ap object
+
+By default, this logs at the :debug level. You can override that globally with:
+
+ :log_level => :info
+
+in the custom defaults (see below). You can also override on a per call basis with:
+
+ logger.ap object, :warn
+
+### ActionView Convenience Method ###
+awesome_print adds the 'ap' method to the ActionView::Base class making it available
+within Rails templates. For example:
+
+ <%= ap @accounts.first %> # ERB
+ != ap @accounts.first # HAML
+
+With other web frameworks (ex: in Sinatra templates) you can explicitly request HTML
+formatting:
+
+ <%= ap @accounts.first, :html => true %>
+
+### Setting Custom Defaults ###
+You can set your own default options by creating ``.aprc`` file in your home
+directory. Within that file assign your defaults to ``AwesomePrint.defaults``.
+For example:
+
+```ruby
+# ~/.aprc file.
+AwesomePrint.defaults = {
+ :indent => -2,
+ :color => {
+ :hash => :pale,
+ :class => :white
+ }
+}
+```
+
+### Running Specs ###
+
+ $ gem install rspec # RSpec 2.x is the requirement.
+ $ rake spec # Run the entire spec suite.
+ $ rspec spec/logger_spec.rb # Run individual spec file.
+
+### Note on Patches/Pull Requests ###
+* Fork the project on Github.
+* Make your feature addition or bug fix.
+* Add specs for it, making sure $ rake spec is all green.
+* Commit, do not mess with rakefile, version, or history.
+* Send commit URL (*do not* send pull requests).
+
+### Contributors ###
+Special thanks goes to awesome team of contributors, namely:
+
+* 6fusion.com -- https://github.com/6fusion
+* Adam Doppelt -- https://github.com/gurgeous
+* Andrew O'Brien -- https://github.com/AndrewO
+* Andrew Horsman -- https://github.com/basicxman
+* Barry Allard -- https://github.com/steakknife
+* Benoit Daloze -- http://github.com/eregon
+* Brandon Zylstra -- https://github.com/brandondrew
+* Dan Lynn -- https://github.com/danlynn
+* Daniel Johnson -- https://github.com/adhd360
+* Daniel Bretoi -- http://github.com/danielb2
+* Eloy Duran -- http://github.com/alloy
+* Elpizo Choi -- https://github.com/fuJiin
+* Evan Senter -- https://github.com/evansenter
+* George . -- https://github.com/gardelea
+* Greg Weber -- https://github.com/gregwebs
+* Jan Vansteenkiste -- https://github.com/vStone
+* Jeff Felchner -- https://github.com/jfelchner
+* Jonathan Davies -- send your Github URL ;-)
+* Kevin Olbrich -- https://github.com/olbrich
+* Matthew Schulkind -- https://github.com/mschulkind
+* Mike McQuaid -- https://github.com/mikemcquaid
+* Nami-Doc -- https://github.com/Nami-Doc
+* Nicolas Viennot -- https://github.com/nviennot
+* Nikolaj Nikolajsen -- https://github.com/nikolajsen
+* Richard Hall -- https://github.com/richardardrichard
+* Ryan Schlesinger -- https://github.com/ryansch
+* Scott Hyndman -- https://github.com/shyndman
+* Sean Gallagher -- http://github.com/torandu
+* Stephan Hagemann -- https://github.com/shageman
+* Tim Harper -- http://github.com/timcharper
+* Tobias Crawley -- http://github.com/tobias
+* Thibaut Barrère -- https://github.com/thbar
+* Trevor Wennblom -- https://github.com/trevor
+* vfrride -- https://github.com/vfrride
+* Viktar Basharymau -- https://github.com/DNNX
+
+### License ###
+Copyright (c) 2010-2013 Michael Dvorkin
+
+http://www.dvorkin.net
+
+%w(mike dvorkin.net) * "@" || "twitter.com/mid"
+
+Released under the MIT license. See LICENSE file for details.
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..f2bc512
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,11 @@
+require "bundler"
+Bundler::GemHelper.install_tasks
+
+task :default => :spec
+
+desc "Run all awesome_print gem specs"
+task :spec do
+ # Run plain rspec command without RSpec::Core::RakeTask overrides.
+ exec "rspec -c spec"
+end
+
diff --git a/lib/ap.rb b/lib/ap.rb
new file mode 100755
index 0000000..793a9af
--- /dev/null
+++ b/lib/ap.rb
@@ -0,0 +1,10 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+#
+# Keeping this for backwards compatibility to allow
+# require "ap"
+#
+require File.dirname(__FILE__) + "/awesome_print"
diff --git a/lib/awesome_print.rb b/lib/awesome_print.rb
new file mode 100755
index 0000000..98d0c74
--- /dev/null
+++ b/lib/awesome_print.rb
@@ -0,0 +1,35 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+#
+# AwesomePrint might be loaded implicitly through ~/.irbrc or ~/.pryrc
+# so do nothing for subsequent requires.
+#
+unless defined?(AwesomePrint::Inspector)
+ %w(array string method object class kernel).each do |file|
+ require File.dirname(__FILE__) + "/awesome_print/core_ext/#{file}"
+ end
+
+ require File.dirname(__FILE__) + "/awesome_print/inspector"
+ require File.dirname(__FILE__) + "/awesome_print/formatter"
+ require File.dirname(__FILE__) + "/awesome_print/version"
+ require File.dirname(__FILE__) + "/awesome_print/core_ext/logger" if defined?(Logger)
+ #
+ # Load the following under normal circumstances as well as in Rails
+ # console when required from ~/.irbrc or ~/.pryrc.
+ #
+ require File.dirname(__FILE__) + "/awesome_print/ext/active_record" if defined?(ActiveRecord) || AwesomePrint.rails_console?
+ require File.dirname(__FILE__) + "/awesome_print/ext/active_support" if defined?(ActiveSupport) || AwesomePrint.rails_console?
+ #
+ # Load remaining extensions.
+ #
+ require File.dirname(__FILE__) + "/awesome_print/ext/action_view" if defined?(ActionView::Base)
+ require File.dirname(__FILE__) + "/awesome_print/ext/mongo_mapper" if defined?(MongoMapper)
+ require File.dirname(__FILE__) + "/awesome_print/ext/mongoid" if defined?(Mongoid)
+ require File.dirname(__FILE__) + "/awesome_print/ext/nokogiri" if defined?(Nokogiri)
+ require File.dirname(__FILE__) + "/awesome_print/ext/no_brainer" if defined?(NoBrainer)
+ require File.dirname(__FILE__) + "/awesome_print/ext/ripple" if defined?(Ripple)
+ require File.dirname(__FILE__) + "/awesome_print/ext/sequel" if defined?(Sequel)
+end
diff --git a/lib/awesome_print/core_ext/array.rb b/lib/awesome_print/core_ext/array.rb
new file mode 100644
index 0000000..ec1a1cd
--- /dev/null
+++ b/lib/awesome_print/core_ext/array.rb
@@ -0,0 +1,81 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+#
+# The following makes it possible to invoke awesome_print while performing
+# operations on method arrays, ex:
+#
+# ap [].methods - Object.methods
+# ap ''.methods.grep(/!|\?/)
+#
+# If you could think of a better way please let me know :-)
+#
+class Array #:nodoc:
+ [ :-, :& ].each do |operator|
+ original_operator = instance_method(operator)
+
+ define_method operator do |*args|
+ arr = original_operator.bind(self).call(*args)
+ if self.instance_variable_defined?('@__awesome_methods__')
+ arr.instance_variable_set('@__awesome_methods__', self.instance_variable_get('@__awesome_methods__'))
+ arr.sort! { |a, b| a.to_s <=> b.to_s } # Need the block since Ruby 1.8.x can't sort arrays of symbols.
+ end
+ arr
+ end
+ end
+ #
+ # Intercepting Array#grep needs a special treatment since grep accepts
+ # an optional block.
+ #
+ alias :original_grep :grep
+ def grep(pattern, &blk)
+ #
+ # The following looks rather insane and I've sent numerous hours trying
+ # to figure it out. The problem is that if grep gets called with the
+ # block, for example:
+ #
+ # [].methods.grep(/(.+?)_by/) { $1.to_sym }
+ #
+ # ...then simple:
+ #
+ # original_grep(pattern, &blk)
+ #
+ # doesn't set $1 within the grep block which causes nil.to_sym failure.
+ # The workaround below has been tested with Ruby 1.8.7/Rails 2.3.8 and
+ # Ruby 1.9.2/Rails 3.0.0. For more info see the following thread dating
+ # back to 2003 when Ruby 1.8.0 was as fresh off the grill as Ruby 1.9.2
+ # is in 2010 :-)
+ #
+ # http://www.justskins.com/forums/bug-when-rerouting-string-52852.html
+ #
+ # BTW, if you figure out a better way of intercepting Array#grep please
+ # let me know: twitter.com/mid -- or just say hi so I know you've read
+ # the comment :-)
+ #
+ arr = unless blk
+ original_grep(pattern)
+ else
+ original_grep(pattern) do |match|
+ #
+ # The binding can only be used with Ruby-defined methods, therefore
+ # we must rescue potential "ArgumentError: Can't create Binding from
+ # C level Proc" error.
+ #
+ # For example, the following raises ArgumentError since #succ method
+ # is defined in C.
+ #
+ # [ 0, 1, 2, 3, 4 ].grep(1..2, &:succ)
+ #
+ eval("%Q/#{match.to_s.gsub('/', '\/')}/ =~ #{pattern.inspect}", blk.binding) rescue ArgumentError
+ yield match
+ end
+ end
+ if self.instance_variable_defined?('@__awesome_methods__')
+ arr.instance_variable_set('@__awesome_methods__', self.instance_variable_get('@__awesome_methods__'))
+ arr.reject! { |item| !(item.is_a?(Symbol) || item.is_a?(String)) } # grep block might return crap.
+ end
+ arr
+ end
+end
diff --git a/lib/awesome_print/core_ext/class.rb b/lib/awesome_print/core_ext/class.rb
new file mode 100644
index 0000000..5faac7e
--- /dev/null
+++ b/lib/awesome_print/core_ext/class.rb
@@ -0,0 +1,22 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+class Class #:nodoc:
+ #
+ # Intercept methods below to inject @__awesome_print__ instance variable
+ # so we know it is the *methods* array when formatting an array.
+ #
+ # Remaining public/private etc. '_methods' are handled in core_ext/object.rb.
+ #
+ %w(instance_methods private_instance_methods protected_instance_methods public_instance_methods).each do |name|
+ original_method = instance_method(name)
+
+ define_method name do |*args|
+ methods = original_method.bind(self).call(*args)
+ methods.instance_variable_set('@__awesome_methods__', self)
+ methods
+ end
+ end
+end
diff --git a/lib/awesome_print/core_ext/kernel.rb b/lib/awesome_print/core_ext/kernel.rb
new file mode 100644
index 0000000..a87d19c
--- /dev/null
+++ b/lib/awesome_print/core_ext/kernel.rb
@@ -0,0 +1,26 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module Kernel
+
+ def ai(options = {})
+ ap = AwesomePrint::Inspector.new(options)
+ awesome = ap.awesome self
+ if options[:html]
+ awesome = "<pre>#{awesome}</pre>"
+ awesome = awesome.html_safe if defined? ActiveSupport
+ end
+ awesome
+ end
+ alias :awesome_inspect :ai
+
+ def ap(object, options = {})
+ puts object.ai(options)
+ object unless AwesomePrint.console?
+ end
+ alias :awesome_print :ap
+
+ module_function :ap
+end
diff --git a/lib/awesome_print/core_ext/logger.rb b/lib/awesome_print/core_ext/logger.rb
new file mode 100644
index 0000000..516609c
--- /dev/null
+++ b/lib/awesome_print/core_ext/logger.rb
@@ -0,0 +1,20 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+ module Logger
+
+ # Add ap method to logger
+ #------------------------------------------------------------------------------
+ def ap(object, level = nil)
+ level ||= AwesomePrint.defaults[:log_level] if AwesomePrint.defaults
+ level ||= :debug
+ send level, object.ai
+ end
+ end
+end
+
+Logger.send(:include, AwesomePrint::Logger)
+ActiveSupport::BufferedLogger.send(:include, AwesomePrint::Logger) if defined?(ActiveSupport::BufferedLogger)
diff --git a/lib/awesome_print/core_ext/method.rb b/lib/awesome_print/core_ext/method.rb
new file mode 100644
index 0000000..a30b148
--- /dev/null
+++ b/lib/awesome_print/core_ext/method.rb
@@ -0,0 +1,21 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+#
+# Method#name was intorduced in Ruby 1.8.7 so we define it here as necessary.
+#
+unless nil.method(:class).respond_to?(:name)
+ class Method
+ def name
+ inspect.split(/[#.>]/)[-1]
+ end
+ end
+
+ class UnboundMethod
+ def name
+ inspect.split(/[#.>]/)[-1]
+ end
+ end
+end
\ No newline at end of file
diff --git a/lib/awesome_print/core_ext/object.rb b/lib/awesome_print/core_ext/object.rb
new file mode 100644
index 0000000..c58e279
--- /dev/null
+++ b/lib/awesome_print/core_ext/object.rb
@@ -0,0 +1,22 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+class Object #:nodoc:
+ #
+ # Intercept methods below to inject @__awesome_print__ instance variable
+ # so we know it is the *methods* array when formatting an array.
+ #
+ # Remaining instance '_methods' are handled in core_ext/class.rb.
+ #
+ %w(methods private_methods protected_methods public_methods singleton_methods).each do |name|
+ original_method = instance_method(name)
+
+ define_method name do |*args|
+ methods = original_method.bind(self).call(*args)
+ methods.instance_variable_set('@__awesome_methods__', self)
+ methods
+ end
+ end
+end
diff --git a/lib/awesome_print/core_ext/string.rb b/lib/awesome_print/core_ext/string.rb
new file mode 100644
index 0000000..3fa1ed9
--- /dev/null
+++ b/lib/awesome_print/core_ext/string.rb
@@ -0,0 +1,31 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+class String
+ #
+ # ANSI color codes:
+ # \e => escape
+ # 30 => color base
+ # 1 => bright
+ # 0 => normal
+ #
+ # For HTML coloring we use <kbd> tag instead of <span> to require monospace
+ # font. Note that beloved <tt> has been removed from HTML5.
+ #
+ %w(gray red green yellow blue purple cyan white).zip(
+ %w(black darkred darkgreen brown navy darkmagenta darkcyan slategray)).each_with_index do |(color, shade), i|
+ define_method color do |*html|
+ html[0] ? %Q|<kbd style="color:#{color}">#{self}</kbd>| : "\e[1;#{30+i}m#{self}\e[0m"
+ end
+
+ define_method "#{color}ish" do |*html|
+ html[0] ? %Q|<kbd style="color:#{shade}">#{self}</kbd>| : "\e[0;#{30+i}m#{self}\e[0m"
+ end
+ end
+
+ alias :black :grayish
+ alias :pale :whiteish
+
+end
diff --git a/lib/awesome_print/ext/action_view.rb b/lib/awesome_print/ext/action_view.rb
new file mode 100644
index 0000000..c34e8d0
--- /dev/null
+++ b/lib/awesome_print/ext/action_view.rb
@@ -0,0 +1,18 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+ module ActionView
+
+ # Use HTML colors and add default "debug_dump" class to the resulting HTML.
+ def ap_debug(object, options = {})
+ object.ai(options.merge(:html => true)).sub(/^<pre([\s>])/, '<pre class="debug_dump"\\1')
+ end
+
+ alias_method :ap, :ap_debug
+ end
+end
+
+ActionView::Base.send(:include, AwesomePrint::ActionView)
diff --git a/lib/awesome_print/ext/active_record.rb b/lib/awesome_print/ext/active_record.rb
new file mode 100644
index 0000000..b15f3c6
--- /dev/null
+++ b/lib/awesome_print/ext/active_record.rb
@@ -0,0 +1,69 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+ module ActiveRecord
+
+ def self.included(base)
+ base.send :alias_method, :cast_without_active_record, :cast
+ base.send :alias_method, :cast, :cast_with_active_record
+ end
+
+ # Add ActiveRecord class names to the dispatcher pipeline.
+ #------------------------------------------------------------------------------
+ def cast_with_active_record(object, type)
+ cast = cast_without_active_record(object, type)
+ return cast if !defined?(::ActiveRecord)
+
+ if object.is_a?(::ActiveRecord::Base)
+ cast = :active_record_instance
+ elsif object.is_a?(Class) && object.ancestors.include?(::ActiveRecord::Base)
+ cast = :active_record_class
+ elsif type == :activerecord_relation
+ cast = :array
+ end
+ cast
+ end
+
+ private
+
+ # Format ActiveRecord instance object.
+ #
+ # NOTE: by default only instance attributes (i.e. columns) are shown. To format
+ # ActiveRecord instance as regular object showing its instance variables and
+ # accessors use :raw => true option:
+ #
+ # ap record, :raw => true
+ #
+ #------------------------------------------------------------------------------
+ def awesome_active_record_instance(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash)
+ return awesome_object(object) if @options[:raw]
+
+ data = object.class.column_names.inject(::ActiveSupport::OrderedHash.new) do |hash, name|
+ if object.has_attribute?(name) || object.new_record?
+ value = object.respond_to?(name) ? object.send(name) : object.read_attribute(name)
+ hash[name.to_sym] = value
+ end
+ hash
+ end
+ "#{object} " << awesome_hash(data)
+ end
+
+ # Format ActiveRecord class object.
+ #------------------------------------------------------------------------------
+ def awesome_active_record_class(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash) || !object.respond_to?(:columns) || object.to_s == "ActiveRecord::Base"
+
+ data = object.columns.inject(::ActiveSupport::OrderedHash.new) do |hash, c|
+ hash[c.name.to_sym] = c.type
+ hash
+ end
+ "class #{object} < #{object.superclass} " << awesome_hash(data)
+ end
+ end
+end
+
+AwesomePrint::Formatter.send(:include, AwesomePrint::ActiveRecord)
diff --git a/lib/awesome_print/ext/active_support.rb b/lib/awesome_print/ext/active_support.rb
new file mode 100644
index 0000000..2774990
--- /dev/null
+++ b/lib/awesome_print/ext/active_support.rb
@@ -0,0 +1,47 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+ module ActiveSupport
+
+ def self.included(base)
+ base.send :alias_method, :cast_without_active_support, :cast
+ base.send :alias_method, :cast, :cast_with_active_support
+ end
+
+ def cast_with_active_support(object, type)
+ cast = cast_without_active_support(object, type)
+ if defined?(::ActiveSupport) && defined?(::HashWithIndifferentAccess)
+ if (defined?(::ActiveSupport::TimeWithZone) && object.is_a?(::ActiveSupport::TimeWithZone)) || object.is_a?(::Date)
+ cast = :active_support_time
+ elsif object.is_a?(::HashWithIndifferentAccess)
+ cast = :hash_with_indifferent_access
+ end
+ end
+ cast
+ end
+
+ # Format ActiveSupport::TimeWithZone as standard Time.
+ #------------------------------------------------------------------------------
+ def awesome_active_support_time(object)
+ colorize(object.inspect, :time)
+ end
+
+ # Format HashWithIndifferentAccess as standard Hash.
+ #------------------------------------------------------------------------------
+ def awesome_hash_with_indifferent_access(object)
+ awesome_hash(object)
+ end
+ end
+end
+
+AwesomePrint::Formatter.send(:include, AwesomePrint::ActiveSupport)
+#
+# Colorize Rails logs.
+#
+if defined?(ActiveSupport::LogSubscriber)
+ AwesomePrint.force_colors! ActiveSupport::LogSubscriber.colorize_logging
+end
+
diff --git a/lib/awesome_print/ext/mongo_mapper.rb b/lib/awesome_print/ext/mongo_mapper.rb
new file mode 100644
index 0000000..4e7a81a
--- /dev/null
+++ b/lib/awesome_print/ext/mongo_mapper.rb
@@ -0,0 +1,121 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+ module MongoMapper
+
+ def self.included(base)
+ base.send :alias_method, :cast_without_mongo_mapper, :cast
+ base.send :alias_method, :cast, :cast_with_mongo_mapper
+ end
+
+ # Add MongoMapper class names to the dispatcher pipeline.
+ #------------------------------------------------------------------------------
+ def cast_with_mongo_mapper(object, type)
+ apply_default_mongo_mapper_options
+ cast = cast_without_mongo_mapper(object, type)
+
+ if defined?(::MongoMapper::Document)
+ if object.is_a?(Class) && (object.ancestors & [ ::MongoMapper::Document, ::MongoMapper::EmbeddedDocument ]).size > 0
+ cast = :mongo_mapper_class
+ elsif object.is_a?(::MongoMapper::Document) || object.is_a?(::MongoMapper::EmbeddedDocument)
+ cast = :mongo_mapper_instance
+ elsif object.is_a?(::MongoMapper::Plugins::Associations::Base)
+ cast = :mongo_mapper_association
+ elsif object.is_a?(::BSON::ObjectId)
+ cast = :mongo_mapper_bson_id
+ end
+ end
+
+ cast
+ end
+
+ # Format MongoMapper class object.
+ #------------------------------------------------------------------------------
+ def awesome_mongo_mapper_class(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash) || !object.respond_to?(:keys)
+
+ data = object.keys.sort.inject(::ActiveSupport::OrderedHash.new) do |hash, c|
+ hash[c.first] = (c.last.type || "undefined").to_s.underscore.intern
+ hash
+ end
+
+ # Add in associations
+ if @options[:mongo_mapper][:show_associations]
+ object.associations.each do |name, assoc|
+ data[name.to_s] = assoc
+ end
+ end
+
+ "class #{object} < #{object.superclass} " << awesome_hash(data)
+ end
+
+ # Format MongoMapper instance object.
+ #
+ # NOTE: by default only instance attributes (i.e. keys) are shown. To format
+ # MongoMapper instance as regular object showing its instance variables and
+ # accessors use :raw => true option:
+ #
+ # ap record, :raw => true
+ #
+ #------------------------------------------------------------------------------
+ def awesome_mongo_mapper_instance(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash)
+ return awesome_object(object) if @options[:raw]
+
+ data = object.keys.keys.sort_by{|k| k}.inject(::ActiveSupport::OrderedHash.new) do |hash, name|
+ hash[name] = object[name]
+ hash
+ end
+
+ # Add in associations
+ if @options[:mongo_mapper][:show_associations]
+ object.associations.each do |name, assoc|
+ if @options[:mongo_mapper][:inline_embedded] and assoc.embeddable?
+ data[name.to_s] = object.send(name)
+ else
+ data[name.to_s] = assoc
+ end
+ end
+ end
+
+ label = object.to_s
+ label = "#{colorize('embedded', :assoc)} #{label}" if object.is_a?(::MongoMapper::EmbeddedDocument)
+
+ "#{label} " << awesome_hash(data)
+ end
+
+ # Format MongoMapper association object.
+ #------------------------------------------------------------------------------
+ def awesome_mongo_mapper_association(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash)
+ return awesome_object(object) if @options[:raw]
+
+ association = object.class.name.split('::').last.titleize.downcase.sub(/ association$/,'')
+ association = "embeds #{association}" if object.embeddable?
+ class_name = object.class_name
+
+ "#{colorize(association, :assoc)} #{colorize(class_name, :class)}"
+ end
+
+ # Format BSON::ObjectId
+ #------------------------------------------------------------------------------
+ def awesome_mongo_mapper_bson_id(object)
+ object.inspect
+ end
+
+ private
+
+ def apply_default_mongo_mapper_options
+ @options[:color][:assoc] ||= :greenish
+ @options[:mongo_mapper] ||= {
+ :show_associations => false, # Display association data for MongoMapper documents and classes.
+ :inline_embedded => false # Display embedded associations inline with MongoMapper documents.
+ }
+ end
+ end
+end
+
+AwesomePrint::Formatter.send(:include, AwesomePrint::MongoMapper)
diff --git a/lib/awesome_print/ext/mongoid.rb b/lib/awesome_print/ext/mongoid.rb
new file mode 100644
index 0000000..7f8b8e0
--- /dev/null
+++ b/lib/awesome_print/ext/mongoid.rb
@@ -0,0 +1,65 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+ module Mongoid
+
+ def self.included(base)
+ base.send :alias_method, :cast_without_mongoid, :cast
+ base.send :alias_method, :cast, :cast_with_mongoid
+ end
+
+ # Add Mongoid class names to the dispatcher pipeline.
+ #------------------------------------------------------------------------------
+ def cast_with_mongoid(object, type)
+ cast = cast_without_mongoid(object, type)
+ if defined?(::Mongoid::Document)
+ if object.is_a?(Class) && object.ancestors.include?(::Mongoid::Document)
+ cast = :mongoid_class
+ elsif object.class.ancestors.include?(::Mongoid::Document)
+ cast = :mongoid_document
+ elsif (defined?(::BSON) && object.is_a?(::BSON::ObjectId)) || (defined?(::Moped) && object.is_a?(::Moped::BSON::ObjectId))
+ cast = :mongoid_bson_id
+ end
+ end
+ cast
+ end
+
+ # Format Mongoid class object.
+ #------------------------------------------------------------------------------
+ def awesome_mongoid_class(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash) || !object.respond_to?(:fields)
+
+ data = object.fields.sort_by { |key| key }.inject(::ActiveSupport::OrderedHash.new) do |hash, c|
+ hash[c[1].name.to_sym] = (c[1].type || "undefined").to_s.underscore.intern
+ hash
+ end
+ "class #{object} < #{object.superclass} " << awesome_hash(data)
+ end
+
+ # Format Mongoid Document object.
+ #------------------------------------------------------------------------------
+ def awesome_mongoid_document(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash)
+
+ data = (object.attributes || {}).sort_by { |key| key }.inject(::ActiveSupport::OrderedHash.new) do |hash, c|
+ hash[c[0].to_sym] = c[1]
+ hash
+ end
+ if !object.errors.empty?
+ data = {:errors => object.errors, :attributes => data}
+ end
+ "#{object} #{awesome_hash(data)}"
+ end
+
+ # Format BSON::ObjectId
+ #------------------------------------------------------------------------------
+ def awesome_mongoid_bson_id(object)
+ object.inspect
+ end
+ end
+end
+
+AwesomePrint::Formatter.send(:include, AwesomePrint::Mongoid)
diff --git a/lib/awesome_print/ext/no_brainer.rb b/lib/awesome_print/ext/no_brainer.rb
new file mode 100644
index 0000000..431509d
--- /dev/null
+++ b/lib/awesome_print/ext/no_brainer.rb
@@ -0,0 +1,58 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+ module NoBrainer
+
+ def self.included(base)
+ base.send :alias_method, :cast_without_no_brainer, :cast
+ base.send :alias_method, :cast, :cast_with_no_brainer
+ end
+
+ # Add NoBrainer class names to the dispatcher pipeline.
+ #------------------------------------------------------------------------------
+ def cast_with_no_brainer(object, type)
+ cast = cast_without_no_brainer(object, type)
+ if defined?(::NoBrainer::Document)
+ if object.is_a?(Class) && object.ancestors.include?(::NoBrainer::Document)
+ cast = :no_brainer_class
+ elsif object.class.ancestors.include?(::NoBrainer::Document)
+ cast = :no_brainer_document
+ end
+ end
+ cast
+ end
+
+ # Format NoBrainer class object.
+ #------------------------------------------------------------------------------
+ def awesome_no_brainer_class(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash) || !object.respond_to?(:fields)
+
+ # We want id first
+ data = object.fields.sort_by { |key| key[0] == :id ? '_id' : key[0].to_s }.inject(::ActiveSupport::OrderedHash.new) do |hash, c|
+ hash[c[0]] = :object
+ hash
+ end
+ "class #{object} < #{object.superclass} " << awesome_hash(data)
+ end
+
+ # Format NoBrainer Document object.
+ #------------------------------------------------------------------------------
+ def awesome_no_brainer_document(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash)
+
+ data = object.attributes.sort_by { |key| key }.inject(::ActiveSupport::OrderedHash.new) do |hash, c|
+ hash[c[0].to_sym] = c[1]
+ hash
+ end
+ if !object.errors.empty?
+ data = {:errors => object.errors, :attributes => data}
+ end
+ "#{object} #{awesome_hash(data)}"
+ end
+ end
+end
+
+AwesomePrint::Formatter.send(:include, AwesomePrint::NoBrainer)
diff --git a/lib/awesome_print/ext/nokogiri.rb b/lib/awesome_print/ext/nokogiri.rb
new file mode 100644
index 0000000..4d26c92
--- /dev/null
+++ b/lib/awesome_print/ext/nokogiri.rb
@@ -0,0 +1,45 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+ module Nokogiri
+
+ def self.included(base)
+ base.send :alias_method, :cast_without_nokogiri, :cast
+ base.send :alias_method, :cast, :cast_with_nokogiri
+ end
+
+ # Add Nokogiri XML Node and NodeSet names to the dispatcher pipeline.
+ #------------------------------------------------------------------------------
+ def cast_with_nokogiri(object, type)
+ cast = cast_without_nokogiri(object, type)
+ if (defined?(::Nokogiri::XML::Node) && object.is_a?(::Nokogiri::XML::Node)) ||
+ (defined?(::Nokogiri::XML::NodeSet) && object.is_a?(::Nokogiri::XML::NodeSet))
+ cast = :nokogiri_xml_node
+ end
+ cast
+ end
+
+ #------------------------------------------------------------------------------
+ def awesome_nokogiri_xml_node(object)
+ if object.is_a?(::Nokogiri::XML::NodeSet) && object.empty?
+ return "[]"
+ end
+ xml = object.to_xml(:indent => 2)
+ #
+ # Colorize tag, id/class name, and contents.
+ #
+ xml.gsub!(/(<)(\/?[A-Za-z1-9]+)/) { |tag| "#{$1}#{colorize($2, :keyword)}" }
+ xml.gsub!(/(id|class)="[^"]+"/i) { |id| colorize(id, :class) }
+ xml.gsub!(/>([^<]+)</) do |contents|
+ contents = colorize($1, :trueclass) if contents && !contents.empty?
+ ">#{contents}<"
+ end
+ xml
+ end
+ end
+end
+
+AwesomePrint::Formatter.send(:include, AwesomePrint::Nokogiri)
diff --git a/lib/awesome_print/ext/ripple.rb b/lib/awesome_print/ext/ripple.rb
new file mode 100644
index 0000000..a98927a
--- /dev/null
+++ b/lib/awesome_print/ext/ripple.rb
@@ -0,0 +1,72 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+ module Ripple
+
+ def self.included(base)
+ base.send :alias_method, :cast_without_ripple, :cast
+ base.send :alias_method, :cast, :cast_with_ripple
+ end
+
+ # Add Ripple class names to the dispatcher pipeline.
+ #------------------------------------------------------------------------------
+ def cast_with_ripple(object, type)
+ cast = cast_without_ripple(object, type)
+ return cast if !defined?(::Ripple)
+
+ if object.is_a?(::Ripple::AttributeMethods) # Module used to access attributes across documents and embedded documents
+ cast = :ripple_document_instance
+ elsif object.is_a?(::Ripple::Properties) # Used to access property metadata on Ripple classes
+ cast = :ripple_document_class
+ end
+ cast
+ end
+
+ private
+
+ # Format Ripple instance object.
+ #
+ # NOTE: by default only instance attributes are shown. To format a Ripple document instance
+ # as a regular object showing its instance variables and accessors use :raw => true option:
+ #
+ # ap document, :raw => true
+ #
+ #------------------------------------------------------------------------------
+ def awesome_ripple_document_instance(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash)
+ return awesome_object(object) if @options[:raw]
+ exclude_assoc = @options[:exclude_assoc] or @options[:exclude_associations]
+
+ data = object.attributes.inject(::ActiveSupport::OrderedHash.new) do |hash, (name, value)|
+ hash[name.to_sym] = object.send(name)
+ hash
+ end
+
+ unless exclude_assoc
+ data = object.class.embedded_associations.inject(data) do |hash, assoc|
+ hash[assoc.name] = object.get_proxy(assoc) # Should always be array or Ripple::EmbeddedDocument for embedded associations
+ hash
+ end
+ end
+
+ "##{object} " << awesome_hash(data)
+ end
+
+ # Format Ripple class object.
+ #------------------------------------------------------------------------------
+ def awesome_ripple_document_class(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash) || !object.respond_to?(:properties)
+
+ data = object.properties.inject(::ActiveSupport::OrderedHash.new) do |hash, (name, defn)|
+ hash[name.to_sym] = defn.type.to_s.downcase.to_sym
+ hash
+ end
+ "class #{object} < #{object.superclass} " << awesome_hash(data)
+ end
+ end
+end
+
+AwesomePrint::Formatter.send(:include, AwesomePrint::Ripple)
diff --git a/lib/awesome_print/ext/sequel.rb b/lib/awesome_print/ext/sequel.rb
new file mode 100644
index 0000000..75cfa23
--- /dev/null
+++ b/lib/awesome_print/ext/sequel.rb
@@ -0,0 +1,57 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+ module Sequel
+
+ def self.included(base)
+ base.send :alias_method, :cast_without_sequel, :cast
+ base.send :alias_method, :cast, :cast_with_sequel
+ end
+
+ # Add Sequel class names to the dispatcher pipeline.
+ #------------------------------------------------------------------------------
+ def cast_with_sequel(object, type)
+ cast = cast_without_sequel(object, type)
+ if defined?(::Sequel::Model) && object.is_a?(::Sequel::Model)
+ cast = :sequel_document
+ elsif defined?(::Sequel::Model) && object.is_a?(Class) && object.ancestors.include?(::Sequel::Model)
+ cast = :sequel_model_class
+ elsif defined?(::Sequel::Mysql2::Dataset) && object.class.ancestors.include?(::Sequel::Mysql2::Dataset)
+ cast = :sequel_dataset
+ end
+ cast
+ end
+
+ # Format Sequel Document object.
+ #------------------------------------------------------------------------------
+ def awesome_sequel_document(object)
+ data = object.values.sort_by { |key| key.to_s }.inject({}) do |hash, c|
+ hash[c[0].to_sym] = c[1]
+ hash
+ end
+ if !object.errors.empty?
+ data = {:errors => object.errors, :values => data}
+ end
+ "#{object} #{awesome_hash(data)}"
+ end
+
+ # Format Sequel Dataset object.
+ #------------------------------------------------------------------------------
+ def awesome_sequel_dataset(dataset)
+ [awesome_array(dataset.to_a), awesome_print(dataset.sql)].join("\n")
+ end
+
+ # Format Sequel Model class.
+ #------------------------------------------------------------------------------
+ def awesome_sequel_model_class(object)
+ data = object.db_schema.inject({}) {|h, (name,data)| h.merge(name => data[:db_type])}
+ "class #{object} < #{object.superclass} " << awesome_hash(data)
+ end
+ end
+
+end
+
+AwesomePrint::Formatter.send(:include, AwesomePrint::Sequel)
diff --git a/lib/awesome_print/formatter.rb b/lib/awesome_print/formatter.rb
new file mode 100755
index 0000000..3019c50
--- /dev/null
+++ b/lib/awesome_print/formatter.rb
@@ -0,0 +1,407 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+autoload :CGI, "cgi"
+require "shellwords"
+
+module AwesomePrint
+ class Formatter
+
+ CORE = [ :array, :bigdecimal, :class, :dir, :file, :hash, :method, :rational, :set, :struct, :unboundmethod ]
+ DEFAULT_LIMIT_SIZE = 7
+
+ def initialize(inspector)
+ @inspector = inspector
+ @options = inspector.options
+ @indentation = @options[:indent].abs
+ end
+
+ # Main entry point to format an object.
+ #------------------------------------------------------------------------------
+ def format(object, type = nil)
+ core_class = cast(object, type)
+ awesome = if core_class != :self
+ send(:"awesome_#{core_class}", object) # Core formatters.
+ else
+ awesome_self(object, type) # Catch all that falls back to object.inspect.
+ end
+ awesome
+ end
+
+ # Hook this when adding custom formatters. Check out lib/awesome_print/ext
+ # directory for custom formatters that ship with awesome_print.
+ #------------------------------------------------------------------------------
+ def cast(object, type)
+ CORE.grep(type)[0] || :self
+ end
+
+ # Pick the color and apply it to the given string as necessary.
+ #------------------------------------------------------------------------------
+ def colorize(str, type)
+ str = CGI.escapeHTML(str) if @options[:html]
+ if @options[:plain] || !@options[:color][type] || !@inspector.colorize?
+ str
+ #
+ # Check if the string color method is defined by awesome_print and accepts
+ # html parameter or it has been overriden by some gem such as colorize.
+ #
+ elsif str.method(@options[:color][type]).arity == -1 # Accepts html parameter.
+ str.send(@options[:color][type], @options[:html])
+ else
+ str = %Q|<kbd style="color:#{@options[:color][type]}">#{str}</kbd>| if @options[:html]
+ str.send(@options[:color][type])
+ end
+ end
+
+
+ private
+
+ # Catch all method to format an arbitrary object.
+ #------------------------------------------------------------------------------
+ def awesome_self(object, type)
+ if @options[:raw] && object.instance_variables.any?
+ awesome_object(object)
+ elsif object == ENV
+ awesome_hash(object.to_hash)
+ else
+ colorize(object.inspect.to_s, type)
+ end
+ end
+
+ # Format an array.
+ #------------------------------------------------------------------------------
+ def awesome_array(a)
+ return "[]" if a == []
+
+ if a.instance_variable_defined?('@__awesome_methods__')
+ methods_array(a)
+ elsif @options[:multiline]
+ width = (a.size - 1).to_s.size
+
+ data = a.inject([]) do |arr, item|
+ index = indent
+ index << colorize("[#{arr.size.to_s.rjust(width)}] ", :array) if @options[:index]
+ indented do
+ arr << (index << @inspector.awesome(item))
+ end
+ end
+
+ data = limited(data, width) if should_be_limited?
+ "[\n" << data.join(",\n") << "\n#{outdent}]"
+ else
+ "[ " << a.map{ |item| @inspector.awesome(item) }.join(", ") << " ]"
+ end
+ end
+
+ # Format a hash. If @options[:indent] if negative left align hash keys.
+ #------------------------------------------------------------------------------
+ def awesome_hash(h)
+ return "{}" if h == {}
+
+ keys = @options[:sort_keys] ? h.keys.sort { |a, b| a.to_s <=> b.to_s } : h.keys
+ data = keys.map do |key|
+ plain_single_line do
+ [ @inspector.awesome(key), h[key] ]
+ end
+ end
+
+ width = data.map { |key, | key.size }.max || 0
+ width += @indentation if @options[:indent] > 0
+
+ data = data.map do |key, value|
+ indented do
+ align(key, width) << colorize(" => ", :hash) << @inspector.awesome(value)
+ end
+ end
+
+ data = limited(data, width, :hash => true) if should_be_limited?
+ if @options[:multiline]
+ "{\n" << data.join(",\n") << "\n#{outdent}}"
+ else
+ "{ #{data.join(', ')} }"
+ end
+ end
+
+ # Format an object.
+ #------------------------------------------------------------------------------
+ def awesome_object(o)
+ vars = o.instance_variables.map do |var|
+ property = var.to_s[1..-1].to_sym # to_s because of some monkey patching done by Puppet.
+ accessor = if o.respond_to?(:"#{property}=")
+ o.respond_to?(property) ? :accessor : :writer
+ else
+ o.respond_to?(property) ? :reader : nil
+ end
+ if accessor
+ [ "attr_#{accessor} :#{property}", var ]
+ else
+ [ var.to_s, var ]
+ end
+ end
+
+ data = vars.sort.map do |declaration, var|
+ key = left_aligned do
+ align(declaration, declaration.size)
+ end
+
+ unless @options[:plain]
+ if key =~ /(@\w+)/
+ key.sub!($1, colorize($1, :variable))
+ else
+ key.sub!(/(attr_\w+)\s(\:\w+)/, "#{colorize('\\1', :keyword)} #{colorize('\\2', :method)}")
+ end
+ end
+ indented do
+ key << colorize(" = ", :hash) + @inspector.awesome(o.instance_variable_get(var))
+ end
+ end
+ if @options[:multiline]
+ "#<#{awesome_instance(o)}\n#{data.join(%Q/,\n/)}\n#{outdent}>"
+ else
+ "#<#{awesome_instance(o)} #{data.join(', ')}>"
+ end
+ end
+
+ # Format a set.
+ #------------------------------------------------------------------------------
+ def awesome_set(s)
+ awesome_array(s.to_a)
+ end
+
+ # Format a Struct.
+ #------------------------------------------------------------------------------
+ def awesome_struct(s)
+ #
+ # The code is slightly uglier because of Ruby 1.8.6 quirks:
+ # awesome_hash(Hash[s.members.zip(s.values)]) <-- ArgumentError: odd number of arguments for Hash)
+ # awesome_hash(Hash[*s.members.zip(s.values).flatten]) <-- s.members returns strings, not symbols.
+ #
+ hash = {}
+ s.each_pair { |key, value| hash[key] = value }
+ awesome_hash(hash)
+ end
+
+ # Format Class object.
+ #------------------------------------------------------------------------------
+ def awesome_class(c)
+ if superclass = c.superclass # <-- Assign and test if nil.
+ colorize("#{c.inspect} < #{superclass}", :class)
+ else
+ colorize(c.inspect, :class)
+ end
+ end
+
+ # Format File object.
+ #------------------------------------------------------------------------------
+ def awesome_file(f)
+ ls = File.directory?(f) ? `ls -adlF #{f.path.shellescape}` : `ls -alF #{f.path.shellescape}`
+ colorize(ls.empty? ? f.inspect : "#{f.inspect}\n#{ls.chop}", :file)
+ end
+
+ # Format Dir object.
+ #------------------------------------------------------------------------------
+ def awesome_dir(d)
+ ls = `ls -alF #{d.path.shellescape}`
+ colorize(ls.empty? ? d.inspect : "#{d.inspect}\n#{ls.chop}", :dir)
+ end
+
+ # Format BigDecimal object.
+ #------------------------------------------------------------------------------
+ def awesome_bigdecimal(n)
+ colorize(n.to_s("F"), :bigdecimal)
+ end
+
+ # Format Rational object.
+ #------------------------------------------------------------------------------
+ def awesome_rational(n)
+ colorize(n.to_s, :rational)
+ end
+
+ # Format a method.
+ #------------------------------------------------------------------------------
+ def awesome_method(m)
+ name, args, owner = method_tuple(m)
+ "#{colorize(owner, :class)}##{colorize(name, :method)}#{colorize(args, :args)}"
+ end
+ alias :awesome_unboundmethod :awesome_method
+
+ # Format object instance.
+ #------------------------------------------------------------------------------
+ def awesome_instance(o)
+ "#{o.class}:0x%08x" % (o.__id__ * 2)
+ end
+
+ # Format object.methods array.
+ #------------------------------------------------------------------------------
+ def methods_array(a)
+ a.sort! { |x, y| x.to_s <=> y.to_s } # Can't simply a.sort! because of o.methods << [ :blah ]
+ object = a.instance_variable_get('@__awesome_methods__')
+ tuples = a.map do |name|
+ if name.is_a?(Symbol) || name.is_a?(String) # Ignore garbage, ex. 42.methods << [ :blah ]
+ tuple = if object.respond_to?(name, true) # Is this a regular method?
+ the_method = object.method(name) rescue nil # Avoid potential ArgumentError if object#method is overridden.
+ if the_method && the_method.respond_to?(:arity) # Is this original object#method?
+ method_tuple(the_method) # Yes, we are good.
+ end
+ elsif object.respond_to?(:instance_method) # Is this an unbound method?
+ method_tuple(object.instance_method(name)) rescue nil # Rescue to avoid NameError when the method is not
+ end # available (ex. File.lchmod on Ubuntu 12).
+ end
+ tuple || [ name.to_s, '(?)', '?' ] # Return WTF default if all the above fails.
+ end
+
+ width = (tuples.size - 1).to_s.size
+ name_width = tuples.map { |item| item[0].size }.max || 0
+ args_width = tuples.map { |item| item[1].size }.max || 0
+
+ data = tuples.inject([]) do |arr, item|
+ index = indent
+ index << "[#{arr.size.to_s.rjust(width)}]" if @options[:index]
+ indented do
+ arr << "#{index} #{colorize(item[0].rjust(name_width), :method)}#{colorize(item[1].ljust(args_width), :args)} #{colorize(item[2], :class)}"
+ end
+ end
+
+ "[\n" << data.join("\n") << "\n#{outdent}]"
+ end
+
+ # Return [ name, arguments, owner ] tuple for a given method.
+ #------------------------------------------------------------------------------
+ def method_tuple(method)
+ if method.respond_to?(:parameters) # Ruby 1.9.2+
+ # See http://ruby.runpaint.org/methods#method-objects-parameters
+ args = method.parameters.inject([]) do |arr, (type, name)|
+ name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
+ arr << case type
+ when :req then name.to_s
+ when :opt, :rest then "*#{name}"
+ when :block then "&#{name}"
+ else '?'
+ end
+ end
+ else # See http://ruby-doc.org/core/classes/Method.html#M001902
+ args = (1..method.arity.abs).map { |i| "arg#{i}" }
+ args[-1] = "*#{args[-1]}" if method.arity < 0
+ end
+
+ # method.to_s formats to handle:
+ #
+ # #<Method: Fixnum#zero?>
+ # #<Method: Fixnum(Integer)#years>
+ # #<Method: User(#<Module:0x00000103207c00>)#_username>
+ # #<Method: User(id: integer, username: string).table_name>
+ # #<Method: User(id: integer, username: string)(ActiveRecord::Base).current>
+ # #<UnboundMethod: Hello#world>
+ #
+ if method.to_s =~ /(Unbound)*Method: (.*)[#\.]/
+ unbound, klass = $1 && '(unbound)', $2
+ if klass && klass =~ /(\(\w+:\s.*?\))/ # Is this ActiveRecord-style class?
+ klass.sub!($1, '') # Yes, strip the fields leaving class name only.
+ end
+ owner = "#{klass}#{unbound}".gsub('(', ' (')
+ end
+
+ [ method.name.to_s, "(#{args.join(', ')})", owner.to_s ]
+ end
+
+ # Format hash keys as plain strings regardless of underlying data type.
+ #------------------------------------------------------------------------------
+ def plain_single_line
+ plain, multiline = @options[:plain], @options[:multiline]
+ @options[:plain], @options[:multiline] = true, false
+ yield
+ ensure
+ @options[:plain], @options[:multiline] = plain, multiline
+ end
+
+ # Utility methods.
+ #------------------------------------------------------------------------------
+ def align(value, width)
+ if @options[:multiline]
+ if @options[:indent] > 0
+ value.rjust(width)
+ elsif @options[:indent] == 0
+ indent + value.ljust(width)
+ else
+ indent[0, @indentation + @options[:indent]] + value.ljust(width)
+ end
+ else
+ value
+ end
+ end
+
+ def indented
+ @indentation += @options[:indent].abs
+ yield
+ ensure
+ @indentation -= @options[:indent].abs
+ end
+
+ def left_aligned
+ current, @options[:indent] = @options[:indent], 0
+ yield
+ ensure
+ @options[:indent] = current
+ end
+
+ def indent
+ ' ' * @indentation
+ end
+
+ def outdent
+ ' ' * (@indentation - @options[:indent].abs)
+ end
+
+ # To support limited output, for example:
+ #
+ # ap ('a'..'z').to_a, :limit => 3
+ # [
+ # [ 0] "a",
+ # [ 1] .. [24],
+ # [25] "z"
+ # ]
+ #
+ # ap (1..100).to_a, :limit => true # Default limit is 7.
+ # [
+ # [ 0] 1,
+ # [ 1] 2,
+ # [ 2] 3,
+ # [ 3] .. [96],
+ # [97] 98,
+ # [98] 99,
+ # [99] 100
+ # ]
+ #------------------------------------------------------------------------------
+ def should_be_limited?
+ @options[:limit] == true or (@options[:limit].is_a?(Fixnum) and @options[:limit] > 0)
+ end
+
+ def get_limit_size
+ @options[:limit] == true ? DEFAULT_LIMIT_SIZE : @options[:limit]
+ end
+
+ def limited(data, width, is_hash = false)
+ limit = get_limit_size
+ if data.length <= limit
+ data
+ else
+ # Calculate how many elements to be displayed above and below the separator.
+ head = limit / 2
+ tail = head - (limit - 1) % 2
+
+ # Add the proper elements to the temp array and format the separator.
+ temp = data[0, head] + [ nil ] + data[-tail, tail]
+
+ if is_hash
+ temp[head] = "#{indent}#{data[head].strip} .. #{data[data.length - tail - 1].strip}"
+ else
+ temp[head] = "#{indent}[#{head.to_s.rjust(width)}] .. [#{data.length - tail - 1}]"
+ end
+
+ temp
+ end
+ end
+ end
+end
diff --git a/lib/awesome_print/inspector.rb b/lib/awesome_print/inspector.rb
new file mode 100755
index 0000000..0893a90
--- /dev/null
+++ b/lib/awesome_print/inspector.rb
@@ -0,0 +1,171 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+
+ class << self # Class accessors for custom defaults.
+ attr_accessor :defaults, :force_colors
+
+ # Class accessor to force colorized output (ex. forked subprocess where TERM
+ # might be dumb).
+ #------------------------------------------------------------------------------
+ def force_colors!(value = true)
+ @force_colors = value
+ end
+
+ def console?
+ !!(defined?(IRB) || defined?(Pry))
+ end
+
+ def rails_console?
+ console? && !!(defined?(Rails::Console) || ENV["RAILS_ENV"])
+ end
+
+ def irb!
+ return unless defined?(IRB)
+ unless IRB.version.include?("DietRB")
+ IRB::Irb.class_eval do
+ def output_value
+ ap @context.last_value
+ end
+ end
+ else # MacRuby
+ IRB.formatter = Class.new(IRB::Formatter) do
+ def inspect_object(object)
+ object.ai
+ end
+ end.new
+ end
+ end
+
+ def pry!
+ if defined?(Pry)
+ Pry.print = proc { |output, value| output.puts value.ai }
+ end
+ end
+ end
+
+ class Inspector
+ attr_accessor :options
+
+ AP = :__awesome_print__
+
+ def initialize(options = {})
+ @options = {
+ :indent => 4, # Indent using 4 spaces.
+ :index => true, # Display array indices.
+ :html => false, # Use ANSI color codes rather than HTML.
+ :multiline => true, # Display in multiple lines.
+ :plain => false, # Use colors.
+ :raw => false, # Do not recursively format object instance variables.
+ :sort_keys => false, # Do not sort hash keys.
+ :limit => false, # Limit large output for arrays and hashes. Set to a boolean or integer.
+ :color => {
+ :args => :pale,
+ :array => :white,
+ :bigdecimal => :blue,
+ :class => :yellow,
+ :date => :greenish,
+ :falseclass => :red,
+ :fixnum => :blue,
+ :float => :blue,
+ :hash => :pale,
+ :keyword => :cyan,
+ :method => :purpleish,
+ :nilclass => :red,
+ :rational => :blue,
+ :string => :yellowish,
+ :struct => :pale,
+ :symbol => :cyanish,
+ :time => :greenish,
+ :trueclass => :green,
+ :variable => :cyanish
+ }
+ }
+
+ # Merge custom defaults and let explicit options parameter override them.
+ merge_custom_defaults!
+ merge_options!(options)
+
+ @formatter = AwesomePrint::Formatter.new(self)
+ Thread.current[AP] ||= []
+ end
+
+ # Dispatcher that detects data nesting and invokes object-aware formatter.
+ #------------------------------------------------------------------------------
+ def awesome(object)
+ if Thread.current[AP].include?(object.object_id)
+ nested(object)
+ else
+ begin
+ Thread.current[AP] << object.object_id
+ unnested(object)
+ ensure
+ Thread.current[AP].pop
+ end
+ end
+ end
+
+ # Return true if we are to colorize the output.
+ #------------------------------------------------------------------------------
+ def colorize?
+ AwesomePrint.force_colors ||= false
+ AwesomePrint.force_colors || (STDOUT.tty? && ((ENV['TERM'] && ENV['TERM'] != 'dumb') || ENV['ANSICON']))
+ end
+
+ private
+
+ # Format nested data, for example:
+ # arr = [1, 2]; arr << arr
+ # => [1,2, [...]]
+ # hash = { :a => 1 }; hash[:b] = hash
+ # => { :a => 1, :b => {...} }
+ #------------------------------------------------------------------------------
+ def nested(object)
+ case printable(object)
+ when :array then @formatter.colorize("[...]", :array)
+ when :hash then @formatter.colorize("{...}", :hash)
+ when :struct then @formatter.colorize("{...}", :struct)
+ else @formatter.colorize("...#{object.class}...", :class)
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ def unnested(object)
+ @formatter.format(object, printable(object))
+ end
+
+ # Turn class name into symbol, ex: Hello::World => :hello_world. Classes that
+ # inherit from Array, Hash, File, Dir, and Struct are treated as the base class.
+ #------------------------------------------------------------------------------
+ def printable(object)
+ case object
+ when Array then :array
+ when Hash then :hash
+ when File then :file
+ when Dir then :dir
+ when Struct then :struct
+ else object.class.to_s.gsub(/:+/, "_").downcase.to_sym
+ end
+ end
+
+ # Update @options by first merging the :color hash and then the remaining keys.
+ #------------------------------------------------------------------------------
+ def merge_options!(options = {})
+ @options[:color].merge!(options.delete(:color) || {})
+ @options.merge!(options)
+ end
+
+ # Load ~/.aprc file with custom defaults that override default options.
+ #------------------------------------------------------------------------------
+ def merge_custom_defaults!
+ dotfile = File.join(ENV["HOME"], ".aprc")
+ load dotfile if File.readable?(dotfile)
+ merge_options!(AwesomePrint.defaults) if AwesomePrint.defaults.is_a?(Hash)
+ rescue => e
+ $stderr.puts "Could not load #{dotfile}: #{e}"
+ end
+ end
+end
diff --git a/lib/awesome_print/version.rb b/lib/awesome_print/version.rb
new file mode 100644
index 0000000..2bca309
--- /dev/null
+++ b/lib/awesome_print/version.rb
@@ -0,0 +1,10 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+ def self.version
+ "1.2.0"
+ end
+end
diff --git a/metadata.yml b/metadata.yml
new file mode 100644
index 0000000..9900a41
--- /dev/null
+++ b/metadata.yml
@@ -0,0 +1,117 @@
+--- !ruby/object:Gem::Specification
+name: awesome_print
+version: !ruby/object:Gem::Version
+ version: 1.2.0
+ prerelease:
+platform: ruby
+authors:
+- Michael Dvorkin
+autorequire:
+bindir: bin
+cert_chain: []
+date: 2013-09-24 00:00:00.000000000 Z
+dependencies:
+- !ruby/object:Gem::Dependency
+ name: rspec
+ requirement: !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ! '>='
+ - !ruby/object:Gem::Version
+ version: 2.6.0
+ type: :development
+ prerelease: false
+ version_requirements: !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ! '>='
+ - !ruby/object:Gem::Version
+ version: 2.6.0
+- !ruby/object:Gem::Dependency
+ name: fakefs
+ requirement: !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ! '>='
+ - !ruby/object:Gem::Version
+ version: 0.2.1
+ type: :development
+ prerelease: false
+ version_requirements: !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ! '>='
+ - !ruby/object:Gem::Version
+ version: 0.2.1
+description: ! 'Great Ruby dubugging companion: pretty print Ruby objects to visualize
+ their structure. Supports custom object formatting via plugins'
+email: mike at dvorkin.net
+executables: []
+extensions: []
+extra_rdoc_files: []
+files:
+- CHANGELOG
+- Gemfile
+- Gemfile.lock
+- LICENSE
+- Rakefile
+- README.md
+- lib/ap.rb
+- lib/awesome_print/core_ext/array.rb
+- lib/awesome_print/core_ext/class.rb
+- lib/awesome_print/core_ext/kernel.rb
+- lib/awesome_print/core_ext/logger.rb
+- lib/awesome_print/core_ext/method.rb
+- lib/awesome_print/core_ext/object.rb
+- lib/awesome_print/core_ext/string.rb
+- lib/awesome_print/ext/action_view.rb
+- lib/awesome_print/ext/active_record.rb
+- lib/awesome_print/ext/active_support.rb
+- lib/awesome_print/ext/mongo_mapper.rb
+- lib/awesome_print/ext/mongoid.rb
+- lib/awesome_print/ext/no_brainer.rb
+- lib/awesome_print/ext/nokogiri.rb
+- lib/awesome_print/ext/ripple.rb
+- lib/awesome_print/ext/sequel.rb
+- lib/awesome_print/formatter.rb
+- lib/awesome_print/inspector.rb
+- lib/awesome_print/version.rb
+- lib/awesome_print.rb
+- spec/colors_spec.rb
+- spec/formats_spec.rb
+- spec/methods_spec.rb
+- spec/misc_spec.rb
+- spec/objects_spec.rb
+- spec/spec_helper.rb
+- .gitignore
+homepage: http://github.com/michaeldv/awesome_print
+licenses: []
+post_install_message:
+rdoc_options: []
+require_paths:
+- lib
+required_ruby_version: !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ! '>='
+ - !ruby/object:Gem::Version
+ version: '0'
+required_rubygems_version: !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ! '>='
+ - !ruby/object:Gem::Version
+ version: '0'
+requirements: []
+rubyforge_project: awesome_print
+rubygems_version: 1.8.24
+signing_key:
+specification_version: 3
+summary: Pretty print Ruby objects with proper indentation and colors
+test_files:
+- spec/colors_spec.rb
+- spec/formats_spec.rb
+- spec/methods_spec.rb
+- spec/misc_spec.rb
+- spec/objects_spec.rb
+- spec/spec_helper.rb
diff --git a/spec/colors_spec.rb b/spec/colors_spec.rb
new file mode 100644
index 0000000..17f2e63
--- /dev/null
+++ b/spec/colors_spec.rb
@@ -0,0 +1,106 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+
+describe "AwesomePrint" do
+ def stub_tty!(output = true, stream = STDOUT)
+ if output
+ stream.instance_eval { def tty?; true; end }
+ else
+ stream.instance_eval { def tty?; false; end }
+ end
+ end
+
+ before do
+ stub_dotfile!
+ end
+
+ describe "colorization" do
+ PLAIN = '[ 1, :two, "three", [ nil, [ true, false ] ] ]'
+ COLORIZED = "[ \e[1;34m1\e[0m, \e[0;36m:two\e[0m, \e[0;33m\"three\"\e[0m, [ \e[1;31mnil\e[0m, [ \e[1;32mtrue\e[0m, \e[1;31mfalse\e[0m ] ] ]"
+
+ before do
+ ENV['TERM'] = "xterm-colors"
+ ENV.delete('ANSICON')
+ @arr = [ 1, :two, "three", [ nil, [ true, false] ] ]
+ end
+
+ describe "default settings (no forced colors)" do
+ before do
+ AwesomePrint.force_colors! false
+ end
+
+ it "colorizes tty processes by default" do
+ stub_tty!
+ @arr.ai(:multiline => false).should == COLORIZED
+ end
+
+ it "colorizes processes with ENV['ANSICON'] by default" do
+ begin
+ stub_tty!
+ term, ENV['ANSICON'] = ENV['ANSICON'], "1"
+ @arr.ai(:multiline => false).should == COLORIZED
+ ensure
+ ENV['ANSICON'] = term
+ end
+ end
+
+ it "does not colorize tty processes running in dumb terminals by default" do
+ begin
+ stub_tty!
+ term, ENV['TERM'] = ENV['TERM'], "dumb"
+ @arr.ai(:multiline => false).should == PLAIN
+ ensure
+ ENV['TERM'] = term
+ end
+ end
+
+ it "does not colorize subprocesses by default" do
+ begin
+ stub_tty! false
+ @arr.ai(:multiline => false).should == PLAIN
+ ensure
+ stub_tty!
+ end
+ end
+ end
+
+ describe "forced colors override" do
+ before do
+ AwesomePrint.force_colors!
+ end
+
+ it "still colorizes tty processes" do
+ stub_tty!
+ @arr.ai(:multiline => false).should == COLORIZED
+ end
+
+ it "colorizes processes with ENV['ANSICON'] set to 0" do
+ begin
+ stub_tty!
+ term, ENV['ANSICON'] = ENV['ANSICON'], "1"
+ @arr.ai(:multiline => false).should == COLORIZED
+ ensure
+ ENV['ANSICON'] = term
+ end
+ end
+
+ it "colorizes dumb terminals" do
+ begin
+ stub_tty!
+ term, ENV['TERM'] = ENV['TERM'], "dumb"
+ @arr.ai(:multiline => false).should == COLORIZED
+ ensure
+ ENV['TERM'] = term
+ end
+ end
+
+ it "colorizes subprocess" do
+ begin
+ stub_tty! false
+ @arr.ai(:multiline => false).should == COLORIZED
+ ensure
+ stub_tty!
+ end
+ end
+ end
+ end
+end
diff --git a/spec/formats_spec.rb b/spec/formats_spec.rb
new file mode 100644
index 0000000..b577ede
--- /dev/null
+++ b/spec/formats_spec.rb
@@ -0,0 +1,712 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+require "bigdecimal"
+require "rational"
+require "set"
+
+describe "AwesomePrint" do
+ before do
+ stub_dotfile!
+ end
+
+ describe "Array" do
+ before do
+ @arr = [ 1, :two, "three", [ nil, [ true, false] ] ]
+ end
+
+ it "empty array" do
+ [].ai.should == "[]"
+ end
+
+ it "plain multiline" do
+ @arr.ai(:plain => true).should == <<-EOS.strip
+[
+ [0] 1,
+ [1] :two,
+ [2] "three",
+ [3] [
+ [0] nil,
+ [1] [
+ [0] true,
+ [1] false
+ ]
+ ]
+]
+EOS
+ end
+
+ it "plain multiline without index" do
+ @arr.ai(:plain => true, :index => false).should == <<-EOS.strip
+[
+ 1,
+ :two,
+ "three",
+ [
+ nil,
+ [
+ true,
+ false
+ ]
+ ]
+]
+EOS
+ end
+
+ it "plain multiline indented" do
+ @arr.ai(:plain => true, :indent => 2).should == <<-EOS.strip
+[
+ [0] 1,
+ [1] :two,
+ [2] "three",
+ [3] [
+ [0] nil,
+ [1] [
+ [0] true,
+ [1] false
+ ]
+ ]
+]
+EOS
+ end
+
+ it "plain multiline indented without index" do
+ @arr.ai(:plain => true, :indent => 2, :index => false).should == <<-EOS.strip
+[
+ 1,
+ :two,
+ "three",
+ [
+ nil,
+ [
+ true,
+ false
+ ]
+ ]
+]
+EOS
+ end
+
+ it "plain single line" do
+ @arr.ai(:plain => true, :multiline => false).should == '[ 1, :two, "three", [ nil, [ true, false ] ] ]'
+ end
+
+ it "colored multiline (default)" do
+ @arr.ai.should == <<-EOS.strip
+[
+ \e[1;37m[0] \e[0m\e[1;34m1\e[0m,
+ \e[1;37m[1] \e[0m\e[0;36m:two\e[0m,
+ \e[1;37m[2] \e[0m\e[0;33m\"three\"\e[0m,
+ \e[1;37m[3] \e[0m[
+ \e[1;37m[0] \e[0m\e[1;31mnil\e[0m,
+ \e[1;37m[1] \e[0m[
+ \e[1;37m[0] \e[0m\e[1;32mtrue\e[0m,
+ \e[1;37m[1] \e[0m\e[1;31mfalse\e[0m
+ ]
+ ]
+]
+EOS
+ end
+
+ it "colored multiline indented" do
+ @arr.ai(:indent => 8).should == <<-EOS.strip
+[
+ \e[1;37m[0] \e[0m\e[1;34m1\e[0m,
+ \e[1;37m[1] \e[0m\e[0;36m:two\e[0m,
+ \e[1;37m[2] \e[0m\e[0;33m\"three\"\e[0m,
+ \e[1;37m[3] \e[0m[
+ \e[1;37m[0] \e[0m\e[1;31mnil\e[0m,
+ \e[1;37m[1] \e[0m[
+ \e[1;37m[0] \e[0m\e[1;32mtrue\e[0m,
+ \e[1;37m[1] \e[0m\e[1;31mfalse\e[0m
+ ]
+ ]
+]
+EOS
+ end
+
+ it "colored single line" do
+ @arr.ai(:multiline => false).should == "[ \e[1;34m1\e[0m, \e[0;36m:two\e[0m, \e[0;33m\"three\"\e[0m, [ \e[1;31mnil\e[0m, [ \e[1;32mtrue\e[0m, \e[1;31mfalse\e[0m ] ] ]"
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Nested Array" do
+ before do
+ @arr = [ 1, 2 ]
+ @arr << @arr
+ end
+
+ it "plain multiline" do
+ @arr.ai(:plain => true).should == <<-EOS.strip
+[
+ [0] 1,
+ [1] 2,
+ [2] [...]
+]
+EOS
+ end
+
+ it "plain multiline without index" do
+ @arr.ai(:plain => true, :index => false).should == <<-EOS.strip
+[
+ 1,
+ 2,
+ [...]
+]
+EOS
+ end
+
+ it "plain single line" do
+ @arr.ai(:plain => true, :multiline => false).should == "[ 1, 2, [...] ]"
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Limited Output Array" do
+ before(:each) do
+ @arr = (1..1000).to_a
+ end
+
+ it "plain limited output large" do
+ @arr.ai(:plain => true, :limit => true).should == <<-EOS.strip
+[
+ [ 0] 1,
+ [ 1] 2,
+ [ 2] 3,
+ [ 3] .. [996],
+ [997] 998,
+ [998] 999,
+ [999] 1000
+]
+EOS
+ end
+
+ it "plain limited output small" do
+ @arr = @arr[0..3]
+ @arr.ai(:plain => true, :limit => true).should == <<-EOS.strip
+[
+ [0] 1,
+ [1] 2,
+ [2] 3,
+ [3] 4
+]
+EOS
+ end
+
+ it "plain limited output with 10 lines" do
+ @arr.ai(:plain => true, :limit => 10).should == <<-EOS.strip
+[
+ [ 0] 1,
+ [ 1] 2,
+ [ 2] 3,
+ [ 3] 4,
+ [ 4] 5,
+ [ 5] .. [995],
+ [996] 997,
+ [997] 998,
+ [998] 999,
+ [999] 1000
+]
+EOS
+ end
+
+ it "plain limited output with 11 lines" do
+ @arr.ai(:plain => true, :limit => 11).should == <<-EOS.strip
+[
+ [ 0] 1,
+ [ 1] 2,
+ [ 2] 3,
+ [ 3] 4,
+ [ 4] 5,
+ [ 5] .. [994],
+ [995] 996,
+ [996] 997,
+ [997] 998,
+ [998] 999,
+ [999] 1000
+]
+EOS
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Limited Output Hash" do
+ before(:each) do
+ @hash = ("a".."z").inject({}) { |h, v| h.merge({ v => v.to_sym }) }
+ end
+
+ it "plain limited output" do
+ @hash.ai(:sort_keys => true, :plain => true, :limit => true).should == <<-EOS.strip
+{
+ "a" => :a,
+ "b" => :b,
+ "c" => :c,
+ "d" => :d .. "w" => :w,
+ "x" => :x,
+ "y" => :y,
+ "z" => :z
+}
+EOS
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Hash" do
+ before do
+ @hash = { 1 => { :sym => { "str" => { [1, 2, 3] => { { :k => :v } => Hash } } } } }
+ end
+
+ it "empty hash" do
+ {}.ai.should == "{}"
+ end
+
+ it "plain multiline" do
+ @hash.ai(:plain => true).should == <<-EOS.strip
+{
+ 1 => {
+ :sym => {
+ "str" => {
+ [ 1, 2, 3 ] => {
+ { :k => :v } => Hash < Object
+ }
+ }
+ }
+ }
+}
+EOS
+ end
+
+ it "plain multiline indented" do
+ @hash.ai(:plain => true, :indent => 1).should == <<-EOS.strip
+{
+ 1 => {
+ :sym => {
+ "str" => {
+ [ 1, 2, 3 ] => {
+ { :k => :v } => Hash < Object
+ }
+ }
+ }
+ }
+}
+EOS
+ end
+
+ it "plain single line" do
+ @hash.ai(:plain => true, :multiline => false).should == '{ 1 => { :sym => { "str" => { [ 1, 2, 3 ] => { { :k => :v } => Hash < Object } } } } }'
+ end
+
+ it "colored multiline (default)" do
+ @hash.ai.should == <<-EOS.strip
+{
+ 1\e[0;37m => \e[0m{
+ :sym\e[0;37m => \e[0m{
+ \"str\"\e[0;37m => \e[0m{
+ [ 1, 2, 3 ]\e[0;37m => \e[0m{
+ { :k => :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m
+ }
+ }
+ }
+ }
+}
+EOS
+ end
+
+ it "colored multiline indented" do
+ @hash.ai(:indent => 2).should == <<-EOS.strip
+{
+ 1\e[0;37m => \e[0m{
+ :sym\e[0;37m => \e[0m{
+ \"str\"\e[0;37m => \e[0m{
+ [ 1, 2, 3 ]\e[0;37m => \e[0m{
+ { :k => :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m
+ }
+ }
+ }
+ }
+}
+EOS
+ end
+
+ it "colored single line" do
+ @hash.ai(:multiline => false).should == "{ 1\e[0;37m => \e[0m{ :sym\e[0;37m => \e[0m{ \"str\"\e[0;37m => \e[0m{ [ 1, 2, 3 ]\e[0;37m => \e[0m{ { :k => :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m } } } } }"
+ end
+
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Nested Hash" do
+ before do
+ @hash = {}
+ @hash[:a] = @hash
+ end
+
+ it "plain multiline" do
+ @hash.ai(:plain => true).should == <<-EOS.strip
+{
+ :a => {...}
+}
+EOS
+ end
+
+ it "plain single line" do
+ @hash.ai(:plain => true, :multiline => false).should == '{ :a => {...} }'
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Hash with several keys" do
+ before do
+ @hash = {"b" => "b", :a => "a", :z => "z", "alpha" => "alpha"}
+ end
+
+ it "plain multiline" do
+ out = @hash.ai(:plain => true)
+ if RUBY_VERSION.to_f < 1.9 # Order of @hash keys is not guaranteed.
+ out.should =~ /^\{[^\}]+\}/m
+ out.should =~ / "b" => "b",?/
+ out.should =~ / :a => "a",?/
+ out.should =~ / :z => "z",?/
+ out.should =~ / "alpha" => "alpha",?$/
+ else
+ out.should == <<-EOS.strip
+{
+ "b" => "b",
+ :a => "a",
+ :z => "z",
+ "alpha" => "alpha"
+}
+EOS
+ end
+ end
+
+ it "plain multiline with sorted keys" do
+ @hash.ai(:plain => true, :sort_keys => true).should == <<-EOS.strip
+{
+ :a => "a",
+ "alpha" => "alpha",
+ "b" => "b",
+ :z => "z"
+}
+EOS
+ end
+
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Negative options[:indent]" do
+ #
+ # With Ruby < 1.9 the order of hash keys is not defined so we can't
+ # reliably compare the output string.
+ #
+ it "hash keys must be left aligned" do
+ hash = { [0, 0, 255] => :yellow, :red => "rgb(255, 0, 0)", "magenta" => "rgb(255, 0, 255)" }
+ out = hash.ai(:plain => true, :indent => -4, :sort_keys => true)
+ out.should == <<-EOS.strip
+{
+ [ 0, 0, 255 ] => :yellow,
+ "magenta" => "rgb(255, 0, 255)",
+ :red => "rgb(255, 0, 0)"
+}
+EOS
+ end
+
+ it "nested hash keys should be indented (array of hashes)" do
+ arr = [ { :a => 1, :bb => 22, :ccc => 333}, { 1 => :a, 22 => :bb, 333 => :ccc} ]
+ out = arr.ai(:plain => true, :indent => -4, :sort_keys => true)
+ out.should == <<-EOS.strip
+[
+ [0] {
+ :a => 1,
+ :bb => 22,
+ :ccc => 333
+ },
+ [1] {
+ 1 => :a,
+ 22 => :bb,
+ 333 => :ccc
+ }
+]
+EOS
+ end
+
+ it "nested hash keys should be indented (hash of hashes)" do
+ arr = { :first => { :a => 1, :bb => 22, :ccc => 333}, :second => { 1 => :a, 22 => :bb, 333 => :ccc} }
+ out = arr.ai(:plain => true, :indent => -4, :sort_keys => true)
+ out.should == <<-EOS.strip
+{
+ :first => {
+ :a => 1,
+ :bb => 22,
+ :ccc => 333
+ },
+ :second => {
+ 1 => :a,
+ 22 => :bb,
+ 333 => :ccc
+ }
+}
+EOS
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Class" do
+ it "shoud show superclass (plain)" do
+ self.class.ai(:plain => true).should == "#{self.class} < #{self.class.superclass}"
+ end
+
+ it "shoud show superclass (color)" do
+ self.class.ai.should == "#{self.class} < #{self.class.superclass}".yellow
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "File" do
+ it "should display a file (plain)" do
+ File.open(__FILE__, "r") do |f|
+ f.ai(:plain => true).should == "#{f.inspect}\n" << `ls -alF #{f.path}`.chop
+ end
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Dir" do
+ it "should display a direcory (plain)" do
+ Dir.open(File.dirname(__FILE__)) do |d|
+ d.ai(:plain => true).should == "#{d.inspect}\n" << `ls -alF #{d.path}`.chop
+ end
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "BigDecimal and Rational" do
+ it "should present BigDecimal object with arbitrary precision" do
+ big = BigDecimal("201020102010201020102010201020102010.4")
+ big.ai(:plain => true).should == "201020102010201020102010201020102010.4"
+ end
+
+ it "should present Rational object with arbitrary precision" do
+ rat = Rational(201020102010201020102010201020102010, 2)
+ out = rat.ai(:plain => true)
+ #
+ # Ruby 1.9 slightly changed the format of Rational#to_s, see
+ # http://techtime.getharvest.com/blog/harvest-is-now-on-ruby-1-dot-9-3 and
+ # http://www.ruby-forum.com/topic/189397
+ #
+ if RUBY_VERSION < "1.9"
+ out.should == "100510051005100510051005100510051005"
+ else
+ out.should == "100510051005100510051005100510051005/1"
+ end
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Utility methods" do
+ it "should merge options" do
+ ap = AwesomePrint::Inspector.new
+ ap.send(:merge_options!, { :color => { :array => :black }, :indent => 0 })
+ options = ap.instance_variable_get("@options")
+ options[:color][:array].should == :black
+ options[:indent].should == 0
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Set" do
+ before do
+ @arr = [1, :two, "three" ]
+ @set = Set.new(@arr)
+ end
+
+ it "empty set" do
+ Set.new.ai.should == [].ai
+ end
+
+ if RUBY_VERSION > "1.9"
+ it "plain multiline" do
+ @set.ai(:plain => true).should == @arr.ai(:plain => true)
+ end
+
+ it "plain multiline indented" do
+ @set.ai(:plain => true, :indent => 1).should == @arr.ai(:plain => true, :indent => 1)
+ end
+
+ it "plain single line" do
+ @set.ai(:plain => true, :multiline => false).should == @arr.ai(:plain => true, :multiline => false)
+ end
+
+ it "colored multiline (default)" do
+ @set.ai.should == @arr.ai
+ end
+ else # Prior to Ruby 1.9 the order of set values is unpredicatble.
+ it "plain multiline" do
+ @set.sort_by{ |x| x.to_s }.ai(:plain => true).should == @arr.sort_by{ |x| x.to_s }.ai(:plain => true)
+ end
+
+ it "plain multiline indented" do
+ @set.sort_by{ |x| x.to_s }.ai(:plain => true, :indent => 1).should == @arr.sort_by{ |x| x.to_s }.ai(:plain => true, :indent => 1)
+ end
+
+ it "plain single line" do
+ @set.sort_by{ |x| x.to_s }.ai(:plain => true, :multiline => false).should == @arr.sort_by{ |x| x.to_s }.ai(:plain => true, :multiline => false)
+ end
+
+ it "colored multiline (default)" do
+ @set.sort_by{ |x| x.to_s }.ai.should == @arr.sort_by{ |x| x.to_s }.ai
+ end
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Struct" do
+ before do
+ @struct = unless defined?(Struct::SimpleStruct)
+ Struct.new("SimpleStruct", :name, :address).new
+ else
+ Struct::SimpleStruct.new
+ end
+ @struct.name = "Herman Munster"
+ @struct.address = "1313 Mockingbird Lane"
+ end
+
+ it "empty struct" do
+ Struct.new("EmptyStruct").ai.should == "\e[1;33mStruct::EmptyStruct < Struct\e[0m"
+ end
+
+ it "plain multiline" do
+ s1 = <<-EOS.strip
+{
+ :address => "1313 Mockingbird Lane",
+ :name => "Herman Munster"
+}
+EOS
+ s2 = <<-EOS.strip
+{
+ :name => "Herman Munster",
+ :address => "1313 Mockingbird Lane"
+}
+EOS
+ @struct.ai(:plain => true).should satisfy { |match| match == s1 || match == s2 }
+ end
+
+ it "plain multiline indented" do
+ s1 = <<-EOS.strip
+{
+ :address => "1313 Mockingbird Lane",
+ :name => "Herman Munster"
+}
+EOS
+ s2 = <<-EOS.strip
+{
+ :name => "Herman Munster",
+ :address => "1313 Mockingbird Lane"
+}
+EOS
+ @struct.ai(:plain => true, :indent => 1).should satisfy { |match| match == s1 || match == s2 }
+ end
+
+ it "plain single line" do
+ s1 = "{ :address => \"1313 Mockingbird Lane\", :name => \"Herman Munster\" }"
+ s2 = "{ :name => \"Herman Munster\", :address => \"1313 Mockingbird Lane\" }"
+ @struct.ai(:plain => true, :multiline => false).should satisfy { |match| match == s1 || match == s2 }
+ end
+
+ it "colored multiline (default)" do
+ s1 = <<-EOS.strip
+{
+ :address\e[0;37m => \e[0m\e[0;33m\"1313 Mockingbird Lane\"\e[0m,
+ :name\e[0;37m => \e[0m\e[0;33m\"Herman Munster\"\e[0m
+}
+EOS
+ s2 = <<-EOS.strip
+{
+ :name\e[0;37m => \e[0m\e[0;33m\"Herman Munster\"\e[0m,
+ :address\e[0;37m => \e[0m\e[0;33m\"1313 Mockingbird Lane\"\e[0m
+}
+EOS
+ @struct.ai.should satisfy { |match| match == s1 || match == s2 }
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Inherited from standard Ruby classes" do
+ after do
+ Object.instance_eval{ remove_const :My } if defined?(My)
+ end
+
+ it "inherited from Array should be displayed as Array" do
+ class My < Array; end
+
+ my = My.new([ 1, :two, "three", [ nil, [ true, false ] ] ])
+ my.ai(:plain => true).should == <<-EOS.strip
+[
+ [0] 1,
+ [1] :two,
+ [2] "three",
+ [3] [
+ [0] nil,
+ [1] [
+ [0] true,
+ [1] false
+ ]
+ ]
+]
+EOS
+ end
+
+ it "inherited from Hash should be displayed as Hash" do
+ class My < Hash; end
+
+ my = My[ { 1 => { :sym => { "str" => { [1, 2, 3] => { { :k => :v } => Hash } } } } } ]
+ my.ai(:plain => true).should == <<-EOS.strip
+{
+ 1 => {
+ :sym => {
+ "str" => {
+ [ 1, 2, 3 ] => {
+ { :k => :v } => Hash < Object
+ }
+ }
+ }
+ }
+}
+EOS
+ end
+
+ it "inherited from File should be displayed as File" do
+ class My < File; end
+
+ my = File.new('/dev/null') rescue File.new('nul')
+ my.ai(:plain => true).should == "#{my.inspect}\n" << `ls -alF #{my.path}`.chop
+ end
+
+ it "inherited from Dir should be displayed as Dir" do
+ class My < Dir; end
+
+ require 'tmpdir'
+ my = My.new(Dir.tmpdir)
+ my.ai(:plain => true).should == "#{my.inspect}\n" << `ls -alF #{my.path}`.chop
+ end
+
+ it "should handle a class that defines its own #send method" do
+ class My
+ def send(arg1, arg2, arg3); end
+ end
+
+ my = My.new
+ my.methods.ai(:plain => true).should_not raise_error(ArgumentError)
+ end
+
+ it "should handle a class defines its own #method method (ex. request.method)" do
+ class My
+ def method
+ 'POST'
+ end
+ end
+
+ my = My.new
+ my.methods.ai(:plain => true).should_not raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/methods_spec.rb b/spec/methods_spec.rb
new file mode 100644
index 0000000..22d5ca3
--- /dev/null
+++ b/spec/methods_spec.rb
@@ -0,0 +1,459 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+
+describe "Single method" do
+ before do
+ stub_dotfile!
+ end
+
+ after do
+ Object.instance_eval{ remove_const :Hello } if defined?(Hello)
+ end
+
+ it "plain: should handle a method with no arguments" do
+ method = ''.method(:upcase)
+ method.ai(:plain => true).should == 'String#upcase()'
+ end
+
+ it "color: should handle a method with no arguments" do
+ method = ''.method(:upcase)
+ method.ai.should == "\e[1;33mString\e[0m#\e[0;35mupcase\e[0m\e[0;37m()\e[0m"
+ end
+
+ it "plain: should handle a method with one argument" do
+ method = ''.method(:include?)
+ method.ai(:plain => true).should == 'String#include?(arg1)'
+ end
+
+ it "color: should handle a method with one argument" do
+ method = ''.method(:include?)
+ method.ai.should == "\e[1;33mString\e[0m#\e[0;35minclude?\e[0m\e[0;37m(arg1)\e[0m"
+ end
+
+ it "plain: should handle a method with two arguments" do
+ method = ''.method(:tr)
+ method.ai(:plain => true).should == 'String#tr(arg1, arg2)'
+ end
+
+ it "color: should handle a method with two arguments" do
+ method = ''.method(:tr)
+ method.ai.should == "\e[1;33mString\e[0m#\e[0;35mtr\e[0m\e[0;37m(arg1, arg2)\e[0m"
+ end
+
+ it "plain: should handle a method with multiple arguments" do
+ method = ''.method(:split)
+ method.ai(:plain => true).should == 'String#split(*arg1)'
+ end
+
+ it "color: should handle a method with multiple arguments" do
+ method = ''.method(:split)
+ method.ai.should == "\e[1;33mString\e[0m#\e[0;35msplit\e[0m\e[0;37m(*arg1)\e[0m"
+ end
+
+ it "plain: should handle a method defined in mixin" do
+ method = ''.method(:is_a?)
+ method.ai(:plain => true).should == 'String (Kernel)#is_a?(arg1)'
+ end
+
+ it "color: should handle a method defined in mixin" do
+ method = ''.method(:is_a?)
+ method.ai.should == "\e[1;33mString (Kernel)\e[0m#\e[0;35mis_a?\e[0m\e[0;37m(arg1)\e[0m"
+ end
+
+ it "plain: should handle an unbound method" do
+ class Hello
+ def world; end
+ end
+ method = Hello.instance_method(:world)
+ method.ai(:plain => true).should == 'Hello (unbound)#world()'
+ end
+
+ it "color: should handle an unbound method" do
+ class Hello
+ def world(a,b); end
+ end
+ method = Hello.instance_method(:world)
+ if RUBY_VERSION < '1.9.2'
+ method.ai.should == "\e[1;33mHello (unbound)\e[0m#\e[0;35mworld\e[0m\e[0;37m(arg1, arg2)\e[0m"
+ else
+ method.ai.should == "\e[1;33mHello (unbound)\e[0m#\e[0;35mworld\e[0m\e[0;37m(a, b)\e[0m"
+ end
+ end
+end
+
+describe "Object methods" do
+ before do
+ stub_dotfile!
+ end
+
+ after do
+ Object.instance_eval{ remove_const :Hello } if defined?(Hello)
+ end
+
+ describe "object.methods" do
+ it "index: should handle object.methods" do
+ out = nil.methods.ai(:plain => true).split("\n").grep(/is_a\?/).first
+ out.should =~ /^\s+\[\s*\d+\]\s+is_a\?\(arg1\)\s+NilClass \(Kernel\)$/
+ end
+
+ it "no index: should handle object.methods" do
+ out = nil.methods.ai(:plain => true, :index => false).split("\n").grep(/is_a\?/).first
+ out.should =~ /^\s+is_a\?\(arg1\)\s+NilClass \(Kernel\)$/
+ end
+ end
+
+ describe "object.public_methods" do
+ it "index: should handle object.public_methods" do
+ out = nil.public_methods.ai(:plain => true).split("\n").grep(/is_a\?/).first
+ out.should =~ /^\s+\[\s*\d+\]\s+is_a\?\(arg1\)\s+NilClass \(Kernel\)$/
+ end
+
+ it "no index: should handle object.public_methods" do
+ out = nil.public_methods.ai(:plain => true, :index => false).split("\n").grep(/is_a\?/).first
+ out.should =~ /^\s+is_a\?\(arg1\)\s+NilClass \(Kernel\)$/
+ end
+ end
+
+ describe "object.private_methods" do
+ it "index: should handle object.private_methods" do
+ out = nil.private_methods.ai(:plain => true).split("\n").grep(/sleep/).first
+ out.should =~ /^\s+\[\s*\d+\]\s+sleep\(\*arg1\)\s+NilClass \(Kernel\)$/
+ end
+
+ it "no index: should handle object.private_methods" do
+ out = nil.private_methods.ai(:plain => true, :index => false).split("\n").grep(/sleep/).first
+ out.should =~ /^\s+sleep\(\*arg1\)\s+NilClass \(Kernel\)$/
+ end
+ end
+
+ describe "object.protected_methods" do
+ it "index: should handle object.protected_methods" do
+ class Hello
+ protected
+ def m1; end
+ def m2; end
+ end
+ Hello.new.protected_methods.ai(:plain => true).should == "[\n [0] m1() Hello\n [1] m2() Hello\n]"
+ end
+
+ it "no index: should handle object.protected_methods" do
+ class Hello
+ protected
+ def m3(a,b); end
+ end
+ if RUBY_VERSION < '1.9.2'
+ Hello.new.protected_methods.ai(:plain => true, :index => false).should == "[\n m3(arg1, arg2) Hello\n]"
+ else
+ Hello.new.protected_methods.ai(:plain => true, :index => false).should == "[\n m3(a, b) Hello\n]"
+ end
+ end
+ end
+
+ describe "object.private_methods" do
+ it "index: should handle object.private_methods" do
+ class Hello
+ private
+ def m1; end
+ def m2; end
+ end
+
+ out = Hello.new.private_methods.ai(:plain => true).split("\n").grep(/m\d/)
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(\)\s+Hello$/
+ out.last.should =~ /^\s+\[\s*\d+\]\s+m2\(\)\s+Hello$/
+ end
+
+ it "no index: should handle object.private_methods" do
+ class Hello
+ private
+ def m3(a,b); end
+ end
+ out = Hello.new.private_methods.ai(:plain => true).split("\n").grep(/m\d/)
+ if RUBY_VERSION < '1.9.2'
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m3\(arg1, arg2\)\s+Hello$/
+ else
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m3\(a, b\)\s+Hello$/
+ end
+ end
+ end
+
+ describe "object.singleton_methods" do
+ it "index: should handle object.singleton_methods" do
+ class Hello
+ class << self
+ def m1; end
+ def m2; end
+ end
+ end
+ out = Hello.singleton_methods.ai(:plain => true).split("\n").grep(/m\d/)
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(\)\s+Hello$/
+ out.last.should =~ /^\s+\[\s*\d+\]\s+m2\(\)\s+Hello$/
+ end
+
+ it "no index: should handle object.singleton_methods" do
+ class Hello
+ def self.m3(a,b); end
+ end
+ out = Hello.singleton_methods.ai(:plain => true, :index => false).split("\n").grep(/m\d/)
+ if RUBY_VERSION < '1.9.2'
+ out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello$/
+ else
+ out.first.should =~ /^\s+m3\(a, b\)\s+Hello$/
+ end
+ end
+ end
+end
+
+describe "Class methods" do
+ before do
+ stub_dotfile!
+ end
+
+ after do
+ Object.instance_eval{ remove_const :Hello } if defined?(Hello)
+ end
+
+ describe "class.instance_methods" do
+ it "index: should handle unbound class.instance_methods" do
+ class Hello
+ def m1; end
+ def m2; end
+ end
+ out = Hello.instance_methods.ai(:plain => true).split("\n").grep(/m\d/)
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(\)\s+Hello\s\(unbound\)$/
+ out.last.should =~ /^\s+\[\s*\d+\]\s+m2\(\)\s+Hello\s\(unbound\)$/
+ end
+
+ it "no index: should handle unbound class.instance_methods" do
+ class Hello
+ def m3(a,b); end
+ end
+ out = Hello.instance_methods.ai(:plain => true, :index => false).split("\n").grep(/m\d/)
+ if RUBY_VERSION < '1.9.2'
+ out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/
+ else
+ out.first.should =~ /^\s+m3\(a, b\)\s+Hello\s\(unbound\)$/
+ end
+ end
+ end
+
+ describe "class.public_instance_methods" do
+ it "index: should handle class.public_instance_methods" do
+ class Hello
+ def m1; end
+ def m2; end
+ end
+ out = Hello.public_instance_methods.ai(:plain => true).split("\n").grep(/m\d/)
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(\)\s+Hello\s\(unbound\)$/
+ out.last.should =~ /^\s+\[\s*\d+\]\s+m2\(\)\s+Hello\s\(unbound\)$/
+ end
+
+ it "no index: should handle class.public_instance_methods" do
+ class Hello
+ def m3(a,b); end
+ end
+ out = Hello.public_instance_methods.ai(:plain => true, :index => false).split("\n").grep(/m\d/)
+ if RUBY_VERSION < '1.9.2'
+ out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/
+ else
+ out.first.should =~ /^\s+m3\(a, b\)\s+Hello\s\(unbound\)$/
+ end
+ end
+ end
+
+ describe "class.protected_instance_methods" do
+ it "index: should handle class.protected_instance_methods" do
+ class Hello
+ protected
+ def m1; end
+ def m2; end
+ end
+ out = Hello.protected_instance_methods.ai(:plain => true).split("\n").grep(/m\d/)
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(\)\s+Hello\s\(unbound\)$/
+ out.last.should =~ /^\s+\[\s*\d+\]\s+m2\(\)\s+Hello\s\(unbound\)$/
+ end
+
+ it "no index: should handle class.protected_instance_methods" do
+ class Hello
+ protected
+ def m3(a,b); end
+ end
+ out = Hello.protected_instance_methods.ai(:plain => true, :index => false).split("\n").grep(/m\d/)
+ if RUBY_VERSION < '1.9.2'
+ out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/
+ else
+ out.first.should =~ /^\s+m3\(a, b\)\s+Hello\s\(unbound\)$/
+ end
+ end
+ end
+
+ describe "class.private_instance_methods" do
+ it "index: should handle class.private_instance_methods" do
+ class Hello
+ private
+ def m1; end
+ def m2; end
+ end
+ out = Hello.private_instance_methods.ai(:plain => true).split("\n").grep(/m\d/)
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(\)\s+Hello\s\(unbound\)$/
+ out.last.should =~ /^\s+\[\s*\d+\]\s+m2\(\)\s+Hello\s\(unbound\)$/
+ end
+
+ it "no index: should handle class.private_instance_methods" do
+ class Hello
+ private
+ def m3(a,b); end
+ end
+ out = Hello.private_instance_methods.ai(:plain => true, :index => false).split("\n").grep(/m\d/)
+ if RUBY_VERSION < '1.9.2'
+ out.first.should =~ /^\s+m3\(arg1, arg2\)\s+Hello\s\(unbound\)$/
+ else
+ out.first.should =~ /^\s+m3\(a, b\)\s+Hello\s\(unbound\)$/
+ end
+ end
+ end
+end
+
+if RUBY_VERSION >= '1.9.2'
+ describe "Ruby 1.9.2+ Method#parameters" do
+ before do
+ stub_dotfile!
+ end
+
+ after do
+ Object.instance_eval{ remove_const :Hello } if defined?(Hello)
+ end
+
+ it "()" do
+ class Hello
+ def m1; end
+ end
+ out = Hello.new.methods.ai(:plain => true).split("\n").grep(/m1/)
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(\)\s+Hello$/
+ end
+
+ it ":req" do
+ class Hello
+ def m1(a, b, c); end
+ end
+ out = Hello.new.methods.ai(:plain => true).split("\n").grep(/m1/)
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(a, b, c\)\s+Hello$/
+ end
+
+ it ":opt" do
+ class Hello
+ def m1(a, b = 1, c = 2); end # m1(a, *b, *c)
+ end
+ out = Hello.new.methods.ai(:plain => true).split("\n").grep(/m1/)
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(a, \*b, \*c\)\s+Hello$/
+ end
+
+ it ":rest" do
+ class Hello
+ def m1(*a); end # m1(*a)
+ end
+ out = Hello.new.methods.ai(:plain => true).split("\n").grep(/m1/)
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(\*a\)\s+Hello$/
+ end
+
+ it ":block" do
+ class Hello
+ def m1(a, b = nil, &blk); end # m1(a, *b, &blk)
+ end
+ out = Hello.new.methods.ai(:plain => true).split("\n").grep(/m1/)
+ out.first.should =~ /^\s+\[\s*\d+\]\s+m1\(a, \*b, &blk\)\s+Hello$/
+ end
+ end
+end
+
+describe "Methods arrays" do
+ after do
+ Object.instance_eval{ remove_const :Hello } if defined?(Hello)
+ Object.instance_eval{ remove_const :World } if defined?(World)
+ end
+
+ it "obj1.methods - obj2.methods should be awesome printed" do
+ stub_dotfile!
+ class Hello
+ def self.m1; end
+ end
+ out = (Hello.methods - Class.methods).ai(:plain => true)
+ out.should == "[\n [0] m1() Hello\n]"
+ end
+
+ it "obj1.methods & obj2.methods should be awesome printed" do
+ stub_dotfile!
+ class Hello
+ def self.m1; end
+ def self.m2; end
+ end
+ class World
+ def self.m1; end
+ end
+ out = (Hello.methods & World.methods - Class.methods).ai(:plain => true)
+ out.should == "[\n [0] m1() Hello\n]"
+ end
+
+ it "obj1.methods.grep(pattern) should be awesome printed" do
+ stub_dotfile!
+ class Hello
+ def self.m1; end
+ def self.m2; end
+ def self.m3; end
+ end
+ out = Hello.methods.grep(/^m1$/).ai(:plain => true)
+ out.should == "[\n [0] m1() Hello\n]"
+ out = Hello.methods.grep(/^m\d$/).ai(:plain => true)
+ out.should == "[\n [0] m1() Hello\n [1] m2() Hello\n [2] m3() Hello\n]"
+ end
+
+ it "obj1.methods.grep(pattern, &block) should pass the matching string within the block" do
+ class Hello
+ def self.m_one; end
+ def self.m_two; end
+ end
+
+ out = Hello.methods.sort.grep(/^m_(.+)$/) { $1.to_sym }
+ out.should == [:one, :two]
+ end
+
+ it "obj1.methods.grep(pattern, &block) should be awesome printed" do
+ stub_dotfile!
+ class Hello
+ def self.m0; end
+ def self.none; end
+ def self.m1; end
+ def self.one; end
+ end
+
+ out = Hello.methods.grep(/^m(\d)$/) { %w(none one)[$1.to_i] }.ai(:plain => true)
+ out.should == "[\n [0] none() Hello\n [1] one() Hello\n]"
+ end
+
+ # See https://github.com/michaeldv/awesome_print/issues/30 for details.
+ it "grepping methods and converting them to_sym should work as expected" do
+ class Hello
+ private
+ def him; end
+
+ def his
+ private_methods.grep(/^h..$/) { |n| n.to_sym }
+ end
+
+ def her
+ private_methods.grep(/^.e.$/) { |n| n.to_sym }
+ end
+ end
+
+ hello = Hello.new
+ (hello.send(:his) - hello.send(:her)).sort_by { |x| x.to_s }.should == [ :him, :his ]
+ end
+
+ it "appending garbage to methods array should not raise error" do
+ arr = 42.methods << [ :wtf ]
+ arr.ai(:plain => true).should_not raise_error(TypeError)
+ if RUBY_VERSION < '1.9.2'
+ arr.ai(:plain => true).should =~ /\s+wtf\(\?\)\s+\?/ # [ :wtf ].to_s => "wtf"
+ else
+ arr.ai(:plain => true).should =~ /\s+\[:wtf\]\(\?\)\s+\?/ # [ :wtf ].to_s => [:wtf]
+ end
+ end
+end
diff --git a/spec/misc_spec.rb b/spec/misc_spec.rb
new file mode 100644
index 0000000..2d21ee6
--- /dev/null
+++ b/spec/misc_spec.rb
@@ -0,0 +1,229 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+
+describe "AwesomePrint" do
+
+ describe "Misc" do
+ before do
+ stub_dotfile!
+ end
+
+ it "handle weird objects that return nil on inspect" do
+ weird = Class.new do
+ def inspect
+ nil
+ end
+ end
+ weird.new.ai(:plain => true).should == ''
+ end
+
+ it "handle frozen object.inspect" do
+ weird = Class.new do
+ def inspect
+ "ice".freeze
+ end
+ end
+ weird.new.ai(:plain => false).should == "ice"
+ end
+
+ # See https://github.com/michaeldv/awesome_print/issues/35
+ it "handle array grep when pattern contains / chapacter" do
+ hash = { "1/x" => 1, "2//x" => :"2" }
+ grepped = hash.keys.sort.grep(/^(\d+)\//) { $1 }
+ grepped.ai(:plain => true, :multiline => false).should == '[ "1", "2" ]'
+ end
+
+ # See https://github.com/michaeldv/awesome_print/issues/85
+ if RUBY_VERSION >= "1.8.7"
+ it "handle array grep when a method is defined in C and thus doesn't have a binding" do
+ arr = (0..6).to_a
+ grepped = arr.grep(1..4, &:succ)
+ grepped.ai(:plain => true, :multiline => false).should == '[ 2, 3, 4, 5 ]'
+ end
+ end
+
+ it "returns value passed as a parameter" do
+ object = rand
+ self.stub!(:puts)
+ (ap object).should == object
+ end
+
+ # Require different file name this time (lib/ap.rb vs. lib/awesome_print).
+ it "several require 'awesome_print' should do no harm" do
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/ap')
+ lambda { rand.ai }.should_not raise_error
+ end
+
+ it "format ENV as hash" do
+ ENV.ai(:plain => true).should == ENV.to_hash.ai(:plain => true)
+ ENV.ai.should == ENV.to_hash.ai
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "HTML output" do
+ before do
+ stub_dotfile!
+ end
+
+ it "wraps ap output with plain <pre> tag" do
+ markup = rand
+ markup.ai(:html => true, :plain => true).should == "<pre>#{markup}</pre>"
+ end
+
+ it "wraps ap output with <pre> tag with colorized <kbd>" do
+ markup = rand
+ markup.ai(:html => true).should == %Q|<pre><kbd style="color:blue">#{markup}</kbd></pre>|
+ end
+
+ it "wraps multiline ap output with <pre> tag with colorized <kbd>" do
+ markup = [ 1, :two, "three" ]
+ markup.ai(:html => true).should == <<-EOS.strip
+<pre>[
+ <kbd style="color:white">[0] </kbd><kbd style="color:blue">1</kbd>,
+ <kbd style="color:white">[1] </kbd><kbd style="color:darkcyan">:two</kbd>,
+ <kbd style="color:white">[2] </kbd><kbd style="color:brown">"three"</kbd>
+]</pre>
+EOS
+ end
+
+ it "wraps hash ap output with only an outer <pre> tag" do
+ markup = [ { "hello" => "world" } ]
+ markup.ai(:html => true).should == <<-EOS.strip
+<pre>[
+ <kbd style="color:white">[0] </kbd>{
+ "hello"<kbd style="color:slategray"> => </kbd><kbd style="color:brown">"world"</kbd>
+ }
+]</pre>
+ EOS
+ end
+
+ it "encodes HTML entities (plain)" do
+ markup = ' &<hello>'
+ markup.ai(:html => true, :plain => true).should == '<pre>" &<hello>"</pre>'
+ end
+
+ it "encodes HTML entities (color)" do
+ markup = ' &<hello>'
+ markup.ai(:html => true).should == '<pre><kbd style="color:brown">" &<hello>"</kbd></pre>'
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "AwesomePrint.defaults" do
+ before do
+ stub_dotfile!
+ end
+
+ after do
+ AwesomePrint.defaults = nil
+ end
+
+ # See https://github.com/michaeldv/awesome_print/issues/98
+ it "should properly merge the defaults" do
+ AwesomePrint.defaults = { :indent => -2, :sort_keys => true }
+ hash = { [0, 0, 255] => :yellow, :red => "rgb(255, 0, 0)", "magenta" => "rgb(255, 0, 255)" }
+ out = hash.ai(:plain => true)
+ out.should == <<-EOS.strip
+{
+ [ 0, 0, 255 ] => :yellow,
+ "magenta" => "rgb(255, 0, 255)",
+ :red => "rgb(255, 0, 0)"
+}
+EOS
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Coexistence with the colorize gem" do
+ before do
+ stub_dotfile!
+ end
+
+ before do # Redefine String#red just like colorize gem does it.
+ @awesome_method = "".method(:red)
+
+ String.instance_eval do
+ define_method :red do # Method arity is now 0 in Ruby 1.9+.
+ "[red]#{self}[/red]"
+ end
+ end
+ end
+
+ after do # Restore String#red method.
+ awesome_method = @awesome_method
+ String.instance_eval do
+ define_method :red, awesome_method
+ end
+ end
+
+ it "shoud not raise ArgumentError when formatting HTML" do
+ out = "hello".ai(:color => { :string => :red }, :html => true)
+ if RUBY_VERSION >= "1.9"
+ out.should == %Q|<pre>[red]<kbd style="color:red">"hello"</kbd>[/red]</pre>|
+ else
+ out.should == %Q|<pre>[red]"hello"[/red]</pre>|
+ end
+ end
+
+ it "shoud not raise ArgumentError when formatting HTML (shade color)" do
+ out = "hello".ai(:color => { :string => :redish }, :html => true)
+ out.should == %Q|<pre><kbd style="color:darkred">"hello"</kbd></pre>|
+ end
+
+ it "shoud not raise ArgumentError when formatting non-HTML" do
+ out = "hello".ai(:color => { :string => :red }, :html => false)
+ out.should == %Q|[red]"hello"[/red]|
+ end
+
+ it "shoud not raise ArgumentError when formatting non-HTML (shade color)" do
+ out = "hello".ai(:color => { :string => :redish }, :html => false)
+ out.should == %Q|\e[0;31m"hello"\e[0m|
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "Console" do
+ it "should detect IRB" do
+ class IRB; end
+ AwesomePrint.console?.should == true
+ AwesomePrint.rails_console?.should == false
+ Object.instance_eval{ remove_const :IRB }
+ end
+
+ it "should detect Pry" do
+ class Pry; end
+ AwesomePrint.console?.should == true
+ AwesomePrint.rails_console?.should == false
+ Object.instance_eval{ remove_const :Pry }
+ end
+
+ it "should detect Rails::Console" do
+ class IRB; end
+ class Rails; class Console; end; end
+ AwesomePrint.console?.should == true
+ AwesomePrint.rails_console?.should == true
+ Object.instance_eval{ remove_const :IRB }
+ Object.instance_eval{ remove_const :Rails }
+ end
+
+ it "should detect ENV['RAILS_ENV']" do
+ class Pry; end
+ ENV["RAILS_ENV"] = "development"
+ AwesomePrint.console?.should == true
+ AwesomePrint.rails_console?.should == true
+ Object.instance_eval{ remove_const :Pry }
+ end
+
+ it "should return the actual object when *not* running under console" do
+ capture! { ap([ 1, 2, 3 ]) }.should == [ 1, 2, 3 ]
+ capture! { ap({ :a => 1 }) }.should == { :a => 1 }
+ end
+
+ it "should return nil when running under console" do
+ class IRB; end
+ capture! { ap([ 1, 2, 3 ]) }.should == nil
+ capture! { ap({ :a => 1 }) }.should == nil
+ Object.instance_eval{ remove_const :IRB }
+ end
+ end
+end
diff --git a/spec/objects_spec.rb b/spec/objects_spec.rb
new file mode 100644
index 0000000..1802e9a
--- /dev/null
+++ b/spec/objects_spec.rb
@@ -0,0 +1,85 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+
+describe "Objects" do
+ before do
+ stub_dotfile!
+ end
+
+ after do
+ Object.instance_eval{ remove_const :Hello } if defined?(Hello)
+ end
+
+ describe "Formatting an object" do
+ it "attributes" do
+ class Hello
+ attr_reader :abra
+ attr_writer :ca
+ attr_accessor :dabra
+
+ def initialize
+ @abra, @ca, @dabra = 1, 2, 3
+ end
+ end
+
+ hello = Hello.new
+ out = hello.ai(:plain => true, :raw => true)
+ str = <<-EOS.strip
+#<Hello:0x01234567
+ attr_accessor :dabra = 3,
+ attr_reader :abra = 1,
+ attr_writer :ca = 2
+>
+EOS
+ out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
+ hello.ai(:plain => true, :raw => false).should == hello.inspect
+ end
+
+ it "instance variables" do
+ class Hello
+ def initialize
+ @abra, @ca, @dabra = 1, 2, 3
+ end
+ end
+
+ hello = Hello.new
+ out = hello.ai(:plain => true, :raw => true)
+ str = <<-EOS.strip
+#<Hello:0x01234567
+ @abra = 1,
+ @ca = 2,
+ @dabra = 3
+>
+EOS
+ out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
+ hello.ai(:plain => true, :raw => false).should == hello.inspect
+ end
+
+ it "attributes and instance variables" do
+ class Hello
+ attr_reader :abra
+ attr_writer :ca
+ attr_accessor :dabra
+
+ def initialize
+ @abra, @ca, @dabra = 1, 2, 3
+ @scooby, @dooby, @doo = 3, 2, 1
+ end
+ end
+
+ hello = Hello.new
+ out = hello.ai(:plain => true, :raw => true)
+ str = <<-EOS.strip
+#<Hello:0x01234567
+ @doo = 1,
+ @dooby = 2,
+ @scooby = 3,
+ attr_accessor :dabra = 3,
+ attr_reader :abra = 1,
+ attr_writer :ca = 2
+>
+EOS
+ out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
+ hello.ai(:plain => true, :raw => false).should == hello.inspect
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..9a4ebab
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,64 @@
+# Copyright (c) 2010-2013 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+#
+# Running specs from the command line:
+# $ rake spec # Entire spec suite.
+# $ rspec spec/objects_spec.rb # Individual spec file.
+#
+# NOTE: To successfully run specs with Ruby 1.8.6 the older versions of
+# Bundler and RSpec gems are required:
+#
+# $ gem install bundler -v=1.0.2
+# $ gem install rspec -v=2.6.0
+#
+$LOAD_PATH.unshift(File.dirname(__FILE__))
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+require 'awesome_print'
+
+def stub_dotfile!
+ dotfile = File.join(ENV["HOME"], ".aprc")
+ File.should_receive(:readable?).at_least(:once).with(dotfile).and_return(false)
+end
+
+def capture!
+ standard, $stdout = $stdout, StringIO.new
+ yield
+ensure
+ $stdout = standard
+end
+
+# The following is needed for the Infinity Test. It runs tests as subprocesses,
+# which sets STDOUT.tty? to false and would otherwise prematurely disallow colors.
+### AwesomePrint.force_colors!
+
+# Ruby 1.8.6 only: define missing String methods that are needed for the specs to pass.
+if RUBY_VERSION < '1.8.7'
+ class String
+ def shellescape # Taken from Ruby 1.9.2 standard library, see lib/shellwords.rb.
+ return "''" if self.empty?
+ str = self.dup
+ str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1")
+ str.gsub!(/\n/, "'\n'")
+ str
+ end
+
+ def start_with?(*prefixes)
+ prefixes.each do |prefix|
+ prefix = prefix.to_s
+ return true if prefix == self[0, prefix.size]
+ end
+ false
+ end
+
+ def end_with?(*suffixes)
+ suffixes.each do |suffix|
+ suffix = suffix.to_s
+ return true if suffix == self[-suffix.size, suffix.size]
+ end
+ false
+ end
+ end
+end
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-awesome-print.git
More information about the Pkg-ruby-extras-commits
mailing list