{"id":16382476,"url":"https://github.com/andyobtiva/puts_debuggerer","last_synced_at":"2025-04-06T09:10:10.664Z","repository":{"id":39703020,"uuid":"82921458","full_name":"AndyObtiva/puts_debuggerer","owner":"AndyObtiva","description":"Ruby library for improved puts debugging, automatically displaying bonus useful information such as source line number and source code.","archived":false,"fork":false,"pushed_at":"2024-04-26T21:23:07.000Z","size":270,"stargazers_count":91,"open_issues_count":3,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-04-26T22:23:52.439Z","etag":null,"topics":["debugging-tool","logger","output","print-engine","rails","ruby"],"latest_commit_sha":null,"homepage":"https://github.com","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AndyObtiva.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-02-23T11:37:51.000Z","updated_at":"2024-05-31T18:43:03.424Z","dependencies_parsed_at":"2023-02-10T17:45:53.498Z","dependency_job_id":"8f4d7633-e901-4ddc-8382-0a594f76f5f9","html_url":"https://github.com/AndyObtiva/puts_debuggerer","commit_stats":{"total_commits":181,"total_committers":5,"mean_commits":36.2,"dds":0.3646408839779005,"last_synced_commit":"5b29115de7b9be703aec467cf34169a5c1d984fc"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndyObtiva%2Fputs_debuggerer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndyObtiva%2Fputs_debuggerer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndyObtiva%2Fputs_debuggerer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndyObtiva%2Fputs_debuggerer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AndyObtiva","download_url":"https://codeload.github.com/AndyObtiva/puts_debuggerer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247457803,"owners_count":20941906,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["debugging-tool","logger","output","print-engine","rails","ruby"],"created_at":"2024-10-11T04:05:33.092Z","updated_at":"2025-04-06T09:10:10.644Z","avatar_url":"https://github.com/AndyObtiva.png","language":"Ruby","readme":"# Puts Debuggerer 1.0.1\n## Debugger-less Debugging FTW\n## [Featured in State of the Art Rails 2023 Edition](https://github.com/DanielVartanov/state-of-the-art-rails/tree/bd7a509f5f0ab07cebfeada779b5c73e1eaf22ed)\n[![Gem Version](https://badge.fury.io/rb/puts_debuggerer.svg)](http://badge.fury.io/rb/puts_debuggerer)\n[![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/puts_debuggerer/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/puts_debuggerer?branch=master)\n[![Maintainability](https://api.codeclimate.com/v1/badges/81d8f6e046eb1b4a36f4/maintainability)](https://codeclimate.com/github/AndyObtiva/puts_debuggerer/maintainability)\n\n(credit to Aaron Patterson for partial inspiration: https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer.html)\n\nIf you like [Awesome_Print](https://rubygems.org/gems/awesome_print) (or [Amazing_Print](https://github.com/amazing-print/amazing_print)), you will love Puts Debuggerer (which builds upon them)!\n\nDebuggers are great! They help us troubleshoot complicated programming problems by inspecting values produced by code, line by line. They are invaluable when trying to understand what is going on in a large application composed of thousands or millions of lines of code.\n\nIn day-to-day test-driven development and simple app debugging though, a puts statement can be a lot quicker in revealing what is going on than halting execution completely just to inspect a single value or a few. This is certainly true when writing the simplest possible code that could possibly work, and running a test every few seconds or minutes. Still, there are a number of problems with puts debugging, like difficulty in locating puts statements in a large output log, knowing which files, line numbers, and methods the puts statements were invoked from, identifying which variables were printed, and seeing the content of structured hashes and arrays in an understandable format.\n\nEnter [puts_debuggerer](https://rubygems.org/gems/puts_debuggerer)! A guilt-free puts debugging Ruby gem FTW that prints file names, line numbers, class names, method names, code statements, headers, footers, and stack traces; and formats output nicely courtesy of [awesome_print](https://rubygems.org/gems/awesome_print) (or [amazing_print](https://github.com/amazing-print/amazing_print) if you prefer).\n\n[puts_debuggerer](https://rubygems.org/gems/puts_debuggerer) automates tips mentioned in [this blog post](https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer.html) by Aaron Patterson using the `pd` method available everywhere after requiring the [gem](https://rubygems.org/gems/puts_debuggerer).\n\nBasic Example:\n\n```ruby\n# /Users/User/trivia_app.rb      # line 1\nrequire 'pd'                     # line 2\nclass TriviaApp                  # line 3\n  def question                   # line 4\n    bug_or_band = 'Beatles'      # line 5\n    pd bug_or_band               # line 6\n  end                            # line 7\nend                              # line 8\nTriviaApp.new.question           # line 9\n```\n\nOutput:\n\n```bash\n[PD] /Users/User/trivia_app.rb:6 in TriviaApp.question\n   \u003e pd bug_or_band               # line 6\n  =\u003e \"Beatles\"\n```\n\n`pd` revealed that the variable contains the band name \"Beatles\" not the bug \"Beetle\", in addition to revealing the printed code statement `pd bug_or_band`, the file name `/Users/User/trivia_app.rb`, the line number `6`, the class name `TriviaApp`, and the method name `question`.\n\n## Background\n\nIt can be quite frustrating to lose puts statements in a large output or log file. One way to help find them is add an announcer (e.g. `puts \"The Order Total\"`) or a header (e.g. `puts '\u003e'*80`) before every puts statement. Unfortunately, that leads to repetitive wasteful effort that adds up quickly over many work sessions and interrupts thinking flow while solving problems.\n\nputs_debuggerer automates that work via the short and simple `pd` command, automatically printing meaningful headers for output and accelerating problem solving work due to ease of typing.\n\nExample without pd:\n\n```ruby\nputs order_total\n```\n\nOutput:\n```\n195.50\n```\n\nWhich gets lost in a logging stream such as:\n\n```\n   (2.7ms)  CREATE TABLE \"ar_internal_metadata\" (\"key\" character varying PRIMARY KEY, \"value\" character varying, \"created_at\" timestamp NOT NULL, \"updated_at\" timestamp NOT NULL)\n  ActiveRecord::InternalMetadata Load (0.4ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n   (0.2ms)  BEGIN\n  SQL (0.3ms)  INSERT INTO \"ar_internal_metadata\" (\"key\", \"value\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"key\"  [[\"key\", \"environment\"], [\"value\", \"development\"], [\"created_at\", 2017-08-24 22:56:52 UTC], [\"updated_at\", 2017-08-24 22:56:52 UTC]]\n   (0.3ms)  COMMIT\n   195.50\n  ActiveRecord::InternalMetadata Load (0.3ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n   (0.2ms)  BEGIN\n   (0.2ms)  COMMIT\n```\n\nHere is a simple example using `pd` instead, which provides everything the puts statements above provide in addition to deducing the file name, line number, class name, and method name automatically for dead-easy debugging:\n\n```ruby\npd order_total\n```\n\nOutput:\n\n```\n    (2.7ms)  CREATE TABLE \"ar_internal_metadata\" (\"key\" character varying PRIMARY KEY, \"value\" character varying, \"created_at\" timestamp NOT NULL, \"updated_at\" timestamp NOT NULL)\n  ActiveRecord::InternalMetadata Load (0.4ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n   (0.2ms)  BEGIN\n  SQL (0.3ms)  INSERT INTO \"ar_internal_metadata\" (\"key\", \"value\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"key\"  [[\"key\", \"environment\"], [\"value\", \"development\"], [\"created_at\", 2017-08-24 22:56:52 UTC], [\"updated_at\", 2017-08-24 22:56:52 UTC]]\n   (0.3ms)  COMMIT\n[PD] /Users/User/ordering/order.rb:39 in Order.calculate_order_total\n  \u003e pd order_total\n =\u003e 195.50\n  ActiveRecord::InternalMetadata Load (0.3ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n   (0.2ms)  BEGIN\n   (0.2ms)  COMMIT\n```\n\nThis is not only easy to locate in a logging stream such as the one below, but also announces the `order_total` variable with `[PD]` for easy findability among other pd statements (you may always enter `[PD]` or variable name `order_total` using the CMD+F Quick Find to instantly jump to that line in the log):\n\n```ruby\npd order_total\npd order_summary\npd order_details\n```\n\nOutput:\n\n```\n   (2.7ms)  CREATE TABLE \"ar_internal_metadata\" (\"key\" character varying PRIMARY KEY, \"value\" character varying, \"created_at\" timestamp NOT NULL, \"updated_at\" timestamp NOT NULL)\n  ActiveRecord::InternalMetadata Load (0.4ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n[PD] /Users/User/ordering/order.rb:39 in Order.calculate_order_total\n  \u003e pd order_total\n =\u003e 195.50\n   (0.2ms)  BEGIN\n  SQL (0.3ms)  INSERT INTO \"ar_internal_metadata\" (\"key\", \"value\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"key\"  [[\"key\", \"environment\"], [\"value\", \"development\"], [\"created_at\", 2017-08-24 22:56:52 UTC], [\"updated_at\", 2017-08-24 22:56:52 UTC]]\n   (0.3ms)  COMMIT\n[PD] /Users/User/ordering/order.rb:40 in Order.calculate_order_total\n  \u003e pd order_summary\n =\u003e \"Pragmatic Ruby Book\"\n  ActiveRecord::InternalMetadata Load (0.3ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n   (0.2ms)  BEGIN\n   (0.2ms)  COMMIT\n[PD] /Users/User/ordering/order.rb:41 in Order.calculate_order_total\n  \u003e pd order_details\n =\u003e \"[Hard Cover] Pragmatic Ruby Book - English Version\"\n```\n\nWhat if you would like to add a header for faster findability of groups of related pd statements? Just use the `header` option:\n\n```ruby\npd order_total, header: true\npd order_summary\npd order_details\n```\n\nOr the `h` shortcut:\n\n```ruby\npd order_total, h: :t\npd order_summary\npd order_details\n```\n\nOutput:\n\n```\n   (2.7ms)  CREATE TABLE \"ar_internal_metadata\" (\"key\" character varying PRIMARY KEY, \"value\" character varying, \"created_at\" timestamp NOT NULL, \"updated_at\" timestamp NOT NULL)\n  ActiveRecord::InternalMetadata Load (0.4ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\n[PD] /Users/User/ordering/order.rb:39 in Order.calculate_order_total\n  \u003e pd order_total, header: true\n =\u003e 195.50\n   (0.2ms)  BEGIN\n  SQL (0.3ms)  INSERT INTO \"ar_internal_metadata\" (\"key\", \"value\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"key\"  [[\"key\", \"environment\"], [\"value\", \"development\"], [\"created_at\", 2017-08-24 22:56:52 UTC], [\"updated_at\", 2017-08-24 22:56:52 UTC]]\n   (0.3ms)  COMMIT\n[PD] /Users/User/ordering/order.rb:40 in Order.calculate_order_total\n  \u003e pd order_summary\n =\u003e \"Pragmatic Ruby Book\"\n  ActiveRecord::InternalMetadata Load (0.3ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n   (0.2ms)  BEGIN\n   (0.2ms)  COMMIT\n[PD] /Users/User/ordering/order.rb:41 in Order.calculate_order_total\n  \u003e pd order_details\n =\u003e \"[Hard Cover] Pragmatic Ruby Book - English Version\"\n```\n\nWanna add a footer too? No problem!\n\n```ruby\npd order_total, header: true\npd order_summary\npd order_details, footer: true\n```\n\nOr use the `f` shortcut:\n\n```ruby\npd order_total, h: :t\npd order_summary\npd order_details, f: :t\n```\n\nOutput:\n\n```\n   (2.7ms)  CREATE TABLE \"ar_internal_metadata\" (\"key\" character varying PRIMARY KEY, \"value\" character varying, \"created_at\" timestamp NOT NULL, \"updated_at\" timestamp NOT NULL)\n  ActiveRecord::InternalMetadata Load (0.4ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n################################################################################\n[PD] /Users/User/ordering/order.rb:39 in Order.calculate_order_total\n  \u003e pd order_total, header: '\u003e'*80\n =\u003e 195.50\n   (0.2ms)  BEGIN\n  SQL (0.3ms)  INSERT INTO \"ar_internal_metadata\" (\"key\", \"value\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"key\"  [[\"key\", \"environment\"], [\"value\", \"development\"], [\"created_at\", 2017-08-24 22:56:52 UTC], [\"updated_at\", 2017-08-24 22:56:52 UTC]]\n   (0.3ms)  COMMIT\n[PD] /Users/User/ordering/order.rb:40 in Order.calculate_order_total\n  \u003e pd order_summary\n =\u003e \"Pragmatic Ruby Book\"\n  ActiveRecord::InternalMetadata Load (0.3ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n   (0.2ms)  BEGIN\n   (0.2ms)  COMMIT\n[PD] /Users/User/ordering/order.rb:41 in Order.calculate_order_total\n  \u003e pd order_details, footer: '\u003c'*80\n =\u003e \"[Hard Cover] Pragmatic Ruby Book - English Version\"\n################################################################################\n```\n\nNeed a quick stack trace? Just use the `caller` option (you may surround with header and footer too via `wrapper`).\n\n```ruby\npd order_total, caller: true, wrapper: true\npd order_summary\npd order_details\n```\n\nOr use the `c` and `w` shortcuts:\n\n```ruby\npd order_total, c: :t, w: :t\npd order_summary\npd order_details\n```\n\nOutput:\n\n```\n   (2.7ms)  CREATE TABLE \"ar_internal_metadata\" (\"key\" character varying PRIMARY KEY, \"value\" character varying, \"created_at\" timestamp NOT NULL, \"updated_at\" timestamp NOT NULL)\n  ActiveRecord::InternalMetadata Load (0.4ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n********************************************************************************\n[PD] /Users/User/ordering/order.rb:39 in Order.calculate_order_total\n  \u003e pd order_total, caller: true, wrapper: true\n =\u003e 195.50\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `block in require'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:257:in `load_dependency'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `require'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/commands/server/server_command.rb:145:in `block in perform'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/commands/server/server_command.rb:142:in `tap'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/commands/server/server_command.rb:142:in `perform'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/thor-1.0.1/lib/thor/command.rb:27:in `run'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/thor-1.0.1/lib/thor/invocation.rb:127:in `invoke_command'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/thor-1.0.1/lib/thor.rb:392:in `dispatch'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/command/base.rb:69:in `perform'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/command.rb:46:in `invoke'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/commands.rb:18:in `\u003cmain\u003e'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `block in require'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:257:in `load_dependency'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `require'\n     /Users/User/code/sample-glimmer-dsl-opal-rails5-app/bin/rails:9:in `\u003ctop (required)\u003e'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `load'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `call'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/client/command.rb:7:in `call'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/client.rb:30:in `run'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/bin/spring:49:in `\u003ctop (required)\u003e'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `load'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `\u003ctop (required)\u003e'\n     /Users/User/code/sample-glimmer-dsl-opal-rails5-app/bin/spring:15:in `require'\n     /Users/User/code/sample-glimmer-dsl-opal-rails5-app/bin/spring:15:in `\u003ctop (required)\u003e'\n     bin/rails:3:in `load'\n     bin/rails:3:in `\u003cmain\u003e'\n********************************************************************************\n   (0.2ms)  BEGIN\n  SQL (0.3ms)  INSERT INTO \"ar_internal_metadata\" (\"key\", \"value\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"key\"  [[\"key\", \"environment\"], [\"value\", \"development\"], [\"created_at\", 2017-08-24 22:56:52 UTC], [\"updated_at\", 2017-08-24 22:56:52 UTC]]\n   (0.3ms)  COMMIT\n[PD] /Users/User/ordering/order.rb:40 in Order.calculate_order_total\n  \u003e pd order_summary\n =\u003e \"Pragmatic Ruby Book\"\n  ActiveRecord::InternalMetadata Load (0.3ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n   (0.2ms)  BEGIN\n   (0.2ms)  COMMIT\n[PD] /Users/User/ordering/order.rb:41 in Order.calculate_order_total\n  \u003e pd order_details\n =\u003e \"[Hard Cover] Pragmatic Ruby Book - English Version\"\n```\n\nIs the stack trace too long? Shorten it by passing number of lines to display to `caller` option.\n\n```ruby\npd order_total, caller: 3, wrapper: true\npd order_summary\npd order_details\n```\n\nOr use shortcut syntax:\n\n```ruby\npd order_total, c: 3, w: :t\npd order_summary\npd order_details\n```\n\n```\n   (2.7ms)  CREATE TABLE \"ar_internal_metadata\" (\"key\" character varying PRIMARY KEY, \"value\" character varying, \"created_at\" timestamp NOT NULL, \"updated_at\" timestamp NOT NULL)\n  ActiveRecord::InternalMetadata Load (0.4ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n********************************************************************************\n[PD] /Users/User/ordering/order.rb:39 in Order.calculate_order_total\n  \u003e pd order_total, caller: 3, wrapper: true\n =\u003e 195.50\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'\n     /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'\n********************************************************************************\n   (0.2ms)  BEGIN\n  SQL (0.3ms)  INSERT INTO \"ar_internal_metadata\" (\"key\", \"value\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"key\"  [[\"key\", \"environment\"], [\"value\", \"development\"], [\"created_at\", 2017-08-24 22:56:52 UTC], [\"updated_at\", 2017-08-24 22:56:52 UTC]]\n   (0.3ms)  COMMIT\n[PD] /Users/User/ordering/order.rb:40 in Order.calculate_order_total\n  \u003e pd order_summary\n =\u003e \"Pragmatic Ruby Book\"\n  ActiveRecord::InternalMetadata Load (0.3ms)  SELECT  \"ar_internal_metadata\".* FROM \"ar_internal_metadata\" WHERE \"ar_internal_metadata\".\"key\" = $1 LIMIT $2  [[\"key\", :environment], [\"LIMIT\", 1]]\n   (0.2ms)  BEGIN\n   (0.2ms)  COMMIT\n[PD] /Users/User/ordering/order.rb:41 in Order.calculate_order_total\n  \u003e pd order_details\n =\u003e \"[Hard Cover] Pragmatic Ruby Book - English Version\"\n```\n\nThere are many more options and features in [puts_debuggerer](https://rubygems.org/gems/puts_debuggerer) as detailed below.\n\n## Instructions\n\n### Option 1: Bundler\n\nThis is the recommended way for installing in [Rails](rubyonrails.org) apps in addition to configuring the [`app_path` option](#putsdebuggererapp_path).\n\nAdd the following to bundler's `Gemfile` (in Rails, you can optionally limit to the `:development` and `:test` groups).\n\n```ruby\ngem 'puts_debuggerer', '~\u003e 1.0.1'\n```\n\nRun:\n\n```\nbundle\n```\n\nOptionally, you may configure the [Rails](rubyonrails.org) initializer `config/initializers/puts_debuggerer_options.rb` with further customizations as per the [Options](#options) section below.\n\nAlso, you may want to add the following to the initializer too if you limited the `puts_debuggerer` gem to the `:development` and `:test` groups:\n\n```ruby\nunless Rails.env.development? || Rails.env.test?\n  def pd(*args, \u0026block) # `pd(...)` in Ruby 2.7+\n    # No Op (just a stub in case developers forget troubleshooting pd calls in the code and deploy to production)\n  end\nend\n```\n\nThe Rails `config.log_level` is assumed to be `:debug`. If you have it set to something else like `:info`, then you need to update `PutsDebuggerer.printer` to print at a different log level (e.g. `:info`) by adding the following code to the initializer above (this code is a modification of the default at `PutsDebuggerer::PRINTER_RAILS`):\n\n```ruby\nPutsDebuggerer.printer = lambda do |output| \n  puts output if Rails.env.test?\n  Rails.logger.info(output)  \nend\n```\n\n### Option 2: Manual\n\nOr manually install and require library.\n\n```bash\ngem install puts_debuggerer -v1.0.1\n```\n\n```ruby\nrequire 'puts_debuggerer'\n```\n\nOr the shorter form (often helpful to quickly troubleshoot an app):\n\n```ruby\nrequire 'pd'\n```\n\n### Awesome Print\n\n[puts_debuggerer](https://rubygems.org/gems/puts_debuggerer) comes with [awesome_print](https://github.com/awesome-print/awesome_print).\n\nIt is the default `PutsDebuggerer.print_engine`\n\nStill, if you do not need it, you may disable by setting `PutsDebuggerer.print_engine` to another value. Example:\n\n```ruby\nPutsDebuggerer.print_engine = :puts\n```\n\nIf you also avoid requiring 'awesome_print', PutsDebuggerer will NOT require it either if it sees that you have a different `print_engine`. In fact, you may switch to another print engine if you prefer like [amazing_print](https://github.com/amazing-print/amazing_print) as [explained here](https://github.com/AndyObtiva/puts_debuggerer#putsdebuggererprint_engine).\n\nYou may also avoid requiring in Bundler `Gemfile` with `require: false`:\n\n```ruby\ngem \"awesome_print\", require: false\ngem \"puts_debuggerer\"\n```\n\n### Usage\n\nFirst, add `pd` method anywhere in your code to display details about an object or expression (if you're used to awesome_print, you're in luck! puts_debuggerer includes awesome_print (or amazing_print if preferred) as the default print engine for output).\n\nExample:\n\n```ruby\n# /Users/User/trivia_app.rb      # line 1\nrequire 'pd'                     # line 2\nclass TriviaApp                  # line 3\n  def question                   # line 4\n    bug_or_band = 'Beatles'      # line 5\n    pd bug_or_band               # line 6\n  end                            # line 7\nend                              # line 8\nTriviaApp.new.question           # line 9\n```\n\nOutput:\n\n```bash\n[PD] /Users/User/trivia_app.rb:6 in TriviaApp.question\n   \u003e pd bug_or_band               # line 6\n  =\u003e \"Beatles\"\n```\n\nIn addition to the object/expression output, you get to see the source file name, line number, class name, method name, and source code to help you debug and troubleshoot problems quicker (it even works in IRB).\n\nYou can use `pd` at the top-level main object too, and it prings `Object.\u003cmain\u003e` for the class/method.\n\nExample:\n\n```ruby\n# /Users/User/finance_calculator_app/pd_test.rb           # line 1\nbug = 'Beetle'                                            # line 2\npd \"Show me the source of the bug: #{bug}\"                # line 3\npd \"Show me the result of the calculation: #{(12.0/3.0)}\" # line 4\n```\n\nOutput:\n\n```bash\n[PD] /Users/User/finance_calculator_app/pd_test.rb:3 in Object.\u003cmain\u003e\n   \u003e pd \"Show me the source of the bug: #{bug}\"\n  =\u003e \"Show me the source of the bug: Beetle\"\n[PD] /Users/User/finance_calculator_app/pd_test.rb:4 in Object.\u003cmain\u003e\n   \u003e pd \"Show me the result of the calculation: #{(12.0/3.0)}\"\n  =\u003e \"Show me the result of the calculation: 4.0\"\n```\n\nSecond, quickly locate printed lines using the Find feature (e.g. CTRL+F) by looking for:\n* [PD]\n* file:line_number\n* class.method\n* known ruby expression.\n\nThird, easily remove your ` pd ` statements via the source code Find feature once done debugging.\n\nNote that `pd` returns the passed in object or expression argument unchanged, permitting debugging with shorter syntax than tap, and supporting chaining of extra method invocations afterward.\n\nExample:\n\n```ruby\n# /Users/User/greeting_app/pd_test.rb                     # line 1\nname = 'Robert'                                           # line 2\ngreeting = \"Hello #{pd(name)}\"                            # line 3\n```\n\nOutput:\n\n```bash\n[PD] /Users/User/greeting_app/pd_test.rb:3 in Object.\u003cmain\u003e\n   \u003e greeting = \"Hello #{pd(name)}\"\n  =\u003e \"Hello Robert\"\n```\n\nHappy puts_debuggerering!\n\n#### `pd_inspect` kernel method\n\nYou may want to just return the string produced by the `pd` method without printing it.\n\nIn that case, you may use the `pd` alternative to `object.inspect`:\n- `object.pd_inspect`\n- `obj.pdi` (shorter alias)\n\nThis returns the `pd` formatted string without printing to the terminal or log files.\n\n#### Ruby Logger and Logging::Logger\n\nRuby Logger and Logging::Logger (from [logging gem](https://github.com/TwP/logging)) are supported as [printers](#putsdebuggererprinter) (learn more under [PutsDebuggerer#printer](#putsdebuggererprinter)).\n\n### Options\n\nOptions enable more data to be displayed with puts_debuggerer, such as the caller\nbacktrace, header, and footer. They also allow customization of output format.\n\nOptions can be set as a global configuration or piecemeal per puts statement.\n\nGlobal configuration is done via `PutsDebuggerer` module attribute writers.\nOn the other hand, piecemeal options can be passed to the `pd` global method as\nthe second argument.\n\nExample 1:\n\n```ruby\n# File Name: /Users/User/project/piecemeal.rb\ndata = [1, [2, 3]]\npd data, header: true\n```\n\nPrints out:\n\n```bash\n\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\n[PD] /Users/User/project/piecemeal.rb:3 in Object.\u003cmain\u003e\n   \u003e pd data, header: true\n  =\u003e [1, [2, 3]]\n```\n\nExample 2:\n\n```ruby\n# File Name: /Users/User/project/piecemeal.rb\ndata = [1, [2, 3]]\npd data, header: '\u003e'*80, footer: '\u003c'*80, announcer: \"   -\u003c[PD]\u003e-\\n  \"\n```\n\nPrints out:\n\n```bash\n\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\n   -\u003c[PD]\u003e-\n   /Users/User/project/piecemeal.rb:3 in Object.\u003cmain\u003e\n   \u003e pd data, header: '\u003e'*80, footer: '\u003c'*80, announcer: \"   -\u003c[PD]\u003e-\\n  \"\n  =\u003e [1, [2, 3]]\n\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\n```\n\nDetails about all the available options are included below.\n\n#### `PutsDebuggerer.app_path`\n(default = `nil`)\n\nSets absolute application path. Makes `pd` file path output relative to it.\n\nIn [Rails](rubyonrails.org), you can add the following code to a `config/initializers/puts_debuggerer_options.rb` file to make all output relative to [Rails](rubyonrails.org) application path:\n\n```ruby\nPutsDebuggerer.app_path = Rails.root.to_s\n```\n\nExample:\n\n```ruby\n# /Users/User/finance_calculator_app/pd_test.rb                                 # line 1\nPutsDebuggerer.app_path = File.join('/Users', 'User', 'finance_calculator_app') # line 2\nbug = 'Beetle'                                                                  # line 3\npd \"Show me the source of the bug: #{bug}\"                                      # line 4\n```\n\nExample Printout:\n\n```bash\n[PD] /pd_test.rb:4 in Object.\u003cmain\u003e\n   \u003e pd \"Show me the source of the bug: #{bug}\"\n  =\u003e \"Show me the source of the bug: Beetle\"\n```\n\n#### `PutsDebuggerer.header`\n(default = `'\u003e'*80`) [shortcut: `h`]\n\nHeader to include at the top of every print out.\n* Default value is `nil`\n* Value `true` enables header as `'\u003e'*80`\n* Value `false`, `nil`, or empty string disables header\n* Any other string value gets set as a custom header\n\nExample:\n\n```ruby\npd (x=1), header: true\n```\n\nPrints out:\n\n```bash\n\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\n[PD] /Users/User/example.rb:1 in Object.\u003cmain\u003e\n   \u003e pd (x=1), header: true\n  =\u003e \"1\"\n```\n\nShortcut Example:\n\n```ruby\npd (x=1), h: :t\n```\n\nPrints out:\n\n```bash\n\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\n[PD] /Users/User/example.rb:1 in Object.\u003cmain\u003e\n   \u003e pd (x=1), h: :t\n  =\u003e \"1\"\n```\n\nGlobal Option Example:\n\n```ruby\nPutsDebuggerer.header = true\npd (x=1)\npd (x=2)\n```\n\nPrints out:\n\n```bash\n\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\n[PD] /Users/User/example.rb:2 in Object.\u003cmain\u003e\n   \u003e pd (x=1)\n  =\u003e \"1\"\n\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\u003e\n[PD] /Users/User/example.rb:3 in Object.\u003cmain\u003e\n   \u003e pd (x=2)\n  =\u003e \"2\"\n```\n\n#### `PutsDebuggerer.footer`\n(default = `'\u003c'*80`) [shortcut: `f`]\n\nFooter to include at the bottom of every print out.\n* Default value is `nil`\n* Value `true` enables footer as `'\u003c'*80`\n* Value `false`, `nil`, or empty string disables footer\n* Any other string value gets set as a custom footer\n\nExample:\n\n```ruby\npd (x=1), footer: true\n```\n\nPrints out:\n\n```bash\n[PD] /Users/User/example.rb:1 in Object.\u003cmain\u003e\n   \u003e pd (x=1), footer: true\n  =\u003e \"1\"\n\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\n```\n\nShortcut Example:\n\n```ruby\npd (x=1), f: :t\n```\n\nPrints out:\n\n```bash\n[PD] /Users/User/example.rb:1 in Object.\u003cmain\u003e\n   \u003e pd (x=1), f: :t\n  =\u003e \"1\"\n\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\n```\n\nGlobal Option Example:\n\n```ruby\nPutsDebuggerer.footer = true\npd (x=1)\npd (x=2)\n```\n\nPrints out:\n\n```bash\n[PD] /Users/User/example.rb:2 in Object.\u003cmain\u003e\n   \u003e pd (x=1)\n  =\u003e \"1\"\n\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\n[PD] /Users/User/example.rb:3 in Object.\u003cmain\u003e\n   \u003e pd (x=2)\n  =\u003e \"2\"\n\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\n```\n\n#### `PutsDebuggerer.wrapper`\n(default = `'*'*80`) [shortcut: `w`]\n\nWrapper to include at the top and bottom of every print out (both header and footer).\n* Default value is `nil`\n* Value `true` enables wrapper as `'*'*80`\n* Value `false`, `nil`, or empty string disables wrapper\n* Any other string value gets set as a custom wrapper\n\nExample:\n\n```ruby\npd (x=1), wrapper: true\n```\n\nPrints out:\n\n```bash\n********************************************************************************\n[PD] /Users/User/example.rb:1 in Object.\u003cmain\u003e\n   \u003e pd x=1, wrapper: true\n  =\u003e \"1\"\n********************************************************************************\n```\n\nShortcut Example:\n\n```ruby\npd (x=1), w: :t\n```\n\nPrints out:\n\n```bash\n********************************************************************************\n[PD] /Users/User/example.rb:1 in Object.\u003cmain\u003e\n   \u003e pd x=1, w: :t\n  =\u003e \"1\"\n********************************************************************************\n```\n\nGlobal Option Example:\n\n```ruby\nPutsDebuggerer.wrapper = true\npd (x=1)\npd (x=2)\n```\n\nPrints out:\n\n```bash\n********************************************************************************\n[PD] /Users/User/example.rb:2 in Object.\u003cmain\u003e\n   \u003e pd (x=1)\n  =\u003e \"1\"\n********************************************************************************\n********************************************************************************\n[PD] /Users/User/example.rb:3 in Object.\u003cmain\u003e\n   \u003e pd (x=2)\n  =\u003e \"2\"\n********************************************************************************\n```\n\n#### `PutsDebuggerer.source_line_count`\n(default = `1`)\n\nPrints multiple source code lines as per count specified. Useful when a statement is broken down on multiple lines or when there is a need to get more context around the line printed.\n\nExample:\n\n```ruby\npd (true ||\n  false), source_line_count: 2\n```\n\nPrints out:\n\n```\n[PD] /Users/User/example.rb:1 in Object.\u003cmain\u003e\n   \u003e pd (true ||\n       false), source_line_count: 2\n  =\u003e \"true\"\n```\n\nExample:\n\n```ruby\nPutsDebuggerer.source_line_count = 2 # setting via global option\npd (true ||\n  false)\n```\n\nPrints out:\n\n```\n[PD] /Users/User/example.rb:2 in Object.\u003cmain\u003e\n   \u003e pd (true ||\n       false), source_line_count: 2\n  =\u003e \"true\"\n```\n\n#### `PutsDebuggerer.printer`\n(default = `:puts`)\n\nPrinter is a global method symbol, lambda expression, or logger to use in printing to the user.\n\nExamples of a global method are `:puts` and `:print`.\nAn example of a lambda expression is `lambda {|output| Rails.logger.info(output)}`\nExamples of a logger are a Ruby `Logger` instance or `Logging::Logger` instance\n\nWhen a logger is supplied, it is automatically enhanced with a PutsDebuggerer formatter to use\nwhen calling logger methods outside of PutsDebuggerer (e.g. `logger.error('msg')` will use `pd`)\n\nPrinter may be set to `false` to avoid printing and only return the formatted string.\nIt is equivalent of just calling `.pd_inspect` (or alias `.pdi`) on the object\n\nDefaults to `:puts`\nIn Rails, it defaults to:\n```ruby\nlambda do |output|\n  puts output if Rails.env.test?\n  Rails.logger.debug(output)\nend\n```\n\nExample of adding the following code to `config/initializers/puts_debuggerer_options.rb`:\n\n```ruby\n# File Name: /Users/user/railsapp/config/initializers/puts_debuggerer_options.rb\nPutsDebuggerer.printer = lambda do |output|\n  puts output\nend\nstr = \"Hello\"\npd str\n```\n\nPrints out the following in standard out stream only (not in log files):\n\n```bash\n[PD] /Users/user/railsapp/config/initializers/puts_debuggerer_options.rb:6\n   \u003e pd str\n  =\u003e Hello\n```\n\n#### `PutsDebuggerer.print_engine`\n(default = `:ap`)\n\nPrint engine is similar to `printer`, except it is focused on the scope of formatting\nthe data object being printed (excluding metadata such as file name, line number,\nclass name, method name, and expression, which are handled by the `printer`).\nAs such, it is also a global method symbol or lambda expression.\nExamples of global methods are `:p`, `:ap`, and `:pp`.\nAn example of a lambda expression is `lambda {|object| puts object.to_a.join(\" | \")}`\n\nDefaults to [awesome_print](https://github.com/awesome-print/awesome_print). It does not load the library however until the first use of the `pd` command.\n\nIf you want to avoid loading [awesome_print](https://github.com/awesome-print/awesome_print) to use an alternative instead like [amazing_print](https://github.com/amazing-print/amazing_print), make sure to load [amazing_print](https://github.com/amazing-print/amazing_print) and call `PutsDebuggerer.print_engine = :ap` before the first `pd` call ([amazing_print](https://github.com/amazing-print/amazing_print) works through `ap` just like [awesome_print](https://github.com/awesome-print/awesome_print)).\n\nExample:\n\n```ruby\n# File Name: /Users/User/example.rb\nPutsDebuggerer.print_engine = :p\narray = [1, [2, 3]]\npd array\n```\n\nPrints out:\n\n```bash\n[PD] /Users/User/example.rb:4 in Object.\u003cmain\u003e\n   \u003e pd array\n  =\u003e [1, [2, 3]]\n```\n\n#### `PutsDebuggerer.announcer`\n(default = `\"[PD]\"`) [shortcut: `a`]\n\nAnnouncer (e.g. `[PD]`) to announce every print out with (default: `\"[PD]\"`)\n\nExample:\n\n```ruby\nPutsDebuggerer.announcer = \"*** PD ***\\n  \"\npd (x=1)\n```\n\nPrints out:\n\n```bash\n*** PD ***\n   /Users/User/example.rb:2 in Object.\u003cmain\u003e\n   \u003e pd x=1\n  =\u003e \"1\"\n```\n\n#### `PutsDebuggerer.formatter`\n(default = `PutsDebuggerer::FORMATTER_DEFAULT`)\n\nFormatter used in every print out\nPassed a data argument with the following keys:\n* `:announcer` (`String`)\n* `:caller` (`Array`)\n* `:class` (`String`)\n* `:file` (`String`)\n* `:footer` (`String`)\n* `:header` (`String`)\n* `:line_number` (`String`)\n* `:method` (`String`)\n* `:pd_expression` (`String`)\n* `:object` (`Object`)\n* `:object_printer` (`Proc`)\n\nNOTE: data for :object_printer is not a string, yet a proc that must\nbe called to output value. It is a proc as it automatically handles usage\nof print_engine and encapsulates its details. In any case, data for :object\nis available should one want to avoid altogether.\n\nExample:\n\n```ruby\nPutsDebuggerer.formatter = -\u003e (data) {\n  puts \"-\u003c#{data[:announcer]}\u003e-\"\n  puts \"HEADER: #{data[:header]}\"\n  puts \"FILE: #{data[:file]}\"\n  puts \"LINE: #{data[:line_number]}\"\n  puts \"CLASS: #{data[:class]}\"\n  puts \"METHOD: #{data[:method]}\"\n  puts \"EXPRESSION: #{data[:pd_expression]}\"\n  print \"PRINT OUT: \"\n  data[:object_printer].call\n  puts \"CALLER: #{data[:caller].to_a.first}\"\n  puts \"FOOTER: #{data[:footer]}\"\n}\npd (x=1)\n```\n\nPrints out:\n\n```bash\n-\u003c[PD]\u003e-\nHEADER: ********************************************************************************\nFILE: /Users/User/example.rb\nLINE: 9\nCLASS: Example\nMETHOD: test\nEXPRESSION: x=1\nPRINT OUT: 1\nCALLER: #/Users/User/master_examples.rb:83:in `block (3 levels) in \u003ctop (required)\u003e'\nFOOTER: ********************************************************************************\n```\n\n#### `PutsDebuggerer.caller`\n(default = nil) [shortcut: `c`]\n\nCaller backtrace included at the end of every print out\nPassed an argument of true/false, nil, or depth as an integer.\n* true and -1 means include full caller backtrace\n* false and nil means do not include caller backtrace\n* depth (0-based) means include limited caller backtrace depth\n\nExample:\n\n```ruby\n# File Name: /Users/User/sample_app/lib/sample.rb\nclass Sample\n  pd (x=1), caller: 3\nend\n```\n\nPrints out (fictional):\n\n```bash\n[PD] /Users/User/sample_app/lib/sample.rb:3 in Sample.\u003cclass:Sample\u003e\n    \u003e pd x=1, caller: 3\n   =\u003e 1\n     /Users/User/sample_app/lib/master_samples.rb:368:in \\`block (3 levels) in \u003ctop (required)\u003e\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \\`eval\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \\`evaluate\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/context.rb:381:in \\`evaluate\\'\n```\n\nShortcut Example:\n\n```ruby\n# File Name: /Users/User/sample_app/lib/sample.rb\nclass Sample\n  pd (x=1), c: 3\nend\n```\n\nPrints out (fictional):\n\n```bash\n[PD] /Users/User/sample_app/lib/sample.rb:3 in Sample.\u003cclass:Sample\u003e\n    \u003e pd x=1, caller: 3\n   =\u003e 1\n     /Users/User/sample_app/lib/master_samples.rb:368:in \\`block (3 levels) in \u003ctop (required)\u003e\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \\`eval\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \\`evaluate\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/context.rb:381:in \\`evaluate\\'\n```\n\nGlobal Option Example:\n\n```ruby\n# File Name: /Users/User/sample_app/lib/sample.rb\nPutsDebuggerer.caller = 3 # always print 3 lines only of the stack trace\nclass Sample\n  class \u003c\u003c self\n    def test\n      pd (x=1)\n      pd (x=2)\n    end\n  end\nend\nSample.test\n```\n\nPrints out:\n\n```bash\n[PD] /Users/User/sample_app/lib/sample.rb:6 in Sample.test\n    \u003e pd (x=1)\n   =\u003e 1\n     /Users/User/sample_app/lib/master_samples.rb:368:in \\`block (3 levels) in \u003ctop (required)\u003e\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \\`eval\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \\`evaluate\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/context.rb:381:in \\`evaluate\\'\n[PD] /Users/User/sample_app/lib/sample.rb:7 in Sample.test\n    \u003e pd (x=2)\n   =\u003e 2\n     /Users/User/sample_app/lib/master_samples.rb:368:in \\`block (3 levels) in \u003ctop (required)\u003e\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \\`eval\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \\`evaluate\\'\n     /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/context.rb:381:in \\`evaluate\\'\n```\n\n#### `PutsDebuggerer.run_at`\n(default = nil)\n\nSet condition for when to run as specified by an index, array, or range.\n* Default value is `nil` meaning always\n* Value as an Integer index (1-based) specifies at which run to print once\n* Value as an Array of indices specifies at which runs to print multiple times\n* Value as a range specifies at which runs to print multiple times,\n  indefinitely if it ends with ..-1 or ...-1\n\nCan be set globally via `PutsDebuggerer.run_at` or piecemeal via `pd object, run_at: run_at_value`\n\nGlobal usage should be good enough for most cases. When there is a need to track\na single expression among several, you may add the option piecemeal, but it expects\nthe same exact `object` passed to `pd` for counting.\n\nExamples (global):\n\n```ruby\n  PutsDebuggerer.run_at = 1\n  pd (x=1) # prints standard PD output\n  pd (x=1) # prints nothing\n\n  PutsDebuggerer.run_at = 2\n  pd (x=1) # prints nothing\n  pd (x=1) # prints standard PD output\n\n  PutsDebuggerer.run_at = [1, 3]\n  pd (x=1) # prints standard PD output\n  pd (x=1) # prints nothing\n  pd (x=1) # prints standard PD output\n  pd (x=1) # prints nothing\n\n  PutsDebuggerer.run_at = 3..5\n  pd (x=1) # prints nothing\n  pd (x=1) # prints nothing\n  pd (x=1) # prints standard PD output\n  pd (x=1) # prints standard PD output\n  pd (x=1) # prints standard PD output\n  pd (x=1) # prints nothing\n  pd (x=1) # prints nothing\n\n  PutsDebuggerer.run_at = 3...6\n  pd (x=1) # prints nothing\n  pd (x=1) # prints nothing\n  pd (x=1) # prints standard PD output\n  pd (x=1) # prints standard PD output\n  pd (x=1) # prints standard PD output\n  pd (x=1) # prints nothing\n\n  PutsDebuggerer.run_at = 3..-1\n  pd (x=1) # prints nothing\n  pd (x=1) # prints nothing\n  pd (x=1) # prints standard PD output\n  pd (x=1) # ... continue printing indefinitely on all subsequent runs\n\n  PutsDebuggerer.run_at = 3...-1\n  pd (x=1) # prints nothing\n  pd (x=1) # prints nothing\n  pd (x=1) # prints standard PD output\n  pd (x=1) # ... continue printing indefinitely on all subsequent runs\n```\n\nYou may reset the run_at number counter via:\n`PutsDebuggerer.reset_run_at_global_number` for global usage.\n\nAnd:\n`PutsDebuggerer.reset_run_at_number` or\n`PutsDebuggerer.reset_run_at_numbers`\nfor piecemeal usage.\n\n### Bonus API\n\nputs_debuggerer comes with the following bonus API methods:\n\n#### `__caller_line_number__(caller_depth=0)`\n\nProvides caller line number starting 1 level above caller of this method (with default `caller_depth=0`).\n\nExample:\n\n```ruby\n# File Name: lib/example.rb             # line 1\n# Print out __caller_line_number__      # line 2\nputs __caller_line_number__             # line 3\n```\n\nPrints out `3`\n\n\n#### `__caller_file__(caller_depth=0)`\n\nProvides caller file starting 1 level above caller of this method (with default `caller_depth=0`).\n\nExample:\n\n```ruby\n# File Name: lib/example.rb\nputs __caller_file__\n```\n\nPrints out `lib/example.rb`\n\n#### `__caller_source_line__(caller_depth=0)`\n\nProvides caller source line starting 1 level above caller of this method (with default `caller_depth=0`).\n\nExample:\n\n```ruby\nputs __caller_source_line__\n```\n\nPrints out `puts __caller_source_line__`\n\n## Compatibility\n\n[puts_debuggerer](https://rubygems.org/gems/puts_debuggerer) is fully compatible with:\n- [Ruby](https://www.ruby-lang.org/en/)\n- [JRuby](https://www.jruby.org/)\n- IRB (including Rails Console)\n- Pry (experimental and fragile because Pry's API is not reliable)\n\n### Opal Ruby\n\n[puts_debuggerer](https://rubygems.org/gems/puts_debuggerer) provides partial-compatibility in [Opal Ruby](https://opalrb.com/) with everything working except:\n- AwesomePrint (using the `:p` printer instead)\n- Source code display\n\n[puts_debuggerer](https://rubygems.org/gems/puts_debuggerer) renders clickable source file/line links in Opal Ruby that take you to the source code in the web browser.\n\nHere is an example of `pd` output in Opal:\n\n```\n[PD] http://localhost:3000/assets/views/garderie_rainbow_daily_agenda/app_view.self-72626d75e0f68a619b1c8ad139535d799d45ab6c730d083820b790d71338e983.js?body=1:72:12\n   \u003e\n  =\u003e \"body\"\n```\n\nNote that it ignores the configured printer when printing exceptions as it relies on Opal's `$stderr.puts` instead to show the stack trace in the web console.\n\n## Change Log\n\n[CHANGELOG.md](CHANGELOG.md)\n\n## TODO\n\n[TODO.md](TODO)\n\n## Contributing\n\n* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.\n* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.\n* Fork the project.\n* Change directory into project\n* Run `gem install bundler \u0026\u0026 bundle \u0026\u0026 rake` and make sure RSpec tests are passing\n* Start a feature/bugfix branch.\n* Write RSpec tests, Code, Commit and push until you are happy with your contribution.\n* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.\n* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.\n\n## Copyright\n\n[MIT](LICENSE.txt)\n\nCopyright (c) 2017-2024 - Andy Maleh.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandyobtiva%2Fputs_debuggerer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandyobtiva%2Fputs_debuggerer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandyobtiva%2Fputs_debuggerer/lists"}