├── .editorconfig
├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── .rspec
├── CODE_OF_CONDUCT.md
├── ChangeLog.md
├── Gemfile
├── MIT-LICENSE.txt
├── README.md
├── Rakefile
├── debugging.gemspec
├── lib
├── debugging.rb
└── debugging
│ ├── all.rb
│ ├── at.rb
│ ├── beep.rb
│ ├── callstack.rb
│ ├── howtocall.rb
│ ├── q.rb
│ ├── re.rb
│ └── version.rb
└── spec
├── howtocall_spec.rb
├── q_spec.rb
├── re_spec.rb
└── spec_helper.rb
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | insert_final_newline = true
8 | trim_trailing_whitespace = true
9 |
10 | [*.{md,rdoc,txt}]
11 | indent_size = 4
12 |
13 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | test:
7 | name: Ruby ${{ matrix.ruby }} (${{ matrix.os }})
8 | if: "!contains(github.event.head_commit.message, '[skip ci]')"
9 | strategy:
10 | matrix:
11 | ruby:
12 | - 3.2
13 | - 3.1
14 | - '3.0'
15 | - 2.7
16 | - jruby
17 | - truffleruby
18 | os:
19 | - ubuntu-latest
20 | # - macos-latest
21 | runs-on: ${{matrix.os}}
22 | steps:
23 | - uses: actions/checkout@v2
24 | - name: Set up Ruby
25 | uses: ruby/setup-ruby@v1
26 | with:
27 | ruby-version: ${{matrix.ruby}}
28 | bundler-cache: true
29 | - name: Run tests
30 | run: bundle exec rake
31 |
32 | test-windows:
33 | name: Ruby ${{ matrix.ruby }} (windows-latest)
34 | if: "!contains(github.event.head_commit.message, '[skip ci]')"
35 | strategy:
36 | matrix:
37 | ruby:
38 | - 3.1
39 | - '3.0'
40 | - 2.7
41 | runs-on: windows-latest
42 | steps:
43 | - uses: actions/checkout@v2
44 | - name: Set up Ruby
45 | uses: ruby/setup-ruby@v1
46 | with:
47 | ruby-version: ${{matrix.ruby}}
48 | bundler-cache: true
49 | - run: cinst ansicon
50 | - name: Run tests
51 | run: bundle exec rake
52 |
53 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Gemfile.lock
2 | pkg
3 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --colour --format documentation
2 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, gender identity and expression, level of experience,
9 | nationality, personal appearance, race, religion, or sexual identity and
10 | orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at conduct@janlelis.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at [http://contributor-covenant.org/version/1/4][version]
72 |
73 | [homepage]: http://contributor-covenant.org
74 | [version]: http://contributor-covenant.org/version/1/4/
75 |
--------------------------------------------------------------------------------
/ChangeLog.md:
--------------------------------------------------------------------------------
1 | ## ChangeLog
2 |
3 | ### 2.1.0 / 2022-12-25
4 |
5 | * Remove `debugging/mof`; use looksee, object shadow, or IRB's own ls for reliable lookup path inspection
6 | * Fix that `debugging/all` also loads howtocall
7 |
8 | ### 2.0.0 / 2021-12-30
9 |
10 | * Remove `debugging/repl`, since Ruby now has `binding.irb`
11 |
12 | ### 1.1.2 / 2020-12-29
13 |
14 | * Relax required Ruby version
15 |
16 | ### 1.1.1 / 2017-03-18
17 |
18 | * Make howtocall private
19 | * Relax paint dependency (allow paint versions 2.x)
20 |
21 | ### 1.1.0 / 2015-03-26
22 |
23 | * Added:
24 | * howtocall
25 | * Change output from `mof`, now only returns singleton methods per module for modules
26 | * Make q compatible with paint ~> 1.0
27 | * Drop support for Ruby 1
28 |
29 |
30 | ### 1.0.2 / 2015-01-24
31 |
32 | * Bump binding.repl version
33 |
34 |
35 | ### 1.0.1 / 2014-02-15
36 |
37 | * Bump binding.repl version
38 |
39 |
40 | ### 1.0.0 / 2014-01-19
41 |
42 | * Adjusted concept: Only helper method style
43 | * Removed:
44 | * dd
45 | * binding.vars
46 |
47 | * Added:
48 | * beep
49 | * repl
50 |
51 | * Renamed:
52 | * oo -> at
53 | * cc -> callstack
54 | * mm -> mof
55 | * regexp_visualize -> re
56 |
57 | * Method List: Display all available ancestors by default and add third argument for grepping
58 | * Moved from zucker 13.1 gem into its own gem
59 |
60 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gemspec
4 |
5 | ### ### ###
6 |
7 | # 3.2 workaround for RSpec 2.99, see https://bugs.ruby-lang.org/issues/17391
8 | def File.exists?(f)exist?(f)end unless defined? File.exists?
9 |
10 | ### ### ###
11 |
12 |
--------------------------------------------------------------------------------
/MIT-LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010-2022 Jan Lelis
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ruby Print Debugging [](https://badge.fury.io/rb/debugging) [
](https://github.com/janlelis/debugging/actions?query=workflow%3ATest)
2 |
3 | Helps you to introspect and debug your code.
4 |
5 |
6 | ## Setup
7 |
8 | Install gem:
9 |
10 | ```
11 | $ gem install debugging
12 | ```
13 |
14 |
15 | In Ruby:
16 |
17 | ```ruby
18 | require 'debugging/all'
19 | ```
20 |
21 | Instead of requiring all, you can also require only one function, e.g:
22 |
23 | ```ruby
24 | require 'debugging/q'
25 | ```
26 |
27 | In a bundler project, you will need to add the gem to your project's `Gemfile`:
28 |
29 | ```ruby
30 | gem 'debugging', require: 'debugging/all'
31 | ```
32 |
33 | ## Methods
34 | ### at(label = nil)
35 |
36 | Prints out that a specific point in a script has been reached.
37 |
38 | ```
39 | [label] @ method `...', line ... of file ....
40 | ```
41 |
42 | ### beep
43 |
44 | Lets your terminal bell ring.
45 |
46 | ### callstack
47 |
48 | Prints out your current callstack. For example:
49 |
50 | ```
51 |
52 | start
53 | catch
54 | block in start
55 | eval_input
56 | each_top_level_statement
57 | catch
58 | block in each_top_level_statement
59 | loop
60 | block (2 levels) in each_top_level_statement
61 | block in eval_input
62 | signal_status
63 | block (2 levels) in eval_input
64 | evaluate
65 | evaluate
66 | eval
67 | irb_binding
68 | ```
69 |
70 | ### howtocall(obj = self, method_or_proc)
71 |
72 | Displays parameter names and types for a proc or method (identified by a symbol):
73 |
74 | ```ruby
75 | def function(a, b = 3, &c)
76 | end
77 | howtocall :function #=> function(a, b, &c)
78 | ```
79 |
80 | What is not visible in the example above: All optional parameters are displayed underlined.
81 |
82 | If you want to access a function that is defined on an other object than the current one,
83 | you can pass it as an optional parameter:
84 |
85 | ```ruby
86 | howtocall FileUtils, :cd #=> cd(dir, options, &block)
87 | howtocall Open3, :popen3 #=> popen3(*cmd, **opts, &block)
88 |
89 | ```
90 |
91 | An example with lambdas and keyword arguments:
92 |
93 | ```ruby
94 | a = ->(filter: /\A.*\z/, string:){ string[filter] }
95 | howtocall a #=> call(string:, filter:)
96 | ```
97 |
98 | ### q(*args)
99 |
100 | Like `Kernel#p`, but with colors on one line:
101 |
102 | ```ruby
103 | q :is_like, ?p, "but on one line"
104 | ```
105 |
106 | ### re(string, regex, groups = nil)
107 |
108 | Assists you when matching regexes againts strings. Try this one:
109 |
110 | ```ruby
111 | re "mail@janlelis.de", /\b([A-Z0-9._%+-]+)@([A-Z0-9.-]+\.[A-Z]{2,10})\b/i, 0..2
112 | ```
113 |
114 | ## J-_-L
115 |
116 | Copyright (c) 2010-2022 Jan Lelis. MIT License. Originated from the
117 | [zucker](https://github.com/janlelis/sugar_refinery) gem.
118 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # # #
2 | # Get gemspec info
3 |
4 | gemspec_file = Dir['*.gemspec'].first
5 | gemspec = eval File.read(gemspec_file), binding, gemspec_file
6 | info = "#{gemspec.name} | #{gemspec.version} | " \
7 | "#{gemspec.runtime_dependencies.size} dependencies | " \
8 | "#{gemspec.files.size} files"
9 |
10 |
11 | # # #
12 | # Gem build and install task
13 |
14 | desc info
15 | task :gem do
16 | puts info + "\n\n"
17 | print " "; sh "gem build #{gemspec_file}"
18 | FileUtils.mkdir_p 'pkg'
19 | FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg'
20 | puts; sh %{gem install --no-document pkg/#{gemspec.name}-#{gemspec.version}.gem}
21 | end
22 |
23 |
24 | # # #
25 | # Start an IRB session with the gem loaded
26 |
27 | desc "#{gemspec.name} | IRB"
28 | task :irb do
29 | sh "irb -I ./lib -r #{gemspec.name.gsub '-','/'}"
30 | end
31 |
32 |
33 | # # #
34 | # Spec
35 |
36 | desc "#{gemspec.name} | Spec"
37 | task :spec do
38 | sh "rspec"
39 | end
40 |
41 | task :test => :spec
42 | task :default => :spec
43 |
--------------------------------------------------------------------------------
/debugging.gemspec:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | require File.expand_path('../lib/debugging/version', __FILE__)
4 |
5 | Gem::Specification.new do |gem|
6 | gem.name = "debugging"
7 | gem.version = Debugging::VERSION
8 | gem.summary = 'Print debugging helpers'
9 | gem.description = 'Utilities for better "print debugging"'
10 | gem.license = "MIT"
11 | gem.authors = ["Jan Lelis"]
12 | gem.email = ["hi@ruby.consulting"]
13 | gem.homepage = "https://github.com/janlelis/debugging"
14 |
15 | gem.files = Dir['{**/}{.*,*}'].select { |path| File.file?(path) && path !~ /pkg/ }
16 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18 | gem.require_paths = ['lib']
19 | gem.metadata = { "rubygems_mfa_required" => "true" }
20 |
21 | gem.required_ruby_version = '>= 2.0', '< 4.0'
22 |
23 | gem.add_dependency 'paint', '>= 0.9', '< 3.0'
24 |
25 | gem.add_development_dependency 'rake', '~> 13.0'
26 | gem.add_development_dependency 'rspec', '~> 2.99'
27 | end
28 |
--------------------------------------------------------------------------------
/lib/debugging.rb:
--------------------------------------------------------------------------------
1 | require_relative 'debugging/version'
2 | require 'paint'
3 |
4 | Object.send :include, Debugging
5 |
--------------------------------------------------------------------------------
/lib/debugging/all.rb:
--------------------------------------------------------------------------------
1 | %w[
2 | at
3 | beep
4 | callstack
5 | howtocall
6 | q
7 | re
8 | ].each{ |m| require_relative(m) }
9 |
--------------------------------------------------------------------------------
/lib/debugging/at.rb:
--------------------------------------------------------------------------------
1 | require 'debugging'
2 |
3 | module Debugging
4 | private
5 |
6 | def at(label = nil)
7 | caller[0].rindex( /:(\d+)(:in (`.*'))?$/ )
8 | puts "#{ label && Paint["#{label} ", :yellow] }@"\
9 | " #{ $3 && "method #{ Paint[$3, :red] }, " }line "\
10 | "#{ Paint[$1, :blue]} of file #{ Paint[$`, :green]}"
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/lib/debugging/beep.rb:
--------------------------------------------------------------------------------
1 | require 'debugging'
2 |
3 | module Debugging
4 | private
5 |
6 | def beep
7 | $stdout.print "\a"
8 | end
9 | end
--------------------------------------------------------------------------------
/lib/debugging/callstack.rb:
--------------------------------------------------------------------------------
1 | require 'debugging'
2 |
3 | module Debugging
4 | private
5 |
6 | def callstack
7 | caller.reverse.map{ |m|
8 | m.rindex( /:\d+(:in `(.*)')?$/ )
9 | $2
10 | }.compact.each.with_index{ |m, i|
11 | puts " "*i + m
12 | }
13 |
14 | nil
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/lib/debugging/howtocall.rb:
--------------------------------------------------------------------------------
1 | require 'debugging'
2 |
3 | module Debugging
4 | private
5 |
6 | def howtocall(object = self, method_or_proc)
7 | if method_or_proc.is_a? Proc
8 | params = method_or_proc.parameters
9 | template = "call(%s)"
10 | else
11 | unless method_or_proc.is_a?(Method) || method_or_proc.is_a?(UnboundMethod)
12 | method_or_proc = object.method(method_or_proc)
13 | end
14 | params = method_or_proc.parameters
15 | template = "#{method_or_proc.name}(%s)"
16 | end
17 |
18 | sig = params.map{ |type, name|
19 | param = ""
20 | param << "*" if type == :rest
21 | param << "**" if type == :keyrest
22 | param << "&" if type == :block
23 | name = ?? if !name && !(type == :rest || type == :keyrest)
24 | if type == :opt || type == :key
25 | param << Paint[name, :underline]
26 | else
27 | param << name.to_s
28 | end
29 | param << ":" if type == :key || type == :keyreq
30 | param
31 | }*", "
32 |
33 | puts template %(sig)
34 | nil
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/lib/debugging/q.rb:
--------------------------------------------------------------------------------
1 | require 'debugging'
2 |
3 | module Debugging
4 | private
5 |
6 | def q(*args)
7 | puts args.map{ |e| Paint[e.inspect, Paint.random] }*' ' unless args.empty?
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/lib/debugging/re.rb:
--------------------------------------------------------------------------------
1 | require 'debugging'
2 |
3 | module Debugging
4 | private
5 |
6 | def re(string, regex, groups = nil)
7 | if regex =~ string
8 | if !groups
9 | puts $` + Paint[$&, :green] + $'
10 | else
11 | Array( groups ).each{ |group_nr|
12 | begin
13 | raise IndexError unless $~[group_nr]
14 | gr_string = string.dup
15 | gr_string[ $~.end( group_nr ), 0 ] = Paint::NOTHING
16 | gr_string[ $~.begin( group_nr ), 0 ] = Paint.color(:green)
17 | puts group_nr.to_s + ': ' + gr_string
18 | rescue IndexError
19 | puts group_nr.to_s + ': ' + Paint['no match', :red]
20 | end
21 | }
22 | end
23 | else
24 | puts Paint['no match', :red]
25 | end
26 |
27 | nil
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/lib/debugging/version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Debugging
4 | VERSION = "2.1.0"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/howtocall_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'debugging/howtocall'
3 |
4 | describe "howtocall" do
5 | it "displays method parameters" do
6 | def function(a, b)
7 | end
8 |
9 | expect( capture_stdout{ howtocall :function } ).to eq "function(a, b)\n"
10 | end
11 |
12 | it "underlines optional parameters" do
13 | def function(a, b = 3)
14 | end
15 |
16 | expect( capture_stdout{ howtocall :function } ).to eq "function(a, \e[4mb\e[0m)\n"
17 | end
18 |
19 | it "shows block parameters" do
20 | def function(a, &b)
21 | end
22 |
23 | expect( capture_stdout{ howtocall :function } ).to eq "function(a, &b)\n"
24 | end
25 |
26 | it "optionally takes an object where the method shoud be looked for (if not self)" do
27 | module Klass
28 | def self.function(a,b)
29 | end
30 | end
31 |
32 | expect( capture_stdout{ howtocall Klass, :function } ).to eq "function(a, b)\n"
33 | end
34 |
35 | it "appends : for keyword arguments" do
36 | def function(a: 42, b: 43)
37 | end
38 |
39 | expect( capture_stdout{ howtocall :function } ).to eq "function(\e[4ma\e[0m:, \e[4mb\e[0m:)\n"
40 | end
41 |
42 | it "shows *splats and keyword **splats" do
43 | def function(*cmd, **opts)
44 | end
45 |
46 | expect( capture_stdout{ howtocall :function } ).to eq "function(*cmd, **opts)\n"
47 | end
48 |
49 | it "shows ? for array deconstructor parameters" do
50 | def function((a, b))
51 | end
52 |
53 | expect( capture_stdout{ howtocall :function } ).to eq "function(?)\n"
54 | end
55 |
56 | it "also works for procs" do
57 | lambda = ->(a, b){}
58 |
59 | expect( capture_stdout{ howtocall lambda } ).to eq "call(a, b)\n"
60 | end
61 |
62 | if RUBY_ENGINE == "ruby" || RUBY_ENGINE == "jruby"
63 | context "[native methods]" do
64 | it "shows ? instead of parameter names for fixed amount of parameters" do
65 | expect( capture_stdout{ howtocall :is_a? } ).to eq "is_a?(?)\n"
66 | end
67 |
68 | it "shows * instead of parameters for variable amount of parameters" do
69 | expect( capture_stdout{ howtocall :puts } ).to eq "puts(*)\n"
70 | end
71 | end
72 | end
73 |
74 | end
75 |
--------------------------------------------------------------------------------
/spec/q_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'debugging/q'
3 |
4 | describe 'q' do
5 | it "should output the same as p for a single arg" do
6 | expect(
7 | Paint.unpaint(capture_stdout{q /some object/})
8 | ).to eq capture_stdout{p /some object/}
9 | end
10 |
11 | it "should output the same as p but for multiple args one one line, values separated by two spaces" do
12 | expect(
13 | Paint.unpaint(capture_stdout{
14 | q 1, "1", 2..5, [], {:hallo => :du}, nil, true
15 | }
16 | ).chop ).to eq capture_stdout{
17 | p 1, "1", 2..5, [], {:hallo => :du}, nil, true
18 | }.chop.gsub( "\n", ' ' )
19 | end
20 | end
21 |
22 |
--------------------------------------------------------------------------------
/spec/re_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'debugging/re'
3 |
4 | describe 're' do
5 | let :regex do /\b([A-Z0-9._%+-]+)@([A-Z0-9.-]+\.[A-Z]{2,4})\b/i end # r from regular-expressions.info/email.html
6 |
7 | it 'should display a string where mark the found regex in green' do
8 | capture_stdout do
9 | re 'I do not contain an email address.', regex
10 | end.chomp.should == Paint.color(:red) + 'no match' + Paint::NOTHING
11 | end
12 |
13 | it 'should display "no match" if the regex could not be matched' do
14 | capture_stdout do
15 | re 'I contain an email address: mail@example.com', regex
16 | end.chomp.should == 'I contain an email address: ' + Paint.color(:green) + 'mail@example.com' + Paint::NOTHING + ''
17 | end
18 |
19 | it 'should display a string and mark the found regex group in green if group identifier is given as arg2' do
20 | capture_stdout do
21 | re 'mail@example.com', regex, 1
22 | end.chomp.should == '1: ' + Paint.color(:green) + 'mail' + Paint::NOTHING + '@example.com'
23 | end
24 |
25 | it 'should display "group identifier: no match" if the arg2 group could not be matched' do
26 | capture_stdout do
27 | re 'mail@example.com', regex, 3
28 | end.chomp.should == '3: ' + Paint.color(:red) + 'no match' + Paint::NOTHING
29 | end
30 |
31 | it 'should also take an array of group identfiers as arg2' do
32 | capture_stdout do
33 | re 'mail@example.com', regex, [0,1,2]
34 | end.chomp.should == '0: ' + Paint.color(:green) + 'mail@example.com' + Paint::NOTHING + "\n" +
35 | '1: ' + Paint.color(:green) + 'mail' + Paint::NOTHING + '@example.com' + "\n" +
36 | '2: mail@' + Paint.color(:green) + 'example.com' + Paint::NOTHING
37 | end
38 | end
39 |
40 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require 'rspec'
2 | require 'stringio'
3 |
4 | def capture_stdout
5 | capture = StringIO.new
6 | restore, $stdout = $stdout, capture
7 | yield
8 | $stdout = restore
9 | capture.string
10 | end
11 |
12 | def capture_stderr
13 | capture = StringIO.new
14 | restore, $stderr = $stderr, capture
15 | yield
16 | $stderr = restore
17 | capture.string
18 | end
19 |
--------------------------------------------------------------------------------