mirror of
https://github.com/awesome-print/awesome_print
synced 2023-03-27 23:22:34 -04:00
Resolved merge conflicts
This commit is contained in:
commit
7a35496b7f
25 changed files with 924 additions and 290 deletions
10
CHANGELOG
10
CHANGELOG
|
@ -1,3 +1,13 @@
|
||||||
|
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
|
0.3.2
|
||||||
- Make sure Rails mixins get loaded in Rails console when required from .irbrc
|
- 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 an issue with classes that define their own #send method (ex: Socket)
|
||||||
|
|
63
README.md
63
README.md
|
@ -15,15 +15,16 @@ objects and usage within Rails templates are supported via included mixins.
|
||||||
|
|
||||||
### Usage ###
|
### Usage ###
|
||||||
|
|
||||||
require "ap"
|
require "awesome_print"
|
||||||
ap object, options = {}
|
ap object, options = {}
|
||||||
|
|
||||||
Default options:
|
Default options:
|
||||||
|
|
||||||
:multiline => true, # Display in multipe lines.
|
:multiline => true, # Display in multiple lines.
|
||||||
:plain => false, # Use colors.
|
:plain => false, # Use colors.
|
||||||
:indent => 4, # Indent using 4 spaces.
|
:indent => 4, # Indent using 4 spaces.
|
||||||
:index => true, # Display array indices.
|
:index => true, # Display array indices.
|
||||||
|
:html => false, # Use ANSI color codes rather than HTML.
|
||||||
:sorted_hash_keys => false, # Do not sort hash keys.
|
:sorted_hash_keys => false, # Do not sort hash keys.
|
||||||
:color => {
|
:color => {
|
||||||
:array => :white,
|
:array => :white,
|
||||||
|
@ -48,7 +49,7 @@ Supported color names:
|
||||||
|
|
||||||
### Examples ###
|
### Examples ###
|
||||||
$ cat > 1.rb
|
$ cat > 1.rb
|
||||||
require "ap"
|
require "awesome_print"
|
||||||
data = [ false, 42, %w(forty two), { :now => Time.now, :class => Time.now.class, :distance => 42e42 } ]
|
data = [ false, 42, %w(forty two), { :now => Time.now, :class => Time.now.class, :distance => 42e42 } ]
|
||||||
ap data
|
ap data
|
||||||
^D
|
^D
|
||||||
|
@ -68,7 +69,7 @@ Supported color names:
|
||||||
]
|
]
|
||||||
|
|
||||||
$ cat > 2.rb
|
$ cat > 2.rb
|
||||||
require "ap"
|
require "awesome_print"
|
||||||
data = { :now => Time.now, :class => Time.now.class, :distance => 42e42 }
|
data = { :now => Time.now, :class => Time.now.class, :distance => 42e42 }
|
||||||
ap data, :indent => -2 # <-- Left align hash keys.
|
ap data, :indent => -2 # <-- Left align hash keys.
|
||||||
^D
|
^D
|
||||||
|
@ -80,7 +81,7 @@ Supported color names:
|
||||||
}
|
}
|
||||||
|
|
||||||
$ cat > 3.rb
|
$ cat > 3.rb
|
||||||
require "ap"
|
require "awesome_print"
|
||||||
data = [ false, 42, %w(forty two) ]
|
data = [ false, 42, %w(forty two) ]
|
||||||
data << data # <-- Nested array.
|
data << data # <-- Nested array.
|
||||||
ap data, :multiline => false
|
ap data, :multiline => false
|
||||||
|
@ -89,7 +90,7 @@ Supported color names:
|
||||||
[ false, 42, [ "forty", "two" ], [...] ]
|
[ false, 42, [ "forty", "two" ], [...] ]
|
||||||
|
|
||||||
$ cat > 4.rb
|
$ cat > 4.rb
|
||||||
require "ap"
|
require "awesome_print"
|
||||||
class Hello
|
class Hello
|
||||||
def self.world(x, y, z = nil, &blk)
|
def self.world(x, y, z = nil, &blk)
|
||||||
end
|
end
|
||||||
|
@ -102,7 +103,7 @@ Supported color names:
|
||||||
]
|
]
|
||||||
|
|
||||||
$ cat > 5.rb
|
$ cat > 5.rb
|
||||||
require "ap"
|
require "awesome_print"
|
||||||
ap (''.methods - Object.methods).grep(/!/)
|
ap (''.methods - Object.methods).grep(/!/)
|
||||||
^D
|
^D
|
||||||
$ ruby 5.rb
|
$ ruby 5.rb
|
||||||
|
@ -129,10 +130,17 @@ Supported color names:
|
||||||
[19] upcase!() String
|
[19] upcase!() String
|
||||||
]
|
]
|
||||||
|
|
||||||
|
$ cat > 6.rb
|
||||||
|
require "awesome_print"
|
||||||
|
ap 42 == ap(42)
|
||||||
|
^D
|
||||||
|
$ ruby 6.rb
|
||||||
|
42
|
||||||
|
true
|
||||||
|
|
||||||
### Example (Rails console) ###
|
### Example (Rails console) ###
|
||||||
$ ruby script/console
|
$ rails console
|
||||||
Loading development environment (Rails 2.3.5)
|
rails> require "awesome_print"
|
||||||
rails> require "ap"
|
|
||||||
rails> ap Account.all(:limit => 2)
|
rails> ap Account.all(:limit => 2)
|
||||||
[
|
[
|
||||||
[0] #<Account:0x1033220b8> {
|
[0] #<Account:0x1033220b8> {
|
||||||
|
@ -192,7 +200,7 @@ To use awesome_print as default formatter in irb and Rails console add the follo
|
||||||
lines into your ~/.irbrc file:
|
lines into your ~/.irbrc file:
|
||||||
|
|
||||||
require "rubygems"
|
require "rubygems"
|
||||||
require "ap"
|
require "awesome_print"
|
||||||
|
|
||||||
unless IRB.version.include?('DietRB')
|
unless IRB.version.include?('DietRB')
|
||||||
IRB::Irb.class_eval do
|
IRB::Irb.class_eval do
|
||||||
|
@ -209,25 +217,30 @@ lines into your ~/.irbrc file:
|
||||||
end
|
end
|
||||||
|
|
||||||
### Logger Convenience Method ###
|
### Logger Convenience Method ###
|
||||||
awesome_print adds an ap method to the Logger and ActiveSupport::BufferedLogger classes,
|
awesome_print adds the 'ap' method to the Logger and ActiveSupport::BufferedLogger classes
|
||||||
allowing you to call:
|
letting you call:
|
||||||
|
|
||||||
logger.ap object
|
logger.ap object
|
||||||
|
|
||||||
By default, this logs at the :debug level. You can override that globally with
|
By default, this logs at the :debug level. You can override that globally with:
|
||||||
|
|
||||||
:log_level => :info
|
:log_level => :info
|
||||||
|
|
||||||
in the custom defaults (see below), or you can override on a per call basis with
|
in the custom defaults (see below). You can also override on a per call basis with:
|
||||||
|
|
||||||
logger.ap object, :warn
|
logger.ap object, :warn
|
||||||
|
|
||||||
### ActionView Convenience Method ###
|
### ActionView Convenience Method ###
|
||||||
awesome_print adds an ap method to the ActionView::Base class making it available
|
awesome_print adds the 'ap' method to the ActionView::Base class making it available
|
||||||
within Rails templates. For example:
|
within Rails templates. For example:
|
||||||
|
|
||||||
<%= ap @accounts.first %>
|
<%= ap @accounts.first %>
|
||||||
|
|
||||||
|
With other web frameworks (ex: in Sinatra templates) you can explicitly request HTML
|
||||||
|
formatting:
|
||||||
|
|
||||||
|
<%= ap @accounts.first, :html => true %>
|
||||||
|
|
||||||
### Setting Custom Defaults ###
|
### Setting Custom Defaults ###
|
||||||
You can set your own default options by creating ``.aprc`` file in your home
|
You can set your own default options by creating ``.aprc`` file in your home
|
||||||
directory. Within that file assign your defaults to ``AwesomePrint.defaults``.
|
directory. Within that file assign your defaults to ``AwesomePrint.defaults``.
|
||||||
|
@ -244,9 +257,9 @@ For example:
|
||||||
|
|
||||||
### Running Specs ###
|
### Running Specs ###
|
||||||
|
|
||||||
$ rake spec # Entire spec suite.
|
$ gem install rspec # RSpec 2.x is the requirement.
|
||||||
$ ruby -rubygems spec/logger_spec.rb # Individual spec file (Ruby 1.8.7 and RSpec 1.3+)
|
$ rake spec # Run the entire spec suite.
|
||||||
$ rspec spec/logger_spec.rb # Individual spec file (Ruby 1.9.2 and RSpec 2.0+)
|
$ rspec spec/logger_spec.rb # Run individual spec file.
|
||||||
|
|
||||||
### Note on Patches/Pull Requests ###
|
### Note on Patches/Pull Requests ###
|
||||||
* Fork the project on Github.
|
* Fork the project on Github.
|
||||||
|
@ -257,16 +270,22 @@ For example:
|
||||||
|
|
||||||
### Contributors ###
|
### Contributors ###
|
||||||
|
|
||||||
|
* Andrew O'Brien -- https://github.com/AndrewO
|
||||||
* Daniel Bretoi -- http://github.com/danielb2
|
* Daniel Bretoi -- http://github.com/danielb2
|
||||||
* Eloy Duran -- http://github.com/alloy
|
* Eloy Duran -- http://github.com/alloy
|
||||||
|
* Elpizo Choi -- https://github.com/fuJiin
|
||||||
* Benoit Daloze -- http://github.com/eregon
|
* Benoit Daloze -- http://github.com/eregon
|
||||||
* Sean Gallagher -- http://github.com/torandu
|
* Sean Gallagher -- http://github.com/torandu
|
||||||
|
* Stephan Hagemann -- https://github.com/shageman
|
||||||
* Tim Harper -- http://github.com/timcharper
|
* Tim Harper -- http://github.com/timcharper
|
||||||
* Tobias Crawley -- http://github.com/tobias
|
* Tobias Crawley -- http://github.com/tobias
|
||||||
|
* Viktar Basharymau -- https://github.com/DNNX
|
||||||
|
|
||||||
### License ###
|
### License ###
|
||||||
Copyright (c) 2010-2011 Michael Dvorkin
|
Copyright (c) 2010-2011 Michael Dvorkin
|
||||||
|
|
||||||
twitter.com/mid
|
twitter.com/mid
|
||||||
|
|
||||||
%w(mike dvorkin.net) * "@" || %w(mike fatfreecrm.com) * "@"
|
%w(mike dvorkin.net) * "@" || %w(mike fatfreecrm.com) * "@"
|
||||||
|
|
||||||
Released under the MIT license. See LICENSE file for details.
|
Released under the MIT license. See LICENSE file for details.
|
||||||
|
|
38
Rakefile
38
Rakefile
|
@ -11,13 +11,8 @@ begin
|
||||||
gem.email = "mike@dvorkin.net"
|
gem.email = "mike@dvorkin.net"
|
||||||
gem.homepage = "http://github.com/michaeldv/awesome_print"
|
gem.homepage = "http://github.com/michaeldv/awesome_print"
|
||||||
gem.authors = ["Michael Dvorkin"]
|
gem.authors = ["Michael Dvorkin"]
|
||||||
if RUBY_VERSION.to_f >= 1.9
|
gem.add_development_dependency "rspec", ">= 2.5.0"
|
||||||
gem.add_development_dependency "rspec", ">= 2.0.0"
|
|
||||||
else
|
|
||||||
gem.add_development_dependency "rspec", ">= 1.3.0"
|
|
||||||
end
|
|
||||||
gem.files = FileList["[A-Z]*", "lib/**/*.rb", "rails/*.rb", "spec/*", "init.rb"]
|
gem.files = FileList["[A-Z]*", "lib/**/*.rb", "rails/*.rb", "spec/*", "init.rb"]
|
||||||
gem.has_rdoc = false
|
|
||||||
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
||||||
end
|
end
|
||||||
Jeweler::GemcutterTasks.new
|
Jeweler::GemcutterTasks.new
|
||||||
|
@ -25,30 +20,15 @@ rescue LoadError
|
||||||
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
||||||
end
|
end
|
||||||
|
|
||||||
if RUBY_VERSION.to_f >= 1.9
|
require "rspec/core/rake_task"
|
||||||
require "rspec/core/rake_task" # RSpec 2.0
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
||||||
RSpec::Core::RakeTask.new(:spec) do |spec|
|
spec.pattern = 'spec/**/*_spec.rb'
|
||||||
spec.pattern = 'spec/**/*_spec.rb'
|
spec.rspec_opts = ['--color']
|
||||||
spec.rspec_opts = ['--color']
|
end
|
||||||
end
|
|
||||||
|
|
||||||
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
||||||
spec.rcov = true
|
spec.rcov = true
|
||||||
spec.rcov_opts = %q[--exclude "spec"]
|
spec.rcov_opts = %q[--exclude "spec"]
|
||||||
end
|
|
||||||
else
|
|
||||||
require 'spec/rake/spectask'
|
|
||||||
Spec::Rake::SpecTask.new(:spec) do |spec|
|
|
||||||
spec.libs << 'lib' << 'spec'
|
|
||||||
spec.spec_opts = ['--color']
|
|
||||||
spec.spec_files = FileList['spec/**/*_spec.rb']
|
|
||||||
end
|
|
||||||
|
|
||||||
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
|
||||||
spec.libs << 'lib' << 'spec'
|
|
||||||
spec.pattern = 'spec/**/*_spec.rb'
|
|
||||||
spec.rcov = true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
task :spec => :check_dependencies
|
task :spec => :check_dependencies
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
0.3.2
|
0.4.0
|
||||||
|
|
|
@ -1,77 +1,70 @@
|
||||||
# Generated by jeweler
|
# Generated by jeweler
|
||||||
# DO NOT EDIT THIS FILE DIRECTLY
|
# DO NOT EDIT THIS FILE DIRECTLY
|
||||||
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
Gem::Specification.new do |s|
|
Gem::Specification.new do |s|
|
||||||
s.name = %q{awesome_print}
|
s.name = %q{awesome_print}
|
||||||
s.version = "0.3.2"
|
s.version = "0.4.0"
|
||||||
|
|
||||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||||
s.authors = ["Michael Dvorkin"]
|
s.authors = ["Michael Dvorkin"]
|
||||||
s.date = %q{2011-02-02}
|
s.date = %q{2011-05-13}
|
||||||
s.description = %q{Great Ruby dubugging companion: pretty print Ruby objects to visualize their structure. Supports Rails ActiveRecord objects via included mixin.}
|
s.description = %q{Great Ruby dubugging companion: pretty print Ruby objects to visualize their structure. Supports Rails ActiveRecord objects via included mixin.}
|
||||||
s.email = %q{mike@dvorkin.net}
|
s.email = %q{mike@dvorkin.net}
|
||||||
s.extra_rdoc_files = [
|
s.extra_rdoc_files = [
|
||||||
"LICENSE",
|
"LICENSE",
|
||||||
"README.md"
|
"README.md"
|
||||||
]
|
]
|
||||||
s.files = [
|
s.files = [
|
||||||
"CHANGELOG",
|
"CHANGELOG",
|
||||||
"LICENSE",
|
"LICENSE",
|
||||||
"README.md",
|
"README.md",
|
||||||
"Rakefile",
|
"Rakefile",
|
||||||
"VERSION",
|
"VERSION",
|
||||||
"init.rb",
|
"init.rb",
|
||||||
"lib/ap.rb",
|
"lib/ap.rb",
|
||||||
"lib/ap/awesome_print.rb",
|
"lib/ap/awesome_print.rb",
|
||||||
"lib/ap/core_ext/array.rb",
|
"lib/ap/core_ext/array.rb",
|
||||||
"lib/ap/core_ext/class.rb",
|
"lib/ap/core_ext/class.rb",
|
||||||
"lib/ap/core_ext/kernel.rb",
|
"lib/ap/core_ext/kernel.rb",
|
||||||
"lib/ap/core_ext/logger.rb",
|
"lib/ap/core_ext/logger.rb",
|
||||||
"lib/ap/core_ext/method.rb",
|
"lib/ap/core_ext/method.rb",
|
||||||
"lib/ap/core_ext/object.rb",
|
"lib/ap/core_ext/object.rb",
|
||||||
"lib/ap/core_ext/string.rb",
|
"lib/ap/core_ext/string.rb",
|
||||||
"lib/ap/mixin/action_view.rb",
|
"lib/ap/mixin/action_view.rb",
|
||||||
"lib/ap/mixin/active_record.rb",
|
"lib/ap/mixin/active_record.rb",
|
||||||
"lib/ap/mixin/active_support.rb",
|
"lib/ap/mixin/active_support.rb",
|
||||||
"lib/awesome_print.rb",
|
"lib/ap/mixin/mongo_mapper.rb",
|
||||||
"rails/init.rb",
|
"lib/awesome_print.rb",
|
||||||
"spec/action_view_spec.rb",
|
"rails/init.rb",
|
||||||
"spec/active_record_spec.rb",
|
"spec/action_view_spec.rb",
|
||||||
"spec/awesome_print_spec.rb",
|
"spec/active_record_spec.rb",
|
||||||
"spec/logger_spec.rb",
|
"spec/awesome_print_spec.rb",
|
||||||
"spec/methods_spec.rb",
|
"spec/colorization_spec.rb",
|
||||||
"spec/spec_helper.rb",
|
"spec/logger_spec.rb",
|
||||||
"spec/string_spec.rb"
|
"spec/methods_spec.rb",
|
||||||
|
"spec/mongo_mapper_spec.rb",
|
||||||
|
"spec/spec_helper.rb",
|
||||||
|
"spec/string_spec.rb"
|
||||||
]
|
]
|
||||||
s.homepage = %q{http://github.com/michaeldv/awesome_print}
|
s.homepage = %q{http://github.com/michaeldv/awesome_print}
|
||||||
s.rdoc_options = ["--charset=UTF-8"]
|
|
||||||
s.require_paths = ["lib"]
|
s.require_paths = ["lib"]
|
||||||
s.rubyforge_project = %q{awesome_print}
|
s.rubyforge_project = %q{awesome_print}
|
||||||
s.rubygems_version = %q{1.3.6}
|
s.rubygems_version = %q{1.3.7}
|
||||||
s.summary = %q{Pretty print Ruby objects with proper indentation and colors.}
|
s.summary = %q{Pretty print Ruby objects with proper indentation and colors.}
|
||||||
s.test_files = [
|
|
||||||
"spec/action_view_spec.rb",
|
|
||||||
"spec/active_record_spec.rb",
|
|
||||||
"spec/awesome_print_spec.rb",
|
|
||||||
"spec/logger_spec.rb",
|
|
||||||
"spec/methods_spec.rb",
|
|
||||||
"spec/spec_helper.rb",
|
|
||||||
"spec/string_spec.rb"
|
|
||||||
]
|
|
||||||
|
|
||||||
if s.respond_to? :specification_version then
|
if s.respond_to? :specification_version then
|
||||||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||||
s.specification_version = 3
|
s.specification_version = 3
|
||||||
|
|
||||||
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
||||||
s.add_development_dependency(%q<rspec>, [">= 1.3.0"])
|
s.add_development_dependency(%q<rspec>, [">= 2.5.0"])
|
||||||
else
|
else
|
||||||
s.add_dependency(%q<rspec>, [">= 1.3.0"])
|
s.add_dependency(%q<rspec>, [">= 2.5.0"])
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
s.add_dependency(%q<rspec>, [">= 1.3.0"])
|
s.add_dependency(%q<rspec>, [">= 2.5.0"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
2
init.rb
2
init.rb
|
@ -1 +1 @@
|
||||||
require File.join(File.dirname(__FILE__), "lib", "ap")
|
require File.join(File.dirname(__FILE__), "lib", "awesome_print")
|
||||||
|
|
31
lib/ap.rb
31
lib/ap.rb
|
@ -3,16 +3,23 @@
|
||||||
# Awesome Print is freely distributable under the terms of MIT license.
|
# Awesome Print is freely distributable under the terms of MIT license.
|
||||||
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
%w(array string method object class kernel).each do |file|
|
#
|
||||||
require File.dirname(__FILE__) + "/ap/core_ext/#{file}"
|
# AwesomePrint might be loaded implicitly through ~/.irbrc so do nothing
|
||||||
|
# for subsequent requires.
|
||||||
|
#
|
||||||
|
unless defined?(AwesomePrint)
|
||||||
|
%w(array string method object class kernel).each do |file|
|
||||||
|
require File.dirname(__FILE__) + "/ap/core_ext/#{file}"
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.dirname(__FILE__) + "/ap/inspector"
|
||||||
|
require File.dirname(__FILE__) + "/ap/formatter"
|
||||||
|
require File.dirname(__FILE__) + "/ap/core_ext/logger" if defined?(Logger)
|
||||||
|
require File.dirname(__FILE__) + "/ap/mixin/action_view" if defined?(ActionView)
|
||||||
|
|
||||||
|
# Load the following under normal circumstatnces as well as in Rails
|
||||||
|
# console when required from ~/.irbrc.
|
||||||
|
require File.dirname(__FILE__) + "/ap/mixin/active_record" if defined?(ActiveRecord) || (defined?(IRB) && ENV['RAILS_ENV'])
|
||||||
|
require File.dirname(__FILE__) + "/ap/mixin/active_support" if defined?(ActiveSupport) || (defined?(IRB) && ENV['RAILS_ENV'])
|
||||||
|
require File.dirname(__FILE__) + "/ap/mixin/mongo_mapper" if defined?(MongoMapper)
|
||||||
end
|
end
|
||||||
|
|
||||||
require File.dirname(__FILE__) + "/ap/inspector"
|
|
||||||
require File.dirname(__FILE__) + "/ap/formatter"
|
|
||||||
require File.dirname(__FILE__) + "/ap/core_ext/logger" if defined?(Logger)
|
|
||||||
require File.dirname(__FILE__) + "/ap/mixin/action_view" if defined?(ActionView)
|
|
||||||
|
|
||||||
# Load the following under normal circumstatnces as well as in Rails
|
|
||||||
# console when required from ~/.irbrc.
|
|
||||||
require File.dirname(__FILE__) + "/ap/mixin/active_record" if defined?(ActiveRecord) || (defined?(IRB) && ENV['RAILS_ENV'])
|
|
||||||
require File.dirname(__FILE__) + "/ap/mixin/active_support" if defined?(ActiveSupport) || (defined?(IRB) && ENV['RAILS_ENV'])
|
|
||||||
|
|
352
lib/ap/awesome_print.rb
Executable file
352
lib/ap/awesome_print.rb
Executable file
|
@ -0,0 +1,352 @@
|
||||||
|
# Copyright (c) 2010-2011 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
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
require "cgi"
|
||||||
|
require "shellwords"
|
||||||
|
|
||||||
|
class AwesomePrint
|
||||||
|
AP = :__awesome_print__ unless defined?(AwesomePrint::AP)
|
||||||
|
CORE = [ :array, :hash, :class, :file, :dir, :bigdecimal, :rational, :struct, :method, :unboundmethod ] unless defined?(AwesomePrint::CORE)
|
||||||
|
@@force_colors = false
|
||||||
|
|
||||||
|
def initialize(options = {})
|
||||||
|
@options = {
|
||||||
|
:multiline => true, # Display in multiple lines.
|
||||||
|
:plain => false, # Use colors.
|
||||||
|
:indent => 4, # Indent using 4 spaces.
|
||||||
|
:index => true, # Display array indices.
|
||||||
|
:html => false, # Use ANSI color codes rather than HTML.
|
||||||
|
:sorted_hash_keys => false, # Do not sort hash keys.
|
||||||
|
:color => {
|
||||||
|
:array => :white,
|
||||||
|
:bigdecimal => :blue,
|
||||||
|
:class => :yellow,
|
||||||
|
:date => :greenish,
|
||||||
|
:falseclass => :red,
|
||||||
|
:fixnum => :blue,
|
||||||
|
:float => :blue,
|
||||||
|
:hash => :pale,
|
||||||
|
:struct => :pale,
|
||||||
|
:nilclass => :red,
|
||||||
|
:string => :yellowish,
|
||||||
|
:symbol => :cyanish,
|
||||||
|
:time => :greenish,
|
||||||
|
:trueclass => :green,
|
||||||
|
:method => :purpleish,
|
||||||
|
:args => :pale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Merge custom defaults and let explicit options parameter override them.
|
||||||
|
merge_custom_defaults!
|
||||||
|
merge_options!(options)
|
||||||
|
|
||||||
|
@indentation = @options[:indent].abs
|
||||||
|
Thread.current[AP] ||= []
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# 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 = if @options[:index]
|
||||||
|
colorize("#{indent}[#{arr.size.to_s.rjust(width)}] ", :array)
|
||||||
|
else
|
||||||
|
colorize(indent, :array)
|
||||||
|
end
|
||||||
|
indented do
|
||||||
|
arr << (index << awesome(item))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
"[\n" << data.join(",\n") << "\n#{outdent}]"
|
||||||
|
else
|
||||||
|
"[ " << a.map{ |item| 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[:sorted_hash_keys] ? h.keys.sort { |a, b| a.to_s <=> b.to_s } : h.keys
|
||||||
|
data = keys.map do |key|
|
||||||
|
plain_single_line do
|
||||||
|
[ 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|
|
||||||
|
if @options[:multiline]
|
||||||
|
formatted_key = (@options[:indent] >= 0 ? key.rjust(width) : indent + key.ljust(width))
|
||||||
|
else
|
||||||
|
formatted_key = key
|
||||||
|
end
|
||||||
|
indented do
|
||||||
|
formatted_key << colorize(" => ", :hash) << awesome(value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if @options[:multiline]
|
||||||
|
"{\n" << data.join(",\n") << "\n#{outdent}}"
|
||||||
|
else
|
||||||
|
"{ #{data.join(', ')} }"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Format a Struct. If @options[:indent] is negative left align hash keys.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def awesome_struct(s)
|
||||||
|
h = {}
|
||||||
|
s.each_pair { |k,v| h[k] = v }
|
||||||
|
awesome_hash(h)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Format Class object.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def awesome_class(c)
|
||||||
|
if superclass = c.superclass # <-- Assign and test if nil.
|
||||||
|
awesome_self(c, :with => " < #{superclass}")
|
||||||
|
else
|
||||||
|
awesome_self(c)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Format File object.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def awesome_file(f)
|
||||||
|
ls = File.directory?(f) ? `ls -adlF #{f.path.shellescape}` : `ls -alF #{f.path.shellescape}`
|
||||||
|
awesome_self(f, :with => ls.empty? ? nil : "\n#{ls.chop}")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Format Dir object.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def awesome_dir(d)
|
||||||
|
ls = `ls -alF #{d.path.shellescape}`
|
||||||
|
awesome_self(d, :with => ls.empty? ? nil : "\n#{ls.chop}")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Format BigDecimal and Rational objects by convering them to Float.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def awesome_bigdecimal(n)
|
||||||
|
awesome_self(n.to_f, :as => :bigdecimal)
|
||||||
|
end
|
||||||
|
alias :awesome_rational :awesome_bigdecimal
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Catch all method to format an arbitrary object.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def awesome_self(object, appear = {})
|
||||||
|
colorize(object.inspect.to_s << appear[:with].to_s, appear[:as] || declassify(object))
|
||||||
|
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
|
||||||
|
send(:"awesome_#{printable(object)}", object)
|
||||||
|
ensure
|
||||||
|
Thread.current[AP].pop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Format object.methods array.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def methods_array(a)
|
||||||
|
object = a.instance_variable_get('@__awesome_methods__')
|
||||||
|
tuples = a.map do |name|
|
||||||
|
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))
|
||||||
|
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 = if @options[:index]
|
||||||
|
"#{indent}[#{arr.size.to_s.rjust(width)}]"
|
||||||
|
else
|
||||||
|
indent
|
||||||
|
end
|
||||||
|
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
|
||||||
|
|
||||||
|
# Format nested data, for example:
|
||||||
|
# arr = [1, 2]; arr << arr
|
||||||
|
# => [1,2, [...]]
|
||||||
|
# hsh = { :a => 1 }; hsh[:b] = hsh
|
||||||
|
# => { :a => 1, :b => {...} }
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def nested(object)
|
||||||
|
case printable(object)
|
||||||
|
when :array then colorize("[...]", :array)
|
||||||
|
when :hash then colorize("{...}", :hash)
|
||||||
|
when :struct then colorize("{...}", :struct)
|
||||||
|
else colorize("...#{object.class}...", :class)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return one of the "core" types that have a formatter of :self otherwise.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def printable(object)
|
||||||
|
CORE.grep(declassify(object))[0] || :self
|
||||||
|
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 declassify(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
|
||||||
|
|
||||||
|
# Pick the color and apply it to the given string as necessary.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def colorize(s, type)
|
||||||
|
s = CGI.escapeHTML(s) if @options[:html]
|
||||||
|
if @options[:plain] || !@options[:color][type] || !colorize?
|
||||||
|
@options[:html] ? "<pre>#{s}</pre>" : s
|
||||||
|
else
|
||||||
|
s.send(@options[:color][type], @options[:html])
|
||||||
|
end
|
||||||
|
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
|
||||||
|
|
||||||
|
if method.to_s =~ /(Unbound)*Method: (.*?)[#\.]/
|
||||||
|
owner = "#{$2}#{$1 ? '(unbound)' : ''}".gsub('(', ' (')
|
||||||
|
end
|
||||||
|
|
||||||
|
[ method.name.to_s, "(#{args.join(', ')})", owner.to_s ]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Format hash keys as plain string 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
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def indented
|
||||||
|
@indentation += @options[:indent].abs
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
@indentation -= @options[:indent].abs
|
||||||
|
end
|
||||||
|
|
||||||
|
def indent
|
||||||
|
@indent = ' ' * @indentation
|
||||||
|
end
|
||||||
|
|
||||||
|
def outdent
|
||||||
|
@outdent = ' ' * (@indentation - @options[:indent].abs)
|
||||||
|
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")
|
||||||
|
if File.readable?(dotfile)
|
||||||
|
load dotfile
|
||||||
|
merge_options!(self.class.defaults)
|
||||||
|
end
|
||||||
|
rescue => e
|
||||||
|
$stderr.puts "Could not load #{dotfile}: #{e}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return true if we are to colorize the output.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def colorize?
|
||||||
|
@@force_colors || (STDOUT.tty? && ((ENV['TERM'] && ENV['TERM'] != 'dumb') || ENV['ANSICON']))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Class accessor to force colorized output (ex. forked subprocess where TERM
|
||||||
|
# might be dumb).
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def self.force_colors!(value = true)
|
||||||
|
@@force_colors = value
|
||||||
|
end
|
||||||
|
|
||||||
|
# Class accessors for custom defaults.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def self.defaults
|
||||||
|
@@defaults ||= {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.defaults=(args = {})
|
||||||
|
@@defaults = args
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -14,12 +14,13 @@
|
||||||
#
|
#
|
||||||
class Array #:nodoc:
|
class Array #:nodoc:
|
||||||
[ :-, :& ].each do |operator|
|
[ :-, :& ].each do |operator|
|
||||||
alias :"original_#{operator.object_id}" :"#{operator}"
|
original_operator = instance_method(operator)
|
||||||
|
|
||||||
define_method operator do |*args|
|
define_method operator do |*args|
|
||||||
arr = self.__send__(:"original_#{operator.object_id}", *args)
|
arr = original_operator.bind(self).call(*args)
|
||||||
if self.instance_variable_defined?('@__awesome_methods__')
|
if self.instance_variable_defined?('@__awesome_methods__')
|
||||||
arr.instance_variable_set('@__awesome_methods__', self.instance_variable_get('@__awesome_methods__'))
|
arr.instance_variable_set('@__awesome_methods__', self.instance_variable_get('@__awesome_methods__'))
|
||||||
arr.sort!
|
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
|
end
|
||||||
arr
|
arr
|
||||||
end
|
end
|
||||||
|
@ -56,7 +57,10 @@ class Array #:nodoc:
|
||||||
arr = unless blk
|
arr = unless blk
|
||||||
original_grep(pattern)
|
original_grep(pattern)
|
||||||
else
|
else
|
||||||
original_grep(pattern) { |match| eval("%Q/#{match}/ =~ #{pattern.inspect}", blk.binding); yield match }
|
original_grep(pattern) do |match|
|
||||||
|
eval("%Q/#{match.to_s.gsub('/', '\/')}/ =~ #{pattern.inspect}", blk.binding)
|
||||||
|
yield match
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if self.instance_variable_defined?('@__awesome_methods__')
|
if self.instance_variable_defined?('@__awesome_methods__')
|
||||||
arr.instance_variable_set('@__awesome_methods__', self.instance_variable_get('@__awesome_methods__'))
|
arr.instance_variable_set('@__awesome_methods__', self.instance_variable_get('@__awesome_methods__'))
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
class Class #:nodoc:
|
class Class #:nodoc:
|
||||||
# Remaining public/private etc. '_methods' are handled in core_ext/object.rb.
|
# 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|
|
%w(instance_methods private_instance_methods protected_instance_methods public_instance_methods).each do |name|
|
||||||
alias :"original_#{name}" :"#{name}"
|
original_method = instance_method(name)
|
||||||
|
|
||||||
define_method name do |*args|
|
define_method name do |*args|
|
||||||
methods = self.__send__(:"original_#{name}", *args)
|
methods = original_method.bind(self).call(*args)
|
||||||
methods.instance_variable_set('@__awesome_methods__', self) # Evil?!
|
methods.instance_variable_set('@__awesome_methods__', self) # Evil?!
|
||||||
methods.sort!
|
methods.sort!
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,6 +13,7 @@ module Kernel
|
||||||
|
|
||||||
def ap(object, options = {})
|
def ap(object, options = {})
|
||||||
puts object.ai(options)
|
puts object.ai(options)
|
||||||
|
object
|
||||||
end
|
end
|
||||||
alias :awesome_print :ap
|
alias :awesome_print :ap
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
class Object #:nodoc:
|
class Object #:nodoc:
|
||||||
# Remaining instance '_methods' are handled in core_ext/class.rb.
|
# Remaining instance '_methods' are handled in core_ext/class.rb.
|
||||||
%w(methods private_methods protected_methods public_methods singleton_methods).each do |name|
|
%w(methods private_methods protected_methods public_methods singleton_methods).each do |name|
|
||||||
alias :"original_#{name}" :"#{name}"
|
original_method = instance_method(name)
|
||||||
|
|
||||||
define_method name do |*args|
|
define_method name do |*args|
|
||||||
methods = self.__send__(:"original_#{name}", *args)
|
methods = original_method.bind(self).call(*args)
|
||||||
methods.instance_variable_set('@__awesome_methods__', self) # Evil?!
|
methods.instance_variable_set('@__awesome_methods__', self) # Evil?!
|
||||||
methods.sort!
|
methods.sort!
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,13 +11,14 @@ class String
|
||||||
# 1 => bright
|
# 1 => bright
|
||||||
# 0 => normal
|
# 0 => normal
|
||||||
|
|
||||||
[ :gray, :red, :green, :yellow, :blue, :purple, :cyan, :white ].each_with_index do |color, i|
|
%w(gray red green yellow blue purple cyan white).zip(
|
||||||
if STDOUT.tty? && ENV['TERM'] && ENV['TERM'] != 'dumb'
|
%w(black darkred darkgreen brown navy darkmagenta darkcyan slategray)).each_with_index do |(color, shade), i|
|
||||||
define_method color do "\033[1;#{30+i}m#{self}\033[0m" end
|
define_method color do |*html|
|
||||||
define_method :"#{color}ish" do "\033[0;#{30+i}m#{self}\033[0m" end
|
html[0] ? %Q|<pre style="color:#{color}">#{self}</pre>| : "\033[1;#{30+i}m#{self}\033[0m"
|
||||||
else
|
end
|
||||||
define_method color do self end
|
|
||||||
alias_method :"#{color}ish", color
|
define_method "#{color}ish" do |*html|
|
||||||
|
html[0] ? %Q|<pre style="color:#{shade}">#{self}</pre>| : "\033[0;#{30+i}m#{self}\033[0m"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,37 +3,15 @@
|
||||||
# Awesome Print is freely distributable under the terms of MIT license.
|
# Awesome Print is freely distributable under the terms of MIT license.
|
||||||
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
module AwesomePrint
|
module AwesomePrintActionView
|
||||||
module ActionView
|
|
||||||
|
|
||||||
def self.included(base)
|
# Use HTML colors and add default "debug_dump" class to the resulting HTML.
|
||||||
unless base.const_defined?(:AP_ANSI_TO_HTML)
|
def ap_debug(object, options = {})
|
||||||
hash = {} # Build ANSI => HTML color map.
|
object.ai(options.merge(:html => true)).sub(/^<pre([\s>])/, '<pre class="debug_dump"\\1')
|
||||||
[ :gray, :red, :green, :yellow, :blue, :purple, :cyan, :white ].each_with_index do |color, i|
|
|
||||||
hash["\033[1;#{30+i}m"] = color
|
|
||||||
end
|
|
||||||
[ :black, :darkred, :darkgreen, :brown, :navy, :darkmagenta, :darkcyan, :slategray ].each_with_index do |color, i|
|
|
||||||
hash["\033[0;#{30+i}m"] = color
|
|
||||||
end
|
|
||||||
base.const_set(:AP_ANSI_TO_HTML, hash.freeze)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def ap_debug(object, options = {})
|
|
||||||
formatted = h(object.ai(options))
|
|
||||||
|
|
||||||
unless options[:plain]
|
|
||||||
self.class::AP_ANSI_TO_HTML.each do |key, value|
|
|
||||||
formatted.gsub!(key, %Q|<font color="#{value}">|)
|
|
||||||
end
|
|
||||||
formatted.gsub!("\033[0m", "</font>")
|
|
||||||
end
|
|
||||||
|
|
||||||
content_tag(:pre, formatted, :class => "debug_dump")
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method :ap, :ap_debug
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
alias_method :ap, :ap_debug
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
ActionView::Base.send(:include, AwesomePrint::ActionView) if defined?(ActionView)
|
ActionView::Base.send(:include, AwesomePrintActionView) if defined?(ActionView)
|
||||||
|
|
54
lib/ap/mixin/mongo_mapper.rb
Normal file
54
lib/ap/mixin/mongo_mapper.rb
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
# Copyright (c) 2010-2011 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 AwesomePrintMongoMapper
|
||||||
|
|
||||||
|
def self.included(base)
|
||||||
|
base.send :alias_method, :printable_without_mongo_mapper, :printable
|
||||||
|
base.send :alias_method, :printable, :printable_with_mongo_mapper
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add MongoMapper class names to the dispatcher pipeline.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def printable_with_mongo_mapper(object)
|
||||||
|
printable = printable_without_mongo_mapper(object)
|
||||||
|
return printable if !defined?(MongoMapper::Document)
|
||||||
|
|
||||||
|
if printable == :self
|
||||||
|
if object.is_a?(MongoMapper::Document) || object.is_a?(MongoMapper::EmbeddedDocument)
|
||||||
|
printable = :mongo_mapper_instance
|
||||||
|
end
|
||||||
|
elsif printable == :class && (object.ancestors & [MongoMapper::Document, MongoMapper::EmbeddedDocument]).size > 0
|
||||||
|
printable = :mongo_mapper_class
|
||||||
|
end
|
||||||
|
printable
|
||||||
|
end
|
||||||
|
|
||||||
|
# Format MongoMapper instance object.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
def awesome_mongo_mapper_instance(object)
|
||||||
|
return object.inspect if !defined?(ActiveSupport::OrderedHash)
|
||||||
|
|
||||||
|
data = object.keys.keys.sort_by{|k| k}.inject(ActiveSupport::OrderedHash.new) do |hash, name|
|
||||||
|
hash[name] = object[name]
|
||||||
|
hash
|
||||||
|
end
|
||||||
|
"#{object} " + awesome_hash(data)
|
||||||
|
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_by{|k| k}.inject(ActiveSupport::OrderedHash.new) do |hash, c|
|
||||||
|
hash[c.first] = (c.last.type || "undefined").to_s.underscore.intern
|
||||||
|
hash
|
||||||
|
end
|
||||||
|
"class #{object} < #{object.superclass} " << awesome_hash(data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
AwesomePrint.send(:include, AwesomePrintMongoMapper)
|
|
@ -7,19 +7,21 @@
|
||||||
# This is the copy of original 'ap.rb' file that matches the gem name. It makes
|
# This is the copy of original 'ap.rb' file that matches the gem name. It makes
|
||||||
# it possible to omit the :require part in bundler's Gemfile:
|
# it possible to omit the :require part in bundler's Gemfile:
|
||||||
#
|
#
|
||||||
# gem 'awesome_print', '>= 0.2.1', :require => 'ap'
|
# gem 'awesome_print', '>= 0.4.0'
|
||||||
# gem 'awesome_print', '>= 3.0.0'
|
|
||||||
#
|
#
|
||||||
%w(array string method object class kernel).each do |file|
|
unless defined?(AwesomePrint)
|
||||||
require File.dirname(__FILE__) + "/ap/core_ext/#{file}"
|
%w(array string method object class kernel).each do |file|
|
||||||
|
require File.dirname(__FILE__) + "/ap/core_ext/#{file}"
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.dirname(__FILE__) + "/ap/inspector"
|
||||||
|
require File.dirname(__FILE__) + "/ap/formatter"
|
||||||
|
require File.dirname(__FILE__) + "/ap/core_ext/logger" if defined?(Logger)
|
||||||
|
require File.dirname(__FILE__) + "/ap/mixin/action_view" if defined?(ActionView)
|
||||||
|
|
||||||
|
# Load the following under normal circumstatnces as well as in Rails
|
||||||
|
# console when required from ~/.irbrc.
|
||||||
|
require File.dirname(__FILE__) + "/ap/mixin/active_record" if defined?(ActiveRecord) || (defined?(IRB) && ENV['RAILS_ENV'])
|
||||||
|
require File.dirname(__FILE__) + "/ap/mixin/active_support" if defined?(ActiveSupport) || (defined?(IRB) && ENV['RAILS_ENV'])
|
||||||
|
require File.dirname(__FILE__) + "/ap/mixin/mongo_mapper" if defined?(MongoMapper)
|
||||||
end
|
end
|
||||||
|
|
||||||
require File.dirname(__FILE__) + "/ap/inspector"
|
|
||||||
require File.dirname(__FILE__) + "/ap/formatter"
|
|
||||||
require File.dirname(__FILE__) + "/ap/core_ext/logger" if defined?(Logger)
|
|
||||||
require File.dirname(__FILE__) + "/ap/mixin/action_view" if defined?(ActionView)
|
|
||||||
|
|
||||||
# Load the following under normal circumstatnces as well as in Rails
|
|
||||||
# console when required from ~/.irbrc.
|
|
||||||
require File.dirname(__FILE__) + "/ap/mixin/active_record" if defined?(ActiveRecord) || (defined?(IRB) && ENV['RAILS_ENV'])
|
|
||||||
require File.dirname(__FILE__) + "/ap/mixin/active_support" if defined?(ActiveSupport) || (defined?(IRB) && ENV['RAILS_ENV'])
|
|
||||||
|
|
|
@ -6,8 +6,4 @@
|
||||||
#
|
#
|
||||||
# Load awesome_print when installed as Rails 2.3.x plugin.
|
# Load awesome_print when installed as Rails 2.3.x plugin.
|
||||||
#
|
#
|
||||||
# NOTE: After Rails 2.3.x console loads awesome_print/lib/ap.rb it attempts
|
|
||||||
# to load this file as well. Make sure to check whether the awesome_print
|
|
||||||
# is already loaded to avoid Ruby stack overflow when extending core classes.
|
|
||||||
#
|
|
||||||
require File.join(File.dirname(__FILE__), "..", "init") unless defined?(AwesomePrint)
|
require File.join(File.dirname(__FILE__), "..", "init") unless defined?(AwesomePrint)
|
||||||
|
|
|
@ -1,35 +1,25 @@
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
||||||
|
|
||||||
require 'action_view'
|
begin
|
||||||
require 'ap/mixin/action_view'
|
require 'action_view'
|
||||||
|
require 'ap/mixin/action_view'
|
||||||
|
|
||||||
describe "AwesomePrint ActionView extensions" do
|
describe "AwesomePrint ActionView extensions" do
|
||||||
before do
|
before do
|
||||||
@view = ActionView::Base.new
|
@view = ActionView::Base.new
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should wrap ap output with <pre> tag" do
|
it "uses HTML and adds 'debug_dump' class to plain <pre> tag" do
|
||||||
obj = 42
|
markup = rand
|
||||||
@view.ap(obj, :plain => true).should == '<pre class="debug_dump">42</pre>'
|
@view.ap(markup, :plain => true).should == %Q|<pre class="debug_dump">#{markup}</pre>|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should encode HTML entities" do
|
it "uses HTML and adds 'debug_dump' class to colorized <pre> tag" do
|
||||||
obj = " &<hello>"
|
markup = ' &<hello>'
|
||||||
@view.ap(obj, :plain => true).should == '<pre class="debug_dump">" &<hello>"</pre>'
|
@view.ap(markup).should == '<pre class="debug_dump" style="color:brown">" &<hello>"</pre>'
|
||||||
end
|
|
||||||
|
|
||||||
it "should convert primary ANSI colors to HTML" do
|
|
||||||
obj = 42
|
|
||||||
[ :gray, :red, :green, :yellow, :blue, :purple, :cyan, :white ].each do |color|
|
|
||||||
@view.ap(obj, :color => { :fixnum => color }).should == %Q|<pre class="debug_dump"><font color="#{color}">42</font></pre>|
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should convert mixed ANSI colors to HTML" do
|
rescue LoadError
|
||||||
obj = 42
|
puts "Skipping ActionView specs..."
|
||||||
[ :grayish, :redish, :greenish, :yellowish, :blueish, :purpleish, :cyanish, :whiteish, :black, :pale ].zip(
|
|
||||||
[ :black, :darkred, :darkgreen, :brown, :navy, :darkmagenta, :darkcyan, :slategray, :black, :slategray ]) do |ansi, html|
|
|
||||||
@view.ap(obj, :color => { :fixnum => ansi }).should == %Q|<pre class="debug_dump"><font color="#{html}">42</font></pre>|
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,54 +1,56 @@
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
||||||
|
|
||||||
require 'active_record'
|
begin
|
||||||
require 'ap/mixin/active_record'
|
require 'active_record'
|
||||||
|
require 'ap/mixin/active_record'
|
||||||
|
|
||||||
|
if defined?(::ActiveRecord)
|
||||||
|
|
||||||
# Create tableless ActiveRecord model.
|
# Create tableless ActiveRecord model.
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
class User < ActiveRecord::Base
|
class User < ActiveRecord::Base
|
||||||
def self.columns()
|
def self.columns()
|
||||||
@columns ||= []
|
@columns ||= []
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.column(name, sql_type = nil, default = nil, null = true)
|
def self.column(name, sql_type = nil, default = nil, null = true)
|
||||||
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
|
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
|
||||||
end
|
end
|
||||||
|
|
||||||
column :id, :integer
|
column :id, :integer
|
||||||
column :name, :string
|
column :name, :string
|
||||||
column :rank, :integer
|
column :rank, :integer
|
||||||
column :admin, :boolean
|
column :admin, :boolean
|
||||||
column :created_at, :datetime
|
column :created_at, :datetime
|
||||||
|
|
||||||
def self.table_exists?
|
def self.table_exists?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
class SubUser < User
|
|
||||||
def self.columns
|
|
||||||
User.columns
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "AwesomePrint::ActiveRecord" do
|
|
||||||
before do
|
|
||||||
stub_dotfile!
|
|
||||||
end
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
describe "ActiveRecord instance" do
|
|
||||||
before do
|
|
||||||
ActiveRecord::Base.default_timezone = :utc
|
|
||||||
@diana = User.new(:name => "Diana", :rank => 1, :admin => false, :created_at => "1992-10-10 12:30:00")
|
|
||||||
@laura = User.new(:name => "Laura", :rank => 2, :admin => true, :created_at => "2003-05-26 14:15:00")
|
|
||||||
@ap = AwesomePrint::Inspector.new(:plain => true)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "display single record" do
|
class SubUser < User
|
||||||
out = @ap.send(:awesome, @diana)
|
def self.columns
|
||||||
str = <<-EOS.strip
|
User.columns
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "AwesomePrint/ActiveRecord" do
|
||||||
|
before(:each) do
|
||||||
|
stub_dotfile!
|
||||||
|
end
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
describe "ActiveRecord instance" do
|
||||||
|
before(:each) do
|
||||||
|
ActiveRecord::Base.default_timezone = :utc
|
||||||
|
@diana = User.new(:name => "Diana", :rank => 1, :admin => false, :created_at => "1992-10-10 12:30:00")
|
||||||
|
@laura = User.new(:name => "Laura", :rank => 2, :admin => true, :created_at => "2003-05-26 14:15:00")
|
||||||
|
@ap = AwesomePrint.new(:plain => true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "display single record" do
|
||||||
|
out = @ap.send(:awesome, @diana)
|
||||||
|
str = <<-EOS.strip
|
||||||
#<User:0x01234567> {
|
#<User:0x01234567> {
|
||||||
:id => nil,
|
:id => nil,
|
||||||
:name => "Diana",
|
:name => "Diana",
|
||||||
|
@ -57,18 +59,18 @@ describe "AwesomePrint::ActiveRecord" do
|
||||||
:created_at => ?
|
:created_at => ?
|
||||||
}
|
}
|
||||||
EOS
|
EOS
|
||||||
if RUBY_VERSION.to_f < 1.9
|
if RUBY_VERSION.to_f < 1.9
|
||||||
str.sub!('?', 'Sat Oct 10 12:30:00 UTC 1992')
|
str.sub!('?', 'Sat Oct 10 12:30:00 UTC 1992')
|
||||||
else
|
else
|
||||||
str.sub!('?', '1992-10-10 12:30:00 UTC')
|
str.sub!('?', '1992-10-10 12:30:00 UTC')
|
||||||
end
|
end
|
||||||
|
|
||||||
out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
|
out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
|
||||||
end
|
end
|
||||||
|
|
||||||
it "display multiple records" do
|
it "display multiple records" do
|
||||||
out = @ap.send(:awesome, [ @diana, @laura ])
|
out = @ap.send(:awesome, [ @diana, @laura ])
|
||||||
str = <<-EOS.strip
|
str = <<-EOS.strip
|
||||||
[
|
[
|
||||||
[0] #<User:0x01234567> {
|
[0] #<User:0x01234567> {
|
||||||
:id => nil,
|
:id => nil,
|
||||||
|
@ -86,23 +88,23 @@ EOS
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
EOS
|
EOS
|
||||||
if RUBY_VERSION.to_f < 1.9
|
if RUBY_VERSION.to_f < 1.9
|
||||||
str.sub!('?', 'Sat Oct 10 12:30:00 UTC 1992')
|
str.sub!('?', 'Sat Oct 10 12:30:00 UTC 1992')
|
||||||
str.sub!('!', 'Mon May 26 14:15:00 UTC 2003')
|
str.sub!('!', 'Mon May 26 14:15:00 UTC 2003')
|
||||||
else
|
else
|
||||||
str.sub!('?', '1992-10-10 12:30:00 UTC')
|
str.sub!('?', '1992-10-10 12:30:00 UTC')
|
||||||
str.sub!('!', '2003-05-26 14:15:00 UTC')
|
str.sub!('!', '2003-05-26 14:15:00 UTC')
|
||||||
|
end
|
||||||
|
|
||||||
|
out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
|
#------------------------------------------------------------------------------
|
||||||
end
|
describe "ActiveRecord class" do
|
||||||
end
|
it "should print the class" do
|
||||||
|
@ap = AwesomePrint.new(:plain => true)
|
||||||
#------------------------------------------------------------------------------
|
@ap.send(:awesome, User).should == <<-EOS.strip
|
||||||
describe "ActiveRecord class" do
|
|
||||||
it "should print the class" do
|
|
||||||
@ap = AwesomePrint::Inspector.new(:plain => true)
|
|
||||||
@ap.send(:awesome, User).should == <<-EOS.strip
|
|
||||||
class User < ActiveRecord::Base {
|
class User < ActiveRecord::Base {
|
||||||
:id => :integer,
|
:id => :integer,
|
||||||
:name => :string,
|
:name => :string,
|
||||||
|
@ -110,13 +112,12 @@ class User < ActiveRecord::Base {
|
||||||
:admin => :boolean,
|
:admin => :boolean,
|
||||||
:created_at => :datetime
|
:created_at => :datetime
|
||||||
}
|
}
|
||||||
EOS
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
end
|
it "should print the class for non-direct subclasses of AR::Base" do
|
||||||
|
@ap = AwesomePrint.new(:plain => true)
|
||||||
it "should print the class for non-direct subclasses of AR::Base" do
|
@ap.send(:awesome, SubUser).should == <<-EOS.strip
|
||||||
@ap = AwesomePrint::Inspector.new(:plain => true)
|
|
||||||
@ap.send(:awesome, SubUser).should == <<-EOS.strip
|
|
||||||
class SubUser < User {
|
class SubUser < User {
|
||||||
:id => :integer,
|
:id => :integer,
|
||||||
:name => :string,
|
:name => :string,
|
||||||
|
@ -124,8 +125,12 @@ class SubUser < User {
|
||||||
:admin => :boolean,
|
:admin => :boolean,
|
||||||
:created_at => :datetime
|
:created_at => :datetime
|
||||||
}
|
}
|
||||||
EOS
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
rescue LoadError
|
||||||
|
puts "Skipping ActiveRecord specs..."
|
||||||
end
|
end
|
||||||
|
|
|
@ -454,6 +454,47 @@ EOS
|
||||||
end
|
end
|
||||||
weird.new.ai(:plain => true).should == ''
|
weird.new.ai(:plain => true).should == ''
|
||||||
end
|
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.grep(/^(\d+)\//) { $1 }
|
||||||
|
grepped.ai(:plain => true, :multiline => false).should == '[ "1", "2" ]'
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "HTML output" do
|
||||||
|
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 colorized <pre> tag" do
|
||||||
|
markup = rand
|
||||||
|
markup.ai(:html => true).should == %Q|<pre style="color:blue">#{markup}</pre>|
|
||||||
|
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 style="color:brown">" &<hello>"</pre>'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
@ -504,14 +545,15 @@ EOS
|
||||||
it "inherited from File should be displayed as File" do
|
it "inherited from File should be displayed as File" do
|
||||||
class My < File; end
|
class My < File; end
|
||||||
|
|
||||||
my = File.new('/dev/null')
|
my = File.new('/dev/null') rescue File.new('nul')
|
||||||
my.ai(:plain => true).should == "#{my.inspect}\n" << `ls -alF #{my.path}`.chop
|
my.ai(:plain => true).should == "#{my.inspect}\n" << `ls -alF #{my.path}`.chop
|
||||||
end
|
end
|
||||||
|
|
||||||
it "inherited from Dir should be displayed as Dir" do
|
it "inherited from Dir should be displayed as Dir" do
|
||||||
class My < Dir; end
|
class My < Dir; end
|
||||||
|
|
||||||
my = My.new('/tmp')
|
require 'tmpdir'
|
||||||
|
my = My.new(Dir.tmpdir)
|
||||||
my.ai(:plain => true).should == "#{my.inspect}\n" << `ls -alF #{my.path}`.chop
|
my.ai(:plain => true).should == "#{my.inspect}\n" << `ls -alF #{my.path}`.chop
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -523,5 +565,16 @@ EOS
|
||||||
my = My.new
|
my = My.new
|
||||||
my.methods.ai(:plain => true).should_not raise_error(ArgumentError)
|
my.methods.ai(:plain => true).should_not raise_error(ArgumentError)
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
84
spec/colorization_spec.rb
Normal file
84
spec/colorization_spec.rb
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
||||||
|
|
||||||
|
describe "AwesomePrint" do
|
||||||
|
before(:each) 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(:each) do
|
||||||
|
AwesomePrint.force_colors!(false)
|
||||||
|
ENV['TERM'] = "xterm-colors"
|
||||||
|
ENV.delete('ANSICON')
|
||||||
|
@arr = [ 1, :two, "three", [ nil, [ true, false] ] ]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "colorizes tty processes by default" do
|
||||||
|
stub_tty!(STDOUT, true)
|
||||||
|
|
||||||
|
@arr.ai(:multiline => false).should == COLORIZED
|
||||||
|
end
|
||||||
|
|
||||||
|
it "colorizes tty processes by default" do
|
||||||
|
stub_tty!(STDOUT, true)
|
||||||
|
|
||||||
|
@arr.ai(:multiline => false).should == COLORIZED
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
it "colorizes processes with ENV['ANSICON'] by default" do
|
||||||
|
stub_tty!(STDOUT, true)
|
||||||
|
ENV['ANSICON'] = "1"
|
||||||
|
|
||||||
|
@arr.ai(:multiline => false).should == COLORIZED
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not colorize tty processes running in dumb terminals by default" do
|
||||||
|
stub_tty!(STDOUT, true)
|
||||||
|
ENV['TERM'] = "dumb"
|
||||||
|
|
||||||
|
@arr.ai(:multiline => false).should == PLAIN
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not colorize subprocesses by default" do
|
||||||
|
stub_tty!(STDOUT, false)
|
||||||
|
|
||||||
|
@arr.ai(:multiline => false).should == PLAIN
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "forced" do
|
||||||
|
before(:each) do
|
||||||
|
AwesomePrint.force_colors!
|
||||||
|
end
|
||||||
|
|
||||||
|
it "still colorizes tty processes" do
|
||||||
|
stub_tty!(STDOUT, true)
|
||||||
|
|
||||||
|
@arr.ai(:multiline => false).should == COLORIZED
|
||||||
|
end
|
||||||
|
|
||||||
|
it "colorizes dumb terminals" do
|
||||||
|
stub_tty!(STDOUT, true)
|
||||||
|
ENV["TERM"] = "dumb"
|
||||||
|
|
||||||
|
@arr.ai(:multiline => false).should == COLORIZED
|
||||||
|
end
|
||||||
|
|
||||||
|
it "colorizes subprocess" do
|
||||||
|
stub_tty!(STDOUT, true)
|
||||||
|
@arr.ai(:multiline => false).should == COLORIZED
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stub_tty!(stream, value)
|
||||||
|
eval(%{class << stream
|
||||||
|
def tty?
|
||||||
|
#{value}
|
||||||
|
end
|
||||||
|
end})
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,7 +6,7 @@ require 'ap/core_ext/logger'
|
||||||
|
|
||||||
describe "AwesomePrint logging extensions" do
|
describe "AwesomePrint logging extensions" do
|
||||||
before(:all) do
|
before(:all) do
|
||||||
@logger = Logger.new('/dev/null')
|
@logger = Logger.new('/dev/null') rescue Logger.new('nul')
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "ap method" do
|
describe "ap method" do
|
||||||
|
|
|
@ -406,4 +406,23 @@ describe "Methods arrays" do
|
||||||
out = Hello.methods.grep(/^m(\d)$/) { %w(none one)[$1.to_i] }.ai(:plain => true)
|
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]"
|
out.should == "[\n [0] none() Hello\n [1] one() Hello\n]"
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
63
spec/mongo_mapper_spec.rb
Normal file
63
spec/mongo_mapper_spec.rb
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
||||||
|
|
||||||
|
begin
|
||||||
|
require "mongo_mapper"
|
||||||
|
require "ap/mixin/mongo_mapper"
|
||||||
|
|
||||||
|
describe "AwesomePrint/MongoMapper" do
|
||||||
|
before :all do
|
||||||
|
class MongoUser
|
||||||
|
include MongoMapper::Document
|
||||||
|
|
||||||
|
key :first_name, String
|
||||||
|
key :last_name, String
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
before :each do
|
||||||
|
@ap = AwesomePrint.new(:plain => true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should print for a class instance" do
|
||||||
|
user = MongoUser.new(:first_name => "Al", :last_name => "Capone")
|
||||||
|
out = @ap.send(:awesome, user)
|
||||||
|
str = <<-EOS.strip
|
||||||
|
#<MongoUser:0x01234567> {
|
||||||
|
"_id" => BSON::ObjectId('4d9183739a546f6806000001'),
|
||||||
|
"first_name" => "Al",
|
||||||
|
"last_name" => "Capone"
|
||||||
|
}
|
||||||
|
EOS
|
||||||
|
out.gsub!(/'([\w]+){23}'/, "'4d9183739a546f6806000001'")
|
||||||
|
out.gsub!(/0x([a-f\d]+)/, "0x01234567")
|
||||||
|
out.should == str
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should print for a class" do
|
||||||
|
@ap.send(:awesome, MongoUser).should == <<-EOS.strip
|
||||||
|
class MongoUser < Object {
|
||||||
|
"_id" => :object_id,
|
||||||
|
"first_name" => :string,
|
||||||
|
"last_name" => :string
|
||||||
|
}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should print for a class when type is undefined" do
|
||||||
|
class Chamelion
|
||||||
|
include MongoMapper::Document
|
||||||
|
key :last_attribute
|
||||||
|
end
|
||||||
|
|
||||||
|
@ap.send(:awesome, Chamelion).should == <<-EOS.strip
|
||||||
|
class Chamelion < Object {
|
||||||
|
"_id" => :object_id,
|
||||||
|
"last_attribute" => :undefined
|
||||||
|
}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue LoadError
|
||||||
|
puts "Skipping MongoMapper specs..."
|
||||||
|
end
|
|
@ -4,25 +4,48 @@
|
||||||
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Running specs with Ruby 1.8.7 and RSpec 1.3+:
|
# Running specs from the command line:
|
||||||
# $ rake spec # Entire spec suite.
|
# $ rake spec # Entire spec suite.
|
||||||
# $ ruby -rubygems spec/logger_spec.rb # Individual spec file.
|
# $ rspec spec/logger_spec.rb # Individual spec file.
|
||||||
#
|
|
||||||
# Running specs with Ruby 1.9.2 and RSpec 2.0+:
|
|
||||||
# $ rake spec # Entire spec suite.
|
|
||||||
# $ rspec spec/logger_spec.rb # Individual spec file.
|
|
||||||
#
|
#
|
||||||
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
||||||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
||||||
require 'ap'
|
require 'awesome_print'
|
||||||
|
|
||||||
if RUBY_VERSION.to_f < 1.9
|
|
||||||
require 'spec'
|
|
||||||
require 'spec/autorun'
|
|
||||||
require 'rubygems'
|
|
||||||
end
|
|
||||||
|
|
||||||
def stub_dotfile!
|
def stub_dotfile!
|
||||||
dotfile = File.join(ENV["HOME"], ".aprc")
|
dotfile = File.join(ENV["HOME"], ".aprc")
|
||||||
File.should_receive(:readable?).at_least(:once).with(dotfile).and_return(false)
|
File.should_receive(:readable?).at_least(:once).with(dotfile).and_return(false)
|
||||||
end
|
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
|
||||||
|
|
Loading…
Reference in a new issue