[
  {
    "path": ".gitignore",
    "content": "/pkg/\n/coverage/\n"
  },
  {
    "path": ".gitlab-ci.yml",
    "content": "\nstages:\n  - test\n\n.test:\n  stage: test\n  image: ruby:${RUBY_VERSION}-bullseye\n  variables:\n    GIT_DEPTH: \"1\"\n    GIT_SUBMODULE_STRATEGY: recursive\n    GIT_SUBMODULE_PATHS: task\n    RUBYOPT: --enable-frozen-string-literal\n  before_script:\n    - bundle install --retry=3\n    - unset CI # Coverage doesn't work well with frozen literal\n  script:\n    - ruby -vr bundler/setup -S rake test\n\nruby:3.2:\n  extends:\n    - .test\n  variables:\n    RUBY_VERSION: '3.2'\n\nruby:3.3:\n  extends:\n    - .test\n  variables:\n    RUBY_VERSION: '3.3'\n\nruby:3.4:\n  extends:\n    - .test\n  variables:\n    RUBY_VERSION: '3.4'\n\njruby:latest:\n  extends:\n    - .test\n  image: jruby:latest\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"task\"]\n\tpath = task\n\turl = https://github.com/godfat/gemgem.git\n"
  },
  {
    "path": "CHANGES.md",
    "content": "# CHANGES\n\n## Rib 1.6.2 -- 2026-01-20\n\n### Bugs fixed\n\n* [core/strip_backtrace] Now it works with backtrace quotes change from\n  `` ` `` to `'`\n\n## Rib 1.6.2 -- 2026-01-19\n\n### Bugs fixed\n\n* [core/multiline] Now it works with prism parser\n* [more/color] Now it works with backtrace quotes change from `` ` `` to `'`\n\n## Rib 1.6.1 -- 2022-12-30\n\n### Bugs fixed\n\n* Fixed `rib rack` for constant resolution.\n\n### Enhancement\n\n* [more/color] Instead of using `$1` and `$2`, use `Regexp.last_match`.\n  It should be the same for MRI, but seems to be working better for JRuby.\n  Perhaps `$1` and `$2` is not thread local on JRuby?\n\n## Rib 1.6.0 -- 2018-06-20\n\n* [core/multiline] Support for JRuby 9.2.0.0 is fixed\n* [more/beep] It would now beep every single time when any evaluation took\n  longer than the threshold.\n* [more/color] Fix whenever the input is just `next` or `break`\n* [more/bottomup_backtrace] This would no longer format backtrace twice\n* [more/caller] It would now properly use the enabled plugins\n* [extra/autoindent] It would now indent with `ensure` for `begin` and `def`.\n  Thanks @MITSUBOSHI https://github.com/godfat/rib/pull/21 and\n  @alpaca-tc https://github.com/godfat/rib/pull/17\n* [extra/autoindent] It would now indent with `for`.\n  Thanks @MITSUBOSHI https://github.com/godfat/rib/pull/18\n* [extra/autoindent] It would now indent with `()` and `[]`.\n  Thanks @MITSUBOSHI https://github.com/godfat/rib/pull/20 and\n  https://github.com/godfat/rib/pull/19\n* [extra/byebug] This is now work-in-progress.\n\n## Rib 1.5.4 -- 2017-10-23\n\n* Removed unnecessary method definition for `puts`\n\n## Rib 1.5.3 -- 2017-08-05\n\n* Now we set trap only when the shell starts, and restore the old trap\n  after the shell stops. This should fix some problems using anchor inside\n  RSpec or Unicorn. They would no longer interfere with them.\n* [core/multiline] Now we support backslash. See:\n  [Using backslash line continuation character results in syntax error](https://github.com/godfat/rib/issues/15)\n\n## Rib 1.5.2 -- 2017-05-01\n\n* We now `require 'rib/version'` from the beginning, avoid loading error\n  under bundler.\n* Introduced `API#started_at` which is `config[:started_at]` for accessing\n  when Rib started.\n* Introduced `API#inspect_result` which would inspect the result. The default\n  behaviour would just inspect the result, but if the result is not a string,\n  emit a warning. https://github.com/godfat/rib/issues/14\n* Now all warnings would be printed after the result was printed. This would\n  make it easier to spot warnings.\n* [more/color] It would now paint warnings.\n* [more/anchor] Introduced `Rib.stop_anchors` to stop all nested anchors.\n  https://github.com/godfat/rib/issues/13\n* Fixed Rib app detection for newer RubyGems\n\n### Breaking changes\n\n* Extending `Rib::Plugin` would no longer automatically also include `Rib`.\n  For compatibility concern, a `const_missing` is now defined in `Rib::Plugin`\n  so that using `Shell` would still refer to `Rib::Shell` for you, considering\n  that this might be a common pattern:\n\n      extend Rib::Plugin\n      Shell.use(self)\n\n  Note that this would be removed in the future, so please take this chance to\n  change it to:\n\n      extend Rib::Plugin\n      Rib::Shell.use(self)\n\n## Rib 1.5.1 -- 2017-03-09\n\n* [more/beep] This plugin would beep via `print \"\\a\"` when the application\n  was loaded and it's been too long. Configure the time via\n  `Rib.config[:beep_threshold]`, default is 5 seconds.\n\n## Rib 1.5.0 -- 2017-02-27\n\n* Removed Ramaze direct support. Use Rack instead.\n* Introduced API#format_backtrace\n* Introduced API#puts\n* [more/anchor] Fixed multiline support when anchoring on an object\n* [more/caller] Added for showing formatted call stack\n* [core/underscore] This is changed to `core/last_value`, and the API is\n  changed to `Rib.last_value` and `Rib.last_exception`. Surely this is less\n  intrusive and more compatible for things like `Rib.anchor 42` because\n  now literal integers are frozen and we cannot define methods on them.\n  Also, using `Rib.last_value` is surely more descriptive. Of course,\n  being able to type `_` is so much easier, but you could just add a plugin\n  which defines `def _; Rib.last_value; end` and keep using `_` for your\n  own taste!\n\n## Rib 1.4.0 -- 2016-11-11\n\n* Search Rib home by directories rather than config/history file.\n* Respect prefix option for detecting Rib home.\n* Update help message for `-n`, which won't load any config.\n* Change `Rib.config[:config]` to `Rib.config_path`.\n* [app/rails] Fix loading boot file when using prefix option.\n* [app/auto] Fix two variable shadowing warnings.\n\n## Rib 1.3.1 -- 2016-11-03\n\n* [core/strip_backtrace], [more/color] No longer show `./` for current path.\n  This would be more friendly to some editors like Sublime.\n\n## Rib 1.3.0 -- 2016-06-28\n\n* Now `rib` would accept `-p` or `--prefix` to allow setting where we want to\n  load the application. This is useful when we don't want to `cd` into a\n  directory and `rib auto` or `rib rails` from there.\n\n## Rib 1.2.91 -- 2016-01-06\n\n* [core/multiline] Fixed a case for JRuby 9.0.4.0.\n* [extra/paging] Disable paging if `tput` is not found.\n* [extra/spring] Require `rib/extra/spring` in your `~/.spring` to enable\n  Rails Spring support. #11 (thanks @swrobel)\n\n## Rib 1.2.9 -- 2015-09-23\n\n* [extra/paging] Disable paging if your terminal is nil. (e.g. on Heroku)\n\n## Rib 1.2.8 -- 2015-09-23\n\n* [extra/paging] Disable paging if your terminal is dumb. (e.g. on Heroku)\n\n## Rib 1.2.7 -- 2015-01-28\n\n* [more/bottomup_backtrace] A new plugin which prints the backtrace bottom-up.\n  Ref: <http://yellerapp.com/posts/2015-01-22-upside-down-stacktraces.html>\n\n## Rib 1.2.6 -- 2014-11-07\n\n* [extra/autoindent] Now `module_function` would indent correctly.\n* [extra/autoindent] Now `else` in `case` would indent correctly.\n* [extra/autoindent] Fixed printing end clause twice. (performance fix)\n* [extra/multiline] Fixed in some cases it's not recognized as multiline\n  in Rubinius (rbx).\n\n## Rib 1.2.5 -- 2014-03-13\n\n* Fixed binding. Sorry my bad.\n\n## Rib 1.2.4 -- 2014-03-13\n\n* Fixed a regression introduced in 1.2.0. Now `rib all -e 'p 123'` should\n  work properly. Previously -e is ignored after rib apps.\n* Fixed a long standing Windows issue, where `rib all` did not work because\n  there's no `which` on Windows. Now we fall back to `where`.\n* Warn on removing main method on `TOPLEVEL_BINDING`. Not sure if this\n  would happen, but at least we could have a warning.\n\n## Rib 1.2.3 -- 2014-02-08\n\n* [extra/paging] Properly disable paging if less or ENV['PAGER'] is not\n  available.\n\n## Rib 1.2.2 -- 2014-01-23\n\n* From now on, we support project specific config file located on\n  \"./.rib/config.rb\". Note that if there's a project specific config file,\n  your home config would not be loaded at all. The history file would also\n  be put into \"./.rib/history.rb\". You might want to ignore it from your\n  repository to avoid leaking confidential information.\n\n* [extra/paging] Now we strip ANSI sequences before calculating if we need\n  a pager. This should make it much more accurate.\n\n## Rib 1.2.1 -- 2014-01-18\n\n* Fixed a bug where it cannot properly elegantly handle errors when loading\n  the config file.\n\n* [extra/paging] This plugin would try to use $PAGER and by default less to\n  paginate for output which cannot fit in a screen.\n\n* [more/edit] Now by default it would pick vim if $EDITOR is not set.\n\n## Rib 1.2.0 -- 2014-01-17\n\n* We no longer really eval on TOPLEVEL_BINDING, but a private binding\n  derived from TOPLEVEL_BINDING. This is due to RubyGems bin stub would\n  actually pollute TOPLEVEL_BINDING, leaving `str` and `version` as\n  local variables. I would like to avoid them, thus introducing this change.\n  Please let me know if this breaks anything, thanks!\n\n* [core/multiline] Fixed a multiline detection for Rubinius.\n\n## Rib 1.1.6 -- 2013-08-14\n\n* [more/color] Fixed inspecting recursive array and hash.\n\n## Rib 1.1.5 -- 2013-07-11\n\n* Fixed `rib -h` with commands don't have a description.\n* Added a description for `rib rack`\n\n## Rib 1.1.4 -- 2013-07-11\n\n* Further fixed a bug for displaying a BasicObject. Rib should never crash.\n* Added `rib-rack` executable which could load the app in config.ru,\n  accessible from calling `app` in the console. Also works for `rib-auto`\n\n## Rib 1.1.3 -- 2013-05-08\n\n* Fixed a bug where if user input doesn't respond to `==` would crash rib.\n\n## Rib 1.1.2 -- 2013-04-02\n\n* [core/multiline] Ruby 2.0 compatibility.\n\n## Rib 1.1.1 -- 2013-01-25\n\n* Fixed some multiline issue with Rubinius and JRuby.\n* Properly indent for multiline prompt.\n* Removed ripl compatibility layer.\n* Only retry 5 times upon failures. This prevents from infinite retries.\n* Don't retry on quiting.\n* Added a half-baked debugger support. Try it with:\n  `require 'rib/extra/debugger'; Rib.debug`\n\n## Rib 1.1.0 -- 2012-07-18\n\n* Support for Ruby 1.8 is dropped.\n* Now `Rib::Plugin` should be extended to the module, instead of included.\n  This fits more naturally with Ruby, but not really compatible with Ruby 1.8?\n* [more/anchor] Fixed a bug where you run rib in top level while anchor in\n  the other source, exit from the inner shell would break from the original\n  call. Now you can safely exit from the inner shell and keep doing the\n  original work.\n\n## Rib 1.0.5 -- 2012-05-15\n\n* [app/rails] Fixed SystemStackError issue. It's because ConsoleMethods\n  should not pollute the Object, redefining `app` method.\n\n## Rib 1.0.4 -- 2012-03-20\n\n* [core/multiline] Fixed a corner case:\n\n  ``` ruby\n      1/1.to_i +\n      1\n  ```\n\n* [rib] Do not crash because of a loop error. Try to relaunch the shell.\n\n## Rib 1.0.3 -- 2012-01-21\n\n### Bugs fixes\n\n* [rib-rails] Fixed sandbox mode.\n* [rib-rails] Bring back `reload!`, `new_session`, and `app` for Rails 3.2.0\n\n## Rib 1.0.2 -- 2011-12-24\n\n### Bugs fixes\n\n* [more/multiline_history] Make sure values are initialized even if\n  before_loop is called later. This helps us enable plugins on the fly.\n\n## Rib 1.0.1 -- 2011-12-15\n\n### Incompatible changes\n\n* [rib] Keyword `quit` to exit rib is removed, preferring `exit`.\n\n### Bugs fixes\n\n* [rib] Now you exit rib with ` exit`. Thanks @ayamomiji\n* [rib] Fixed -e, --eval binding. It should be TOPLEVEL_BINDING\n\n### Enhancement\n\n* [core/history, more/color, more/multiline_history_file, extra/autoindent]\n  Make sure values are initialized even if before_loop is called later.\n  This helps us enable plugins on the fly.\n\n* [extra/autoindent] Now it depends on history plugin as well. This is not\n  really needed, but would help to reduce plugins ordering issue.\n\n## Rib 1.0.0 -- 2011-11-05\n\n### Bugs fixes\n\n* [more/color] Fixed a bug for displaying `1/0`. Fixed #4, thanks @bootleq\n\n## Rib 0.9.9 -- 2011-10-26\n\n### Bugs fixes\n\n* [more/color] Fixed Windows coloring support.\n* [more/color] Properly reset ANSI sequence.\n\n### Enhancement\n\n* [commands] Extract commands description under `__END__` in the commands.\n  Please read [rib-rest-core][] as an example.\n* [rib] Always show original errors if anything is wrong.\n\n[rib-rest-core]: https://github.com/cardinalblue/rest-core/blob/rest-core-0.7.0/bin/rib-rest-core#L21-22\n\n## Rib 0.9.5 -- 2011-09-03\n\n* [rib-rails] Fixed Rails3 (sandbox) and Rails2 (env) console. Thanks bootleq\n* [rib-min] Fixed not being really minimum\n* [rib] Now you can run it with `rib -wdIlib`, isn't it convenient?\n  It's equivalent to `rib -w -d -I lib` or `rib -w -d -I=lib`\n\n## Rib 0.9.4 -- 2011-09-01\n\n* [rib-rails] So now we replicated what Rails did for its console, both for\n  Rails 2 and Rails 3. You can now fully use `rib rails` or `rib auto` as\n  `rails console` or `./script/console` in respect to Rails 2 or 3. For\n  example, it works for:\n\n      rib auto production\n      rib rails production\n      rib auto test --debugger # remember to add ruby-debug(19)? to Gemfile\n      rib auto test --sandbox\n      rib rails test --debugger --sandbox\n\n  It should also make Rails 3 print SQL log to stdout. Thanks tka.\n\n## Rib 0.9.3 -- 2011-08-28\n\n* [rib] Calling `Rib.shell` would no longer automatically `require 'rib/core'`\n  anymore. This is too messy. We should only do this in `bin/rib`. See:\n  commit #7a97441afeecae80f5493f4e8a4a6ba3044e2c33\n\n      require 'rib/more/anchor'\n      Rib.anchor 123\n\n  Should no longer crashed... Thanks Andrew.\n\n## Rib 0.9.2 -- 2011-08-25\n\n* [extra/autoindent] It has been greatly improved. A lot more accurate.\n* [extra/autoindent] Fixed a bug when you're typing too fast upon rib\n                     launching, it might eat your input. Thanks bootleq.\n\n## Rib 0.9.1 -- 2011-08-19\n\n* [extra/autoindent] Autoindent plugin help you indent multiline editing.\n  Note: This plugin is depending on [readline_buffer][], thus GNU Readline.\n\n* [ripl] After `require 'rib/ripl'`, ripl plugins should be usable for rib.\n\n* [rib] Introduce `ENV['RIB_HOME']` to set where to store config and history.\n  By default, it's `~/.rib` now, but it would first search for existing\n  config or history, which would first try to see `~/.rib/config.rb`, and\n  then `~/.rib/history.rb`. If Rib can find anything there, then `RIB_HOME`\n  would be set to `~/.rib`, the same goes to `~/.config/rib`.\n  In short, by default `RIB_HOME` is `~/.rib`, but the old `~/.config/rib`\n  still works.\n\n[readline_buffer]: https://github.com/godfat/readline_buffer\n\n## Rib 0.9.0 -- 2011-08-14\n\n* First serious release!\n* So much enhancement over ripl-rc!\n"
  },
  {
    "path": "Gemfile",
    "content": "\nsource 'https://rubygems.org'\n\ngemspec\n\ngem 'rake'\ngem 'pork'\ngem 'muack'\n\ngem 'bond'\ngem 'hirb'\n\ngem 'simplecov', :require => false if ENV['COV']\ngem 'coveralls', :require => false if ENV['CI']\n\nplatforms :ruby do\n  gem 'readline_buffer'\nend\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# Rib [![Pipeline status](https://gitlab.com/godfat/rib/badges/master/pipeline.svg)](https://gitlab.com/godfat/rib/-/pipelines)\n\nby Lin Jen-Shin ([godfat](https://godfat.org))\n\n## LINKS:\n\n* [github](https://github.com/godfat/rib)\n* [rubygems](https://rubygems.org/gems/rib)\n* [rdoc](https://rubydoc.info/github/godfat/rib)\n* [issues](https://github.com/godfat/rib/issues) (feel free to ask for support)\n\n## DESCRIPTION:\n\nRuby-Interactive-ruBy -- Yet another interactive Ruby shell\n\nRib is based on the design of [ripl][] and the work of [ripl-rc][], some of\nthe features are also inspired by [pry][]. The aim of Rib is to be fully\nfeatured and yet very easy to opt-out or opt-in other features. It shall\nbe simple, lightweight and modular so that everyone could customize Rib.\n\n[ripl]: https://github.com/cldwalker/ripl\n[ripl-rc]: https://github.com/godfat/ripl-rc\n[pry]: https://github.com/pry/pry\n\n## REQUIREMENTS:\n\n* Tested with MRI (official CRuby) and JRuby.\n* All gem dependencies are optional, but it's highly recommended to use\n  Rib with [bond][] for tab completion.\n\n[bond]: https://github.com/cldwalker/bond\n\n## INSTALLATION:\n\n    gem install rib\n\n## SYNOPSIS:\n\n![Screenshot](https://github.com/godfat/rib/raw/master/screenshot.png)\n\n### As an interactive shell\n\nAs IRB (reads `~/.rib/config.rb` writes `~/.rib/history.rb`)\n\n    rib\n\nAs Rails console\n\n    rib rails\n\nYou could also run in production and pass arguments normally as you'd do in\n`rails console` or `./script/console`\n\n    rib rails production --sandbox --debugger\n\nNote: You might need to add ruby-debug or ruby-debug19 to your Gemfile if\nyou're passing --debugger and using bundler together.\n\nFor [Rails Spring](https://github.com/rails/spring) support, put this line\nin your `~/.spring.rb`:\n\n    require 'rib/extra/spring'\n\nAs Rack console\n\n    rib rack\n\nAs a console for whichever the app in the current path\nit should be (for now, it's either Rails or Rack)\n\n    rib auto\n\nIf you're trying to use `rib auto` for a Rails app, you could also pass\narguments as if you were using `rib rails`. `rib auto` is merely passing\narguments.\n\n    rib auto production --sandbox --debugger\n\nAs a fully featured interactive Ruby shell (as ripl-rc)\n\n    rib all\n\nAs a fully featured app console (yes, some commands could be used together)\n\n    rib all auto # or `rib auto all`, the order doesn't really matter\n\n#### Customization\n\nYou can customize Rib's behaviour by setting a config file located at\n`$RIB_HOME/config.rb`, or `./.rib/config.rb`, or `~/.rib/config.rb`, or\n`~/.config/rib/config.rb`, searched by respected order. The default\nwould be `~/.rib/config.rb`. Since it's merely a Ruby script which would\nbe loaded into memory before launching Rib shell session, You can put any\ncustomization or monkey patch there. Personally, I use all plugins provided\nby Rib.\n\nMy Personal [~/.config/rib/config](https://github.com/godfat/dev-tool/blob/master/.config/rib/config.rb)\n\nAs you can see, putting `require 'rib/all'` into config file is exactly the\nsame as running `rib all` without a config file. What `rib all` would do is\nmerely require the file, and that file is also merely requiring all plugins,\nbut without **extra plugins**, which you should enable them one by one. This\nis because most extra plugins are depending on other gems, or hard to work\nwith other plugins, or having strong personal tastes, so you won't want to\nenable them all. Suppose you only want to use the core plugins and color\nplugin, you'll put this into your config file:\n\n``` ruby\nrequire 'rib/core'\nrequire 'rib/more/color'\n```\n\nYou can also write your plugins there. Here's another example:\n\n``` ruby\nrequire 'rib/core'\nrequire 'pp'\nRib.config[:prompt] = '$ '\n\nmodule RibPP\n  Rib::Shell.send(:include, self)\n\n  def format_result result\n    result_prompt + result.pretty_inspect\n  end\nend\n```\n\nSo that we override the original format_result to pretty_inspect the result.\nYou can also build your own gem and then simply require it in your config\nfile. To see a list of overridable API, please read [api.rb][]\n\n[api.rb]: https://github.com/godfat/rib/blob/master/lib/rib/api.rb\n\n#### Disable enabled plugins\n\nWhile it's convenient to just `require 'rib/all'`, you might not want to use\nall the plugins. No worries, you don't have to list everything in order to\nnot use something. For example, you might not get used to `bottomup_backtrace`\nand don't want to use it. You could put this in your config:\n\n``` ruby\nrequire 'rib/all'\n\nRib::BottomupBacktrace.disable\n```\n\nThis could disable `bottomup_backtrace` so you get regular top-down backtrace\nwith all other plugins. This is particularly useful whenever there's a bug\nin one of the plugins, and you might need to disable some plugins in order to\ndebug. You could always enable it again with:\n\n``` ruby\nRib::BottomupBacktrace.enable\n```\n\nYou could do this any time, in the config, or in the shell session. No need to\nrestart anything, because it takes effect immediately.\n\n#### Rib home and history file\n\nRib home is used to store a config file and a history file, which is\nsearched in this order:\n\n* $RIB_HOME\n* ./.rib\n* ~/.rib\n* ~/.config/rib\n\nRib would stop searching whenever the directory is found. If none could be\nfound, the default would be:\n\n* ~/.rib\n\nSo the default history file would be located at `~/.rib/history.rb`.\n\n#### Project config and history\n\nSince `./.rib` would be searched before `~/.rib`, you could create project\nlevel config at the project directory, and the history would also be\nseparated from each other, located at the respected `./.rib/history.rb`.\n\nTo do this, you don't really have to create a project config. Creating an\nempty directory for Rib home at the project directory would also work.\n\n#### Project directory and command line options\n\nYou could set the project directory by using `-p, --prefix` command line\noption. So consider this:\n\n    cd ~/project\n    rib auto\n\nWould work the same as:\n\n    cd /tmp\n    rib -p ~/project auto\n\nAnd the project config and history would be located at `~/project/.rib`.\n\nTo check for more command line options, run `rib -h`:\n\n```\nUsage: rib [ruby OPTIONS] [rib OPTIONS] [rib COMMANDS]\nruby options:\n  -e, --eval LINE        Evaluate a LINE of code\n  -d, --debug            Set debugging flags (set $DEBUG to true)\n  -w, --warn             Turn warnings on (set $-w and $VERBOSE to true)\n  -I, --include PATH     Specify $LOAD_PATH (may be used more than once)\n  -r, --require LIBRARY  Require the library, before executing your script\nrib options:\n  -c, --config FILE      Load config from FILE\n  -p, --prefix PATH      Prefix to locate the app. Default to .\n  -n, --no-config        Suppress loading ~/.config/rib/config.rb\n  -h, --help             Print this message\n  -v, --version          Print the version\nrib commands:\n  all                    Load all recommended plugins\n  auto                   Run as Rails or Rack console (auto-detect)\n  min                    Run the minimum essence\n  rack                   Run as Rack console\n  rails                  Run as Rails console\n```\n\n#### Basic configuration\n\nRib.config                 | Functionality\n-------------------------- | -------------------------------------------------\nENV['RIB_HOME']            | Specify where Rib should store config and history\nRib.config[:name]          | The name of this shell\nRib.config[:result_prompt] | Default is \"=>\"\nRib.config[:prompt]        | Default is \">>\"\nRib.config[:binding]       | Context, default: TOPLEVEL_BINDING\nRib.config[:exit]          | Commands to exit, default [nil] # control+d\n\n#### Plugin specific configuration\n\nRib.config                     | Functionality\n------------------------------ | ---------------------------------------------\nRib.config[:completion]        | Completion: Bond config\nRib.config[:history_file]      | Default is \"~/.rib/history.rb\"\nRib.config[:history_size]      | Default is 500\nRib.config[:color]             | A hash of Class => :color mapping\nRib.config[:autoindent_spaces] | How to indent? Default is two spaces: '  '\nRib.config[:beep_threshold]    | When it should beep? Default is 5 seconds\n\n#### List of core plugins\n\n``` ruby\nrequire 'rib/core' # You get all of the followings:\n```\n\n* `require 'rib/core/completion'`\n\n  Completion from [bond][].\n\n* `require 'rib/core/history'`\n\n  Remember history in a history file.\n\n* `require 'rib/core/strip_backtrace'`\n\n  Strip backtrace before Rib.\n\n* `require 'rib/core/readline'`\n\n  Readline support.\n\n* `require 'rib/core/multiline'`\n\n  You can interpret multiple lines.\n\n* `require 'rib/core/squeeze_history'`\n\n  Remove duplicated input from history.\n\n* `require 'rib/core/last_value'`\n\n  Save the last result in `Rib.last_value` and the last exception in\n  `Rib.last_exception`.\n\n#### List of more plugins\n\n``` ruby\nrequire 'rib/more' # You get all of the followings:\n```\n\n* `require 'rib/more/multiline_history_file'`\n\n  Not only readline could have multiline history, but also the history file.\n\n* `require 'rib/more/bottomup_backtrace'`\n\n  Show backtrace bottom-up instead of the regular top-down.\n\n* `require 'rib/more/color'`\n\n  Class based colorizing.\n\n* `require 'rib/more/multiline_history'`\n\n  Make readline aware of multiline history.\n\n* `require 'rib/more/beep'`\n\n  Print \"\\a\" when the application was loaded and it's been too long.\n  Configure the threshold via `Rib.config[:beep_threshold]`.\n\n* `require 'rib/more/anchor'`\n\n  See _As a debugging/interacting tool_.\n\n* `require 'rib/more/caller'`\n\n  See _Current call stack (backtrace, caller)_.\n\n* `require 'rib/more/edit'`\n\n  See _In place editing_.\n\n### List of extra plugins\n\nThere's no `require 'rib/extra'` for extra plugins because they might not\nbe doing what you would expect or want, or having an external dependency,\nor having conflicted semantics.\n\n* `require 'rib/extra/autoindent'` This plugin is depending on:\n\n  1. [readline_buffer][]\n  2. readline plugin\n  3. multiline plugin\n\n  Which would autoindent your input.\n\n* `require 'rib/extra/hirb'` This plugin is depending on:\n\n  1. [hirb][]\n\n  Which would print the result with hirb.\n\n* `require 'rib/extra/paging'` This plugin is depending on `less` and `tput`.\n\n  Which would pass the result to `less` (or `$PAGER` if set) if\n  the result string is longer than the screen.\n\n* `require 'rib/extra/spring'` in your `~/.spring.rb`\n  for [Rails Spring](https://github.com/rails/spring) support.\n\n[readline_buffer]: https://github.com/godfat/readline_buffer\n[hirb]: https://github.com/cldwalker/hirb\n\n### As a debugging/interacting tool\n\nRib could be used as a kind of debugging tool which you can set break point\nin the source program.\n\n``` ruby\nrequire 'rib/config' # This would load your Rib config\nrequire 'rib/more/anchor'\n                     # If you enabled anchor in config, then needed not\nRib.anchor binding   # This would give you an interactive shell\n                     # when your program has been executed here.\nRib.anchor 123       # You can also anchor on an object.\n```\n\nBut this might be called in a loop, you might only want to\nenter the shell under certain circumstance, then you'll do:\n\n``` ruby\nrequire 'rib/debug'\n\nRib.enable_anchor do\n  # Only `Rib.anchor` called in the block would launch a shell\nend\n\nRib.anchor binding # No effect (no-op) outside the block\n```\n\nAnchor could also be nested. The level would be shown on the prompt,\nstarting from 1.\n\n### Current call stack (backtrace, caller)\n\nOften time we would want to see current call stack whenever we're using\n`Rib.anchor`. We could do that by simply using `caller` but it's barely\nreadable because it's just returning an array without any format and\nit also contains backtrace from Rib itself. You could use pretty\nformatting with Rib:\n\n``` ruby\nrequire 'rib/more/caller'\n\nRib.caller\n```\n\nIt would use the same format for exception backtrace to show current\ncall stack for you. Colors, bottom up order, etc, if you're also using\nthe corresponding plugins.\n\nSometimes there are also too many stack frames which we don't care about.\nIn this case, we could pass arguments to `Rib.caller` in order to filter\nagainst them. You could either pass:\n\n* A `String` represents the name of the gem you don't care\n* A `Regexp` which would be used to match against paths/methods you don't care\n\nExamples:\n\n``` ruby\nrequire 'rib/more/caller'\n\nRib.caller 'activesupport', /rspec/\n```\n\nTo remove backtrace from gem _activesupport_ and paths or methods containing\nrspec as part of the name, like things for _rspec_ or _rspec-core_ and so on.\nNote that if a method name also contains rspec then it would also be filtered.\nJust keep that in mind when using regular expression.\n\nOr if you don't care about any gems, only want to see application related\ncalls, then try to match against `%r{/gems/}` because gems are often stored\nin a path containing `/gems/`:\n\n```\nRib.caller %r{/gem/}\n```\n\nHappy debugging.\n\n### In place editing\n\nWhenever you called:\n\n``` ruby\nrequire 'rib/more/edit'\n\nRib.edit\n```\n\nRib would open an editor according to `$EDITOR` (`ENV['EDITOR']`) for you.\nBy default it would pick vim if no `$EDITOR` was set. After save and leave\nthe editor, Rib would evaluate what you had input. This also works inside\nan anchor. To use it, require either rib/more/edit or rib/more or rib/all.\n\n### As a shell framework\n\nThe essence is:\n\n``` ruby\nrequire 'rib'\n```\n\nAll others are optional. The core plugins are lying in `rib/core/*.rb`, and\nmore plugins are lying in `rib/more/*.rb`. You can read `rib/app/rack.rb`\nand `bin/rib-rack` as a Rib App reference implementation, because it's very\nsimple, simpler than rib-rails.\n\n## Other plugins and apps\n\n* [rest-more][] `rib rest-core` Run as interactive rest-core client\n* [rib-heroku][] `rib heroku` Run console on Heroku Cedar with your config\n\n[rest-more]: https://github.com/cardinalblue/rest-more\n[rib-heroku]: https://github.com/godfat/rib-heroku\n\n## CONTRIBUTORS:\n\n* Andrew Liu (@eggegg)\n* ayaya (@ayamomiji)\n* Lin Jen-Shin (@godfat)\n* Mr. Big Cat (@miaout17)\n* @alpaca-tc\n* @bootleq\n* @lulalala\n* @MITSUBOSH\n* @tka\n\n## LICENSE:\n\nApache License 2.0 (Apache-2.0)\n\nCopyright (c) 2011-2026, Lin Jen-Shin (godfat)\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n<https://www.apache.org/licenses/LICENSE-2.0>\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "Rakefile",
    "content": "\nbegin\n  require \"#{__dir__}/task/gemgem\"\nrescue LoadError\n  sh 'git submodule update --init --recursive'\n  exec Gem.ruby, '-S', $PROGRAM_NAME, *ARGV\nend\n\nGemgem.init(__dir__) do |s|\n  require 'rib/version'\n  s.name    = 'rib'\n  s.version = Rib::VERSION\n  %w[screenshot.png asciicast.json].each do |file|\n    s.files.delete(file)\n  end\nend\n"
  },
  {
    "path": "TODO.md",
    "content": "# TODO\n\n* cleanup the tests. it's so messy right now\n\n* Runner tests\n* Documentation\n* Implement exception_spy\n\n<https://github.com/godfat/rib/commit/7a97441afeecae80f5493f4e8a4a6ba3044e2c33>\n\nSo here we have a problem. Some plugins are expecting to override\nsome other plugins. The order can't really be arbitrary.....\nActually, users won't care about order either. We just want to\nenable/disable plugins, not really composability.\n\nSo it really should be a bucket of plugins. At least for built-in plugins,\nso that we would be aware of the order. Users shouldn't pay attention\non the order of built-in plugins.\n"
  },
  {
    "path": "asciicast.json",
    "content": "{\n  \"version\": 1,\n  \"width\": 80,\n  \"height\": 24,\n  \"duration\": 31.5,\n  \"command\": null,\n  \"title\": \"rib\",\n  \"env\": {\n    \"TERM\": \"xterm-256color\",\n    \"SHELL\": \"/usr/local/bin/fish\"\n  },\n  \"stdout\": [\n    [\n      0.05,\n      \">> \"\n    ],\n    [\n      0.05,\n      \"{\"\n    ],\n    [\n      0.05,\n      \"a\"\n    ],\n    [\n      0.05,\n      \":\"\n    ],\n    [\n      0.05,\n      \"0\"\n    ],\n    [\n      0.05,\n      \",\"\n    ],\n    [\n      0.05,\n      \"'\"\n    ],\n    [\n      0.05,\n      \"b\"\n    ],\n    [\n      0.05,\n      \"'\"\n    ],\n    [\n      0.05,\n      \"=\"\n    ],\n    [\n      0.05,\n      \">\"\n    ],\n    [\n      0.05,\n      \"[\"\n    ],\n    [\n      0.05,\n      \"O\"\n    ],\n    [\n      0.05,\n      \"b\"\n    ],\n    [\n      0.05,\n      \"j\"\n    ],\n    [\n      0.05,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"c\"\n    ],\n    [\n      0.05,\n      \"t\"\n    ],\n    [\n      0.05,\n      \"]\"\n    ],\n    [\n      0.05,\n      \",\"\n    ],\n    [\n      0.05,\n      \"n\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"l\"\n    ],\n    [\n      0.05,\n      \"=\"\n    ],\n    [\n      0.05,\n      \">\"\n    ],\n    [\n      0.05,\n      \"t\"\n    ],\n    [\n      0.05,\n      \"r\"\n    ],\n    [\n      0.05,\n      \"u\"\n    ],\n    [\n      0.05,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"}\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"=> \\u001b[34m{\\u001b[0m\\u001b[36m:a\\u001b[0m\\u001b[34m=>\\u001b[0m\\u001b[31m0\\u001b[0m\\u001b[34m, \\u001b[0m\\u001b[32m\\\"b\\\"\\u001b[0m\\u001b[34m=>\\u001b[0m\\u001b[34m[\\u001b[0m\\u001b[33mObject\\u001b[0m\\u001b[34m]\\u001b[0m\\u001b[34m, \\u001b[0m\\u001b[35mnil\\u001b[0m\\u001b[34m=>\\u001b[0m\\u001b[35mtrue\\u001b[0m\\u001b[34m}\\u001b[0m\\r\\n\"\n    ],\n    [\n      0.05,\n      \">> \"\n    ],\n    [\n      1.5,\n      \"R\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"b\"\n    ],\n    [\n      0.05,\n      \".\"\n    ],\n    [\n      0.05,\n      \"a\"\n    ],\n    [\n      0.05,\n      \"n\"\n    ],\n    [\n      0.05,\n      \"c\"\n    ],\n    [\n      0.05,\n      \"h\"\n    ],\n    [\n      0.05,\n      \"o\"\n    ],\n    [\n      0.05,\n      \"r\"\n    ],\n    [\n      0.05,\n      \" \"\n    ],\n    [\n      0.05,\n      \"'\"\n    ],\n    [\n      0.05,\n      \"r\"\n    ],\n    [\n      0.05,\n      \"o\"\n    ],\n    [\n      0.05,\n      \"c\"\n    ],\n    [\n      0.05,\n      \"k\"\n    ],\n    [\n      0.05,\n      \"'\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[32m\\\"rock\\\"\\u001b[0m(1)>> \"\n    ],\n    [\n      1.5,\n      \"u\"\n    ],\n    [\n      0.05,\n      \"p\"\n    ],\n    [\n      0.05,\n      \"c\"\n    ],\n    [\n      0.05,\n      \"a\"\n    ],\n    [\n      0.05,\n      \"s\"\n    ],\n    [\n      0.05,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"=> \\u001b[32m\\\"ROCK\\\"\\u001b[0m\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[32m\\\"rock\\\"\\u001b[0m(1)>> \"\n    ],\n    [\n      1.5,\n      \"R\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"b\"\n    ],\n    [\n      0.05,\n      \".\"\n    ],\n    [\n      0.05,\n      \"a\"\n    ],\n    [\n      0.05,\n      \"n\"\n    ],\n    [\n      0.05,\n      \"c\"\n    ],\n    [\n      0.05,\n      \"h\"\n    ],\n    [\n      0.05,\n      \"o\"\n    ],\n    [\n      0.05,\n      \"r\"\n    ],\n    [\n      0.05,\n      \" \"\n    ],\n    [\n      0.05,\n      \"s\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"z\"\n    ],\n    [\n      0.05,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[31m4\\u001b[0m(2)>> \"\n    ],\n    [\n      1.5,\n      \"s\"\n    ],\n    [\n      0.05,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"l\"\n    ],\n    [\n      0.05,\n      \"f\"\n    ],\n    [\n      0.05,\n      \" \"\n    ],\n    [\n      0.05,\n      \"+\"\n    ],\n    [\n      0.05,\n      \" \"\n    ],\n    [\n      0.05,\n      \"1\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"=> \\u001b[31m5\\u001b[0m\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[31m4\\u001b[0m(2)>> \"\n    ],\n    [\n      1.5,\n      \"R\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"b\"\n    ],\n    [\n      0.05,\n      \".\"\n    ],\n    [\n      0.05,\n      \"a\"\n    ],\n    [\n      0.05,\n      \"n\"\n    ],\n    [\n      0.05,\n      \"c\"\n    ],\n    [\n      0.05,\n      \"h\"\n    ],\n    [\n      0.05,\n      \"o\"\n    ],\n    [\n      0.05,\n      \"r\"\n    ],\n    [\n      0.05,\n      \" \"\n    ],\n    [\n      0.05,\n      \"s\"\n    ],\n    [\n      0.05,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"l\"\n    ],\n    [\n      0.05,\n      \"f\"\n    ],\n    [\n      0.05,\n      \".\"\n    ],\n    [\n      0.05,\n      \"c\"\n    ],\n    [\n      0.05,\n      \"l\"\n    ],\n    [\n      0.05,\n      \"a\"\n    ],\n    [\n      0.05,\n      \"s\"\n    ],\n    [\n      0.05,\n      \"s\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[33mInteger\\u001b[0m(3)>> \"\n    ],\n    [\n      1.5,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"x\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"t\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[31m4\\u001b[0m(2)>> \"\n    ],\n    [\n      1.5,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"x\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"t\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[32m\\\"rock\\\"\\u001b[0m(1)>> \"\n    ],\n    [\n      1.5,\n      \"d\"\n    ],\n    [\n      0.05,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"f\"\n    ],\n    [\n      0.05,\n      \" \"\n    ],\n    [\n      0.05,\n      \"g\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[32m\\\"rock\\\"\\u001b[0m(1) | \"\n    ],\n    [\n      0.05,\n      \"  \"\n    ],\n    [\n      0.5,\n      \"a\"\n    ],\n    [\n      0.05,\n      \" \"\n    ],\n    [\n      0.05,\n      \"=\"\n    ],\n    [\n      0.05,\n      \" \"\n    ],\n    [\n      0.05,\n      \"1\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[32m\\\"rock\\\"\\u001b[0m(1) | \"\n    ],\n    [\n      0.05,\n      \"  \"\n    ],\n    [\n      0.5,\n      \"R\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"b\"\n    ],\n    [\n      0.05,\n      \".\"\n    ],\n    [\n      0.05,\n      \"a\"\n    ],\n    [\n      0.05,\n      \"n\"\n    ],\n    [\n      0.05,\n      \"c\"\n    ],\n    [\n      0.05,\n      \"h\"\n    ],\n    [\n      0.05,\n      \"o\"\n    ],\n    [\n      0.05,\n      \"r\"\n    ],\n    [\n      0.05,\n      \" \"\n    ],\n    [\n      0.05,\n      \"b\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"n\"\n    ],\n    [\n      0.05,\n      \"d\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"n\"\n    ],\n    [\n      0.05,\n      \"g\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[32m\\\"rock\\\"\\u001b[0m(1) | \"\n    ],\n    [\n      0.05,\n      \"  \"\n    ],\n    [\n      0.5,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"n\"\n    ],\n    [\n      0.05,\n      \"d\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[1A\\u001b[K\\u001b[32m\\\"rock\\\"\\u001b[0m(1) | end\\r\\n\"\n    ],\n    [\n      0.05,\n      \"=> \\u001b[36m:g\\u001b[0m\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[32m\\\"rock\\\"\\u001b[0m(1)>> \"\n    ],\n    [\n      1.5,\n      \"a\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"  \\u001b[33m\\u001b[33m\\u001b[33m(rib)\\u001b[0m\\u001b[0m\\u001b[0m:\\u001b[31m2\\u001b[0m:in \\u001b[32m\\u001b[32m\\u001b[32m`main'\\u001b[0m\\u001b[0m\\u001b[0m\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[35mNameError: undefined local variable or method `a' for \\\"rock\\\":String\\u001b[0m\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[32m\\\"rock\\\"\\u001b[0m(1)>> \"\n    ],\n    [\n      1.5,\n      \"g\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[33m\\\"rock\\\"\\u001b[0m(2)>> \"\n    ],\n    [\n      1.5,\n      \"a\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"=> \\u001b[31m1\\u001b[0m\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[33m\\\"rock\\\"\\u001b[0m(2)>> \"\n    ],\n    [\n      1.5,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"x\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"t\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \"\\u001b[32m\\\"rock\\\"\\u001b[0m(1)>> \"\n    ],\n    [\n      1.5,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"x\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"t\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ],\n    [\n      0.05,\n      \">> \"\n    ],\n    [\n      1.5,\n      \"e\"\n    ],\n    [\n      0.05,\n      \"x\"\n    ],\n    [\n      0.05,\n      \"i\"\n    ],\n    [\n      0.05,\n      \"t\"\n    ],\n    [\n      0.05,\n      \"\\r\\n\"\n    ]\n  ]\n}\n"
  },
  {
    "path": "bin/rib",
    "content": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\nRib.config[:mimic_irb] = true\nRib::Runner.run(ARGV)\n"
  },
  {
    "path": "bin/rib-all",
    "content": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\nrequire 'rib/all'\nRib::Runner.run(ARGV)\n"
  },
  {
    "path": "bin/rib-auto",
    "content": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\n# create the shell before app to prvent your bundler (if any) kicks in\nRib.shell\n# we need to require anything before loading the app,\n# and both `rib auto` (true) and `rib-auto` (nil) should work\nrequire 'rib/core' if Rib.config.delete(:mimic_irb) != false\nrequire 'rib/app/auto'\n# load the app\nRib::Auto.load\nRib::Runner.run(ARGV)\n"
  },
  {
    "path": "bin/rib-min",
    "content": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\nRib.config[:mimic_irb] = false\nRib::Runner.run(ARGV)\n"
  },
  {
    "path": "bin/rib-rack",
    "content": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\n# create the shell before app to prvent your bundler (if any) kicks in\nRib.shell\n# we need to require anything before loading the app,\n# and both `rib auto` (true) and `rib-auto` (nil) should work\nrequire 'rib/core' if Rib.config.delete(:mimic_irb) != false\nrequire 'rib/app/rack'\n# load the app\nRib::Rack.load\nRib::Runner.run(ARGV)\n"
  },
  {
    "path": "bin/rib-rails",
    "content": "#!/usr/bin/env ruby\n\nrequire 'rib/runner'\n# create the shell before app to prvent your bundler (if any) kicks in\nRib.shell\n# we need to require anything before loading the app,\n# and both `rib auto` (true) and `rib-auto` (nil) should work\nrequire 'rib/core' if Rib.config.delete(:mimic_irb) != false\nrequire 'rib/app/rails'\n# load the app\nRib::Rails.load\nRib::Runner.run(ARGV)\n"
  },
  {
    "path": "lib/rib/all.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib/core'\nrequire 'rib/more'\n"
  },
  {
    "path": "lib/rib/api.rb",
    "content": "# frozen_string_literal: true\n\nmodule Rib; module API\n  # Called before shell starts looping\n  def before_loop\n    self\n  end\n\n  # Called after shell finishes looping\n  def after_loop\n    self\n  end\n\n  # Handle interrupt (control-c)\n  def handle_interrupt; puts                ; end\n  # The prompt string of this shell\n  def prompt       ; config[:prompt]        ; end\n  # The result prompt string of this shell\n  def result_prompt; config[:result_prompt] ; end\n  # The name of this shell\n  def name         ; config[:name]          ; end\n  # The binding for evaluation\n  def eval_binding ; config[:binding]       ; end\n  # The line number for next evaluation\n  def line         ; config[:line]          ; end\n  # When the application loaded\n  def started_at   ; config[:started_at]    ; end\n\n  # Main loop\n  def in_loop\n    input = catch(:rib_exit){ loop_once while running? }\n    puts if input == nil && running?\n  end\n\n  # Loop iteration: REPL\n  def loop_once\n    input, result, err = get_input, nil, nil\n    throw(:rib_exit, input) if config[:exit].include?(input)\n\n    result, err = eval_input(input)\n\n    if err\n      print_eval_error(err)\n    elsif input.strip != '' && !equal_rib_skip(result)\n      print_result(result)\n    else\n      # print nothing for blank input or Rib::Skip\n    end\n\n    flush_warnings\n\n    [result, err]\n  rescue Interrupt\n    handle_interrupt\n  end\n\n  # Get user input. This is most likely overrided in Readline plugin\n  def get_input\n    print(prompt)\n    if input = $stdin.gets\n      input.chomp\n    else\n      nil\n    end\n  end\n\n  # Evaluate the input using #loop_eval and handle it\n  def eval_input input\n    [loop_eval(input), nil]\n  rescue SystemExit\n    throw(:rib_exit, input)\n  rescue Exception => e\n    [nil, e]\n  ensure\n    config[:line] += 1\n  end\n\n  # Evaluate user input with #eval_binding, name and line\n  def loop_eval input\n    if eval_binding.kind_of?(Binding)\n      eval_binding.eval(input, \"(#{name})\", line)\n    else\n      eval_binding.instance_eval(input, \"(#{name})\", line)\n    end\n  end\n\n  def puts str=''\n    super\n  end\n\n  # Print result using #format_result\n  def print_result result\n    puts(format_result(result))\n  rescue StandardError, SyntaxError => e\n    warn(\"Error while printing result:\\n  #{format_error(e)}\")\n  end\n\n  # Print evaluated error using #format_error\n  def print_eval_error err\n    puts(format_error(err))\n  rescue StandardError, SyntaxError => e\n    warn(\"Error while printing error:\\n  #{format_error(e)}\")\n  end\n\n  def warn message\n    warnings << message\n  end\n\n  # Format result using #result_prompt\n  def format_result result\n    \"#{result_prompt}#{inspect_result(result)}\"\n  end\n\n  def inspect_result result\n    string = result.inspect\n    warn(\"#{result.class}#inspect is not returning a string\") unless\n      string.kind_of?(String)\n    string\n  end\n\n  # Format error raised in #loop_eval with #get_error\n  def format_error err\n    message, backtrace = get_error(err)\n    \"#{message}\\n    #{backtrace.join(\"\\n    \")}\"\n  end\n  module_function :format_error\n\n  # Get error message and backtrace from a particular error\n  def get_error err\n    [\"#{err.class}: #{err.message}\", format_backtrace(err.backtrace)]\n  end\n  module_function :get_error\n\n  def format_backtrace backtrace\n    backtrace\n  end\n\n  private\n  def equal_rib_skip result\n    result == Rib::Skip\n  rescue\n    # do nothing, it cannot respond to == correctly, it can't be Rib::Skip\n  end\n\n  def flush_warnings\n    Rib.warn(warnings.shift) until warnings.empty?\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/app/auto.rb",
    "content": "# frozen_string_literal: true\n\nmodule Rib; module Auto\n  module_function\n  def load\n    app, name = %w[rails rack].find{ |n|\n      require \"rib/app/#{n}\"\n      a = Rib.const_get(n.capitalize)\n      break a, n if a.public_send(\"#{n}?\")\n    }\n\n    if app\n      Rib.say(\"Found #{name.capitalize}, loading it...\")\n      begin\n        app.load\n      rescue LoadError => e\n        Rib.warn(\"Error: #{e}\", \"Is this a #{app} app?\")\n      end\n    else\n      Rib.warn(\"No app found\")\n    end\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/app/rack.rb",
    "content": "# frozen_string_literal: true\n\nmodule Rib; module Rack\n  singleton_class.module_eval{ attr_accessor :app }\n\n  module_function\n  def load\n    load_rack\n  rescue LoadError => e\n    Rib.abort(\"Error: #{e}\", \"Is this a Rack app?\")\n  end\n\n  def load_rack\n    require 'rack'\n    Rib.abort(\"Error: Cannot find config.ru\") unless rack?\n    app, _ = ::Rack::Builder.parse_file(configru_path)\n    self.app = app\n    Rib.shell.eval_binding.eval('def app; Rib::Rack.app; end')\n    Rib.say(\"Access your app via :app method\")\n  end\n\n  def rack?\n    File.exist?(configru_path)\n  end\n\n  def configru_path\n    \"#{Rib.config[:prefix]}/config.ru\"\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/app/rails.rb",
    "content": "# frozen_string_literal: true\n\nmodule Rib; module Rails\n  module_function\n  def load\n    load_rails\n  rescue LoadError => e\n    Rib.abort(\"Error: #{e}\", \"Is this a Rails app?\")\n  end\n\n  def load_rails\n    require path_for('boot')\n\n    if File.exist?(path_for('application.rb'))\n      Rib::Rails.load_rails3\n    else\n      Rib::Rails.load_rails2\n    end\n  end\n\n  def load_rails2\n    optparse_env\n    Rib.silence{\n      # rails 2 is so badly written\n      require 'stringio'\n       stderr = $stderr\n      $stderr = StringIO.new\n      Object.const_set('RAILS_ENV', ENV['RAILS_ENV'] || 'development')\n      $stderr = stderr\n    }\n\n    # copied from commands/console\n    [path_for('environment'),\n     'console_app',\n     'console_with_helpers'].each{ |f| require f }\n\n    optparse_rails\n  end\n\n  def load_rails3\n    optparse_env\n\n    # copied from rails/commands\n    require path_for('application')\n    ::Rails.application.require_environment!\n\n    optparse_rails\n  end\n\n  # copied from rails/commands/console\n  def optparse_env\n    # Has to set the RAILS_ENV before config/application is required\n    if ARGV.first && !ARGV.first.index(\"-\") && env = ARGV.shift # has to shift the env ARGV so IRB doesn't freak\n      ENV['RAILS_ENV'] = %w(production development test).detect {|e| e =~ /^#{env}/} || env\n    end\n  end\n\n  # copied from rails/commands/console\n  def optparse_rails\n    require 'optparse'\n    options = {}\n\n    OptionParser.new do |opt|\n      opt.banner = \"Usage: rib rails [environment] [options]\"\n      opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v }\n      opt.on(\"--debugger\", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v }\n      opt.parse!(ARGV)\n    end\n\n      # rails 3\n    if ::Rails.respond_to?(:application) && (app = ::Rails.application)\n      # rails 3.1\n      if app.respond_to?(:sandbox)\n        app.sandbox = options[:sandbox]\n        app.load_console\n      # rails 3.0\n      else\n        app.load_console(options[:sandbox])\n      end\n    else\n      # rails 2\n      require 'console_sandbox' if options[:sandbox]\n    end\n\n    if options[:debugger]\n      begin\n        require 'ruby-debug'\n        puts \"=> Debugger enabled\"\n      rescue Exception\n        puts \"You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'\"\n        exit\n      end\n    end\n\n    if options[:sandbox]\n      puts \"Loading #{::Rails.env} environment in sandbox (Rails #{::Rails.version})\"\n      puts \"Any modifications you make will be rolled back on exit\"\n    else\n      puts \"Loading #{::Rails.env} environment (Rails #{::Rails.version})\"\n    end\n\n    # rails 3.2\n    if ::Rails.const_defined?(:ConsoleMethods)\n      Rib.shell.eval_binding.eval('extend ::Rails::ConsoleMethods')\n    end\n  end\n\n  def rails?\n    File.exist?(path_for('boot.rb')) &&\n      File.exist?(path_for('environment.rb'))\n  end\n\n  def path_for file\n    File.expand_path(\"#{Rib.config[:prefix]}/config/#{file}\")\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/config.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\nRib.require_config\n"
  },
  {
    "path": "lib/rib/core/completion.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Completion\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  def before_loop\n    return super if Completion.disabled?\n    config[:completion]                ||= {}\n    config[:completion][:gems]         ||= []\n    config[:completion][:eval_binding] ||= method(:eval_binding).to_proc\n    Rib.silence{Bond.start(config[:completion]) unless Bond.started?}\n    super\n  end\nend; end\n\nbegin\n  Rib.silence{require 'bond'}\nrescue LoadError => e\n  Rib.warn(\"Error: #{e}\"                                    ,\n           \"Please install bond to use completion plugin:\\n\",\n           \"    gem install bond\\n\"                         ,\n           \"Or add bond to Gemfile if that's the case\"      )\n  Rib::Completion.disable\nend\n"
  },
  {
    "path": "lib/rib/core/history.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\nrequire 'fileutils'\n\nmodule Rib; module History\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  def before_loop\n    return super if History.disabled?\n    history_file\n    history_size\n    FileUtils.mkdir_p(File.dirname(history_file_path))\n    read_history\n    Rib.say(\"History read from: #{history_file_path}\") if $VERBOSE\n    super\n  end\n\n  def after_loop\n    return super if History.disabled?\n    write_history\n    Rib.say(\"History wrote to: #{history_file_path}\") if $VERBOSE\n    super\n  end\n\n  def get_input\n    return super if History.disabled?\n    (history << super).last\n  end\n\n  # --------------- Plugin API ---------------\n\n  # The history data\n  def history; config[:history] ||= []; end\n\n  # Read config[:history_file] into #history, handled in history_file plugin\n  def read_history\n    return super if History.disabled?\n    File.exist?(history_file_path) && history.empty? &&\n      File.readlines(history_file_path).each{ |e| history << e.chomp }\n  end\n\n  # Write #history into config[:history_file], handled in history_file plugin\n  def write_history\n    return super if History.disabled?\n    history_text = \"#{history.to_a.last(history_size).join(\"\\n\")}\\n\"\n    File.write(history_file_path, history_text)\n  end\n\n\n\n  private\n  def history_file\n    config[:history_file]      ||= File.join(Rib.home, 'history.rb')\n  end\n\n  def history_file_path\n    config[:history_file_path] ||= File.expand_path(history_file)\n  end\n\n  def history_size\n    config[:history_size] ||= 500\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/core/last_value.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module LastValue\n  extend Plugin\n  Shell.use(self)\n\n  attr_reader :last_value, :last_exception\n\n  def print_result result\n    return super if LastValue.disabled?\n    @last_value = result\n    super\n  end\n\n  def print_eval_error err\n    return super if LastValue.disabled?\n    @last_exception = err\n    super\n  end\n\n\n\n  module Imp\n    def last_value\n      Rib.shell.last_value\n    end\n\n    def last_exception\n      Rib.shell.last_exception\n    end\n  end\n\n  Rib.extend(Imp)\nend; end\n"
  },
  {
    "path": "lib/rib/core/multiline.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\n# from https://github.com/janlelis/ripl-multi_line\nmodule Rib; module Multiline\n  extend Plugin\n  Shell.use(self)\n\n  engine = if Object.const_defined?(:RUBY_ENGINE)\n             RUBY_ENGINE\n           else\n             'ruby'\n           end\n\n  # test those:\n  # ruby -e '\"'\n  # ruby -e '{'\n  # ruby -e '['\n  # ruby -e '('\n  # ruby -e '/'\n  # ruby -e 'class C'\n  # ruby -e 'def f'\n  # ruby -e 'begin'\n  # ruby -e 'case 1'\n  # ruby -e 'eval \"1+1.to_i +\"'\n  # ruby -e 'eval \"1+1.to_i -\"'\n  # ruby -e 'eval \"1+1.to_i *\"'\n  # ruby -e 'eval \"1+1.to_i /\"'\n  # ruby -e 'eval \"1+1.to_i &\"'\n  # ruby -e 'eval \"1+1.to_i |\"'\n  # ruby -e 'eval \"1+1.to_i ^\"'\n  BINARY_OP = %w[tUPLUS tUMINUS tSTAR tREGEXP_BEG tAMPER]\n  RUBY20_IO = %w[unary+ unary-  *     tREGEXP_BEG &].\n              map(&Regexp.method(:escape))\n  ERROR_REGEXP = case engine\n    when 'ruby' ; Regexp.new(\n                    [ # string or regexp\n                      \"unterminated \\\\w+ meets end of file\",\n                      # mri and rubinius\n                      \"unexpected (#{BINARY_OP.join('|')}), expecting \\\\$end\",\n                      \"syntax error, unexpected \\\\$end\"    ,\n                      # prism\n                      \"expected an? `.+?` to close the\",\n                      \"expected a matching `\\\\)`\",\n                      # ruby 2.0 and prism\n                      \"unexpected end-of-input\",\n                      # ruby 2.0\n                      \"syntax error, unexpected (#{RUBY20_IO.join('|')}),\"\n                                                                  ].join('|'))\n    when 'rbx'  ; Regexp.new(\n                    [ # string or regexp\n                      \"unterminated \\\\w+ meets end of file\",\n                      # mri and rubinius\n                      \"syntax error, unexpected \\\\$end\"    ,\n                      # rubinius\n                      \"expecting keyword_end\"              ,\n                      \"expecting keyword_then\"             ,\n                      \"expecting keyword_when\"             ,\n                      \"expecting keyword_do_cond\"          ,\n                      \"expecting \\\\$end\"                   ,\n                      \"expecting '.+'( or '.+')*\"          ,\n                      \"missing '.+' for '.+' started on line \\\\d+\"].join('|'))\n    when 'jruby'; Regexp.new(\n                    [ # string or regexp\n                      \"unterminated \\\\w+ meets end of file\",\n                      # jruby\n                      \"syntax error, unexpected end\\\\-of\\\\-file\",\n                      # jruby 9.0.4.0\n                      \"formal argument must be local variable\",\n                      # jruby 9.2.0.0\n                      \"syntax error, unexpected (#{RUBY20_IO.join('|')})\",\n                      \"syntax error, unexpected '\\\\W'\"\n                                                                  ].join('|'))\n    end\n\n  # --------------- Rib API ---------------\n\n  def loop_once\n    return super if Multiline.disabled?\n    result = nil\n    catch(:rib_multiline) do\n      result = super\n      multiline_buffer.clear\n    end\n    result\n  end\n\n  def loop_eval input\n    return super if Multiline.disabled?\n    multiline_buffer << input\n    if input =~ /\\\\\\z/\n      throw :rib_multiline\n    else\n      super(multiline_buffer.join(\"\\n\"))\n    end\n  end\n\n  def print_eval_error err\n    return super if Multiline.disabled?\n    if multiline?(err)\n      throw :rib_multiline\n    else\n      super\n    end\n  end\n\n  def prompt\n    return super if Multiline.disabled?\n    if multiline_buffer.empty?\n      super\n    else\n      mprompt = multiline_prompt[0, config[:prompt].size]\n      \"#{' '*(config[:prompt].size-mprompt.size)}#{mprompt}\"\n    end\n  end\n\n  def handle_interrupt\n    return super if Multiline.disabled?\n    if multiline_buffer.empty?\n      super\n    else\n      print \"[removed this line: #{multiline_buffer.pop}]\"\n      super\n      throw :rib_multiline\n    end\n  end\n\n  # --------------- Plugin API ---------------\n\n  def multiline? err\n    err.is_a?(SyntaxError) && err.message =~ ERROR_REGEXP\n  end\n\n  def multiline_prompt\n    config[:multiline_prompt] ||= '| '\n  end\n\n\n  private\n  def multiline_buffer\n    @multiline_buffer ||= []\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/core/readline.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\nrequire 'readline'\n\nmodule Rib; module Readline\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  def before_loop\n    return super if Readline.disabled?\n    config[:history] = ::Readline::HISTORY\n    super\n  end\n\n  def get_input\n    return super if Readline.disabled?\n    ::Readline.readline(prompt, true)\n  end\nend\n\nunless ::Readline::HISTORY.respond_to?(:last)\n  def (::Readline::HISTORY).last\n    self[-1]\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/core/squeeze_history.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib/core/history' # dependency\n\nmodule Rib; module SqueezeHistory\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  # squeeze history in memory too\n  def loop_once\n    return super if SqueezeHistory.disabled?\n    begin\n      input, last_input = history[-1], history[-2]\n    rescue IndexError # EditLine is really broken, to_a is needed for it\n      array = history.to_a\n      input, last_input = array[-1], array[-2]\n    end\n    history.pop if input.to_s.strip == '' ||\n                  (history.size > 1 && input == last_input)\n    super\n  end\n\n  # --------------- Plugin API ---------------\n\n  # write squeezed history\n  def write_history\n    return super if SqueezeHistory.disabled?\n    config[:history] = squeezed_history\n    super\n  end\n\n\n\n  private\n  def squeezed_history\n    history.to_a.inject([]){ |result, item|\n      if result.last == item || item.strip == ''\n        result\n      else\n        result << item\n      end\n    }\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/core/strip_backtrace.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module StripBacktrace\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  def format_error err\n    return super if StripBacktrace.disabled?\n    message, backtrace = get_error(err)\n    \"#{message}\\n  #{backtrace.join(\"\\n  \")}\"\n  end\n\n  def get_error err\n    return super if StripBacktrace.disabled?\n    [\"#{err.class}: #{err.message}\", format_backtrace(err.backtrace)]\n  end\n\n  module_function\n  def format_backtrace backtrace\n    return super if StripBacktrace.disabled?\n    strip_home_backtrace(\n      strip_cwd_backtrace(\n        strip_rib_backtrace(super(backtrace))))\n  end\n\n  def strip_home_backtrace backtrace\n    backtrace.map(&method(:replace_path_prefix).curry[ENV['HOME'], '~/'])\n  end\n\n  def strip_cwd_backtrace backtrace\n    backtrace.map(&method(:replace_path_prefix).curry[Dir.pwd, ''])\n  end\n\n  def strip_rib_backtrace backtrace\n    backtrace[\n      0..backtrace.rindex{ |l| l =~ /\\(#{name}\\):\\d+:in (?:`|').+?'/ } || -1]\n  end\n\n  def replace_path_prefix prefix, substitute, path\n    path.sub(/\\A#{Regexp.escape(prefix)}\\//, substitute)\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/core.rb",
    "content": "# frozen_string_literal: true\n\n# before session starts\nrequire 'rib/core/completion'\n\n# upon session ends\nrequire 'rib/core/history'\n\n# upon formatting output\nrequire 'rib/core/strip_backtrace'\n\n# upon input\nrequire 'rib/core/readline'\nrequire 'rib/core/multiline'\nrequire 'rib/core/squeeze_history'\n\n# special tools\nrequire 'rib/core/last_value'\n"
  },
  {
    "path": "lib/rib/debug.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib/config'\nrequire 'rib/more/anchor'\nRib::Anchor.disable\nRib::Debugger.disable if Rib.const_defined?(:Debugger)\n"
  },
  {
    "path": "lib/rib/extra/autoindent.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib/core/history'   # otherwise the order might be wrong\nrequire 'rib/core/readline'  # dependency\nrequire 'rib/core/multiline' # dependency\n\nmodule Rib; module Autoindent\n  extend Plugin\n  Shell.use(self)\n\n  # begin block could be simpler, because it should also trigger\n  # SyntaxError, otherwise indention would be wiped out.\n  # but end block should be exactly match, because we don't have\n  # SyntaxError information, also triggering SyntaxError doesn't\n  # mean it's not an end block, thinking about nested multiline!\n  BLOCK_REGEXP = {\n    # rescue Expression? (=> VariableName)?\n    # consider cases:\n    # rescue\n    # rescue=>e\n    # rescue => e\n    # rescue =>e\n    # rescue E=>e\n    # rescue E\n    # rescue E => e\n    # rescue E=> e\n    # rescue E =>e\n    # ensure\n    /^begin$/ =>\n      /^(end)\\b|^else$|^rescue *((\\w+)? *(=> *\\w+)?)?$|^ensure$/,\n    /^def\\b/  =>\n      /^(end)\\b|^else$|^rescue *((\\w+)? *(=> *\\w+)?)?$|^ensure$/,\n    # elsif Expression\n    # consider cases:\n    # elsif(true)\n    # elsif true\n    # elsif true == true\n    # elsif (a = true) && false\n    /^if\\b/            => /^(end)\\b|^else$|^elsif\\b/,\n    /^unless\\b/        => /^(end)\\b|^else$|^elsif\\b/,\n    /^case\\b/          => /^(end)\\b|^else$|when\\b/  ,\n    /^class\\b/         => /^(end)\\b/                ,\n    /^module\\b/        => /^(end)\\b/                ,\n    /^while\\b/         => /^(end)\\b/                ,\n    /^for\\b/           => /^(end)\\b/                ,\n    /^until\\b/         => /^(end)\\b/                ,\n    # consider cases:\n    # 'do\n    # ' do\n    # \"' do\n    # /do\n    # '{\n    # %q{\n    # %q| do\n    # hey, two lines are even harder!\n    # \"\n    # begin\n    /do( *\\|.*\\|)?$/ => /^(end)\\b/                ,\n    /\\{( *\\|.*\\|)?$/ => /^(\\})\\B/                 ,\n    /\\($/            => /^(\\))\\B/                 ,\n    /\\[$/            => /^(\\])\\B/                 ,\n    # those are too hard to deal with, so we use syntax error to double check\n    # what about this then?\n    # v = if true\n    #     else\n    #     end\n  }\n\n  # --------------- Rib API ---------------\n\n  def before_loop\n    return super if Autoindent.disabled?\n    autoindent_spaces\n    super\n  end\n\n  def get_input\n    return super if Autoindent.disabled?\n    # this is only a fix in case we don't autoindent correctly\n    # if we're autoindenting 100% correct, then this is a useless check\n    autoindent_stack.clear if multiline_buffer.empty?\n\n    # this should be called after ::Readline.readline, but it's blocking,\n    # and i don't know if there's any hook to do this, so here we use thread\n    Thread.new do\n      sleep(0.01)\n      ::Readline.line_buffer = current_autoindent if\n        ::Readline.line_buffer && ::Readline.line_buffer.empty?\n    end\n\n    super\n  end\n\n  def eval_input raw_input\n    return super if Autoindent.disabled?\n    input  = raw_input.strip\n    indent = detect_autoindent(input)\n    result, err = super\n    handle_autoindent(input, indent, err)\n    [result, err]\n  end\n\n  # --------------- Plugin API ---------------\n\n  def detect_autoindent input\n    _, backmark = BLOCK_REGEXP.find{ |key,  _| input =~ key }\n    if backmark # e.g. begin\n      [:right, backmark]\n    elsif input =~ autoindent_stack.last\n      if $1     # e.g. end, }, etc\n        [:left_end]\n      else      # e.g. elsif, rescue, etc\n        [:left_tmp]\n      end\n    else\n      [:stay]\n    end\n  end\n\n  def handle_autoindent input, indent, err\n    case indent.first\n    when :right    # we need to go deeper\n      if multiline?(err)\n        if err.message =~ /unterminated \\w+ meets end of file/\n          # skip if we're in the middle of a string or regexp\n        else\n          # indent.last is the way (input regexp matches) to go back\n          autoindent_stack << indent.last\n        end\n      end\n\n    when :left_end # we need to go back\n      # could happen in either multiline or not\n      handle_last_line(input)\n      autoindent_stack.pop\n\n    when :left_tmp # temporarily go back\n      handle_last_line(input) if multiline?(err)\n    end\n  end\n\n  def handle_last_line input,\n                       indent=current_autoindent(autoindent_stack.size-1)\n    new_input = \"#{indent}#{input}\"\n    puts(\"\\e[1A\\e[K#{prompt}#{new_input}\")\n    new_input\n  end\n\n\n\n  private\n  def current_autoindent size=autoindent_stack.size\n    autoindent_spaces * size\n  end\n\n  def autoindent_spaces\n    config[:autoindent_spaces] ||= '  '\n  end\n\n  def autoindent_stack\n    @autoindent_stack ||= []\n  end\nend; end\n\nbegin\n  require 'readline_buffer'\nrescue LoadError => e\n  Rib.warn(\"Error: #{e}\"                                               ,\n           \"Please install readline_buffer to use autoindent plugin:\\n\",\n           \"    gem install readline_buffer\\n\"                         ,\n           \"Or add readline_buffer to Gemfile if that's the case\"      )\n  Rib::Autoindent.disable\nend\n"
  },
  {
    "path": "lib/rib/extra/byebug.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib/more/anchor'\nrequire 'byebug/core'\n\n# This is based on lib/byebug/processors/pry_processor.rb\n\nmodule Rib; module Byebug\n  extend Plugin\n  Shell.use(self)\n\n  def before_loop\n    return super if Rib::Byebug.disabled?\n\n    super\n    # ::Byebug::RibProcessor.start\n  end\n\n  module Imp\n    def byebug\n      return if Rib::Byebug.disabled?\n\n      ::Byebug::RibProcessor.start\n    end\n\n    def location\n      Rib.shell.config[:byebug].location\n    end\n\n    def step times=1\n      throw :rib_byebug, [:step, times]\n    end\n\n    def next lines=1\n      throw :rib_byebug, [:next, lines]\n    end\n\n    def finish\n      throw :rib_byebug, [:finish]\n    end\n  end\n\n  Rib.extend(Imp)\nend; end\n\nmodule Byebug\n  class RibProcessor < CommandProcessor\n    def self.start\n      Byebug.start\n      Setting[:autolist] = false\n      Context.processor = self\n      steps = caller.index{ |path| !path.start_with?(__FILE__) }\n      Byebug.current_context.step_out(steps + 2, true)\n    end\n\n    def at_line\n      resume_rib\n    end\n\n    def at_return(_return_value)\n      resume_rib\n    end\n\n    def at_end\n      resume_rib\n    end\n\n    def at_breakpoint(breakpoint)\n      raise NotImplementedError\n    end\n\n    def location\n      context.location\n    end\n\n    private\n\n    def print_location\n      shell = Rib.shell\n      shell.puts(shell.format_backtrace([location]).first)\n    end\n\n    def resume_rib\n      return if Rib.shell.running?\n\n      byebug_binding = frame._binding\n\n      print_location\n\n      action, *args = catch(:rib_byebug) do\n        allowing_other_threads do\n          Rib.anchor byebug_binding, :byebug => self\n        end\n      end\n\n      perform(action, args)\n    end\n\n    def perform action, args\n      case action\n      when :step\n        context.step_into(*args, frame.pos)\n      when :next\n        context.step_over(*args, frame.pos)\n      when :finish\n        context.step_out(1)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/rib/extra/hirb.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Hirb\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  def format_result result\n    return super if Hirb.disabled?\n    ::Hirb::View.view_or_page_output(result) || super\n  end\nend\n\nbegin\n  Rib.silence{\n    require 'hirb'\n    ::Hirb.enable\n  }\nrescue LoadError => e\n  Rib.warn(\"Error: #{e}\"                              ,\n           \"Please install hirb to use hirb plugin:\\n\",\n           \"    gem install hirb\\n\"                   ,\n           \"Or add hirb to Gemfile if that's the case\")\n  Rib::Hirb.disable\nend; end\n"
  },
  {
    "path": "lib/rib/extra/paging.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Paging\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  # Print if the it fits one screen, paging it through a pager otherwise.\n  def puts str=''\n    return super if Paging.disabled?\n    if one_screen?(str)\n      super\n    else\n      page_result(str)\n    end\n  end\n\n  # `less -F` can't cat the output, so we need to detect by ourselves.\n  # `less -X` would mess up the buffers, so it's not desired, either.\n  def one_screen? str\n    cols, lines = `tput cols`.to_i, `tput lines`.to_i\n    (str.count(\"\\n\") + 2) <= lines && # count last line and prompt\n      str.gsub(/\\e\\[[^m]*m/, '').size <= cols * lines\n  end\n\n  def page_result str\n    less = IO.popen(pager, 'w')\n    less.write(str)\n    less.close_write\n  rescue Errno::EPIPE\n    # less quit without consuming all the input\n  end\n\n  def pager\n    ENV['PAGER'] || 'less -R'\n  end\nend; end\n\npager = ENV['PAGER'] || 'less'\n\nif `which #{pager}`.empty?\n  Rib.warn(\"#{pager} is not available, disabling Rib::Paging\")\n  Rib::Paging.disable\nelsif `which tput`.empty?\n  Rib.warn(\"tput is not available, disabling Rib::Paging\")\n  Rib::Paging.disable\nelsif ENV['TERM'] == 'dumb' || ENV['TERM'].nil?\n  Rib.warn(\"Your terminal is dumb, disabling Rib::Paging\")\n  Rib::Paging.disable\nend\n"
  },
  {
    "path": "lib/rib/extra/spring.rb",
    "content": "# frozen_string_literal: true\n\nmodule Spring\n  module Commands\n    class Rib\n      def call\n        load `which rib`.chomp\n      end\n    end\n\n    Spring.register_command 'rib', Rib.new\n  end\nend\n"
  },
  {
    "path": "lib/rib/more/anchor.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Anchor\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  def prompt\n    return super if Rib::Anchor.disabled?\n    return super unless anchor?\n\n    level = \"(#{Rib.shells.size - 1})\"\n    if Rib.const_defined?(:Color) &&\n       kind_of?(Rib::Color)       &&\n       Rib::Color.enabled?\n\n      \"#{format_color(eval_binding, prompt_anchor)}#{level}#{super}\"\n    else\n      \"#{prompt_anchor}#{level}#{super}\"\n    end\n  end\n\n  def anchor?\n    !!config[:prompt_anchor]\n  end\n\n\n\n  private\n  def prompt_anchor\n    @prompt_anchor ||=\n    if eval_binding.kind_of?(Binding)\n      eval_binding.eval('self', __FILE__, __LINE__)\n    else\n      eval_binding\n    end.inspect[0..9]\n  end\n\n  module Imp\n    # Enter an interactive Rib shell based on a particular context.\n    #\n    # @api public\n    # @param obj_or_binding [Object, Binding] The context of the shell.\n    # @param opts [Hash] The config hash passed to the newly created shell.\n    #   See {Rib::Shell#initialize} for all possible options.\n    # @return [Rib::Skip] This is the mark telling Rib do not print anything.\n    #   It's only used internally in Rib.\n    # @see Rib::Shell#initialize\n    # @example\n    #   Rib.anchor binding\n    #   Rib.anchor 123\n    def anchor obj_or_binding, opts={}\n      return if Rib::Anchor.disabled?\n\n      if Rib.shell.running?\n        Rib.shells << Rib::Shell.new(\n          Rib.shell.config.merge( :binding       => obj_or_binding,\n                                  :prompt_anchor => true         ).\n                           merge(opts))\n      else\n          Rib.shell.config.merge!(:binding       => obj_or_binding,\n                                  :prompt_anchor => true         ).\n                           merge!(opts)\n      end\n\n      Rib.shell.loop\n      Rib::Skip\n\n    ensure\n      Rib.shells.pop\n    end\n\n    def stop_anchors\n      Rib.shells.select(&:anchor?).each(&:stop)\n      Rib::Skip\n    end\n  end\n\n  Rib.extend(Imp)\nend; end\n"
  },
  {
    "path": "lib/rib/more/beep.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Beep\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  def loop_once\n    return super if Beep.disabled?\n    beep if started_at && (Time.now - started_at) > beep_threshold\n    config[:started_at] = Time.now\n    super\n  end\n\n  private\n  def beep\n    print \"\\a\"\n  end\n\n  def beep_threshold\n    config[:beep_threshold] ||= 5\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/more/bottomup_backtrace.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module BottomupBacktrace\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  def format_error err\n    return super if BottomupBacktrace.disabled?\n    message, backtrace = get_error(err)\n    \"  #{backtrace.join(\"\\n  \")}\\n#{message}\"\n  end\n\n  def format_backtrace backtrace\n    super(backtrace).reverse\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/more/caller.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Caller\n  extend Plugin\n  Shell.use(self)\n\n  module Imp\n    def caller *filters\n      return if Rib::Caller.disabled?\n\n      display_backtrace(super().drop(1), *filters)\n    end\n\n    def display_backtrace raw_backtrace, *filters\n      backtrace = Rib.shell.format_backtrace(raw_backtrace)\n\n      lib = %r{\\brib-#{Rib::VERSION}/lib/rib/}\n      if backtrace.first =~ lib\n        backtrace.shift while backtrace.first =~ lib\n      elsif backtrace.last =~ lib\n        backtrace.pop while backtrace.last =~ lib\n      end\n\n      result = filters.map do |f|\n        case f\n        when Regexp\n          f\n        when String\n          %r{\\bgems/#{Regexp.escape(f)}\\-[\\d\\.]+/lib/}\n        end\n      end.inject(backtrace, &:grep_v)\n\n      Rib.shell.puts result.map{ |l| \"  #{l}\" }.join(\"\\n\")\n\n      Rib::Skip\n    end\n  end\n\n  Rib.extend(Imp)\nend; end\n"
  },
  {
    "path": "lib/rib/more/color.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Color\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  def before_loop\n    colors\n    super\n  end\n\n  def format_result result\n    return super if Color.disabled?\n    \"#{result_prompt}#{format_color(result)}\"\n  end\n\n  def get_error err\n    return super if Color.disabled?\n    message, backtrace = super\n    [format_color(err, message), backtrace]\n  end\n\n  def warn message\n    return super if Color.disabled?\n    super(red{message})\n  end\n\n  # --------------- Plugin API ---------------\n\n  def colors\n    config[:color] ||= {\n      Numeric    => :red    ,\n      String     => :green  ,\n      Symbol     => :cyan   ,\n      Array      => :blue   ,\n      Hash       => :blue   ,\n      NilClass   => :magenta,\n      TrueClass  => :magenta,\n      FalseClass => :magenta,\n      Exception  => :magenta,\n      Object     => :yellow }\n  end\n\n  def format_color result, display=inspect_result(result)\n    case result\n      when String ; send(colors[String ]){ display }\n      when Numeric; send(colors[Numeric]){ display }\n      when Symbol ; send(colors[Symbol ]){ display }\n\n      when Array  ; send(colors[Array  ]){ '['     }   +\n                      result.map{ |e   | if e.object_id == result.object_id\n                                           send(colors[Array]){'[...]'}\n                                         else\n                                           format_color(e); end }.\n               join(send(colors[Array  ]){ ', '    })  +\n                    send(colors[Array  ]){ ']'     }\n\n      when Hash   ; send(colors[Hash   ]){ '{'     }   +\n                      result.map{ |k, v| format_color(k) +\n                    send(colors[Hash   ]){ '=>'    }   +\n                                         if v.object_id == result.object_id\n                                           send(colors[Hash]){'{...}'}\n                                         else\n                                           format_color(v); end }.\n               join(send(colors[Hash   ]){ ', '    }) +\n                    send(colors[Hash   ]){ '}'     }\n\n      else        ; if color = find_color(colors, result)\n                    send(color){ display }\n                    else\n                    send(colors[Object]){ display }\n                    end\n    end\n  end\n\n  def format_backtrace backtrace\n    colorize_backtrace(super(backtrace))\n  end\n\n\n\n  module_function\n  def colorize_backtrace backtrace\n    backtrace.map{ |b|\n      path, msgs = b.split(':', 2)\n      dir, sep, file = path.rpartition('/')\n      msgs ||= (line - 1).to_s # msgs would be nil when input is next/break\n      msg = msgs.sub(/(\\d+)(:?)/) do\n        m = Regexp.last_match\n        \"#{red{m[1]}}#{m[2]}\"\n      end.sub(/(?:`|').+?'/){green{Regexp.last_match[0]}}\n\n      \"#{dir+sep}#{yellow{file}}:#{msg}\"\n    }\n  end\n\n  def find_color colors, value\n    (colors.sort{ |(k1, _), (k2, _)|\n      # Class <=> Class\n      if    k1 < k2 then -1\n      elsif k1 > k2 then  1\n      else                0\n      end}.find{ |(klass, _)| value.kind_of?(klass) } || []).last\n  end\n\n  def color rgb\n    \"\\e[#{rgb}m\" + if block_given? then \"#{yield}#{reset}\" else '' end\n  end\n\n  def   black &block; color(30, &block); end\n  def     red &block; color(31, &block); end\n  def   green &block; color(32, &block); end\n  def  yellow &block; color(33, &block); end\n  def    blue &block; color(34, &block); end\n  def magenta &block; color(35, &block); end\n  def    cyan &block; color(36, &block); end\n  def   white &block; color(37, &block); end\n  def   reset &block; color( 0, &block); end\nend; end\n\nbegin\n  require 'win32console' if defined?(Gem) && Gem.win_platform?\nrescue LoadError => e\n  Rib.warn(\"Error: #{e}\"                                                  ,\n           \"Please install win32console to use color plugin on Windows:\\n\",\n           \"    gem install win32console\\n\"                               ,\n           \"Or add win32console to Gemfile if that's the case\"            )\n  Rib::Color.disable\nend\n"
  },
  {
    "path": "lib/rib/more/edit.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\nrequire 'tempfile'\n\nmodule Rib; module Edit\n  extend Plugin\n  Shell.use(self)\n\n  module Imp\n    def edit\n      return if Rib::Edit.disabled?\n      file = Tempfile.new(['rib.edit', '.rb'])\n      file.puts(Rib.vars[:edit])\n      file.close\n\n      shell = Rib.shell\n      system(\"#{shell.editor} #{file.path}\")\n\n      if shell.running?\n        shell.send(:multiline_buffer).pop\n      else\n        shell.before_loop\n      end\n\n      shell.loop_eval(Rib.vars[:edit] = File.read(file.path))\n\n    ensure\n      file.close\n      file.unlink\n    end\n  end\n\n  def editor\n    ENV['EDITOR'] || 'vim'\n  end\n\n  Rib.extend(Imp)\nend; end\n"
  },
  {
    "path": "lib/rib/more/multiline_history.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib/core/history'   # dependency\nrequire 'rib/core/multiline' # dependency\n\nmodule Rib; module MultilineHistory\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  def before_loop\n    @multiline_trash = 0\n    super\n  end\n\n  def loop_eval input\n    return super if MultilineHistory.disabled?\n    super\n  ensure\n    # SyntaxError might mean we're multiline editing\n    handle_multiline unless multiline?($!)\n  end\n\n  def handle_interrupt\n    return super if MultilineHistory.disabled?\n    if multiline_buffer.size > 1\n      multiline_trash\n      @multiline_trash += 1\n    end\n    super\n  end\n\n\n\n  private\n  def handle_multiline\n    if multiline_buffer.size > 1\n      # so multiline editing is considering done here\n      # TODO: there's no history.pop(size)\n      (multiline_buffer.size + multiline_trash).times{ history.pop }\n      history << \"\\n\" + multiline_buffer.join(\"\\n\")\n    end\n  end\n\n  def multiline_trash\n    @multiline_trash ||= 0\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/more/multiline_history_file.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib/more/multiline_history'\n\nmodule Rib; module MultilineHistoryFile\n  extend Plugin\n  Shell.use(self)\n\n  # --------------- Rib API ---------------\n\n  def before_loop\n    return super if MultilineHistoryFile.disabled?\n    multiline_history_file_token\n    super\n  end\n\n  # --------------- Plugin API ---------------\n\n  def read_history\n    return super if MultilineHistoryFile.disabled?\n    buffer = []\n    File.exist?(history_file_path) && history.empty? &&\n      IO.readlines(history_file_path).each{ |line|\n        if line.end_with?(\n             \"#{config[:multiline_history_file_token]}\\n\")\n          buffer << line[0...\n                         -multiline_history_file_token.size-1] + \"\\n\"\n        else\n          history << (buffer.join + line).chomp\n          buffer = []\n        end\n      }\n  end\n\n  def write_history\n    return super if MultilineHistoryFile.disabled?\n    # TODO: hisotroy.map is MRI 1.9+\n    config[:history] = history.to_a.map{ |line|\n      line.gsub(\"\\n\", \"#{config[:multiline_history_file_token]}\\n\")\n    }\n    super\n  end\n\n\n\n  private\n  def multiline_history_file_token\n    config[:multiline_history_file_token] ||= ' '\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/more.rb",
    "content": "# frozen_string_literal: true\n\n# upon session ends\nrequire 'rib/more/multiline_history_file'\n\n# upon formatting output\nrequire 'rib/more/bottomup_backtrace'\nrequire 'rib/more/color'\n\n# upon input\nrequire 'rib/more/multiline_history'\n\n# special tools\nrequire 'rib/more/anchor'\nrequire 'rib/more/caller'\nrequire 'rib/more/edit'\n\n# upon application loads\nrequire 'rib/more/beep'\n"
  },
  {
    "path": "lib/rib/plugin.rb",
    "content": "# frozen_string_literal: true\n\nmodule Rib; module Plugin\n  attr_accessor :disabled\n\n  def enable\n    self.disabled = false\n    if block_given? then yield else enabled? end\n  ensure\n    self.disabled = true if block_given?\n  end\n\n  def disable\n    self.disabled = true\n    if block_given? then yield else enabled? end\n  ensure\n    self.disabled = false if block_given?\n  end\n\n  def enabled?\n    !disabled\n  end\n\n  def disabled?\n    !!disabled\n  end\n\n  # Backward compatibility\n  def const_missing mod\n    if Rib.const_defined?(mod)\n      Rib.warn(\"Using #{mod} is deprecated, please change to Rib::#{mod}\",\n               \"This compatibility layer would be removed in Rib 1.6+\",\n               \"Called: #{caller.first}\")\n      Rib.const_get(mod)\n    else\n      super\n    end\n  end\n\n  def self.extended mod\n    return unless mod.name\n\n    snake_name = mod.name.sub(/(\\w+::)+?(\\w+)$/, '\\2').\n      gsub(/([A-Z][a-z]*)/, '\\\\1_').downcase[0..-2]\n\n    code = (%w[enable disable].map{ |meth|\n      <<-RUBY\n        def #{meth}_#{snake_name} &block\n          #{mod.name}.#{meth}(&block)\n        end\n      RUBY\n    } + %w[enabled? disabled?].map{ |meth|\n      <<-RUBY\n        def #{snake_name}_#{meth} &block\n          #{mod.name}.#{meth}(&block)\n        end\n      RUBY\n    }).join(\"\\n\")\n\n    Rib.singleton_class.module_eval(code, __FILE__, __LINE__)\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/runner.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib'\n\nmodule Rib; module Runner\n  module_function\n  def options\n    @options ||=\n    [['ruby options:'    , ''                                      ],\n     ['-e, --eval LINE'                                             ,\n      'Evaluate a LINE of code'                                    ],\n\n     ['-d, --debug'                                                 ,\n      'Set debugging flags (set $DEBUG to true)'                   ],\n\n     ['-w, --warn'                                                  ,\n       'Turn warnings on (set $-w and $VERBOSE to true)'           ],\n\n     ['-I, --include PATH'                                          ,\n       'Specify $LOAD_PATH (may be used more than once)'           ],\n\n     ['-r, --require LIBRARY'                                       ,\n       'Require the library, before executing your script'         ],\n\n     ['rib options:'     , ''                                      ],\n     ['-c, --config FILE', 'Load config from FILE'                 ],\n     ['-p, --prefix PATH', 'Prefix to locate the app. Default to .'],\n     ['-n, --no-config'  , 'Suppress loading any config'           ],\n     ['-h, --help'       , 'Print this message'                    ],\n     ['-v, --version'    , 'Print the version'                     ]] +\n\n    [['rib commands:'    , '']] + commands\n  end\n\n  def commands\n     @commands ||=\n      command_paths.map{ |path|\n        name = File.basename(path)[/^rib\\-(.+)$/, 1]\n        [name, command_descriptions[name]      ||\n               command_descriptions_find(path) || ' '] }\n  end\n\n  def command_paths\n    @command_paths ||=\n    Gem.path.map{ |path|\n      Dir[\"#{path}/bin/*\"].map{ |f|\n        (File.executable?(f) && File.basename(f) =~ /^rib\\-.+$/ && f) ||\n         nil    # a trick to make false to be nil and then\n      }.compact # this compact could eliminate them\n    }.flatten\n  end\n\n  def command_descriptions\n    @command_descriptions ||=\n    {'all'    => 'Load all recommended plugins'              ,\n     'min'    => 'Run the minimum essence'                   ,\n     'auto'   => 'Run as Rails or Rack console (auto-detect)',\n     'rails'  => 'Run as Rails console'                      ,\n     'rack'   => 'Run as Rack console'                       }\n  end\n\n  # Extract the text below __END__ in the bin file as the description\n  def command_descriptions_find path\n    # FIXME: Can we do better? This is not reliable\n    File.read(path) =~ /Gem\\.activate_bin_path\\(['\"](.+)['\"], ['\"](.+)['\"],/\n    (File.read(Gem.bin_path($1, $2))[/\\n__END__\\n(.+)$/m, 1] || '').strip\n  end\n\n  def run argv=ARGV\n    (@running_commands ||= []) << Rib.config[:name]\n    unused = parse(argv)\n    # we only want to run the loop if we're running the rib command,\n    # otherwise, it must be a rib app, which we only want to parse\n    # the arguments and proceed (this is recursive!)\n    if @running_commands.pop == 'rib'\n      Rib.warn(\"Unused arguments: #{unused.inspect}\") unless unused.empty?\n      require 'rib/core' if Rib.config.delete(:mimic_irb)\n      loop\n    end\n  end\n\n  def loop retry_times=5\n    Rib.shell.loop\n  rescue => e\n    if retry_times <= 0\n      Rib.warn(\"Error: #{e}. Too many retries, give up.\")\n    elsif Rib.shells.last.running?\n      Rib.warn(\"Error: #{e}. Relaunching a new shell... ##{retry_times}\")\n      Rib.warn(\"Backtrace: #{e.backtrace}\") if $VERBOSE\n      Rib.shells.pop\n      Rib.shells << Rib::Shell.new(Rib.config)\n      retry_times -= 1\n      retry\n    else\n      Rib.warn(\"Error: #{e}. Closing.\")\n      Rib.warn(\"Backtrace: #{e.backtrace}\") if $VERBOSE\n    end\n  end\n\n  def parse argv\n    unused = []\n    until argv.empty?\n      case arg = argv.shift\n      when /^-e=?(.+)?/, /^--eval=?(.+)?/\n        Rib.shell.eval_binding.eval(\n          $1 || argv.shift || '', __FILE__, __LINE__)\n\n      when /^-d/, '--debug'\n        $DEBUG = true\n        parse_next(argv, arg)\n\n      when /^-w/, '--warn'\n        $-w, $VERBOSE = true, true\n        parse_next(argv, arg)\n\n      when /^-I=?(.+)?/, /^--include=?(.+)?/\n        paths = ($1 || argv.shift).split(':')\n        $LOAD_PATH.unshift(*paths)\n\n      when /^-r=?(.+)?/, /^--require=?(.+)?/\n        require($1 || argv.shift)\n\n      when /^-c=?(.+)?/, /^--config=?(.+)?/\n        Rib.config_path = $1 || argv.shift\n\n      when /^-p=?(.+)?/, /^--prefix=?(.+)?/\n        Rib.config[:prefix] = $1 || argv.shift\n\n      when /^-n/, '--no-config'\n        Rib.config_path = Rib::Skip\n        parse_next(argv, arg)\n\n      when /^-h/, '--help'\n        puts(help)\n        exit\n\n      when /^-v/, '--version'\n        require 'rib/version'\n        puts(Rib::VERSION)\n        exit\n\n      when /^[^-]/\n        load_command(arg)\n\n      else\n        unused << arg\n      end\n    end\n    unused\n  end\n\n  def parse_next argv, arg\n    argv.unshift(\"-#{arg[2..-1]}\") if arg.size > 2\n  end\n\n  def help\n    optt = options.transpose\n    maxn = optt.first.map(&:size).max\n    maxd = optt.last .map(&:size).max\n    \"Usage: #{Rib.config[:name]}\"                    \\\n    \" [ruby OPTIONS] [rib OPTIONS] [rib COMMANDS]\\n\" +\n    options.map{ |(name, desc)|\n      if name.end_with?(':')\n        name\n      else\n        sprintf(\"  %-*s  %-*s\", maxn, name, maxd, desc)\n      end\n    }.join(\"\\n\")\n  end\n\n  def load_command command\n    bin  = \"rib-#{command}\"\n    path = which_bin(bin)\n    if path == ''\n      Rib.warn(\n        \"Can't find #{bin} in $PATH. Please make sure it is installed,\",\n        \"or is there any typo? You can try this to install it:\\n\"      ,\n        \"    gem install #{bin}\")\n    else\n      Rib.config[:name] = bin\n      load(path)\n    end\n  end\n\n  def which_bin bin # handle windows here\n    `which #{bin}`.strip\n  rescue Errno::ENOENT # probably a windows platform, try where\n    `where #{bin}`.lines.first.strip\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/shell.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib/plugin'\nrequire 'rib/api'\n\nmodule Rib; class Shell\n  include API\n\n  def self.use mod\n    include mod\n  end\n\n  attr_reader :config\n\n  # Create a new shell.\n  #\n  # @api public\n  # @param config [Hash] The config of the shell.\n  # @option config [String] :config ('~/.rib/config.rb')\n  #   The path to Rib config file.\n  # @option config [String] :name ('rib')\n  #   The name of the shell. Used for Rib application.\n  # @option config [String] :result_prompt ('=> ')\n  # @option config [String] :prompt ('>> ')\n  # @option config [Binding, Object] :binding (new_private_binding)\n  #   The context of the shell. Could be an Object.\n  # @option config [Array<String>] :exit ([nil])\n  #   The keywords to exit the shell. `nil` means EOF (ctrl+d).\n  # @option config [Fixnum] :line (1) The beginning of line number.\n  # @option config [String] :history_file ('~/.rib/config/history.rb')\n  #   (Only if {Rib::History} plugin is used) The path to history file.\n  # @option config [Fixnum] :history_size (500)\n  #   (Only if {Rib::History} plugin is used) Maximum numbers of history.\n  # @option config [Hash<Class, Symbol>] :color (...)\n  #   (Only if {Rib::Color} plugin is used) Data type colors mapping.\n  # @option config [String] :autoindent_spaces ('  ')\n  #   (Only if {Rib::Autoindent} plugin is used) The indented string.\n  def initialize(config={})\n    config[:binding] ||= new_private_binding\n    self.config = {:result_prompt => '=> ',\n                   :prompt        => '>> ',\n                   :exit          => [nil],\n                   :line          => 1    }.merge(config)\n    stop\n  end\n\n  # Loops shell until user exits\n  def loop\n    before_loop\n    set_trap\n    start\n    in_loop\n    stop\n    self\n  rescue Exception => e\n    Rib.warn(\"Error while running loop:\\n  #{format_error(e)}\")\n    raise\n  ensure\n    release_trap\n    after_loop\n  end\n\n  def start\n    @running = true\n  end\n\n  def stop\n    @running = false\n  end\n\n  def running?\n    !!@running\n  end\n\n  def warnings\n    @warnings ||= []\n  end\n\n  protected\n  attr_writer :config\n\n  def set_trap\n    @trap_proc = trap('INT'){ raise Interrupt }\n  end\n\n  def release_trap\n    trap('INT', &@trap_proc) if @trap_proc.kind_of?(Proc)\n  end\n\n  private\n  # Avoid namespace pollution from rubygems bin stub.\n  # To be specific, version and str.\n  def new_private_binding\n    TOPLEVEL_BINDING.eval <<-RUBY\n      singleton_class.module_eval do\n        Rib.warn(\"Removing existing main...\") if method_defined?(:main)\n        def main; binding; end # any way to define <main> method?\n      end\n      ret = main\n      singleton_class.send(:remove_method, 'main') # never pollute anything\n      ret\n    RUBY\n  end\nend; end\n"
  },
  {
    "path": "lib/rib/test/history.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'tempfile'\n\ncopy :setup_history do\n  before do\n    if readline?\n      ::Readline::HISTORY.clear\n      stub_readline\n    end\n\n    shell(:history_file => history_file)\n  end\n\n  after do\n    tempfile.unlink if @tempfile\n  end\n\n  def tempfile\n    @tempfile ||= Tempfile.new('rib')\n  end\n\n  def history_file\n    tempfile.path\n  end\nend\n"
  },
  {
    "path": "lib/rib/test/multiline.rb",
    "content": "# frozen_string_literal: true\n\ncopy :setup_multiline do\n  def setup_input str\n    if readline?\n      stub_readline(:mock)\n    else\n      mock($stdin).gets{ str.chomp }\n    end\n  end\n\n  def input str\n    setup_input(str)\n    mock(shell).throw(:rib_multiline)\n  end\n\n  def input_done str, err=nil\n    setup_input(str)\n    if err\n      mock(shell).print_eval_error(is_a(err)){}\n    else\n      mock(shell).print_result(is_a(Object)){}\n    end\n    shell.loop_once\n    ok\n  end\n\n  def check str, err=nil\n    yield if block_given?\n\n    lines = str.split(\"\\n\")\n    lines[0...-1].each{ |line|\n      input(line)\n      shell.loop_once\n    }\n    input_done(lines.last, err)\n  end\n\n  before do\n    stub_output\n  end\nend\n\ncopy :multiline do\n  would 'work with no prompt' do\n    shell.config[:prompt] = ''\n    check <<~RUBY\n      def f\n        0\n      end\n    RUBY\n  end\n\n  would 'def f' do\n    check <<~RUBY\n      def f\n        1\n      end\n    RUBY\n  end\n\n  would 'class C' do\n    check <<~RUBY\n      class C\n      end\n    RUBY\n  end\n\n  would 'begin' do\n    check <<~RUBY\n      begin\n      end\n    RUBY\n  end\n\n  would 'begin with RuntimeError' do\n    check <<~RUBY, RuntimeError\n      begin\n        raise 'multiline raised an error'\n      end\n    RUBY\n  end\n\n  would 'do end' do\n    check <<~RUBY\n      [].each do\n      end\n    RUBY\n  end\n\n  would 'block brace' do\n    check <<~RUBY\n      [].each{\n      }\n    RUBY\n  end\n\n  would 'hash' do\n    check <<~RUBY\n      {\n      }\n    RUBY\n  end\n\n  would 'hash value' do\n    check <<~RUBY\n      {1 =>\n       2}\n    RUBY\n  end\n\n  would 'array' do\n    check <<~RUBY\n      [\n      ]\n    RUBY\n  end\n\n  would 'group' do\n    check <<~RUBY\n      (\n      )\n    RUBY\n  end\n\n  would 'string double quote' do\n    check <<~RUBY\n      \"\n      \"\n    RUBY\n  end\n\n  would 'string single quote' do\n    check <<~RUBY\n      '\n      '\n    RUBY\n  end\n\n  would 'be hash treated as a block SyntaxError' do\n    code = <<~RUBY\n      puts { :x => 10 }.class\n    RUBY\n\n    if RUBY_VERSION >= '3.0.0'\n      check code do\n        stub(shell.config[:binding_object]).puts{}\n      end\n    else\n      check code, SyntaxError\n    end\n  end\n\n  would 'SyntaxError' do\n    check <<~RUBY, SyntaxError\n      s-y n\n    RUBY\n  end\n\n  would 'binary operator +' do\n    check <<~RUBY\n      1/1.to_i +\n      1\n    RUBY\n  end\n\n  would 'binary operator -' do\n    check <<~RUBY\n      1*1.to_i -\n      1\n    RUBY\n  end\n\n  would 'binary operator *' do\n    check <<~RUBY\n      1-1.to_i *\n      1\n    RUBY\n  end\n\n  would 'binary operator /' do\n    code = <<~RUBY\n      1+1.to_i /\n      1\n    RUBY\n\n    if RUBY_VERSION >= '3.0.0'\n      check code.lines.first, SyntaxError\n    else\n      check code\n    end\n  end\n\n  would 'binary operator |' do\n    check <<~RUBY\n      1+1.to_i |\n      1\n    RUBY\n  end\n\n  would 'binary operator &' do\n    check <<~RUBY\n      1+1.to_i &\n      1\n    RUBY\n  end\n\n  would 'binary operator ^' do\n    check <<~RUBY\n      1+1.to_i ^\n      1\n    RUBY\n  end\n\n  would 'backslash at the end' do\n    check <<~RUBY\n      'nice ' \\\\\n      'shell'\n    RUBY\n  end\nend\n"
  },
  {
    "path": "lib/rib/test.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'pork/auto'\nrequire 'muack'\n\nPork::Suite.include(Muack::API)\n\nrequire 'rib'\n\ncopy :rib do\n  before do\n    Rib.disable_plugins\n  end\n\n  after do\n    Muack.verify\n  end\n\n  def shell opts={}\n    @shell ||= new_shell(opts)\n  end\n\n  def new_shell opts={}\n    binding_object = Object.new\n    result = Rib::Shell.new(\n      {:binding => binding_object.instance_eval{binding},\n       :binding_object => binding_object}.\n      merge(opts))\n    yield(result) if block_given?\n    result.before_loop\n  end\n\n  def stub_output\n    stub(shell).print(is_a(String)){}\n    stub(shell).puts(is_a(String)){}\n    stub(shell).puts{}\n  end\n\n  def readline?\n    Rib.constants.map(&:to_s).include?('Readline') &&\n      Rib::Readline.enabled?\n  end\n\n  def stub_readline meth=:stub\n    send(meth, ::Readline).readline(is_a(String), true) do\n      (::Readline::HISTORY << str.chomp).last\n    end\n  end\n\n  singleton_class.module_eval do\n    def test_for *plugins, &block\n      require 'rib/all' # exhaustive tests\n      rest = Rib.plugins - plugins\n\n      before do\n        Rib.enable_plugins(plugins)\n        Rib.disable_plugins(rest)\n      end\n\n      describe \"enabling #{plugins}\" do\n        block.call\n\n        case ENV['TEST_LEVEL']\n        when '0'\n        when '1'\n          test_level1(rest, block)\n        when '2'\n          test_level2(rest, block)\n        when '3'\n          test_level3(rest, block)\n        else # test_level3 is too slow because of rr (i guess)\n          test_level2(rest, block)\n        end\n      end\n    end\n\n    def test_level1 rest, block\n      rest.each{ |target|\n        target.enable\n\n        describe \"also enabling #{target}\" do\n          block.call\n        end\n\n        target.disable\n      }\n    end\n\n    def test_level2 rest, block\n      rest.combination(2).each{ |targets|\n        Rib.enable_plugins(targets)\n\n        describe \"also enabling #{targets.join(', ')}\" do\n          block.call\n        end\n\n        Rib.disable_plugins(targets)\n      }\n    end\n\n    def test_level3 rest, block\n      if rest.empty?\n        block.call\n      else\n        rest[0].enable\n\n        describe \"also enabling #{rest[0]}\" do\n          test_level3(rest[1..-1], block)\n        end\n\n        rest[0].disable\n\n        describe \"disabling #{rest[0]}\" do\n          test_level3(rest[1..-1], block)\n        end\n      end\n    end\n  end\nend\n\ndef main\n  'rib'\nend\n\nRib::Blackhole = Object.new\nb = Rib::Blackhole.singleton_class\nb.instance_methods(true).each{ |m|\n  b.send(:undef_method, m) unless\n    [:object_id, :__send__, :__id__].include?(m) }\n"
  },
  {
    "path": "lib/rib/version.rb",
    "content": "# frozen_string_literal: true\n\nmodule Rib\n  VERSION = '1.6.3'\nend\n"
  },
  {
    "path": "lib/rib.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'rib/shell'\nrequire 'rib/version'\n\nmodule Rib\n  Skip = Object.new\n\n  module_function\n  # All default Rib configs, would be passed to Shell.new in Rib.shell,\n  # but calling Shell.new directly won't bring this in.\n  #\n  # @api public\n  def config\n    @config ||= {:name => 'rib', :prefix => '.', :started_at => Time.now}\n  end\n\n  # All shells in the memory\n  def shells\n    @shells ||= []\n  end\n\n  # All shared variables for all shells\n  def vars\n    @vars   ||= {}\n  end\n\n  # Rib.home is where Rib storing things. By default, it goes to '~/.rib',\n  # or somewhere containing a 'config.rb' or 'history.rb' in the order of\n  # './.rib' (project specific config), or '~/.rib' (home config), or\n  # '~/.config/rib' (home config, residing in ~/.config)\n  #\n  # @api public\n  def home\n    ENV['RIB_HOME'] ||= File.expand_path(\n      [\"#{config[:prefix]}/.rib\", '~/.rib', '~/.config/rib'].find{ |path|\n        File.exist?(File.expand_path(path))\n      } || '~/.rib'\n    )\n  end\n\n  # Convenient shell accessor, which would just give you current last shell\n  # or create one and load the config file. If you need a clean shell which\n  # does not load config file, use Shell.new instead.\n  #\n  # @api public\n  def shell\n    shells.last || begin\n      require_config if config_path && config_path != Skip\n      (shells << Shell.new(config)).last\n    end\n  end\n\n  # All plugins which have been loaded into the memory regardless\n  # it's enabled or not.\n  #\n  # @api public\n  def plugins\n    Shell.ancestors.drop(1).select{ |a| a.singleton_class < Plugin }\n  end\n\n  # Convenient way to disable all plugins in the memory.\n  # This could also take a list of plugins and disable them.\n  #\n  # @api public\n  # @param plugs [Array] (Rib.plugins) Plugins which would be disabled.\n  def disable_plugins plugs=plugins\n    plugs.each(&:disable)\n  end\n\n  # Convenient way to enable all plugins in the memory.\n  # This could also take a list of plugins and enable them.\n  #\n  # @api public\n  # @param plugs [Array] (Rib.plugins) Plugins which would be enabled.\n  def enable_plugins plugs=plugins\n    plugs.each(&:enable)\n  end\n\n  # Load (actually require) the config file if it exists.\n  # This might emit warnings if there's some error while loading it.\n  #\n  # @api public\n  def require_config\n    result = require(config_path) if File.exist?(config_path)\n    Rib.say(\"Config loaded from: #{config_path}\") if $VERBOSE && result\n    result\n  rescue StandardError, LoadError, SyntaxError => e\n    Rib.warn(\"Error loading #{config_path}\\n\" \\\n             \"  #{Rib::API.format_error(e)}\")\n  end\n\n  # The config path where Rib tries to load upon Rib.shell.\n  # It is depending on where Rib.home was discovered if\n  # no specific config path was specified via -c or --config command\n  #\n  # @api public\n  def config_path\n    @config_path ||= File.join(home, 'config.rb')\n  end\n\n  def config_path= new_path\n    @config_path = new_path\n  end\n\n  # Say (print to $stdout, with colors in the future, maybe)\n  # something by the name of Rib.\n  #\n  # @api public\n  # @param words [Array[String]] Words you want to say.\n  def say *words\n    $stdout.puts(Rib.prepare(words))\n  end\n\n  # Warn (print to $stderr, with colors in the future, maybe)\n  # something by the name of Rib.\n  #\n  # @api public\n  # @param words [Array[String]] Words you want to warn.\n  def warn *words\n    $stderr.puts(Rib.prepare(words))\n  end\n\n  # Warn (print to $stderr, with colors in the future, maybe)\n  # something by the name of Rib and then exit(1).\n  #\n  # @api public\n  # @param words [Array[String]] Words you want to warn before aborting.\n  def abort *words\n    warn(words)\n    exit(1)\n  end\n\n  def silence\n    w, v = $-w, $VERBOSE\n    $-w, $VERBOSE = false, false\n    yield\n  ensure\n    $-w, $VERBOSE = w, v\n  end\n\n  private\n  def self.prepare words\n    name = config[:name]\n    \"#{name}: #{words.join(\"\\n#{' '*(name.size+2)}\")}\"\n  end\nend\n"
  },
  {
    "path": "rib.gemspec",
    "content": "# -*- encoding: utf-8 -*-\n# stub: rib 1.6.3 ruby lib\n\nGem::Specification.new do |s|\n  s.name = \"rib\".freeze\n  s.version = \"1.6.3\".freeze\n\n  s.required_rubygems_version = Gem::Requirement.new(\">= 0\".freeze) if s.respond_to? :required_rubygems_version=\n  s.require_paths = [\"lib\".freeze]\n  s.authors = [\"Lin Jen-Shin (godfat)\".freeze]\n  s.date = \"2026-01-20\"\n  s.description = \"Ruby-Interactive-ruBy -- Yet another interactive Ruby shell\\n\\nRib is based on the design of [ripl][] and the work of [ripl-rc][], some of\\nthe features are also inspired by [pry][]. The aim of Rib is to be fully\\nfeatured and yet very easy to opt-out or opt-in other features. It shall\\nbe simple, lightweight and modular so that everyone could customize Rib.\\n\\n[ripl]: https://github.com/cldwalker/ripl\\n[ripl-rc]: https://github.com/godfat/ripl-rc\\n[pry]: https://github.com/pry/pry\".freeze\n  s.email = [\"godfat (XD) godfat.org\".freeze]\n  s.executables = [\n  \"rib\".freeze,\n  \"rib-all\".freeze,\n  \"rib-auto\".freeze,\n  \"rib-min\".freeze,\n  \"rib-rack\".freeze,\n  \"rib-rails\".freeze]\n  s.files = [\n  \".gitignore\".freeze,\n  \".gitlab-ci.yml\".freeze,\n  \".gitmodules\".freeze,\n  \"CHANGES.md\".freeze,\n  \"Gemfile\".freeze,\n  \"LICENSE\".freeze,\n  \"README.md\".freeze,\n  \"Rakefile\".freeze,\n  \"TODO.md\".freeze,\n  \"bin/rib\".freeze,\n  \"bin/rib-all\".freeze,\n  \"bin/rib-auto\".freeze,\n  \"bin/rib-min\".freeze,\n  \"bin/rib-rack\".freeze,\n  \"bin/rib-rails\".freeze,\n  \"lib/rib.rb\".freeze,\n  \"lib/rib/all.rb\".freeze,\n  \"lib/rib/api.rb\".freeze,\n  \"lib/rib/app/auto.rb\".freeze,\n  \"lib/rib/app/rack.rb\".freeze,\n  \"lib/rib/app/rails.rb\".freeze,\n  \"lib/rib/config.rb\".freeze,\n  \"lib/rib/core.rb\".freeze,\n  \"lib/rib/core/completion.rb\".freeze,\n  \"lib/rib/core/history.rb\".freeze,\n  \"lib/rib/core/last_value.rb\".freeze,\n  \"lib/rib/core/multiline.rb\".freeze,\n  \"lib/rib/core/readline.rb\".freeze,\n  \"lib/rib/core/squeeze_history.rb\".freeze,\n  \"lib/rib/core/strip_backtrace.rb\".freeze,\n  \"lib/rib/debug.rb\".freeze,\n  \"lib/rib/extra/autoindent.rb\".freeze,\n  \"lib/rib/extra/byebug.rb\".freeze,\n  \"lib/rib/extra/hirb.rb\".freeze,\n  \"lib/rib/extra/paging.rb\".freeze,\n  \"lib/rib/extra/spring.rb\".freeze,\n  \"lib/rib/more.rb\".freeze,\n  \"lib/rib/more/anchor.rb\".freeze,\n  \"lib/rib/more/beep.rb\".freeze,\n  \"lib/rib/more/bottomup_backtrace.rb\".freeze,\n  \"lib/rib/more/caller.rb\".freeze,\n  \"lib/rib/more/color.rb\".freeze,\n  \"lib/rib/more/edit.rb\".freeze,\n  \"lib/rib/more/multiline_history.rb\".freeze,\n  \"lib/rib/more/multiline_history_file.rb\".freeze,\n  \"lib/rib/plugin.rb\".freeze,\n  \"lib/rib/runner.rb\".freeze,\n  \"lib/rib/shell.rb\".freeze,\n  \"lib/rib/test.rb\".freeze,\n  \"lib/rib/test/history.rb\".freeze,\n  \"lib/rib/test/multiline.rb\".freeze,\n  \"lib/rib/version.rb\".freeze,\n  \"rib.gemspec\".freeze,\n  \"task/README.md\".freeze,\n  \"task/gemgem.rb\".freeze,\n  \"test/core/test_completion.rb\".freeze,\n  \"test/core/test_history.rb\".freeze,\n  \"test/core/test_last_value.rb\".freeze,\n  \"test/core/test_multiline.rb\".freeze,\n  \"test/core/test_readline.rb\".freeze,\n  \"test/core/test_squeeze_history.rb\".freeze,\n  \"test/core/test_strip_backtrace.rb\".freeze,\n  \"test/extra/test_autoindent.rb\".freeze,\n  \"test/more/test_anchor.rb\".freeze,\n  \"test/more/test_beep.rb\".freeze,\n  \"test/more/test_caller.rb\".freeze,\n  \"test/more/test_color.rb\".freeze,\n  \"test/more/test_multiline_history.rb\".freeze,\n  \"test/test_api.rb\".freeze,\n  \"test/test_plugin.rb\".freeze,\n  \"test/test_runner.rb\".freeze,\n  \"test/test_shell.rb\".freeze]\n  s.homepage = \"https://github.com/godfat/rib\".freeze\n  s.licenses = [\"Apache-2.0\".freeze]\n  s.rubygems_version = \"4.0.4\".freeze\n  s.summary = \"Ruby-Interactive-ruBy -- Yet another interactive Ruby shell\".freeze\n  s.test_files = [\n  \"test/core/test_completion.rb\".freeze,\n  \"test/core/test_history.rb\".freeze,\n  \"test/core/test_last_value.rb\".freeze,\n  \"test/core/test_multiline.rb\".freeze,\n  \"test/core/test_readline.rb\".freeze,\n  \"test/core/test_squeeze_history.rb\".freeze,\n  \"test/core/test_strip_backtrace.rb\".freeze,\n  \"test/extra/test_autoindent.rb\".freeze,\n  \"test/more/test_anchor.rb\".freeze,\n  \"test/more/test_beep.rb\".freeze,\n  \"test/more/test_caller.rb\".freeze,\n  \"test/more/test_color.rb\".freeze,\n  \"test/more/test_multiline_history.rb\".freeze,\n  \"test/test_api.rb\".freeze,\n  \"test/test_plugin.rb\".freeze,\n  \"test/test_runner.rb\".freeze,\n  \"test/test_shell.rb\".freeze]\nend\n"
  },
  {
    "path": "test/core/test_completion.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/core/completion'\n\ndescribe Rib::Completion do\n  paste :rib\n\n  before do\n    Rib::Completion.enable\n  end\n\n  would 'start bond' do\n    new_shell do |sh|\n      eval_binding = sh.method(:eval_binding).source_location\n\n      mock(Bond).start(having(eval_binding: is_a(Proc))).peek_args do |*args|\n        expect(args.first[:eval_binding].source_location).eq eval_binding\n\n        args\n      end\n    end\n\n    expect(Bond).started?\n  end\nend\n"
  },
  {
    "path": "test/core/test_history.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/test/history'\nrequire 'rib/core/history'\n\ndescribe Rib::History do\n  paste :rib\n  paste :setup_history\n\n  test_for Rib::History do\n    would '#after_loop save history' do\n      inputs = %w[blih blah]\n      shell.history.push(*inputs)\n\n      shell.after_loop\n\n      expect(File.read(history_file)).eq \"#{inputs.join(\"\\n\")}\\n\"\n    end\n\n    would '#before_loop load previous history' do\n      File.write(history_file, \"check\\nthe\\nmike\")\n\n      shell.before_loop\n\n      expect(shell.history.to_a).eq %w[check the mike]\n    end\n\n    would '#before_loop have empty history if no history file exists' do\n      expect(shell.history.to_a).eq []\n    end\n\n    would '#read_history be accessible to plugins in #before_loop' do\n      mod = Module.new do\n        def read_history\n          config[:history] = ['pong_read_history']\n        end\n      end\n      klass = Rib::Shell.dup\n      klass.use(mod)\n\n      shell = klass.new.before_loop\n\n      expect(shell.history).eq ['pong_read_history']\n    end\n\n    would '#write_history be accessible to plugins in #after_loop' do\n      mod = Module.new do\n        def write_history\n          config[:history] = ['pong_write_history']\n        end\n      end\n      klass = Rib::Shell.dup\n      klass.use(mod)\n\n      shell = klass.new.before_loop.after_loop\n\n      expect(shell.history).eq ['pong_write_history']\n    end\n  end\nend\n"
  },
  {
    "path": "test/core/test_last_value.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/core/last_value'\n\ndescribe Rib::LastValue do\n  paste :rib\n\n  before do\n    stub_output\n    stub(Rib).shell{shell}\n  end\n\n  test_for Rib::LastValue do\n    would 'set last_value' do\n      mock(shell).get_input{'Rib.last_value'}\n      mock(shell).get_input{'10**2'}\n      mock(shell).get_input{'Rib.last_value'}\n\n      expect(shell.loop_once).eq [nil, nil]\n\n      shell.loop_once\n\n      expect(shell.loop_once).eq [100, nil]\n    end\n\n    would 'set last_exception' do\n      mock(shell).get_input{'XD'}\n      mock(shell).get_input{'Rib.last_exception'}\n\n      shell.loop_once\n\n      expect(shell.loop_once.first).kind_of?(NameError)\n    end\n  end\nend\n"
  },
  {
    "path": "test/core/test_multiline.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/test/multiline'\nrequire 'rib/core/multiline'\n\ndescribe Rib::Multiline do\n  paste :rib\n  paste :setup_multiline\n\n  test_for Rib::Multiline do\n    paste :multiline\n  end\nend\n"
  },
  {
    "path": "test/core/test_readline.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/core/readline'\n\ndescribe Rib::Readline do\n  paste :rib\n\n  test_for Rib::Readline do\n    would '#before_loop set @history' do\n      expect(shell.history).eq Readline::HISTORY\n    end\n\n    would '#get_input calling Readline.readline' do\n      mock(Readline).readline(shell.prompt, true){'ok'}\n\n      expect(shell.get_input).eq 'ok'\n    end\n  end\nend\n"
  },
  {
    "path": "test/core/test_squeeze_history.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/test/history'\nrequire 'rib/core/squeeze_history'\n\ndescribe Rib::SqueezeHistory do\n  paste :rib\n  paste :setup_history\n\n  test_for Rib::History, Rib::SqueezeHistory do\n    before do\n      @input = %w[foo bar bar foo bar]\n    end\n\n    would 'after_loop saves squeezed history' do\n      shell.history.push(*@input)\n      shell.after_loop\n\n      expect(File.read(history_file)).eq %w[foo bar foo bar].join(\"\\n\") + \"\\n\"\n    end\n\n    would 'loop_once squeeze history' do\n      stub_output\n      stub(shell).get_input{ (shell.history << \"'#{@input.shift}'\").last }\n\n      @input.size.times{ shell.loop_once }\n\n      expect(shell.history.to_a).eq %w[foo bar foo bar].map{ |i| \"'#{i}'\" }\n    end\n\n    would 'be disabled if disabled' do\n      Rib::SqueezeHistory.disable do\n        stub_output\n        stub(shell).get_input{ (shell.history << \"'#{@input.shift}'\").last }\n        input = @input.dup\n\n        @input.size.times{ shell.loop_once }\n\n        expect(shell.history.to_a).eq input.map{ |i| \"'#{i}'\" }\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test/core/test_strip_backtrace.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/core/strip_backtrace'\n\ndescribe Rib::StripBacktrace do\n  would 'strip home' do\n    backtrace = [\"#{ENV['HOME']}/test\", \"/prefix/#{ENV['HOME']}/test\"]\n\n    expect(Rib::StripBacktrace.strip_home_backtrace(backtrace)).\n      eq ['~/test', \"/prefix/#{ENV['HOME']}/test\"]\n  end\n\n  would 'strip current working directory' do\n    backtrace = [File.expand_path(__FILE__)]\n\n    expect(Rib::StripBacktrace.strip_cwd_backtrace(backtrace)).\n      eq ['test/core/test_strip_backtrace.rb']\n  end\nend\n"
  },
  {
    "path": "test/extra/test_autoindent.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/extra/autoindent'\n\ndescribe Rib::Autoindent do\n  paste :rib\n\n  autoindent = Class.new do\n    include Rib::Autoindent, Rib::Multiline, Rib::API\n    def config\n      {:line => 0, :binding => TOPLEVEL_BINDING, :prompt => '>> '}\n    end\n    def stack_size\n      autoindent_stack.size\n    end\n  end\n\n  before do\n    Rib::Multiline.enable\n    Rib::Autoindent.enable\n    @indent = autoindent.new\n\n    mock(@indent).puts(matching(/^\\e/)).times(0)\n\n    expect(@indent.stack_size).eq 0\n  end\n\n  def ri input, size\n    @indent.eval_input(input)\n\n    expect(@indent.stack_size).eq size\n  end\n\n  def le input, size\n    mock(@indent).puts(matching(/^\\e/)){}\n\n    @indent.eval_input(input)\n\n    expect(@indent.stack_size).eq size\n  end\n\n  would 'begin rescue else ensure end' do\n    ri('begin'         , 1)\n    ri(  '1'           , 1)\n    le('rescue'        , 1)\n    ri(  '1'           , 1)\n    le('rescue=>e'     , 1)\n    le('rescue => e'   , 1)\n    le('rescue =>e'    , 1)\n    le('rescue E=>e '  , 1)\n    le('rescue E'      , 1)\n    le('rescue E => e ', 1)\n    le('rescue E=> e'  , 1)\n    le('rescue E =>e ' , 1)\n    le('else'          , 1)\n    ri(  '1'           , 1)\n    le('ensure'        , 1)\n    ri(  '1'           , 1)\n    le('end while nil' , 0)\n  end\n\n  would 'def rescue else ensure end' do\n    ri('def f a'       , 1)\n    ri(  'if a'        , 2)\n    le(  'end'         , 1)\n    le('rescue'        , 1)\n    ri(  '1'           , 1)\n    le('rescue=>e'     , 1)\n    le('rescue => e'   , 1)\n    le('rescue =>e'    , 1)\n    le('rescue E=>e '  , 1)\n    le('rescue E'      , 1)\n    le('rescue E => e ', 1)\n    le('rescue E=> e'  , 1)\n    le('rescue E =>e ' , 1)\n    le('else'          , 1)\n    ri(  '1'           , 1)\n    le('ensure'        , 1)\n    ri(  '1'           , 1)\n    le('end while nil' , 0)\n  end\n\n  would 'if elsif else end' do\n    ri('if true'       , 1)\n    ri(  'if false'    , 2)\n    ri(    '1'         , 2)\n    le(  'end'         , 1)\n    ri(  'if true'     , 2)\n    le(  'elsif true'  , 2)\n    ri(    '1'         , 2)\n    le(  'else'        , 2)\n    ri(    '1'         , 2)\n    le(  'end'         , 1)\n    ri(  'if 1'        , 2)\n    ri(    'if 2'      , 3)\n    le(    'end'       , 2)\n    le(  'end'         , 1)\n    le('end'           , 0)\n  end\n\n  would 'unless else end' do\n    ri('unless 1'      , 1)\n    ri(  'unless 1'    , 2)\n    ri(    '1'         , 2)\n    le(  'end '        , 1)\n    le('else'          , 1)\n    ri(  '1'           , 1)\n    le('end'           , 0)\n  end\n\n  would 'case when else end' do\n    ri('case 1'        , 1)\n    le('when 1'        , 1)\n    ri(  '1'           , 1)\n    le('when 2'        , 1)\n    ri('  if 1'        , 2)\n    le('  end'         , 1)\n    le('else'          , 1)\n    ri(  '1'           , 1)\n    le('end'           , 0)\n  end\n\n  would 'class Object end' do\n    ri('class Object'  , 1)\n    ri(  'if true'     , 2)\n    le(  'end'         , 1)\n    le('end'           , 0)\n  end\n\n  would 'module Rib end' do\n    ri('module Rib'    , 1)\n    ri(  'module_function', 1)\n    ri(  'if true'     , 2)\n    le(  'end'         , 1)\n    le('end'           , 0)\n  end\n\n  would 'while end' do\n    ri('while false'   , 1)\n    ri(  'if true'     , 2)\n    le(  'end'         , 1)\n    le('end'           , 0)\n  end\n\n  would 'for end' do\n    ri('for x in 1..2' , 1)\n    ri(  'if true'     , 2)\n    le(  'end'         , 1)\n    le('end'           , 0)\n  end\n\n  would 'until end' do\n    ri('until true'    , 1)\n    ri(  'if true'     , 2)\n    le(  'end'         , 1)\n    le('end'           , 0)\n  end\n\n  would 'do end' do\n    ri(\"to_s''do\"      , 1)\n    ri(  \"to_s '' do\"  , 2)\n    le(  'end'         , 1)\n    ri(  'to_s \"\" do'  , 2)\n    le(  'end'         , 1)\n    ri(  'to_s // do'  , 2)\n    le(  'end'         , 1)\n    le('end'           , 0)\n  end\n\n  would '{}' do\n    ri('{'             , 1)\n    ri(  ':a => :b'    , 1)\n    le('}'             , 0)\n  end\n\n  would '[].each{}' do\n    ri('[].each{'      , 1)\n    ri(  '0'           , 1)\n    ri(    '[].each {' , 2)\n    le(    '}'         , 1)\n    le('}'             , 0)\n  end\n\n  would '()' do\n    ri('('             , 1)\n    ri(  '0'           , 1)\n    le(')'             , 0)\n  end\n\n  would '{}.dig()' do\n    ri('{}.dig('       , 1)\n    ri(  '0,'          , 1)\n    ri(  '1'           , 1)\n    le(')'             , 0)\n  end\n\n  would '[]' do\n    ri('['             , 1)\n    ri(  '0,'          , 1)\n    ri(  '1,'          , 1)\n    ri(  '['           , 2)\n    ri(    '2'         , 2)\n    le(  ']'           , 1)\n    le(']'             , 0)\n  end\nend\n"
  },
  {
    "path": "test/more/test_anchor.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/more/anchor'\nrequire 'rib/core/multiline'\nrequire 'rib/test/multiline'\n\ndescribe Rib::Anchor do\n  paste :rib\n  paste :setup_multiline\n\n  before do\n    Rib::Anchor.enable\n  end\n\n  describe '#anchor?' do\n    would 'give true when anchoring' do\n      stub(Rib).shell{shell}\n\n      mock(shell).get_input do\n        expect(shell).anchor?\n\n        mock(shell).puts{}\n\n        nil\n      end\n\n      Rib.anchor 'test'\n    end\n\n    would 'give false when not anchoring' do\n      expect(new_shell).not.anchor?\n    end\n  end\n\n  describe '.stop_anchors' do\n    def anchor_deeper shell, index\n      mock(shell).get_input do\n        mock(shell).puts.times(0)\n\n        expect(shell).anchor?\n        expect(shell.loop_eval('self')).eq index\n\n        mock_deeper(index + 1)\n        'Rib.anchor self + 1'\n      end\n    end\n\n    def escape shell\n      mock(shell).get_input do\n        'Rib.stop_anchors'\n      end\n    end\n\n    def mock_deeper index\n      mock(Rib).shell.times(2) # ignore first 2 calls, see Rib.anchor\n      mock(Rib).shell.peek_return do |deeper_shell|\n        if index < 5\n          anchor_deeper(deeper_shell, index)\n        else\n          escape(deeper_shell)\n        end\n\n        deeper_shell\n      end\n    end\n\n    would 'exit all anchors' do\n      shell = Rib.shell\n\n      mock(shell).get_input do\n        mock_deeper(0)\n        'Rib.anchor 0'\n      end\n\n      mock(shell).get_input{}\n      mock(shell).puts{}\n\n      shell.loop\n    end\n  end\n\n  test_for Rib::Anchor, Rib::Multiline do\n    paste :multiline\n  end\nend\n"
  },
  {
    "path": "test/more/test_beep.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/more/beep'\n\ndescribe Rib::Beep do\n  paste :rib\n\n  before do\n    Rib::Beep.enable\n  end\n\n  def verify delay, threshold=nil, &block\n    shell(:started_at => Time.now - delay,\n          :beep_threshold => threshold, &block)\n\n    stub_output\n    mock(shell).get_input{}\n\n    shell.loop\n\n    ok\n  end\n\n  def expect_beep sh\n    mock(sh).print(\"\\a\"){}\n  end\n\n  def unexpect_beep sh\n    stub(sh).print.with_any_args{ flunk }\n  end\n\n  describe 'beep' do\n    would 'beep if loading too long' do\n      verify(10, &method(:expect_beep))\n    end\n\n    would 'be configurable via beep_threshold' do\n      verify(2, 1, &method(:expect_beep))\n    end\n  end\n\n  describe 'not beep' do\n    would 'not beep if not loading long' do\n      verify(2, &method(:unexpect_beep))\n    end\n\n    would 'be configurable via beep_threshold' do\n      verify(10, 15, &method(:unexpect_beep))\n    end\n  end\nend\n"
  },
  {
    "path": "test/more/test_caller.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/more/caller'\n\ndescribe Rib::Caller do\n  paste :rib\n\n  test_for Rib::Caller do\n    would 'puts some backtrace' do\n      mock(Rib.shell).puts(is_a(String)){ ok }\n\n      Rib.caller\n    end\n  end\nend\n"
  },
  {
    "path": "test/more/test_color.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/more/color'\n\ndescribe Rib::Color do\n  paste :rib\n\n  before do\n    Rib::Color.enable\n  end\n\n  color = Class.new do\n    include Rib::Color\n    def colors\n      @colors ||= Rib::Shell.new.before_loop.config[:color]\n    end\n\n    def inspect_result result\n      result.inspect\n    end\n  end.new\n\n  would 'give correct color' do\n    color.send(:format_color,\n      [{0 => :a}, 'b', [nil, {false => Object}], {true => Exception.new}]).\n        should.eq \\\n          \"\\e[34m[\\e[0m\\e[34m{\\e[0m\\e[31m0\\e[0m\\e[34m=>\\e[0m\\e[36m:a\\e[0m\\e\" \\\n          \"[34m}\\e[0m\\e[34m, \\e[0m\\e[32m\\\"b\\\"\\e[0m\\e[34m, \\e[0m\\e[34m[\\e[0m\" \\\n          \"\\e[35mnil\\e[0m\\e[34m, \\e[0m\\e[34m{\\e[0m\\e[35mfalse\\e[0m\\e[34m=>\"  \\\n          \"\\e[0m\\e[33mObject\\e[0m\\e[34m}\\e[0m\\e[34m]\\e[0m\\e[34m, \\e[0m\\e[34m\"\\\n          \"{\\e[0m\\e[35mtrue\\e[0m\\e[34m=>\\e[0m\\e[35m#<Exception: Exception>\"  \\\n          \"\\e[0m\\e[34m}\\e[0m\\e[34m]\\e[0m\"\n  end\n\n  would 'inspect recursive array and hash just like built-in inspect' do\n    a = []\n    a << a\n    h = {}\n    h[0] = h\n    color.send(:format_color, [a, h]).should.eq \\\n      \"\\e[34m[\\e[0m\\e[34m[\\e[0m\\e[34m[...]\\e[0m\\e[34m]\\e[0m\\e[34m, \\e[0m\" \\\n      \"\\e[34m{\\e[0m\\e[31m0\\e[0m\\e[34m=>\\e[0m\\e[34m{...}\\e[0m\\e[34m}\\e[0m\" \\\n      \"\\e[34m]\\e[0m\"\n  end\n\n  # regression test\n  would \"colorize errors with `/' inside\" do\n    error = Class.new(Exception)\n\n    begin\n      line = __LINE__; raise error\n    rescue error => e\n      msg = \"test/more/#{Rib::Color.yellow{'test_color.rb'}}:\" \\\n            \"#{Rib::Color.red{line}}:in #{Rib::Color.green}\"\n      Rib::Color.colorize_backtrace(e.backtrace).first.should =~ \\\n        Regexp.new(\n          \"#{Regexp.escape(msg)}(?:`|').+'#{Regexp.escape(Rib::Color.reset)}\")\n    end\n  end\n\n  would 'colorize warnings' do\n    shell = new_shell\n\n    shell.warn('test')\n\n    expect(shell.warnings).eq [\"\\e[31mtest\\e[0m\"]\n  end\nend\n"
  },
  {
    "path": "test/more/test_multiline_history.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/test/multiline'\nrequire 'rib/more/multiline_history'\n\ndescribe Rib::MultilineHistory do\n  paste :rib\n  paste :setup_multiline\n\n  def check str, err=nil\n    shell.history.clear\n    yield if block_given?\n    with_history(str, err)\n\n    @shell = nil\n    stub_output\n\n    shell.history.clear\n    shell.history << 'old history'\n    yield if block_given?\n    with_history(str, err, 'old history')\n  end\n\n  def with_history str, err, *prefix\n    lines = str.split(\"\\n\")\n    lines[0...-1].inject([]){ |result, line|\n      input(line)\n      shell.loop_once\n      result << line\n\n      expect(shell.history.to_a).eq prefix + result\n\n      result\n    }\n    input_done(lines.last, err)\n\n    history = if lines.size == 1\n                lines.first\n              else\n                \"\\n#{lines.join(\"\\n\")}\"\n              end\n\n    expect(shell.history.to_a).eq prefix + [history]\n  end\n\n  test_for Rib::History, Rib::Multiline, Rib::MultilineHistory do\n    paste :multiline\n  end\nend\n"
  },
  {
    "path": "test/test_api.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/shell'\n\ndescribe Rib::API do\n  paste :rib\n\n  Rib::API.instance_methods.delete_if{ |e| e[/=$/] }.each do |meth|\n    would \"##{meth} be accessible to plugins\" do\n      mod = Module.new do\n        define_method meth do\n          \"pong_#{meth}\"\n        end\n      end\n      klass = Rib::Shell.dup\n      klass.use(mod)\n\n      expect(klass.new.send(meth)).eq \"pong_#{meth}\"\n    end\n  end\n\n  would 'emit a warning whenever result is not a string' do\n    object = Class.new{ alias_method :inspect, :object_id }.new\n\n    mock(shell).get_input{'object'}\n    mock(shell).loop_eval('object'){object}\n    mock(shell).puts(\"=> #{object.object_id}\"){}\n    mock($stderr).puts(including(\"#{object.class}#inspect\")){}\n\n    shell.loop_once\n\n    ok\n  end\n\n  describe '#warn' do\n    would 'append a warning message to warnings' do\n      shell.warn('test')\n\n      expect(shell.warnings).eq ['test']\n    end\n  end\n\n  describe '#flush_warnings' do\n    before do\n      shell.warn('test')\n\n      mock($stderr).puts('rib: test'){}\n    end\n\n    would 'warn to $stderr from #warnings' do\n      shell.send(:flush_warnings)\n\n      ok\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_plugin.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/all'\n\ndescribe Rib::Plugin do\n  paste :rib\n\n  before do\n    @names = Dir[File.expand_path(\n               \"#{File.dirname(__FILE__)}/../lib/rib/{core,more,zore}/*.rb\")].\n               map   {|path| File.basename(path)[0..-4]                     }\n    @mods  = Rib.plugins\n  end\n\n  would 'have shortcut methods' do\n    @names.each do |name|\n      %w[enable disable].each do |meth|\n        expect(Rib).respond_to?(\"#{meth}_#{name}\")\n      end\n\n      %w[enabled? disabled?].each do |meth|\n        expect(Rib).respond_to?(\"#{name}_#{meth}\")\n      end\n    end\n  end\n\n  would 'be the same as mod methods' do\n    @mods.shuffle.take(@mods.size/2).each(&:disable)\n\n    @names.each do |name|\n      %w[enabled? disabled?].each do |meth|\n        expect(Rib.send(\"#{name}_#{meth}\")).eq \\\n          @mods.find{ |mod|\n            mod.name[/::\\w+$/].tr(':', '') ==\n            name.gsub(/([^_]+)/){$1.capitalize}.tr('_', '') }.\n          send(meth)\n      end\n    end\n  end\n\n  would 'have backward compatibility for accessing Shell' do\n    mock(Rib).warn(\n      is_a(String), is_a(String), including(\"#{__FILE__}:47\")){ok}\n\n    Module.new.module_eval <<-RUBY, __FILE__, __LINE__ + 1\n      extend Rib::Plugin\n      Shell\n    RUBY\n  end\nend\n"
  },
  {
    "path": "test/test_runner.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/runner'\n\ndescribe Rib::Runner do\n  paste :rib\n\n  before do\n    mock(Rib).shell{ shell }.times(2)\n  end\n\n  def input *args\n    args.each{ |item| mock(shell).get_input{ item } }\n    mock(shell).get_input{}\n  end\n\n  def output *args\n    args.each{ |item| mock(shell).puts(\"=> #{item}\"){} }\n    mock(shell).puts{}\n  end\n\n  would '-e' do\n     input('a')\n    output('1')\n\n    expect(Rib::Runner.run(%w[-ea=1])).eq shell\n  end\n\n  would '-e nothing' do\n     input\n    output\n\n    expect(Rib::Runner.run(%w[-e])).eq shell\n  end\n\n  def verify_app_e argv\n     input('a')\n    output('1')\n    conf = {:name => 'rib'}\n    min  = 'rib-min'\n\n    mock(Rib::Runner).which_bin(min){ min }\n    mock(Rib::Runner).load(min){ Rib::Runner.run(argv) }\n    stub(Rib).config{ conf }\n\n    expect(Rib::Runner.run(argv)).eq shell\n  end\n\n  would 'min -e' do\n    verify_app_e(%w[min -ea=1])\n  end\n\n  would '-e min' do\n    verify_app_e(%w[-ea=1 min])\n  end\nend\n"
  },
  {
    "path": "test/test_shell.rb",
    "content": "\nrequire 'rib/test'\nrequire 'rib/shell'\n\ndescribe Rib::Shell do\n  paste :rib\n\n  describe '#loop' do\n    def input str=Rib::Skip\n      mock(shell).get_input{if block_given? then yield else str end}\n      shell.loop\n      ok\n    end\n\n    would 'exit'      do                              input('exit' ) end\n    would 'also exit' do                              input(' exit') end\n    would 'ctrl+d'    do mock(shell).puts{}         ; input(nil)     end\n    would ':q'        do shell.config[:exit] << ':q'; input(':q')    end\n    would '\\q'        do shell.config[:exit] << '\\q'; input('\\q')    end\n\n    would 'not puts anything if it is not running' do\n      mock(shell).puts.times(0)\n\n      shell.eval_binding.eval('self').instance_variable_set(:@shell, shell)\n\n      input('@shell.stop; throw :rib_exit')\n    end\n\n    describe 'trap' do\n      before do\n        @token = Class.new(Exception)\n        @old_trap = trap('INT'){ raise @token }\n        mock(shell).handle_interrupt{ mock(shell).get_input{'exit'} }\n      end\n\n      after do\n        trap('INT', &@old_trap)\n      end\n\n      def interrupt\n        Process.kill('SIGINT', Process.pid)\n        sleep\n      end\n\n      would 'fence and restore ctrl+c interruption' do\n        input{ interrupt }\n\n        expect.raise(@token){ interrupt }\n      end\n    end\n  end\n\n  describe '#loop_once' do\n    def input str=nil\n      if block_given?\n        mock(shell).get_input{ yield }\n      else\n        mock(shell).get_input{ str }\n      end\n\n      shell.loop_once\n\n      ok\n    end\n\n    would 'handles ctrl+c' do\n      mock(shell).handle_interrupt{}\n\n      input{ raise Interrupt }\n    end\n\n    would 'prints result' do\n      mock(shell).puts('=> \"mm\"'){}\n\n      input('\"m\" * 2')\n    end\n\n    %w[next break].each do |keyword|\n      would \"handle #{keyword}\" do\n        mock(shell).puts(matching(/^SyntaxError:/)){}\n\n        input(keyword)\n      end\n    end\n\n    would 'error in print_result' do\n      mock(Rib).warn(matching(/Error while printing result.*BOOM/m)){}\n\n      input('obj = Object.new; def obj.inspect; raise \"BOOM\"; end; obj')\n    end\n\n    would 'not crash if user input is a blackhole' do\n      mock(Rib).warn(matching(/Error while printing result/)){}\n\n      input('Rib::Blackhole')\n    end\n\n    would 'print error from eval' do\n      mock(shell).puts(matching(/RuntimeError/)){}\n\n      input('raise \"blah\"')\n    end\n  end\n\n  describe '#prompt' do\n    would 'be changeable' do\n      shell.config[:prompt] = '> '\n\n      expect(shell.prompt).eq  '> '\n    end\n  end\n\n  describe '#eval_input' do\n    before do\n      @line = shell.config[:line]\n    end\n\n    would 'line' do\n      shell.eval_input('10 ** 2')\n\n      expect(shell.config[:line]).eq @line + 1\n    end\n\n    would 'print error and increments line' do\n      result, err = shell.eval_input('{')\n\n      expect(result).eq nil\n      expect(err).kind_of?(SyntaxError)\n      expect(shell.config[:line]).eq @line + 1\n    end\n  end\n\n  describe '#running?' do\n    would 'have complete flow' do\n      expect(shell).not.running?\n\n      mock(shell).get_input do\n        expect(shell).running?\n\n        mock(shell).puts{}\n\n        nil\n      end\n\n      shell.loop\n\n      expect(shell).not.running?\n    end\n  end\n\n  describe '#stop' do\n    would 'stop the loop if it is stopped' do\n      mock(shell).get_input do\n        expect(shell).running?\n\n        shell.stop\n\n        expect(shell).not.running?\n\n        'Rib::Skip'\n      end\n\n      shell.loop\n    end\n  end\n\n  would 'call after_loop even if in_loop raises' do\n    mock(shell).loop_once{ raise 'boom' }\n    mock(Rib).warn(is_a(String)){}\n    mock(shell).after_loop{}\n\n    expect.raise(RuntimeError) do\n      shell.loop\n    end\n  end\n\n  would 'have empty binding' do\n    expect(shell(:binding => nil).eval_input('local_variables').first).empty?\n  end\n\n  would 'not pollute main' do\n    expect(shell(:binding => nil).eval_input('main').first).eq 'rib'\n  end\n\n  would 'be main' do\n    expect(shell(:binding => nil).eval_input('self.inspect').first).eq 'main'\n  end\n\n  would 'warn on removing main' do\n    mock(TOPLEVEL_BINDING.eval('singleton_class')).method_defined?(:main) do\n      true\n    end\n\n    mock(Rib).warn(is_a(String)){}\n\n    expect(shell(:binding => nil).eval_input('main').first).eq 'rib'\n  end\nend\n"
  }
]